FFmpeg  2.6.3
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
vf_framepack.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Vittorio Giovara
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * Generate a frame packed video, by combining two views in a single surface.
24  */
25 
26 #include <string.h>
27 
28 #include "libavutil/imgutils.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/pixdesc.h"
31 #include "libavutil/rational.h"
32 #include "libavutil/stereo3d.h"
33 
34 #include "avfilter.h"
35 #include "formats.h"
36 #include "internal.h"
37 #include "video.h"
38 
39 #define LEFT 0
40 #define RIGHT 1
41 
42 typedef struct FramepackContext {
43  const AVClass *class;
44 
45  const AVPixFmtDescriptor *pix_desc; ///< agreed pixel format
46 
47  enum AVStereo3DType format; ///< frame pack type output
48 
49  AVFrame *input_views[2]; ///< input frames
50 
51  int64_t double_pts; ///< new pts for frameseq mode
53 
54 static const enum AVPixelFormat formats_supported[] = {
59 };
60 
62 {
63  // this will ensure that formats are the same on all pads
65  return 0;
66 }
67 
69 {
70  FramepackContext *s = ctx->priv;
71 
72  // clean any leftover frame
75 }
76 
77 static int config_output(AVFilterLink *outlink)
78 {
79  AVFilterContext *ctx = outlink->src;
80  FramepackContext *s = outlink->src->priv;
81 
82  int width = ctx->inputs[LEFT]->w;
83  int height = ctx->inputs[LEFT]->h;
84  AVRational time_base = ctx->inputs[LEFT]->time_base;
85  AVRational frame_rate = ctx->inputs[LEFT]->frame_rate;
86 
87  // check size and fps match on the other input
88  if (width != ctx->inputs[RIGHT]->w ||
89  height != ctx->inputs[RIGHT]->h) {
90  av_log(ctx, AV_LOG_ERROR,
91  "Left and right sizes differ (%dx%d vs %dx%d).\n",
92  width, height,
93  ctx->inputs[RIGHT]->w, ctx->inputs[RIGHT]->h);
94  return AVERROR_INVALIDDATA;
95  } else if (av_cmp_q(time_base, ctx->inputs[RIGHT]->time_base) != 0) {
96  av_log(ctx, AV_LOG_ERROR,
97  "Left and right time bases differ (%d/%d vs %d/%d).\n",
98  time_base.num, time_base.den,
99  ctx->inputs[RIGHT]->time_base.num,
100  ctx->inputs[RIGHT]->time_base.den);
101  return AVERROR_INVALIDDATA;
102  } else if (av_cmp_q(frame_rate, ctx->inputs[RIGHT]->frame_rate) != 0) {
103  av_log(ctx, AV_LOG_ERROR,
104  "Left and right framerates differ (%d/%d vs %d/%d).\n",
105  frame_rate.num, frame_rate.den,
106  ctx->inputs[RIGHT]->frame_rate.num,
107  ctx->inputs[RIGHT]->frame_rate.den);
108  return AVERROR_INVALIDDATA;
109  }
110 
111  s->pix_desc = av_pix_fmt_desc_get(outlink->format);
112  if (!s->pix_desc)
113  return AVERROR_BUG;
114 
115  // modify output properties as needed
116  switch (s->format) {
118  time_base.den *= 2;
119  frame_rate.num *= 2;
120 
122  break;
123  case AV_STEREO3D_COLUMNS:
125  width *= 2;
126  break;
127  case AV_STEREO3D_LINES:
129  height *= 2;
130  break;
131  default:
132  av_log(ctx, AV_LOG_ERROR, "Unknown packing mode.");
133  return AVERROR_INVALIDDATA;
134  }
135 
136  outlink->w = width;
137  outlink->h = height;
138  outlink->time_base = time_base;
139  outlink->frame_rate= frame_rate;
140 
141  return 0;
142 }
143 
145  AVFrame *dst,
146  int interleaved)
147 {
148  int plane, i;
149  int length = dst->width / 2;
150  int lines = dst->height;
151 
152  for (plane = 0; plane < s->pix_desc->nb_components; plane++) {
153  const uint8_t *leftp = s->input_views[LEFT]->data[plane];
154  const uint8_t *rightp = s->input_views[RIGHT]->data[plane];
155  uint8_t *dstp = dst->data[plane];
156 
157  if (plane == 1 || plane == 2) {
158  length = FF_CEIL_RSHIFT(dst->width / 2, s->pix_desc->log2_chroma_w);
159  lines = FF_CEIL_RSHIFT(dst->height, s->pix_desc->log2_chroma_h);
160  }
161 
162  if (interleaved) {
163  for (i = 0; i < lines; i++) {
164  int j;
165  int k = 0;
166 
167  for (j = 0; j < length; j++) {
168  dstp[k++] = leftp[j];
169  dstp[k++] = rightp[j];
170  }
171 
172  dstp += dst->linesize[plane];
173  leftp += s->input_views[LEFT]->linesize[plane];
174  rightp += s->input_views[RIGHT]->linesize[plane];
175  }
176  } else {
177  av_image_copy_plane(dst->data[plane], dst->linesize[plane],
178  leftp, s->input_views[LEFT]->linesize[plane],
179  length, lines);
180  av_image_copy_plane(dst->data[plane] + length, dst->linesize[plane],
181  rightp, s->input_views[RIGHT]->linesize[plane],
182  length, lines);
183  }
184  }
185 }
186 
188  AVFrame *dst,
189  int interleaved)
190 {
191  int plane, offset;
192  int length = dst->width;
193  int lines = dst->height / 2;
194 
195  for (plane = 0; plane < s->pix_desc->nb_components; plane++) {
196  if (plane == 1 || plane == 2) {
197  length = -(-(dst->width) >> s->pix_desc->log2_chroma_w);
198  lines = -(-(dst->height / 2) >> s->pix_desc->log2_chroma_h);
199  }
200 
201  offset = interleaved ? dst->linesize[plane] : dst->linesize[plane] * lines;
202 
203  av_image_copy_plane(dst->data[plane],
204  dst->linesize[plane] << interleaved,
205  s->input_views[LEFT]->data[plane],
206  s->input_views[LEFT]->linesize[plane],
207  length, lines);
208  av_image_copy_plane(dst->data[plane] + offset,
209  dst->linesize[plane] << interleaved,
210  s->input_views[RIGHT]->data[plane],
211  s->input_views[RIGHT]->linesize[plane],
212  length, lines);
213  }
214 }
215 
217 {
218  switch (s->format) {
220  horizontal_frame_pack(s, dst, 0);
221  break;
222  case AV_STEREO3D_COLUMNS:
223  horizontal_frame_pack(s, dst, 1);
224  break;
226  vertical_frame_pack(s, dst, 0);
227  break;
228  case AV_STEREO3D_LINES:
229  vertical_frame_pack(s, dst, 1);
230  break;
231  }
232 }
233 
235 {
236  FramepackContext *s = inlink->dst->priv;
237  s->input_views[LEFT] = frame;
238  return 0;
239 }
240 
242 {
243  FramepackContext *s = inlink->dst->priv;
244  s->input_views[RIGHT] = frame;
245  return 0;
246 }
247 
248 static int request_frame(AVFilterLink *outlink)
249 {
250  AVFilterContext *ctx = outlink->src;
251  FramepackContext *s = ctx->priv;
252  AVStereo3D *stereo;
253  int ret, i;
254 
255  /* get a frame on the either input, stop as soon as a video ends */
256  for (i = 0; i < 2; i++) {
257  if (!s->input_views[i]) {
258  ret = ff_request_frame(ctx->inputs[i]);
259  if (ret < 0)
260  return ret;
261  }
262  }
263 
264  if (s->format == AV_STEREO3D_FRAMESEQUENCE) {
265  if (s->double_pts == AV_NOPTS_VALUE)
266  s->double_pts = s->input_views[LEFT]->pts;
267 
268  for (i = 0; i < 2; i++) {
269  // set correct timestamps
270  s->input_views[i]->pts = s->double_pts++;
271 
272  // set stereo3d side data
274  if (!stereo)
275  return AVERROR(ENOMEM);
276  stereo->type = s->format;
277 
278  // filter the frame and immediately relinquish its pointer
279  ret = ff_filter_frame(outlink, s->input_views[i]);
280  s->input_views[i] = NULL;
281  if (ret < 0)
282  return ret;
283  }
284  return ret;
285  } else {
286  AVFrame *dst = ff_get_video_buffer(outlink, outlink->w, outlink->h);
287  if (!dst)
288  return AVERROR(ENOMEM);
289 
290  spatial_frame_pack(s, dst);
291 
292  // get any property from the original frame
293  ret = av_frame_copy_props(dst, s->input_views[LEFT]);
294  if (ret < 0) {
295  av_frame_free(&dst);
296  return ret;
297  }
298 
299  for (i = 0; i < 2; i++)
300  av_frame_free(&s->input_views[i]);
301 
302  // set stereo3d side data
303  stereo = av_stereo3d_create_side_data(dst);
304  if (!stereo) {
305  av_frame_free(&dst);
306  return AVERROR(ENOMEM);
307  }
308  stereo->type = s->format;
309 
310  return ff_filter_frame(outlink, dst);
311  }
312 }
313 
314 #define OFFSET(x) offsetof(FramepackContext, x)
315 #define V AV_OPT_FLAG_VIDEO_PARAM
316 static const AVOption options[] = {
317  { "format", "Frame pack output format", OFFSET(format), AV_OPT_TYPE_INT,
318  { .i64 = AV_STEREO3D_SIDEBYSIDE }, 0, INT_MAX, .flags = V, .unit = "format" },
319  { "sbs", "Views are packed next to each other", 0, AV_OPT_TYPE_CONST,
320  { .i64 = AV_STEREO3D_SIDEBYSIDE }, INT_MIN, INT_MAX, .flags = V, .unit = "format" },
321  { "tab", "Views are packed on top of each other", 0, AV_OPT_TYPE_CONST,
322  { .i64 = AV_STEREO3D_TOPBOTTOM }, INT_MIN, INT_MAX, .flags = V, .unit = "format" },
323  { "frameseq", "Views are one after the other", 0, AV_OPT_TYPE_CONST,
324  { .i64 = AV_STEREO3D_FRAMESEQUENCE }, INT_MIN, INT_MAX, .flags = V, .unit = "format" },
325  { "lines", "Views are interleaved by lines", 0, AV_OPT_TYPE_CONST,
326  { .i64 = AV_STEREO3D_LINES }, INT_MIN, INT_MAX, .flags = V, .unit = "format" },
327  { "columns", "Views are interleaved by columns", 0, AV_OPT_TYPE_CONST,
328  { .i64 = AV_STEREO3D_COLUMNS }, INT_MIN, INT_MAX, .flags = V, .unit = "format" },
329  { NULL },
330 };
331 
332 static const AVClass framepack_class = {
333  .class_name = "framepack",
334  .item_name = av_default_item_name,
335  .option = options,
336  .version = LIBAVUTIL_VERSION_INT,
337 };
338 
339 static const AVFilterPad framepack_inputs[] = {
340  {
341  .name = "left",
342  .type = AVMEDIA_TYPE_VIDEO,
343  .filter_frame = filter_frame_left,
344  .needs_fifo = 1,
345  },
346  {
347  .name = "right",
348  .type = AVMEDIA_TYPE_VIDEO,
349  .filter_frame = filter_frame_right,
350  .needs_fifo = 1,
351  },
352  { NULL }
353 };
354 
355 static const AVFilterPad framepack_outputs[] = {
356  {
357  .name = "packed",
358  .type = AVMEDIA_TYPE_VIDEO,
359  .config_props = config_output,
360  .request_frame = request_frame,
361  },
362  { NULL }
363 };
364 
366  .name = "framepack",
367  .description = NULL_IF_CONFIG_SMALL("Generate a frame packed stereoscopic video."),
368  .priv_size = sizeof(FramepackContext),
369  .priv_class = &framepack_class,
371  .inputs = framepack_inputs,
372  .outputs = framepack_outputs,
374 };
#define NULL
Definition: coverity.c:32
static int filter_frame_right(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_framepack.c:241
const char * s
Definition: avisynth_c.h:669
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
Views are packed per line, as if interlaced.
Definition: stereo3d.h:97
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2029
This structure describes decoded (raw) audio or video data.
Definition: frame.h:163
AVOption.
Definition: opt.h:255
Views are alternated temporally.
Definition: stereo3d.h:66
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:73
misc image utilities
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:246
#define LIBAVUTIL_VERSION_INT
Definition: version.h:62
Main libavfilter public API header.
int num
numerator
Definition: rational.h:44
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:66
static enum AVPixelFormat formats_supported[]
Definition: vf_framepack.c:54
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:109
#define RIGHT
Definition: vf_framepack.c:40
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:80
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:294
const char * name
Pad name.
Definition: internal.h:67
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
#define OFFSET(x)
Definition: vf_framepack.c:314
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:641
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1145
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:108
uint8_t
#define av_cold
Definition: attributes.h:74
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:337
AVOptions.
Stereo 3D type: this structure describes how two videos are packed within a single video surface...
Definition: stereo3d.h:123
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:249
static int query_formats(AVFilterContext *ctx)
Definition: vf_framepack.c:61
static AVFrame * frame
static const AVClass framepack_class
Definition: vf_framepack.c:332
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range ...
Definition: pixfmt.h:107
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_...
Definition: pixfmt.h:81
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:539
#define av_log(a,...)
static const AVOption options[]
Definition: vf_framepack.c:316
A filter pad used for either input or output.
Definition: internal.h:61
int width
width and height of the video frame
Definition: frame.h:212
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:175
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:89
#define V
Definition: vf_framepack.c:315
AVFilter ff_vf_framepack
Definition: vf_framepack.c:365
av_default_item_name
BYTE * dstp
Definition: avisynth_c.h:714
#define AVERROR(e)
Definition: error.h:43
static av_always_inline void spatial_frame_pack(FramepackContext *s, AVFrame *dst)
Definition: vf_framepack.c:216
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:148
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:180
void * priv
private data for use by the filter
Definition: avfilter.h:654
int64_t double_pts
new pts for frameseq mode
Definition: vf_framepack.c:51
GLsizei GLsizei * length
Definition: opengl_enc.c:115
static const uint8_t offset[127][2]
Definition: vf_spp.c:92
static int filter_frame_left(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_framepack.c:234
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:72
static void vertical_frame_pack(FramepackContext *s, AVFrame *dst, int interleaved)
Definition: vf_framepack.c:187
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:71
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_...
Definition: pixfmt.h:80
ret
Definition: avfilter.c:974
AVFrame * input_views[2]
input frames
Definition: vf_framepack.c:49
#define FF_CEIL_RSHIFT(a, b)
Definition: common.h:57
enum AVStereo3DType type
How views are packed within the video.
Definition: stereo3d.h:127
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:191
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
#define LEFT
Definition: vf_framepack.c:39
enum AVStereo3DType format
frame pack type output
Definition: vf_framepack.c:47
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
BYTE int const BYTE int int int height
Definition: avisynth_c.h:714
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:74
Describe the class of an AVClass context structure.
Definition: log.h:66
Filter definition.
Definition: avfilter.h:470
static const AVFilterPad inputs[]
Definition: af_ashowinfo.c:237
rational number numerator/denominator
Definition: rational.h:43
static int request_frame(AVFilterLink *outlink)
Definition: vf_framepack.c:248
static const AVFilterPad framepack_inputs[]
Definition: vf_framepack.c:339
const char * name
Filter name.
Definition: avfilter.h:474
AVStereo3DType
List of possible 3D Types.
Definition: stereo3d.h:31
const AVPixFmtDescriptor * pix_desc
agreed pixel format
Definition: vf_framepack.c:45
Views are on top of each other.
Definition: stereo3d.h:55
static int config_output(AVFilterLink *outlink)
Definition: vf_framepack.c:77
AVStereo3D * av_stereo3d_create_side_data(AVFrame *frame)
Allocate a complete AVFrameSideData and add it to the frame.
Definition: stereo3d.c:32
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:174
static av_cold void framepack_uninit(AVFilterContext *ctx)
Definition: vf_framepack.c:68
Views are next to each other.
Definition: stereo3d.h:45
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
rational numbers
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_...
Definition: pixfmt.h:82
int den
denominator
Definition: rational.h:45
Views are packed per column.
Definition: stereo3d.h:107
An instance of a filter.
Definition: avfilter.h:633
int height
Definition: frame.h:212
static const AVFilterPad framepack_outputs[]
Definition: vf_framepack.c:355
#define av_always_inline
Definition: attributes.h:37
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:343
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:273
internal API functions
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:463
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:241
static void horizontal_frame_pack(FramepackContext *s, AVFrame *dst, int interleaved)
Definition: vf_framepack.c:144
static int width