Revert "avvidenc: Set timebase in the ffmpeg context to nanoseconds and set framerate"
[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   if (pkt->dts != AV_NOPTS_VALUE) {
721     frame->dts =
722         gst_ffmpeg_time_ff_to_gst (pkt->dts + ffmpegenc->pts_offset,
723         ffmpegenc->context->time_base);
724   }
725   /* This will lose some precision compared to setting the PTS from the input
726    * buffer directly, but that way we're sure PTS and DTS are consistent, in
727    * particular DTS should always be <= PTS
728    */
729   if (pkt->pts != AV_NOPTS_VALUE) {
730     frame->pts =
731         gst_ffmpeg_time_ff_to_gst (pkt->pts + ffmpegenc->pts_offset,
732         ffmpegenc->context->time_base);
733   }
734
735   ret = gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (ffmpegenc), frame);
736
737 done:
738   return ret;
739 }
740
741 static GstFlowReturn
742 gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
743     GstVideoCodecFrame * frame)
744 {
745   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
746   GstFlowReturn ret;
747   gboolean got_packet;
748
749   /* endoder was drained or flushed, and ffmpeg encoder doesn't support
750    * flushing. We need to re-open encoder then */
751   if (ffmpegenc->need_reopen) {
752     gboolean reopen_ret;
753     GstVideoCodecState *input_state;
754
755     GST_DEBUG_OBJECT (ffmpegenc, "Open encoder again");
756
757     if (!ffmpegenc->input_state) {
758       GST_ERROR_OBJECT (ffmpegenc,
759           "Cannot re-open encoder without input state");
760       return GST_FLOW_NOT_NEGOTIATED;
761     }
762
763     input_state = gst_video_codec_state_ref (ffmpegenc->input_state);
764     reopen_ret = gst_ffmpegvidenc_set_format (encoder, input_state);
765     gst_video_codec_state_unref (input_state);
766
767     if (!reopen_ret) {
768       GST_ERROR_OBJECT (ffmpegenc, "Couldn't re-open encoder");
769       return GST_FLOW_NOT_NEGOTIATED;
770     }
771   }
772
773   ret = gst_ffmpegvidenc_send_frame (ffmpegenc, frame);
774
775   if (ret != GST_FLOW_OK)
776     goto encode_fail;
777
778   gst_video_codec_frame_unref (frame);
779
780   do {
781     ret = gst_ffmpegvidenc_receive_packet (ffmpegenc, &got_packet, TRUE);
782     if (ret != GST_FLOW_OK)
783       break;
784   } while (got_packet);
785
786 done:
787   return ret;
788
789   /* We choose to be error-resilient */
790 encode_fail:
791   {
792 #ifndef GST_DISABLE_GST_DEBUG
793     GstFFMpegVidEncClass *oclass =
794         (GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc));
795     GST_ERROR_OBJECT (ffmpegenc,
796         "avenc_%s: failed to encode buffer", oclass->in_plugin->name);
797 #endif /* GST_DISABLE_GST_DEBUG */
798     /* avoid frame (and ts etc) piling up */
799     ret = gst_video_encoder_finish_frame (encoder, frame);
800     goto done;
801   }
802 }
803
804 static GstFlowReturn
805 gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
806 {
807   GstFlowReturn ret = GST_FLOW_OK;
808   gboolean got_packet;
809
810   GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send);
811
812   /* no need to empty codec if there is none */
813   if (!ffmpegenc->opened)
814     goto done;
815
816   ret = gst_ffmpegvidenc_send_frame (ffmpegenc, NULL);
817
818   if (ret != GST_FLOW_OK)
819     goto done;
820
821   do {
822     ret = gst_ffmpegvidenc_receive_packet (ffmpegenc, &got_packet, send);
823     if (ret != GST_FLOW_OK)
824       break;
825   } while (got_packet);
826   avcodec_flush_buffers (ffmpegenc->context);
827   ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
828
829 done:
830   /* FFMpeg will return AVERROR_EOF if it's internal was fully drained
831    * then we are translating it to GST_FLOW_EOS. However, because this behavior
832    * is fully internal stuff of this implementation and gstvideoencoder
833    * baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
834    * convert this flow returned here */
835   if (ret == GST_FLOW_EOS)
836     ret = GST_FLOW_OK;
837
838   return ret;
839 }
840
841 static void
842 gst_ffmpegvidenc_set_property (GObject * object,
843     guint prop_id, const GValue * value, GParamSpec * pspec)
844 {
845   GstFFMpegVidEnc *ffmpegenc;
846
847   ffmpegenc = (GstFFMpegVidEnc *) (object);
848
849   if (ffmpegenc->opened) {
850     GST_WARNING_OBJECT (ffmpegenc,
851         "Can't change properties once decoder is setup !");
852     return;
853   }
854
855   switch (prop_id) {
856     case PROP_QUANTIZER:
857       ffmpegenc->quantizer = g_value_get_float (value);
858       break;
859     case PROP_PASS:
860       ffmpegenc->pass = g_value_get_enum (value);
861       break;
862     case PROP_FILENAME:
863       g_free (ffmpegenc->filename);
864       ffmpegenc->filename = g_value_dup_string (value);
865       break;
866     default:
867       if (!gst_ffmpeg_cfg_set_property (ffmpegenc->refcontext, value, pspec))
868         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
869       break;
870   }
871 }
872
873 static void
874 gst_ffmpegvidenc_get_property (GObject * object,
875     guint prop_id, GValue * value, GParamSpec * pspec)
876 {
877   GstFFMpegVidEnc *ffmpegenc;
878
879   ffmpegenc = (GstFFMpegVidEnc *) (object);
880
881   switch (prop_id) {
882     case PROP_QUANTIZER:
883       g_value_set_float (value, ffmpegenc->quantizer);
884       break;
885     case PROP_PASS:
886       g_value_set_enum (value, ffmpegenc->pass);
887       break;
888     case PROP_FILENAME:
889       g_value_take_string (value, g_strdup (ffmpegenc->filename));
890       break;
891     default:
892       if (!gst_ffmpeg_cfg_get_property (ffmpegenc->refcontext, value, pspec))
893         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
894       break;
895   }
896 }
897
898 static gboolean
899 gst_ffmpegvidenc_flush (GstVideoEncoder * encoder)
900 {
901   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
902
903   if (ffmpegenc->opened) {
904     avcodec_flush_buffers (ffmpegenc->context);
905     ffmpegenc->pts_offset = GST_CLOCK_TIME_NONE;
906   }
907
908   return TRUE;
909 }
910
911 static gboolean
912 gst_ffmpegvidenc_start (GstVideoEncoder * encoder)
913 {
914   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
915   GstFFMpegVidEncClass *oclass =
916       (GstFFMpegVidEncClass *) G_OBJECT_GET_CLASS (ffmpegenc);
917
918   ffmpegenc->opened = FALSE;
919   ffmpegenc->need_reopen = FALSE;
920
921   /* close old session */
922   avcodec_free_context (&ffmpegenc->context);
923   ffmpegenc->context = avcodec_alloc_context3 (oclass->in_plugin);
924   if (ffmpegenc->context == NULL) {
925     GST_DEBUG_OBJECT (ffmpegenc, "Failed to set context defaults");
926     return FALSE;
927   }
928
929   gst_video_encoder_set_min_pts (encoder, GST_SECOND * 60 * 60 * 1000);
930
931   return TRUE;
932 }
933
934 static gboolean
935 gst_ffmpegvidenc_stop (GstVideoEncoder * encoder)
936 {
937   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
938
939   gst_ffmpegvidenc_flush_buffers (ffmpegenc, FALSE);
940   gst_ffmpeg_avcodec_close (ffmpegenc->context);
941   ffmpegenc->opened = FALSE;
942   ffmpegenc->need_reopen = FALSE;
943
944   if (ffmpegenc->input_state) {
945     gst_video_codec_state_unref (ffmpegenc->input_state);
946     ffmpegenc->input_state = NULL;
947   }
948
949   return TRUE;
950 }
951
952 static GstFlowReturn
953 gst_ffmpegvidenc_finish (GstVideoEncoder * encoder)
954 {
955   GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder;
956
957   return gst_ffmpegvidenc_flush_buffers (ffmpegenc, TRUE);
958 }
959
960 gboolean
961 gst_ffmpegvidenc_register (GstPlugin * plugin)
962 {
963   GTypeInfo typeinfo = {
964     sizeof (GstFFMpegVidEncClass),
965     (GBaseInitFunc) gst_ffmpegvidenc_base_init,
966     NULL,
967     (GClassInitFunc) gst_ffmpegvidenc_class_init,
968     NULL,
969     NULL,
970     sizeof (GstFFMpegVidEnc),
971     0,
972     (GInstanceInitFunc) gst_ffmpegvidenc_init,
973   };
974   GType type;
975   AVCodec *in_plugin;
976   void *i = 0;
977
978   GST_LOG ("Registering encoders");
979
980   while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
981     gchar *type_name;
982
983     /* Skip non-AV codecs */
984     if (in_plugin->type != AVMEDIA_TYPE_VIDEO)
985       continue;
986
987     /* no quasi codecs, please */
988     if (in_plugin->id == AV_CODEC_ID_RAWVIDEO ||
989         in_plugin->id == AV_CODEC_ID_V210 ||
990         in_plugin->id == AV_CODEC_ID_V210X ||
991         in_plugin->id == AV_CODEC_ID_V308 ||
992         in_plugin->id == AV_CODEC_ID_V408 ||
993         in_plugin->id == AV_CODEC_ID_V410 ||
994         in_plugin->id == AV_CODEC_ID_R210
995         || in_plugin->id == AV_CODEC_ID_AYUV
996         || in_plugin->id == AV_CODEC_ID_Y41P
997         || in_plugin->id == AV_CODEC_ID_012V
998         || in_plugin->id == AV_CODEC_ID_YUV4
999 #if AV_VERSION_INT (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) >= \
1000         AV_VERSION_INT (57,4,0)
1001         || in_plugin->id == AV_CODEC_ID_WRAPPED_AVFRAME
1002 #endif
1003         || in_plugin->id == AV_CODEC_ID_ZLIB) {
1004       continue;
1005     }
1006
1007     /* No encoders depending on external libraries (we don't build them, but
1008      * people who build against an external ffmpeg might have them.
1009      * We have native gstreamer plugins for all of those libraries anyway. */
1010     if (!strncmp (in_plugin->name, "lib", 3)) {
1011       GST_DEBUG
1012           ("Not using external library encoder %s. Use the gstreamer-native ones instead.",
1013           in_plugin->name);
1014       continue;
1015     }
1016
1017     /* Skip hardware or hybrid (hardware with software fallback) */
1018     if ((in_plugin->capabilities & AV_CODEC_CAP_HARDWARE) ==
1019         AV_CODEC_CAP_HARDWARE) {
1020       GST_DEBUG
1021           ("Ignoring hardware encoder %s. We can't handle this outside of ffmpeg",
1022           in_plugin->name);
1023       continue;
1024     }
1025
1026     if ((in_plugin->capabilities & AV_CODEC_CAP_HYBRID) == AV_CODEC_CAP_HYBRID) {
1027       GST_DEBUG
1028           ("Ignoring hybrid encoder %s. We can't handle this outside of ffmpeg",
1029           in_plugin->name);
1030       continue;
1031     }
1032
1033     /* only video encoders */
1034     if (!av_codec_is_encoder (in_plugin)
1035         || in_plugin->type != AVMEDIA_TYPE_VIDEO)
1036       continue;
1037
1038     /* FIXME : We should have a method to know cheaply whether we have a mapping
1039      * for the given plugin or not */
1040
1041     GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name);
1042
1043     /* no codecs for which we're GUARANTEED to have better alternatives */
1044     if (!strcmp (in_plugin->name, "gif")) {
1045       GST_LOG ("Ignoring encoder %s", in_plugin->name);
1046       continue;
1047     }
1048
1049     /* construct the type */
1050     type_name = g_strdup_printf ("avenc_%s", in_plugin->name);
1051
1052     type = g_type_from_name (type_name);
1053
1054     if (!type) {
1055
1056       /* create the glib type now */
1057       type =
1058           g_type_register_static (GST_TYPE_VIDEO_ENCODER, type_name, &typeinfo,
1059           0);
1060       g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin);
1061
1062       {
1063         static const GInterfaceInfo preset_info = {
1064           NULL,
1065           NULL,
1066           NULL
1067         };
1068         g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info);
1069       }
1070     }
1071
1072     if (!gst_element_register (plugin, type_name, GST_RANK_SECONDARY, type)) {
1073       g_free (type_name);
1074       return FALSE;
1075     }
1076
1077     g_free (type_name);
1078   }
1079
1080   GST_LOG ("Finished registering encoders");
1081
1082   return TRUE;
1083 }