avvidenc: Don't take ffmpeg timestamps verbatim but only use them to calculate DTS
[platform/upstream/gstreamer.git] / subprojects / gst-libav / ext / libav / gstavvidenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <assert.h>
25 #include <string.h>
26 /* for stats file handling */
27 #include <stdio.h>
28 #include <glib/gstdio.h>
29 #include <errno.h>
30
31 #include <libavcodec/avcodec.h>
32 #include <libavutil/stereo3d.h>
33 #include <libavutil/opt.h>
34
35 #include "gstav.h"
36 #include "gstavcodecmap.h"
37 #include "gstavutils.h"
38 #include "gstavvidenc.h"
39 #include "gstavcfg.h"
40
41
42 enum
43 {
44   PROP_0,
45   PROP_QUANTIZER,
46   PROP_PASS,
47   PROP_FILENAME,
48   PROP_CFG_BASE,
49 };
50
51 static void gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass);
52 static void gst_ffmpegvidenc_base_init (GstFFMpegVidEncClass * klass);
53 static void gst_ffmpegvidenc_init (GstFFMpegVidEnc * ffmpegenc);
54 static void gst_ffmpegvidenc_finalize (GObject * object);
55
56 static gboolean gst_ffmpegvidenc_start (GstVideoEncoder * encoder);
57 static gboolean gst_ffmpegvidenc_stop (GstVideoEncoder * encoder);
58 static GstFlowReturn gst_ffmpegvidenc_finish (GstVideoEncoder * encoder);
59 static gboolean gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
60     GstVideoCodecState * state);
61 static gboolean gst_ffmpegvidenc_propose_allocation (GstVideoEncoder * encoder,
62     GstQuery * query);
63 static gboolean gst_ffmpegvidenc_flush (GstVideoEncoder * encoder);
64
65 static GstFlowReturn gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
66     GstVideoCodecFrame * frame);
67
68 static void gst_ffmpegvidenc_set_property (GObject * object,
69     guint prop_id, const GValue * value, GParamSpec * pspec);
70 static void gst_ffmpegvidenc_get_property (GObject * object,
71     guint prop_id, GValue * value, GParamSpec * pspec);
72
73 #define GST_FFENC_PARAMS_QDATA g_quark_from_static_string("avenc-params")
74
75 static GstElementClass *parent_class = NULL;
76
77 #define GST_TYPE_FFMPEG_PASS (gst_ffmpeg_pass_get_type ())
78 static GType
79 gst_ffmpeg_pass_get_type (void)
80 {
81   static GType ffmpeg_pass_type = 0;
82
83   if (!ffmpeg_pass_type) {
84     static const GEnumValue ffmpeg_passes[] = {
85       {0, "Constant Bitrate Encoding", "cbr"},
86       {AV_CODEC_FLAG_QSCALE, "Constant Quantizer", "quant"},
87       {AV_CODEC_FLAG_PASS1, "VBR Encoding - Pass 1", "pass1"},
88       {AV_CODEC_FLAG_PASS2, "VBR Encoding - Pass 2", "pass2"},
89       {0, NULL, NULL},
90     };
91
92     ffmpeg_pass_type =
93         g_enum_register_static ("GstLibAVEncPass", ffmpeg_passes);
94   }
95
96   return ffmpeg_pass_type;
97 }
98
99 static void
100 gst_ffmpegvidenc_base_init (GstFFMpegVidEncClass * klass)
101 {
102   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
103   AVCodec *in_plugin;
104   GstPadTemplate *srctempl = NULL, *sinktempl = NULL;
105   GstCaps *srccaps = NULL, *sinkcaps = NULL;
106   gchar *longname, *description;
107   const gchar *classification;
108
109   in_plugin =
110       (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
111       GST_FFENC_PARAMS_QDATA);
112   g_assert (in_plugin != NULL);
113
114   /* construct the element details struct */
115   longname = g_strdup_printf ("libav %s encoder", in_plugin->long_name);
116   description = g_strdup_printf ("libav %s encoder", in_plugin->name);
117   classification =
118       gst_ffmpeg_codecid_is_image (in_plugin->id) ? "Codec/Encoder/Image" :
119       "Codec/Encoder/Video";
120   gst_element_class_set_metadata (element_class, longname,
121       classification, description,
122       "Wim Taymans <wim.taymans@gmail.com>, "
123       "Ronald Bultje <rbultje@ronald.bitfreak.net>");
124   g_free (longname);
125   g_free (description);
126
127   if (!(srccaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, TRUE))) {
128     GST_DEBUG ("Couldn't get source caps for encoder '%s'", in_plugin->name);
129     srccaps = gst_caps_new_empty_simple ("unknown/unknown");
130   }
131
132   sinkcaps = gst_ffmpeg_codectype_to_video_caps (NULL,
133       in_plugin->id, TRUE, in_plugin);
134   if (!sinkcaps) {
135     GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name);
136     sinkcaps = gst_caps_new_empty_simple ("unknown/unknown");
137   }
138
139   /* pad templates */
140   sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
141       GST_PAD_ALWAYS, sinkcaps);
142   srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
143
144   gst_element_class_add_pad_template (element_class, srctempl);
145   gst_element_class_add_pad_template (element_class, sinktempl);
146
147   gst_caps_unref (sinkcaps);
148   gst_caps_unref (srccaps);
149
150   klass->in_plugin = in_plugin;
151   klass->srctempl = srctempl;
152   klass->sinktempl = sinktempl;
153
154   return;
155 }
156
157 static void
158 gst_ffmpegvidenc_class_init (GstFFMpegVidEncClass * klass)
159 {
160   GObjectClass *gobject_class;
161   GstVideoEncoderClass *venc_class;
162
163   gobject_class = (GObjectClass *) klass;
164   venc_class = (GstVideoEncoderClass *) klass;
165
166   parent_class = g_type_class_peek_parent (klass);
167
168   gobject_class->set_property = gst_ffmpegvidenc_set_property;
169   gobject_class->get_property = gst_ffmpegvidenc_get_property;
170
171   g_object_class_install_property (gobject_class, PROP_QUANTIZER,
172       g_param_spec_float ("quantizer", "Constant Quantizer",
173           "Constant Quantizer", 0, 30, 0.01f,
174           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
175
176   g_object_class_install_property (gobject_class, PROP_PASS,
177       g_param_spec_enum ("pass", "Encoding pass/type",
178           "Encoding pass/type", GST_TYPE_FFMPEG_PASS, 0,
179           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
180
181   g_object_class_install_property (gobject_class, PROP_FILENAME,
182       g_param_spec_string ("multipass-cache-file", "Multipass Cache File",
183           "Filename for multipass cache file", "stats.log",
184           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
185
186   /* register additional properties, possibly dependent on the exact CODEC */
187   gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin,
188       PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM);
189
190   venc_class->start = gst_ffmpegvidenc_start;
191   venc_class->stop = gst_ffmpegvidenc_stop;
192   venc_class->finish = gst_ffmpegvidenc_finish;
193   venc_class->handle_frame = gst_ffmpegvidenc_handle_frame;
194   venc_class->set_format = gst_ffmpegvidenc_set_format;
195   venc_class->propose_allocation = gst_ffmpegvidenc_propose_allocation;
196   venc_class->flush = gst_ffmpegvidenc_flush;
197
198   gobject_class->finalize = gst_ffmpegvidenc_finalize;
199
200   gst_type_mark_as_plugin_api (GST_TYPE_FFMPEG_PASS, 0);
201 }
202
203 static void
204 gst_ffmpegvidenc_init (GstFFMpegVidEnc * ffmpegenc)
205 {
206   GstFFMpegVidEncClass *klass =
207       (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
208
209   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (ffmpegenc));
210
211   ffmpegenc->context = avcodec_alloc_context3 (klass->in_plugin);
212   ffmpegenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
213   ffmpegenc->picture = av_frame_alloc ();
214   ffmpegenc->opened = FALSE;
215   ffmpegenc->file = NULL;
216 }
217
218 static void
219 gst_ffmpegvidenc_finalize (GObject * object)
220 {
221   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) object;
222
223   /* clean up remaining allocated data */
224   av_frame_free (&ffmpegenc->picture);
225   gst_ffmpeg_avcodec_close (ffmpegenc->context);
226   gst_ffmpeg_avcodec_close (ffmpegenc->refcontext);
227   av_freep (&ffmpegenc->context);
228   av_freep (&ffmpegenc->refcontext);
229   g_free (ffmpegenc->filename);
230
231   G_OBJECT_CLASS (parent_class)->finalize (object);
232 }
233
234 static gboolean
235 gst_ffmpegvidenc_set_format (GstVideoEncoder * encoder,
236     GstVideoCodecState * state)
237 {
238   GstCaps *other_caps;
239   GstCaps *allowed_caps;
240   GstCaps *icaps;
241   GstVideoCodecState *output_format;
242   enum AVPixelFormat pix_fmt;
243   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
244   GstFFMpegVidEncClass *oclass =
245       (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
246
247   ffmpegenc->need_reopen = FALSE;
248
249   /* close old session */
250   if (ffmpegenc->opened) {
251     avcodec_free_context (&ffmpegenc->context);
252     ffmpegenc->opened = FALSE;
253     ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
254     if (ffmpegenc->context == NULL) {
255       GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
256       return FALSE;
257     }
258   }
259
260   /* additional avcodec settings */
261   gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegenc), ffmpegenc->context);
262
263   if (GST_VIDEO_INFO_IS_INTERLACED (&state->info))
264     ffmpegenc->context->flags |=
265         AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME;
266
267   /* and last but not least the pass; CBR, 2-pass, etc */
268   ffmpegenc->context->flags |= ffmpegenc->pass;
269   switch (ffmpegenc->pass) {
270       /* some additional action depends on type of pass */
271     case AV_CODEC_FLAG_QSCALE:
272       ffmpegenc->context->global_quality
273           = ffmpegenc->picture->quality = FF_QP2LAMBDA * ffmpegenc->quantizer;
274       break;
275     case AV_CODEC_FLAG_PASS1:  /* need to prepare a stats file */
276       /* we don't close when changing caps, fingers crossed */
277       if (!ffmpegenc->file)
278         ffmpegenc->file = g_fopen (ffmpegenc->filename, "w");
279       if (!ffmpegenc->file)
280         goto open_file_err;
281       break;
282     case AV_CODEC_FLAG_PASS2:
283     {                           /* need to read the whole stats file ! */
284       gsize size;
285
286       if (!g_file_get_contents (ffmpegenc->filename,
287               &ffmpegenc->context->stats_in, &size, NULL))
288         goto file_read_err;
289
290       break;
291     }
292     default:
293       break;
294   }
295
296   GST_DEBUG_OBJECT (ffmpegenc, "Extracting common video information");
297   /* fetch pix_fmt, fps, par, width, height... */
298   gst_ffmpeg_videoinfo_to_context (&state->info, ffmpegenc->context);
299
300   /* sanitize time base */
301   if (ffmpegenc->context->time_base.num <= 0
302       || ffmpegenc->context->time_base.den <= 0)
303     goto insane_timebase;
304
305   if ((oclass->in_plugin->id == AV_CODEC_ID_MPEG4)
306       && (ffmpegenc->context->time_base.den > 65535)) {
307     /* MPEG4 Standards do not support time_base denominator greater than
308      * (1<<16) - 1 . We therefore scale them down.
309      * Agreed, it will not be the exact framerate... but the difference
310      * shouldn't be that noticeable */
311     ffmpegenc->context->time_base.num =
312         (gint) gst_util_uint64_scale_int (ffmpegenc->context->time_base.num,
313         65535, ffmpegenc->context->time_base.den);
314     ffmpegenc->context->time_base.den = 65535;
315     GST_LOG_OBJECT (ffmpegenc, "MPEG4 : scaled down framerate to %d / %d",
316         ffmpegenc->context->time_base.den, ffmpegenc->context->time_base.num);
317   }
318
319   pix_fmt = ffmpegenc->context->pix_fmt;
320
321   /* some codecs support more than one format, first auto-choose one */
322   GST_DEBUG_OBJECT (ffmpegenc, "picking an output format ...");
323   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
324   if (!allowed_caps) {
325     GST_DEBUG_OBJECT (ffmpegenc, "... but no peer, using template caps");
326     /* we need to copy because get_allowed_caps returns a ref, and
327      * get_pad_template_caps doesn't */
328     allowed_caps =
329         gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
330   }
331   GST_DEBUG_OBJECT (ffmpegenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
332   gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
333       oclass->in_plugin->type, allowed_caps, ffmpegenc->context);
334
335   /* open codec */
336   if (gst_ffmpeg_avcodec_open (ffmpegenc->context, oclass->in_plugin) < 0) {
337     gst_caps_unref (allowed_caps);
338     goto open_codec_fail;
339   }
340
341   /* is the colourspace correct? */
342   if (pix_fmt != ffmpegenc->context->pix_fmt) {
343     gst_caps_unref (allowed_caps);
344     goto pix_fmt_err;
345   }
346
347   /* we may have failed mapping caps to a pixfmt,
348    * and quite some codecs do not make up their own mind about that
349    * in any case, _NONE can never work out later on */
350   if (pix_fmt == AV_PIX_FMT_NONE) {
351     gst_caps_unref (allowed_caps);
352     goto bad_input_fmt;
353   }
354
355   /* second pass stats buffer no longer needed */
356   g_free (ffmpegenc->context->stats_in);
357
358   /* try to set this caps on the other side */
359   other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id,
360       ffmpegenc->context, TRUE);
361
362   if (!other_caps) {
363     gst_caps_unref (allowed_caps);
364     goto unsupported_codec;
365   }
366
367   icaps = gst_caps_intersect (allowed_caps, other_caps);
368   gst_caps_unref (allowed_caps);
369   gst_caps_unref (other_caps);
370   if (gst_caps_is_empty (icaps)) {
371     gst_caps_unref (icaps);
372     goto unsupported_codec;
373   }
374   icaps = gst_caps_fixate (icaps);
375
376   GST_DEBUG_OBJECT (ffmpegenc, "codec flags 0x%08x", ffmpegenc->context->flags);
377
378   /* Store input state and set output state */
379   if (ffmpegenc->input_state)
380     gst_video_codec_state_unref (ffmpegenc->input_state);
381   ffmpegenc->input_state = gst_video_codec_state_ref (state);
382
383   output_format = gst_video_encoder_set_output_state (encoder, icaps, state);
384   gst_video_codec_state_unref (output_format);
385
386   /* Store some tags */
387   {
388     GstTagList *tags = gst_tag_list_new_empty ();
389     const gchar *codec;
390
391     gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_NOMINAL_BITRATE,
392         (guint) ffmpegenc->context->bit_rate, NULL);
393
394     if ((codec =
395             gst_ffmpeg_get_codecid_longname (ffmpegenc->context->codec_id)))
396       gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_VIDEO_CODEC, codec,
397           NULL);
398
399     gst_video_encoder_merge_tags (encoder, tags, GST_TAG_MERGE_REPLACE);
400     gst_tag_list_unref (tags);
401   }
402
403   /* success! */
404   ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
405   ffmpegenc->opened = TRUE;
406
407   return TRUE;
408
409   /* ERRORS */
410 open_file_err:
411   {
412     GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, OPEN_WRITE,
413         (("Could not open file \"%s\" for writing."), ffmpegenc->filename),
414         GST_ERROR_SYSTEM);
415     return FALSE;
416   }
417 file_read_err:
418   {
419     GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, READ,
420         (("Could not get contents of file \"%s\"."), ffmpegenc->filename),
421         GST_ERROR_SYSTEM);
422     return FALSE;
423   }
424
425 insane_timebase:
426   {
427     GST_ERROR_OBJECT (ffmpegenc, "Rejecting time base %d/%d",
428         ffmpegenc->context->time_base.den, ffmpegenc->context->time_base.num);
429     goto cleanup_stats_in;
430   }
431 unsupported_codec:
432   {
433     GST_DEBUG ("Unsupported codec - no caps found");
434     goto cleanup_stats_in;
435   }
436 open_codec_fail:
437   {
438     GST_DEBUG_OBJECT (ffmpegenc, "avenc_%s: Failed to open libav codec",
439         oclass->in_plugin->name);
440     goto close_codec;
441   }
442
443 pix_fmt_err:
444   {
445     GST_DEBUG_OBJECT (ffmpegenc,
446         "avenc_%s: AV wants different colourspace (%d given, %d wanted)",
447         oclass->in_plugin->name, pix_fmt, ffmpegenc->context->pix_fmt);
448     goto close_codec;
449   }
450
451 bad_input_fmt:
452   {
453     GST_DEBUG_OBJECT (ffmpegenc, "avenc_%s: Failed to determine input format",
454         oclass->in_plugin->name);
455     goto close_codec;
456   }
457 close_codec:
458   {
459     avcodec_free_context (&ffmpegenc->context);
460     ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
461     if (ffmpegenc->context == NULL)
462       GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
463     goto cleanup_stats_in;
464   }
465 cleanup_stats_in:
466   {
467     g_free (ffmpegenc->context->stats_in);
468     return FALSE;
469   }
470 }
471
472
473 static gboolean
474 gst_ffmpegvidenc_propose_allocation (GstVideoEncoder * encoder,
475     GstQuery * query)
476 {
477   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
478
479   return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
480       query);
481 }
482
483 static void
484 gst_ffmpegvidenc_free_avpacket (gpointer pkt)
485 {
486   av_packet_unref ((AVPacket *) pkt);
487   g_slice_free (AVPacket, pkt);
488 }
489
490 typedef struct
491 {
492   GstBuffer *buffer;
493   GstVideoFrame vframe;
494 } BufferInfo;
495
496 static void
497 buffer_info_free (void *opaque, guint8 * data)
498 {
499   BufferInfo *info = opaque;
500
501   gst_video_frame_unmap (&info->vframe);
502   gst_buffer_unref (info->buffer);
503   g_slice_free (BufferInfo, info);
504 }
505
506 static enum AVStereo3DType
507 stereo_gst_to_av (GstVideoMultiviewMode mview_mode)
508 {
509   switch (mview_mode) {
510     case GST_VIDEO_MULTIVIEW_MODE_MONO:
511       /* Video is not stereoscopic (and metadata has to be there). */
512       return AV_STEREO3D_2D;
513     case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
514       return AV_STEREO3D_SIDEBYSIDE;
515     case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
516       return AV_STEREO3D_TOPBOTTOM;
517     case GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME:
518       return AV_STEREO3D_FRAMESEQUENCE;
519     case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
520       return AV_STEREO3D_CHECKERBOARD;
521     case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
522       return AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
523     case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
524       return AV_STEREO3D_LINES;
525     case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
526       return AV_STEREO3D_COLUMNS;
527     default:
528       break;
529   }
530   GST_WARNING ("Unsupported multiview mode - no mapping in libav");
531   return AV_STEREO3D_2D;
532 }
533
534 static void
535 gst_ffmpegvidenc_add_cc (GstBuffer * buffer, AVFrame * picture)
536 {
537   GstVideoCaptionMeta *cc_meta;
538   gpointer iter = NULL;
539
540   while ((cc_meta =
541           (GstVideoCaptionMeta *) gst_buffer_iterate_meta_filtered (buffer,
542               &iter, GST_VIDEO_CAPTION_META_API_TYPE))) {
543     AVFrameSideData *sd;
544
545     if (cc_meta->caption_type != GST_VIDEO_CAPTION_TYPE_CEA708_RAW)
546       continue;
547
548     sd = av_frame_new_side_data (picture, AV_FRAME_DATA_A53_CC, cc_meta->size);
549     memcpy (sd->data, cc_meta->data, cc_meta->size);
550   }
551 }
552
553 static GstFlowReturn
554 gst_ffmpegvidenc_send_frame (GstFFMpegVidEnc * ffmpegenc,
555     GstVideoCodecFrame * frame)
556 {
557   GstVideoInfo *info = &ffmpegenc->input_state->info;
558   BufferInfo *buffer_info;
559   guint c;
560   gint res;
561   GstFlowReturn ret = GST_FLOW_ERROR;
562   AVFrame *picture = NULL;
563
564   if (!frame)
565     goto send_frame;
566
567   picture = ffmpegenc->picture;
568
569   gst_ffmpegvidenc_add_cc (frame->input_buffer, picture);
570
571   if (GST_VIDEO_INFO_IS_INTERLACED (&ffmpegenc->input_state->info)) {
572     picture->interlaced_frame = TRUE;
573     picture->top_field_first =
574         GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_VIDEO_BUFFER_FLAG_TFF)
575         || GST_VIDEO_INFO_FIELD_ORDER (&ffmpegenc->input_state->info) ==
576         GST_VIDEO_FIELD_ORDER_TOP_FIELD_FIRST;
577     picture->repeat_pict =
578         GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_VIDEO_BUFFER_FLAG_RFF);
579   }
580
581   if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
582     AVStereo3D *stereo = av_stereo3d_create_side_data (picture);
583     stereo->type = stereo_gst_to_av (GST_VIDEO_INFO_MULTIVIEW_MODE (info));
584
585     if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
586         GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST) {
587       stereo->flags = AV_STEREO3D_FLAG_INVERT;
588     }
589   }
590
591   if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame))
592     picture->pict_type = AV_PICTURE_TYPE_I;
593
594   buffer_info = g_slice_new0 (BufferInfo);
595   buffer_info->buffer = gst_buffer_ref (frame->input_buffer);
596
597   if (!gst_video_frame_map (&buffer_info->vframe, info, frame->input_buffer,
598           GST_MAP_READ)) {
599     GST_ERROR_OBJECT (ffmpegenc, "Failed to map input buffer");
600     gst_buffer_unref (buffer_info->buffer);
601     g_slice_free (BufferInfo, buffer_info);
602     gst_video_codec_frame_unref (frame);
603     goto done;
604   }
605
606   /* Fill avpicture */
607   picture->buf[0] =
608       av_buffer_create (NULL, 0, buffer_info_free, buffer_info, 0);
609   for (c = 0; c < AV_NUM_DATA_POINTERS; c++) {
610     if (c < GST_VIDEO_INFO_N_COMPONENTS (info)) {
611       picture->data[c] = GST_VIDEO_FRAME_PLANE_DATA (&buffer_info->vframe, c);
612       picture->linesize[c] =
613           GST_VIDEO_FRAME_COMP_STRIDE (&buffer_info->vframe, c);
614     } else {
615       picture->data[c] = NULL;
616       picture->linesize[c] = 0;
617     }
618   }
619
620   picture->format = ffmpegenc->context->pix_fmt;
621   picture->width = GST_VIDEO_FRAME_WIDTH (&buffer_info->vframe);
622   picture->height = GST_VIDEO_FRAME_HEIGHT (&buffer_info->vframe);
623
624   if (ffmpegenc->pts_offset == GST_CLOCK_TIME_NONE) {
625     ffmpegenc->pts_offset = frame->pts;
626   }
627
628   if (frame->pts == GST_CLOCK_TIME_NONE) {
629     picture->pts = AV_NOPTS_VALUE;
630   } else if (frame->pts < ffmpegenc->pts_offset) {
631     GST_ERROR_OBJECT (ffmpegenc, "PTS is going backwards");
632     picture->pts = AV_NOPTS_VALUE;
633   } else {
634     picture->pts =
635         gst_ffmpeg_time_gst_to_ff ((frame->pts - ffmpegenc->pts_offset) /
636         ffmpegenc->context->ticks_per_frame, ffmpegenc->context->time_base);
637   }
638
639 send_frame:
640   if (!picture) {
641     GstFFMpegVidEncClass *oclass =
642         (GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc));
643
644     /* If AV_CODEC_CAP_ENCODER_FLUSH wasn't set, we need to re-open
645      * encoder */
646     if (!(oclass->in_plugin->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)) {
647       GST_DEBUG_OBJECT (ffmpegenc, "Encoder needs reopen later");
648
649       /* we will reopen later handle_frame() */
650       ffmpegenc->need_reopen = TRUE;
651     }
652   }
653
654   res = avcodec_send_frame (ffmpegenc->context, picture);
655
656   if (picture)
657     av_frame_unref (picture);
658
659   if (res == 0)
660     ret = GST_FLOW_OK;
661   else if (res == AVERROR_EOF)
662     ret = GST_FLOW_EOS;
663
664 done:
665   return ret;
666 }
667
668 static GstFlowReturn
669 gst_ffmpegvidenc_receive_packet (GstFFMpegVidEnc * ffmpegenc,
670     gboolean * got_packet, gboolean send)
671 {
672   AVPacket *pkt;
673   GstBuffer *outbuf;
674   GstVideoCodecFrame *frame;
675   gint res;
676   GstFlowReturn ret = GST_FLOW_OK;
677
678   *got_packet = FALSE;
679
680   pkt = g_slice_new0 (AVPacket);
681
682   res = avcodec_receive_packet (ffmpegenc->context, pkt);
683
684   if (res == AVERROR (EAGAIN)) {
685     g_slice_free (AVPacket, pkt);
686     goto done;
687   } else if (res == AVERROR_EOF) {
688     g_slice_free (AVPacket, pkt);
689     ret = GST_FLOW_EOS;
690     goto done;
691   } else if (res < 0) {
692     ret = GST_FLOW_ERROR;
693     goto done;
694   }
695
696   *got_packet = TRUE;
697
698   /* save stats info if there is some as well as a stats file */
699   if (ffmpegenc->file && ffmpegenc->context->stats_out)
700     if (fprintf (ffmpegenc->file, "%s", ffmpegenc->context->stats_out) < 0)
701       GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, WRITE,
702           (("Could not write to file \"%s\"."), ffmpegenc->filename),
703           GST_ERROR_SYSTEM);
704
705   /* Get oldest frame */
706   frame = gst_video_encoder_get_oldest_frame (GST_VIDEO_ENCODER (ffmpegenc));
707
708   if (send) {
709     outbuf =
710         gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, pkt->data,
711         pkt->size, 0, pkt->size, pkt, gst_ffmpegvidenc_free_avpacket);
712     frame->output_buffer = outbuf;
713
714     if (pkt->flags & AV_PKT_FLAG_KEY)
715       GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
716     else
717       GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
718   }
719
720   /* calculate the DTS by taking the PTS/DTS difference from the ffmpeg side
721    * and applying it to our PTS. We don't use the ffmpeg timestamps verbatim
722    * because they're too inaccurate and in the framerate time_base
723    */
724   if (pkt->dts != AV_NOPTS_VALUE) {
725     gint64 pts_dts_diff = pkt->dts - pkt->pts;
726     if (pts_dts_diff < 0) {
727       GstClockTime gst_pts_dts_diff = gst_ffmpeg_time_ff_to_gst (-pts_dts_diff,
728           ffmpegenc->context->time_base);
729
730       if (gst_pts_dts_diff > frame->pts)
731         frame->pts = 0;
732       else
733         frame->dts = frame->pts - gst_pts_dts_diff;
734     } else {
735       frame->dts = frame->pts +
736           gst_ffmpeg_time_ff_to_gst (pts_dts_diff,
737           ffmpegenc->context->time_base);
738     }
739   }
740
741   ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame);
742
743 done:
744   return ret;
745 }
746
747 static GstFlowReturn
748 gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
749     GstVideoCodecFrame * frame)
750 {
751   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
752   GstFlowReturn ret;
753   gboolean got_packet;
754
755   /* endoder was drained or flushed, and ffmpeg encoder doesn't support
756    * flushing. We need to re-open encoder then */
757   if (ffmpegenc->need_reopen) {
758     gboolean reopen_ret;
759     GstVideoCodecState *input_state;
760
761     GST_DEBUG_OBJECT (ffmpegenc, "Open encoder again");
762
763     if (!ffmpegenc->input_state) {
764       GST_ERROR_OBJECT (ffmpegenc,
765           "Cannot re-open encoder without input state");
766       return GST_FLOW_NOT_NEGOTIATED;
767     }
768
769     input_state = gst_video_codec_state_ref (ffmpegenc->input_state);
770     reopen_ret = gst_ffmpegvidenc_set_format (encoder, input_state);
771     gst_video_codec_state_unref (input_state);
772
773     if (!reopen_ret) {
774       GST_ERROR_OBJECT (ffmpegenc, "Couldn't re-open encoder");
775       return GST_FLOW_NOT_NEGOTIATED;
776     }
777   }
778
779   ret = gst_ffmpegvidenc_send_frame (ffmpegenc, frame);
780
781   if (ret != GST_FLOW_OK)
782     goto encode_fail;
783
784   gst_video_codec_frame_unref (frame);
785
786   do {
787     ret = gst_ffmpegvidenc_receive_packet (ffmpegenc, &got_packet, TRUE);
788     if (ret != GST_FLOW_OK)
789       break;
790   } while (got_packet);
791
792 done:
793   return ret;
794
795   /* We choose to be error-resilient */
796 encode_fail:
797   {
798 #ifndef GST_DISABLE_GST_DEBUG
799     GstFFMpegVidEncClass *oclass =
800         (GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc));
801     GST_ERROR_OBJECT (ffmpegenc,
802         "avenc_%s: failed to encode buffer", oclass->in_plugin->name);
803 #endif /* GST_DISABLE_GST_DEBUG */
804     /* avoid frame (and ts etc) piling up */
805     ret = gst_video_encoder_finish_frame (encoder, frame);
806     goto done;
807   }
808 }
809
810 static GstFlowReturn
811 gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
812 {
813   GstFlowReturn ret = GST_FLOW_OK;
814   gboolean got_packet;
815
816   GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send);
817
818   /* no need to empty codec if there is none */
819   if (!ffmpegenc->opened)
820     goto done;
821
822   ret = gst_ffmpegvidenc_send_frame (ffmpegenc, NULL);
823
824   if (ret != GST_FLOW_OK)
825     goto done;
826
827   do {
828     ret = gst_ffmpegvidenc_receive_packet (ffmpegenc, &got_packet, send);
829     if (ret != GST_FLOW_OK)
830       break;
831   } while (got_packet);
832   avcodec_flush_buffers (ffmpegenc->context);
833   ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
834
835 done:
836   /* FFMpeg will return AVERROR_EOF if it's internal was fully drained
837    * then we are translating it to GST_FLOW_EOS. However, because this behavior
838    * is fully internal stuff of this implementation and gstvideoencoder
839    * baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
840    * convert this flow returned here */
841   if (ret == GST_FLOW_EOS)
842     ret = GST_FLOW_OK;
843
844   return ret;
845 }
846
847 static void
848 gst_ffmpegvidenc_set_property (GObject * object,
849     guint prop_id, const GValue * value, GParamSpec * pspec)
850 {
851   GstFFMpegVidEnc *ffmpegenc;
852
853   ffmpegenc = (GstFFMpegVidEnc *) (object);
854
855   if (ffmpegenc->opened) {
856     GST_WARNING_OBJECT (ffmpegenc,
857         "Can't change properties once decoder is setup !");
858     return;
859   }
860
861   switch (prop_id) {
862     case PROP_QUANTIZER:
863       ffmpegenc->quantizer = g_value_get_float (value);
864       break;
865     case PROP_PASS:
866       ffmpegenc->pass = g_value_get_enum (value);
867       break;
868     case PROP_FILENAME:
869       g_free (ffmpegenc->filename);
870       ffmpegenc->filename = g_value_dup_string (value);
871       break;
872     default:
873       if (!gst_ffmpeg_cfg_set_property (ffmpegenc->refcontext, value, pspec))
874         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
875       break;
876   }
877 }
878
879 static void
880 gst_ffmpegvidenc_get_property (GObject * object,
881     guint prop_id, GValue * value, GParamSpec * pspec)
882 {
883   GstFFMpegVidEnc *ffmpegenc;
884
885   ffmpegenc = (GstFFMpegVidEnc *) (object);
886
887   switch (prop_id) {
888     case PROP_QUANTIZER:
889       g_value_set_float (value, ffmpegenc->quantizer);
890       break;
891     case PROP_PASS:
892       g_value_set_enum (value, ffmpegenc->pass);
893       break;
894     case PROP_FILENAME:
895       g_value_take_string (value, g_strdup (ffmpegenc->filename));
896       break;
897     default:
898       if (!gst_ffmpeg_cfg_get_property (ffmpegenc->refcontext, value, pspec))
899         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
900       break;
901   }
902 }
903
904 static gboolean
905 gst_ffmpegvidenc_flush (GstVideoEncoder * encoder)
906 {
907   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
908
909   if (ffmpegenc->opened) {
910     avcodec_flush_buffers (ffmpegenc->context);
911     ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
912   }
913
914   return TRUE;
915 }
916
917 static gboolean
918 gst_ffmpegvidenc_start (GstVideoEncoder * encoder)
919 {
920   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
921   GstFFMpegVidEncClass *oclass =
922       (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
923
924   ffmpegenc->opened = FALSE;
925   ffmpegenc->need_reopen = FALSE;
926
927   /* close old session */
928   avcodec_free_context (&ffmpegenc->context);
929   ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
930   if (ffmpegenc->context == NULL) {
931     GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
932     return FALSE;
933   }
934
935   gst_video_encoder_set_min_pts (encoder, GST_SECOND * 60 * 60 * 1000);
936
937   return TRUE;
938 }
939
940 static gboolean
941 gst_ffmpegvidenc_stop (GstVideoEncoder * encoder)
942 {
943   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
944
945   gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE);
946   gst_ffmpeg_avcodec_close (ffmpegenc->context);
947   ffmpegenc->opened = FALSE;
948   ffmpegenc->need_reopen = FALSE;
949
950   if (ffmpegenc->input_state) {
951     gst_video_codec_state_unref (ffmpegenc->input_state);
952     ffmpegenc->input_state = NULL;
953   }
954
955   return TRUE;
956 }
957
958 static GstFlowReturn
959 gst_ffmpegvidenc_finish (GstVideoEncoder * encoder)
960 {
961   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
962
963   return gst_ffmpegvidenc_flush_buffers (ffmpegenc, TRUE);
964 }
965
966 gboolean
967 gst_ffmpegvidenc_register (GstPlugin * plugin)
968 {
969   GTypeInfo typeinfo = {
970     sizeof (GstFFMpegVidEncClass),
971     (GBaseInitFunc) gst_ffmpegvidenc_base_init,
972     NULL,
973     (GClassInitFunc) gst_ffmpegvidenc_class_init,
974     NULL,
975     NULL,
976     sizeof (GstFFMpegVidEnc),
977     0,
978     (GInstanceInitFunc) gst_ffmpegvidenc_init,
979   };
980   GType type;
981   AVCodec *in_plugin;
982   void *i = 0;
983
984   GST_LOG ("Registering encoders");
985
986   while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
987     gchar *type_name;
988
989     /* Skip non-AV codecs */
990     if (in_plugin->type != AVMEDIA_TYPE_VIDEO)
991       continue;
992
993     /* no quasi codecs, please */
994     if (in_plugin->id == AV_CODEC_ID_RAWVIDEO ||
995         in_plugin->id == AV_CODEC_ID_V210 ||
996         in_plugin->id == AV_CODEC_ID_V210X ||
997         in_plugin->id == AV_CODEC_ID_V308 ||
998         in_plugin->id == AV_CODEC_ID_V408 ||
999         in_plugin->id == AV_CODEC_ID_V410 ||
1000         in_plugin->id == AV_CODEC_ID_R210
1001         || in_plugin->id == AV_CODEC_ID_AYUV
1002         || in_plugin->id == AV_CODEC_ID_Y41P
1003         || in_plugin->id == AV_CODEC_ID_012V
1004         || in_plugin->id == AV_CODEC_ID_YUV4
1005 #if AV_VERSION_INT (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) >= \
1006         AV_VERSION_INT (57,4,0)
1007         || in_plugin->id == AV_CODEC_ID_WRAPPED_AVFRAME
1008 #endif
1009         || in_plugin->id == AV_CODEC_ID_ZLIB) {
1010       continue;
1011     }
1012
1013     /* No encoders depending on external libraries (we don't build them, but
1014      * people who build against an external ffmpeg might have them.
1015      * We have native gstreamer plugins for all of those libraries anyway. */
1016     if (!strncmp (in_plugin->name, "lib", 3)) {
1017       GST_DEBUG
1018           ("Not using external library encoder %s. Use the gstreamer-native ones instead.",
1019           in_plugin->name);
1020       continue;
1021     }
1022
1023     /* Skip hardware or hybrid (hardware with software fallback) */
1024     if ((in_plugin->capabilities & AV_CODEC_CAP_HARDWARE) ==
1025         AV_CODEC_CAP_HARDWARE) {
1026       GST_DEBUG
1027           ("Ignoring hardware encoder %s. We can't handle this outside of ffmpeg",
1028           in_plugin->name);
1029       continue;
1030     }
1031
1032     if ((in_plugin->capabilities & AV_CODEC_CAP_HYBRID) == AV_CODEC_CAP_HYBRID) {
1033       GST_DEBUG
1034           ("Ignoring hybrid encoder %s. We can't handle this outside of ffmpeg",
1035           in_plugin->name);
1036       continue;
1037     }
1038
1039     /* only video encoders */
1040     if (!av_codec_is_encoder (in_plugin)
1041         || in_plugin->type != AVMEDIA_TYPE_VIDEO)
1042       continue;
1043
1044     /* FIXME : We should have a method to know cheaply whether we have a mapping
1045      * for the given plugin or not */
1046
1047     GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name);
1048
1049     /* no codecs for which we're GUARANTEED to have better alternatives */
1050     if (!strcmp (in_plugin->name, "gif")) {
1051       GST_LOG ("Ignoring encoder %s", in_plugin->name);
1052       continue;
1053     }
1054
1055     /* construct the type */
1056     type_name = g_strdup_printf ("avenc_%s", in_plugin->name);
1057
1058     type = g_type_from_name (type_name);
1059
1060     if (!type) {
1061
1062       /* create the glib type now */
1063       type =
1064           g_type_register_static (GST_TYPE_VIDEO_ENCODER, type_name, &typeinfo,
1065           0);
1066       g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin);
1067
1068       {
1069         static const GInterfaceInfo preset_info = {
1070           NULL,
1071           NULL,
1072           NULL
1073         };
1074         g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info);
1075       }
1076     }
1077
1078     if (!gst_element_register (plugin, type_name, GST_RANK_SECONDARY, type)) {
1079       g_free (type_name);
1080       return FALSE;
1081     }
1082
1083     g_free (type_name);
1084   }
1085
1086   GST_LOG ("Finished registering encoders");
1087
1088   return TRUE;
1089 }