summaryrefslogtreecommitdiff
path: root/libavfilter
diff options
context:
space:
mode:
authorVittorio Giovara <vittorio.giovara@gmail.com>2015-09-22 14:22:15 +0200
committerVittorio Giovara <vittorio.giovara@gmail.com>2015-09-29 14:33:01 +0200
commitc9943f00cfa2471d1b8a3a9ddc7a21049a71090e (patch)
tree250e707099354cf46eaf03d75b2009a22290af19 /libavfilter
parente94e651c762f90ac5fd2dc9bd3ba1336a77d5b5c (diff)
vf_framepack: Use av_image_copy() where appropriate
This correctly adjust chroma subsampling for column interleaved mode, and allows future high bitdepth support. Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Diffstat (limited to 'libavfilter')
-rw-r--r--libavfilter/vf_framepack.c157
1 files changed, 96 insertions, 61 deletions
diff --git a/libavfilter/vf_framepack.c b/libavfilter/vf_framepack.c
index f5c761a66d..e9806ba1cc 100644
--- a/libavfilter/vf_framepack.c
+++ b/libavfilter/vf_framepack.c
@@ -130,92 +130,127 @@ static int config_output(AVFilterLink *outlink)
return 0;
}
-static void horizontal_frame_pack(FramepackContext *s,
- AVFrame *dst,
+static void horizontal_frame_pack(AVFilterLink *outlink,
+ AVFrame *out,
int interleaved)
{
- int plane, i;
- int length = dst->width / 2;
- int lines = dst->height;
-
- for (plane = 0; plane < s->pix_desc->nb_components; plane++) {
- const uint8_t *leftp = s->input_views[LEFT]->data[plane];
- const uint8_t *rightp = s->input_views[RIGHT]->data[plane];
- uint8_t *dstp = dst->data[plane];
-
- if (plane == 1 || plane == 2) {
- length = -(-(dst->width / 2) >> s->pix_desc->log2_chroma_w);
- lines = -(-(dst->height) >> s->pix_desc->log2_chroma_h);
- }
-
- if (interleaved) {
+ AVFilterContext *ctx = outlink->src;
+ FramepackContext *s = ctx->priv;
+ int i, plane;
+
+ if (interleaved) {
+ const uint8_t *leftp = s->input_views[LEFT]->data[0];
+ const uint8_t *rightp = s->input_views[RIGHT]->data[0];
+ uint8_t *dstp = out->data[0];
+ int length = out->width / 2;
+ int lines = out->height;
+
+ for (plane = 0; plane < s->pix_desc->nb_components; plane++) {
+ if (plane == 1 || plane == 2) {
+ length = -(-(out->width / 2) >> s->pix_desc->log2_chroma_w);
+ lines = -(-(out->height) >> s->pix_desc->log2_chroma_h);
+ }
for (i = 0; i < lines; i++) {
int j;
- int k = 0;
-
+ leftp = s->input_views[LEFT]->data[plane] +
+ s->input_views[LEFT]->linesize[plane] * i;
+ rightp = s->input_views[RIGHT]->data[plane] +
+ s->input_views[RIGHT]->linesize[plane] * i;
+ dstp = out->data[plane] + out->linesize[plane] * i;
for (j = 0; j < length; j++) {
- dstp[k++] = leftp[j];
- dstp[k++] = rightp[j];
+ // interpolate chroma as necessary
+ if ((s->pix_desc->log2_chroma_w ||
+ s->pix_desc->log2_chroma_h) &&
+ (plane == 1 || plane == 2)) {
+ *dstp++ = (*leftp + *rightp) / 2;
+ *dstp++ = (*leftp + *rightp) / 2;
+ } else {
+ *dstp++ = *leftp;
+ *dstp++ = *rightp;
+ }
+ leftp += 1;
+ rightp += 1;
}
-
- dstp += dst->linesize[plane];
- leftp += s->input_views[LEFT]->linesize[plane];
- rightp += s->input_views[RIGHT]->linesize[plane];
}
- } else {
- av_image_copy_plane(dst->data[plane], dst->linesize[plane],
- leftp, s->input_views[LEFT]->linesize[plane],
- length, lines);
- av_image_copy_plane(dst->data[plane] + length, dst->linesize[plane],
- rightp, s->input_views[RIGHT]->linesize[plane],
- length, lines);
+ }
+ } else {
+ for (i = 0; i < 2; i++) {
+ const uint8_t *src[4];
+ uint8_t *dst[4];
+ int sub_w = s->input_views[i]->width >> s->pix_desc->log2_chroma_w;
+
+ src[0] = s->input_views[i]->data[0];
+ src[1] = s->input_views[i]->data[1];
+ src[2] = s->input_views[i]->data[2];
+
+ dst[0] = out->data[0] + i * s->input_views[i]->width;
+ dst[1] = out->data[1] + i * sub_w;
+ dst[2] = out->data[2] + i * sub_w;
+
+ av_image_copy(dst, out->linesize, src, s->input_views[i]->linesize,
+ s->input_views[i]->format,
+ s->input_views[i]->width,
+ s->input_views[i]->height);
}
}
}
-static void vertical_frame_pack(FramepackContext *s,
- AVFrame *dst,
+static void vertical_frame_pack(AVFilterLink *outlink,
+ AVFrame *out,
int interleaved)
{
- int plane, offset;
- int length = dst->width;
- int lines = dst->height / 2;
-
- for (plane = 0; plane < s->pix_desc->nb_components; plane++) {
- if (plane == 1 || plane == 2) {
- length = -(-(dst->width) >> s->pix_desc->log2_chroma_w);
- lines = -(-(dst->height / 2) >> s->pix_desc->log2_chroma_h);
- }
+ AVFilterContext *ctx = outlink->src;
+ FramepackContext *s = ctx->priv;
+ int i;
- offset = interleaved ? dst->linesize[plane] : dst->linesize[plane] * lines;
-
- av_image_copy_plane(dst->data[plane],
- dst->linesize[plane] << interleaved,
- s->input_views[LEFT]->data[plane],
- s->input_views[LEFT]->linesize[plane],
- length, lines);
- av_image_copy_plane(dst->data[plane] + offset,
- dst->linesize[plane] << interleaved,
- s->input_views[RIGHT]->data[plane],
- s->input_views[RIGHT]->linesize[plane],
- length, lines);
+ for (i = 0; i < 2; i++) {
+ const uint8_t *src[4];
+ uint8_t *dst[4];
+ int linesizes[4];
+ int sub_h = s->input_views[i]->height >> s->pix_desc->log2_chroma_h;
+
+ src[0] = s->input_views[i]->data[0];
+ src[1] = s->input_views[i]->data[1];
+ src[2] = s->input_views[i]->data[2];
+
+ dst[0] = out->data[0] + i * out->linesize[0] *
+ (interleaved + s->input_views[i]->height * (1 - interleaved));
+ dst[1] = out->data[1] + i * out->linesize[1] *
+ (interleaved + sub_h * (1 - interleaved));
+ dst[2] = out->data[2] + i * out->linesize[2] *
+ (interleaved + sub_h * (1 - interleaved));
+
+ linesizes[0] = out->linesize[0] +
+ interleaved * out->linesize[0];
+ linesizes[1] = out->linesize[1] +
+ interleaved * out->linesize[1];
+ linesizes[2] = out->linesize[2] +
+ interleaved * out->linesize[2];
+
+ av_image_copy(dst, linesizes, src, s->input_views[i]->linesize,
+ s->input_views[i]->format,
+ s->input_views[i]->width,
+ s->input_views[i]->height);
}
}
-static av_always_inline void spatial_frame_pack(FramepackContext *s, AVFrame *dst)
+static av_always_inline void spatial_frame_pack(AVFilterLink *outlink,
+ AVFrame *dst)
{
+ AVFilterContext *ctx = outlink->src;
+ FramepackContext *s = ctx->priv;
switch (s->format) {
case AV_STEREO3D_SIDEBYSIDE:
- horizontal_frame_pack(s, dst, 0);
+ horizontal_frame_pack(outlink, dst, 0);
break;
case AV_STEREO3D_COLUMNS:
- horizontal_frame_pack(s, dst, 1);
+ horizontal_frame_pack(outlink, dst, 1);
break;
case AV_STEREO3D_TOPBOTTOM:
- vertical_frame_pack(s, dst, 0);
+ vertical_frame_pack(outlink, dst, 0);
break;
case AV_STEREO3D_LINES:
- vertical_frame_pack(s, dst, 1);
+ vertical_frame_pack(outlink, dst, 1);
break;
}
}
@@ -276,7 +311,7 @@ static int request_frame(AVFilterLink *outlink)
if (!dst)
return AVERROR(ENOMEM);
- spatial_frame_pack(s, dst);
+ spatial_frame_pack(outlink, dst);
// get any property from the original frame
ret = av_frame_copy_props(dst, s->input_views[LEFT]);