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>
This commit is contained in:
Vittorio Giovara 2015-09-22 14:22:15 +02:00
parent e94e651c76
commit c9943f00cf
1 changed files with 92 additions and 57 deletions

View File

@ -130,92 +130,127 @@ static int config_output(AVFilterLink *outlink)
return 0; return 0;
} }
static void horizontal_frame_pack(FramepackContext *s, static void horizontal_frame_pack(AVFilterLink *outlink,
AVFrame *dst, AVFrame *out,
int interleaved) int interleaved)
{ {
int plane, i; AVFilterContext *ctx = outlink->src;
int length = dst->width / 2; FramepackContext *s = ctx->priv;
int lines = dst->height; int i, plane;
for (plane = 0; plane < s->pix_desc->nb_components; plane++) { if (interleaved) {
const uint8_t *leftp = s->input_views[LEFT]->data[plane]; const uint8_t *leftp = s->input_views[LEFT]->data[0];
const uint8_t *rightp = s->input_views[RIGHT]->data[plane]; const uint8_t *rightp = s->input_views[RIGHT]->data[0];
uint8_t *dstp = dst->data[plane]; uint8_t *dstp = out->data[0];
int length = out->width / 2;
int lines = out->height;
if (plane == 1 || plane == 2) { for (plane = 0; plane < s->pix_desc->nb_components; plane++) {
length = -(-(dst->width / 2) >> s->pix_desc->log2_chroma_w); if (plane == 1 || plane == 2) {
lines = -(-(dst->height) >> s->pix_desc->log2_chroma_h); length = -(-(out->width / 2) >> s->pix_desc->log2_chroma_w);
} lines = -(-(out->height) >> s->pix_desc->log2_chroma_h);
}
if (interleaved) {
for (i = 0; i < lines; i++) { for (i = 0; i < lines; i++) {
int j; 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++) { for (j = 0; j < length; j++) {
dstp[k++] = leftp[j]; // interpolate chroma as necessary
dstp[k++] = rightp[j]; 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], } else {
leftp, s->input_views[LEFT]->linesize[plane], for (i = 0; i < 2; i++) {
length, lines); const uint8_t *src[4];
av_image_copy_plane(dst->data[plane] + length, dst->linesize[plane], uint8_t *dst[4];
rightp, s->input_views[RIGHT]->linesize[plane], int sub_w = s->input_views[i]->width >> s->pix_desc->log2_chroma_w;
length, lines);
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, static void vertical_frame_pack(AVFilterLink *outlink,
AVFrame *dst, AVFrame *out,
int interleaved) int interleaved)
{ {
int plane, offset; AVFilterContext *ctx = outlink->src;
int length = dst->width; FramepackContext *s = ctx->priv;
int lines = dst->height / 2; int i;
for (plane = 0; plane < s->pix_desc->nb_components; plane++) { for (i = 0; i < 2; i++) {
if (plane == 1 || plane == 2) { const uint8_t *src[4];
length = -(-(dst->width) >> s->pix_desc->log2_chroma_w); uint8_t *dst[4];
lines = -(-(dst->height / 2) >> s->pix_desc->log2_chroma_h); int linesizes[4];
} int sub_h = s->input_views[i]->height >> s->pix_desc->log2_chroma_h;
offset = interleaved ? dst->linesize[plane] : dst->linesize[plane] * lines; src[0] = s->input_views[i]->data[0];
src[1] = s->input_views[i]->data[1];
src[2] = s->input_views[i]->data[2];
av_image_copy_plane(dst->data[plane], dst[0] = out->data[0] + i * out->linesize[0] *
dst->linesize[plane] << interleaved, (interleaved + s->input_views[i]->height * (1 - interleaved));
s->input_views[LEFT]->data[plane], dst[1] = out->data[1] + i * out->linesize[1] *
s->input_views[LEFT]->linesize[plane], (interleaved + sub_h * (1 - interleaved));
length, lines); dst[2] = out->data[2] + i * out->linesize[2] *
av_image_copy_plane(dst->data[plane] + offset, (interleaved + sub_h * (1 - interleaved));
dst->linesize[plane] << interleaved,
s->input_views[RIGHT]->data[plane], linesizes[0] = out->linesize[0] +
s->input_views[RIGHT]->linesize[plane], interleaved * out->linesize[0];
length, lines); 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) { switch (s->format) {
case AV_STEREO3D_SIDEBYSIDE: case AV_STEREO3D_SIDEBYSIDE:
horizontal_frame_pack(s, dst, 0); horizontal_frame_pack(outlink, dst, 0);
break; break;
case AV_STEREO3D_COLUMNS: case AV_STEREO3D_COLUMNS:
horizontal_frame_pack(s, dst, 1); horizontal_frame_pack(outlink, dst, 1);
break; break;
case AV_STEREO3D_TOPBOTTOM: case AV_STEREO3D_TOPBOTTOM:
vertical_frame_pack(s, dst, 0); vertical_frame_pack(outlink, dst, 0);
break; break;
case AV_STEREO3D_LINES: case AV_STEREO3D_LINES:
vertical_frame_pack(s, dst, 1); vertical_frame_pack(outlink, dst, 1);
break; break;
} }
} }
@ -276,7 +311,7 @@ static int request_frame(AVFilterLink *outlink)
if (!dst) if (!dst)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
spatial_frame_pack(s, dst); spatial_frame_pack(outlink, dst);
// get any property from the original frame // get any property from the original frame
ret = av_frame_copy_props(dst, s->input_views[LEFT]); ret = av_frame_copy_props(dst, s->input_views[LEFT]);