From c9943f00cfa2471d1b8a3a9ddc7a21049a71090e Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Tue, 22 Sep 2015 14:22:15 +0200 Subject: 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 --- libavfilter/vf_framepack.c | 157 +++++++++++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 61 deletions(-) (limited to 'libavfilter') 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]); -- cgit v1.2.3