~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/src/video/video_scaler.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
#include "libav_deps.h"
33
33
#include "video_scaler.h"
34
 
#include "check.h"
 
34
#include "logger.h"
 
35
 
 
36
#include <cassert>
35
37
 
36
38
namespace sfl_video {
37
39
 
38
 
VideoScaler::VideoScaler() : ctx_(0), mode_(SWS_FAST_BILINEAR) {}
 
40
VideoScaler::VideoScaler() : ctx_(0), mode_(SWS_FAST_BILINEAR), tmp_data_() {}
39
41
 
40
42
VideoScaler::~VideoScaler() { sws_freeContext(ctx_); }
41
43
 
42
 
void VideoScaler::scale(VideoFrame &input, VideoFrame &output)
 
44
void VideoScaler::scale(const VideoFrame &input, VideoFrame &output)
43
45
{
44
 
    AVFrame *input_frame = input.get();
 
46
    const AVFrame *input_frame = input.get();
45
47
    AVFrame *output_frame = output.get();
46
48
 
47
49
    ctx_ = sws_getCachedContext(ctx_,
59
61
    }
60
62
 
61
63
    sws_scale(ctx_, input_frame->data, input_frame->linesize, 0,
62
 
              input_frame->height, output_frame->data, output_frame->linesize);
63
 
}
64
 
 
65
 
void VideoScaler::scale_and_pad(VideoFrame &input, VideoFrame &output,
 
64
              input_frame->height, output_frame->data,
 
65
              output_frame->linesize);
 
66
}
 
67
 
 
68
void VideoScaler::scale_with_aspect(const VideoFrame &input, VideoFrame &output)
 
69
{
 
70
    AVFrame *output_frame = output.get();
 
71
    scale_and_pad(input, output, 0, 0, output_frame->width,
 
72
                  output_frame->height, true);
 
73
}
 
74
 
 
75
static inline bool is_yuv_planar(const AVPixFmtDescriptor *desc)
 
76
{
 
77
    unsigned used_bit_mask = (1u << desc->nb_components) - 1;
 
78
 
 
79
    if (not (desc->flags & PIX_FMT_PLANAR)
 
80
        or desc->flags & PIX_FMT_RGB)
 
81
        return false;
 
82
 
 
83
    /* handle formats that do not use all planes */
 
84
    for (unsigned i = 0; i < desc->nb_components; ++i)
 
85
        used_bit_mask &= ~(1u << desc->comp[i].plane);
 
86
 
 
87
    return not used_bit_mask;
 
88
}
 
89
 
 
90
void VideoScaler::scale_and_pad(const VideoFrame &input, VideoFrame &output,
66
91
                                unsigned xoff, unsigned yoff,
67
 
                                unsigned dest_width, unsigned dest_height)
 
92
                                unsigned dest_width, unsigned dest_height,
 
93
                                bool keep_aspect)
68
94
{
69
 
    AVFrame *input_frame = input.get();
 
95
    const AVFrame *input_frame = input.get();
70
96
    AVFrame *output_frame = output.get();
71
 
    uint8_t *data[AV_NUM_DATA_POINTERS];
72
 
 
73
 
    for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
74
 
        if (output_frame->data[i]) {
75
 
            const unsigned divisor = i == 0 ? 1 : 2;
76
 
            unsigned offset = (yoff * output_frame->linesize[i] + xoff) / divisor;
77
 
            data[i] = output_frame->data[i] + offset;
78
 
        } else
79
 
            data[i] = 0;
 
97
 
 
98
    /* Correct destination width/height and offset if we need to keep input
 
99
     * frame aspect.
 
100
     */
 
101
    if (keep_aspect) {
 
102
        const float local_ratio = (float)dest_width / dest_height;
 
103
        const float input_ratio = (float)input_frame->width / input_frame->height;
 
104
 
 
105
        if (local_ratio > input_ratio) {
 
106
            auto old_dest_width = dest_width;
 
107
            dest_width = dest_height * input_ratio;
 
108
            xoff += (old_dest_width - dest_width) / 2;
 
109
        } else {
 
110
            auto old_dest_heigth = dest_height;
 
111
            dest_height = dest_width / input_ratio;
 
112
            yoff += (old_dest_heigth - dest_height) / 2;
 
113
        }
80
114
    }
81
115
 
 
116
    // buffer overflow checks
 
117
    assert(xoff + dest_width <= (unsigned)output_frame->width);
 
118
    assert(yoff + dest_height <= (unsigned)output_frame->height);
 
119
 
82
120
    ctx_ = sws_getCachedContext(ctx_,
83
121
                                input_frame->width,
84
122
                                input_frame->height,
93
131
        return;
94
132
    }
95
133
 
 
134
    // Make an offset'ed copy of output data from xoff and yoff
 
135
    const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get((AVPixelFormat)output_frame->format);
 
136
    if (is_yuv_planar(out_desc)) {
 
137
        unsigned x_shift = out_desc->log2_chroma_w;
 
138
        unsigned y_shift = out_desc->log2_chroma_h;
 
139
 
 
140
        tmp_data_[0] = output_frame->data[0] + yoff * output_frame->linesize[0] + xoff;
 
141
        tmp_data_[1] = output_frame->data[1] + (yoff >> y_shift) * output_frame->linesize[1] + (xoff >> x_shift);
 
142
        tmp_data_[2] = output_frame->data[2] + (yoff >> y_shift) * output_frame->linesize[2] + (xoff >> x_shift);
 
143
        tmp_data_[3] = nullptr;
 
144
    } else {
 
145
        memcpy(tmp_data_, output_frame->data, sizeof(tmp_data_));
 
146
        tmp_data_[0] += yoff * output_frame->linesize[0] + xoff;
 
147
    }
 
148
 
96
149
    sws_scale(ctx_, input_frame->data, input_frame->linesize, 0,
97
 
              input_frame->height, data, output_frame->linesize);
 
150
              input_frame->height, tmp_data_, output_frame->linesize);
98
151
}
99
152
 
100
153
void VideoScaler::reset()