avdeinterlace: fix element leak
[platform/upstream/gstreamer.git] / subprojects / gst-libav / ext / libav / gstavaudenc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2012> Collabora Ltd.
4  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <assert.h>
27 #include <string.h>
28 /* for stats file handling */
29 #include <stdio.h>
30 #include <glib/gstdio.h>
31 #include <errno.h>
32
33 #include <libavcodec/avcodec.h>
34 #include <libavutil/opt.h>
35
36 #include <gst/gst.h>
37 #include <gst/base/base.h>
38
39 #include "gstav.h"
40 #include "gstavcfg.h"
41 #include "gstavcodecmap.h"
42 #include "gstavutils.h"
43 #include "gstavaudenc.h"
44
45 enum
46 {
47   PROP_0,
48   PROP_CFG_BASE,
49 };
50
51 static void gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass);
52 static void gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass);
53 static void gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc);
54 static void gst_ffmpegaudenc_finalize (GObject * object);
55
56 static gboolean gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder,
57     GstAudioInfo * info);
58 static GstFlowReturn gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder,
59     GstBuffer * inbuf);
60 static gboolean gst_ffmpegaudenc_start (GstAudioEncoder * encoder);
61 static gboolean gst_ffmpegaudenc_stop (GstAudioEncoder * encoder);
62 static void gst_ffmpegaudenc_flush (GstAudioEncoder * encoder);
63
64 static void gst_ffmpegaudenc_set_property (GObject * object,
65     guint prop_id, const GValue * value, GParamSpec * pspec);
66 static void gst_ffmpegaudenc_get_property (GObject * object,
67     guint prop_id, GValue * value, GParamSpec * pspec);
68
69 #define GST_FFENC_PARAMS_QDATA g_quark_from_static_string("avenc-params")
70
71 static GstElementClass *parent_class = NULL;
72
73 static void
74 gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass)
75 {
76   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
77   AVCodec *in_plugin;
78   GstPadTemplate *srctempl = NULL, *sinktempl = NULL;
79   GstCaps *srccaps = NULL, *sinkcaps = NULL;
80   gchar *longname, *description;
81
82   in_plugin =
83       (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
84       GST_FFENC_PARAMS_QDATA);
85   g_assert (in_plugin != NULL);
86
87   /* construct the element details struct */
88   longname = g_strdup_printf ("libav %s encoder", in_plugin->long_name);
89   description = g_strdup_printf ("libav %s encoder", in_plugin->name);
90   gst_element_class_set_metadata (element_class, longname,
91       "Codec/Encoder/Audio", description,
92       "Wim Taymans <wim.taymans@gmail.com>, "
93       "Ronald Bultje <rbultje@ronald.bitfreak.net>");
94   g_free (longname);
95   g_free (description);
96
97   if (!(srccaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, TRUE))) {
98     GST_DEBUG ("Couldn't get source caps for encoder '%s'", in_plugin->name);
99     srccaps = gst_caps_new_empty_simple ("unknown/unknown");
100   }
101
102   sinkcaps = gst_ffmpeg_codectype_to_audio_caps (NULL,
103       in_plugin->id, TRUE, in_plugin);
104   if (!sinkcaps) {
105     GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name);
106     sinkcaps = gst_caps_new_empty_simple ("unknown/unknown");
107   }
108
109   /* pad templates */
110   sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
111       GST_PAD_ALWAYS, sinkcaps);
112   srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
113
114   gst_element_class_add_pad_template (element_class, srctempl);
115   gst_element_class_add_pad_template (element_class, sinktempl);
116
117   gst_caps_unref (sinkcaps);
118   gst_caps_unref (srccaps);
119
120   klass->in_plugin = in_plugin;
121   klass->srctempl = srctempl;
122   klass->sinktempl = sinktempl;
123
124   return;
125 }
126
127 static void
128 gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass)
129 {
130   GObjectClass *gobject_class;
131   GstAudioEncoderClass *gstaudioencoder_class;
132
133   gobject_class = (GObjectClass *) klass;
134   gstaudioencoder_class = (GstAudioEncoderClass *) klass;
135
136   parent_class = g_type_class_peek_parent (klass);
137
138   gobject_class->set_property = gst_ffmpegaudenc_set_property;
139   gobject_class->get_property = gst_ffmpegaudenc_get_property;
140
141   gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin,
142       PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM);
143
144   gobject_class->finalize = gst_ffmpegaudenc_finalize;
145
146   gstaudioencoder_class->start = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_start);
147   gstaudioencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_stop);
148   gstaudioencoder_class->flush = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_flush);
149   gstaudioencoder_class->set_format =
150       GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_set_format);
151   gstaudioencoder_class->handle_frame =
152       GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_handle_frame);
153 }
154
155 static void
156 gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc)
157 {
158   GstFFMpegAudEncClass *klass =
159       (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
160
161   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (ffmpegaudenc));
162
163   /* ffmpeg objects */
164   ffmpegaudenc->context = avcodec_alloc_context3 (klass->in_plugin);
165   ffmpegaudenc->refcontext = avcodec_alloc_context3 (klass->in_plugin);
166   ffmpegaudenc->opened = FALSE;
167   ffmpegaudenc->frame = av_frame_alloc ();
168
169   gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
170 }
171
172 static void
173 gst_ffmpegaudenc_finalize (GObject * object)
174 {
175   GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) object;
176
177   /* clean up remaining allocated data */
178   av_frame_free (&ffmpegaudenc->frame);
179   avcodec_free_context (&ffmpegaudenc->context);
180   avcodec_free_context (&ffmpegaudenc->refcontext);
181
182   G_OBJECT_CLASS (parent_class)->finalize (object);
183 }
184
185 static gboolean
186 gst_ffmpegaudenc_start (GstAudioEncoder * encoder)
187 {
188   GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
189   GstFFMpegAudEncClass *oclass =
190       (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
191
192   ffmpegaudenc->opened = FALSE;
193   ffmpegaudenc->need_reopen = FALSE;
194
195   avcodec_free_context (&ffmpegaudenc->context);
196   ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
197   if (ffmpegaudenc->context == NULL) {
198     GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
199     return FALSE;
200   }
201
202   return TRUE;
203 }
204
205 static gboolean
206 gst_ffmpegaudenc_stop (GstAudioEncoder * encoder)
207 {
208   GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
209
210   /* close old session */
211   gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
212   ffmpegaudenc->opened = FALSE;
213   ffmpegaudenc->need_reopen = FALSE;
214
215   return TRUE;
216 }
217
218 static void
219 gst_ffmpegaudenc_flush (GstAudioEncoder * encoder)
220 {
221   GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
222
223   if (ffmpegaudenc->opened) {
224     avcodec_flush_buffers (ffmpegaudenc->context);
225   }
226 }
227
228 static gboolean
229 gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
230 {
231   GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
232   GstCaps *other_caps;
233   GstCaps *allowed_caps;
234   GstCaps *icaps;
235   gsize frame_size;
236   GstFFMpegAudEncClass *oclass =
237       (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
238
239   ffmpegaudenc->need_reopen = FALSE;
240
241   /* close old session */
242   if (ffmpegaudenc->opened) {
243     avcodec_free_context (&ffmpegaudenc->context);
244     ffmpegaudenc->opened = FALSE;
245     ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
246     if (ffmpegaudenc->context == NULL) {
247       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
248       return FALSE;
249     }
250   }
251
252   gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
253
254   /* fetch pix_fmt and so on */
255   gst_ffmpeg_audioinfo_to_context (info, ffmpegaudenc->context);
256   if (!ffmpegaudenc->context->time_base.den) {
257     ffmpegaudenc->context->time_base.den = GST_AUDIO_INFO_RATE (info);
258     ffmpegaudenc->context->time_base.num = 1;
259     ffmpegaudenc->context->ticks_per_frame = 1;
260   }
261
262   if (ffmpegaudenc->context->channel_layout) {
263     gst_ffmpeg_channel_layout_to_gst (ffmpegaudenc->context->channel_layout,
264         ffmpegaudenc->context->channels, ffmpegaudenc->ffmpeg_layout);
265     ffmpegaudenc->needs_reorder =
266         (memcmp (ffmpegaudenc->ffmpeg_layout, info->position,
267             sizeof (GstAudioChannelPosition) *
268             ffmpegaudenc->context->channels) != 0);
269   }
270
271   /* some codecs support more than one format, first auto-choose one */
272   GST_DEBUG_OBJECT (ffmpegaudenc, "picking an output format ...");
273   allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
274   if (!allowed_caps) {
275     GST_DEBUG_OBJECT (ffmpegaudenc, "... but no peer, using template caps");
276     /* we need to copy because get_allowed_caps returns a ref, and
277      * get_pad_template_caps doesn't */
278     allowed_caps =
279         gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
280   }
281   GST_DEBUG_OBJECT (ffmpegaudenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
282   gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
283       oclass->in_plugin->type, allowed_caps, ffmpegaudenc->context);
284
285   /* open codec */
286   if (gst_ffmpeg_avcodec_open (ffmpegaudenc->context, oclass->in_plugin) < 0) {
287     gst_caps_unref (allowed_caps);
288     avcodec_free_context (&ffmpegaudenc->context);
289     GST_DEBUG_OBJECT (ffmpegaudenc, "avenc_%s: Failed to open FFMPEG codec",
290         oclass->in_plugin->name);
291     ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
292     if (ffmpegaudenc->context == NULL)
293       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
294
295     if ((oclass->in_plugin->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
296         ffmpegaudenc->context->strict_std_compliance !=
297         FF_COMPLIANCE_EXPERIMENTAL) {
298       GST_ELEMENT_ERROR (ffmpegaudenc, LIBRARY, SETTINGS,
299           ("Codec is experimental, but settings don't allow encoders to "
300               "produce output of experimental quality"),
301           ("This codec may not create output that is conformant to the specs "
302               "or of good quality. If you must use it anyway, set the "
303               "compliance property to experimental"));
304     }
305     return FALSE;
306   }
307
308   /* try to set this caps on the other side */
309   other_caps = gst_ffmpeg_codecid_to_caps (oclass->in_plugin->id,
310       ffmpegaudenc->context, TRUE);
311
312   if (!other_caps) {
313     gst_caps_unref (allowed_caps);
314     avcodec_free_context (&ffmpegaudenc->context);
315     GST_DEBUG ("Unsupported codec - no caps found");
316     ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
317     if (ffmpegaudenc->context == NULL)
318       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
319     return FALSE;
320   }
321
322   icaps = gst_caps_intersect (allowed_caps, other_caps);
323   gst_caps_unref (allowed_caps);
324   gst_caps_unref (other_caps);
325   if (gst_caps_is_empty (icaps)) {
326     gst_caps_unref (icaps);
327     return FALSE;
328   }
329   icaps = gst_caps_fixate (icaps);
330
331   if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc),
332           icaps)) {
333     avcodec_free_context (&ffmpegaudenc->context);
334     gst_caps_unref (icaps);
335     ffmpegaudenc->context = avcodec_alloc_context3 (oclass->in_plugin);
336     if (ffmpegaudenc->context == NULL)
337       GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to set context defaults");
338     return FALSE;
339   }
340   gst_caps_unref (icaps);
341
342   frame_size = ffmpegaudenc->context->frame_size;
343   if (frame_size > 1) {
344     gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
345         frame_size);
346     gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
347         frame_size);
348     gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 1);
349   } else {
350     gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
351         0);
352     gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
353         0);
354     gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 0);
355   }
356
357   /* Store some tags */
358   {
359     GstTagList *tags = gst_tag_list_new_empty ();
360     const gchar *codec;
361
362     gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_NOMINAL_BITRATE,
363         (guint) ffmpegaudenc->context->bit_rate, NULL);
364
365     if ((codec =
366             gst_ffmpeg_get_codecid_longname (ffmpegaudenc->context->codec_id)))
367       gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, codec,
368           NULL);
369
370     gst_audio_encoder_merge_tags (encoder, tags, GST_TAG_MERGE_REPLACE);
371     gst_tag_list_unref (tags);
372   }
373
374   /* success! */
375   ffmpegaudenc->opened = TRUE;
376   ffmpegaudenc->need_reopen = FALSE;
377
378   return TRUE;
379 }
380
381 static void
382 gst_ffmpegaudenc_free_avpacket (gpointer pkt)
383 {
384   av_packet_unref ((AVPacket *) pkt);
385   g_slice_free (AVPacket, pkt);
386 }
387
388 typedef struct
389 {
390   GstBuffer *buffer;
391   GstMapInfo map;
392
393   guint8 **ext_data_array, *ext_data;
394 } BufferInfo;
395
396 static void
397 buffer_info_free (void *opaque, guint8 * data)
398 {
399   BufferInfo *info = opaque;
400
401   if (info->buffer) {
402     gst_buffer_unmap (info->buffer, &info->map);
403     gst_buffer_unref (info->buffer);
404   } else {
405     av_freep (&info->ext_data);
406     av_freep (&info->ext_data_array);
407   }
408   g_slice_free (BufferInfo, info);
409 }
410
411 static GstFlowReturn
412 gst_ffmpegaudenc_send_frame (GstFFMpegAudEnc * ffmpegaudenc, GstBuffer * buffer)
413 {
414   GstAudioEncoder *enc;
415   AVCodecContext *ctx;
416   GstFlowReturn ret;
417   gint res;
418   GstAudioInfo *info;
419   AVFrame *frame = ffmpegaudenc->frame;
420   gboolean planar;
421   gint nsamples = -1;
422
423   enc = GST_AUDIO_ENCODER (ffmpegaudenc);
424
425   ctx = ffmpegaudenc->context;
426
427   if (buffer != NULL) {
428     BufferInfo *buffer_info = g_slice_new0 (BufferInfo);
429     guint8 *audio_in;
430     guint in_size;
431
432     buffer_info->buffer = buffer;
433     gst_buffer_map (buffer, &buffer_info->map, GST_MAP_READ);
434     audio_in = buffer_info->map.data;
435     in_size = buffer_info->map.size;
436
437     GST_LOG_OBJECT (ffmpegaudenc, "encoding buffer %p size:%u", audio_in,
438         in_size);
439
440     info = gst_audio_encoder_get_audio_info (enc);
441     planar = av_sample_fmt_is_planar (ffmpegaudenc->context->sample_fmt);
442     frame->format = ffmpegaudenc->context->sample_fmt;
443     frame->sample_rate = ffmpegaudenc->context->sample_rate;
444     frame->channels = ffmpegaudenc->context->channels;
445     frame->channel_layout = ffmpegaudenc->context->channel_layout;
446
447     if (planar && info->channels > 1) {
448       gint channels;
449       gint i, j;
450
451       nsamples = frame->nb_samples = in_size / info->bpf;
452       channels = info->channels;
453
454       frame->buf[0] =
455           av_buffer_create (NULL, 0, buffer_info_free, buffer_info, 0);
456
457       if (info->channels > AV_NUM_DATA_POINTERS) {
458         buffer_info->ext_data_array = frame->extended_data =
459             av_malloc_array (info->channels, sizeof (uint8_t *));
460       } else {
461         frame->extended_data = frame->data;
462       }
463
464       buffer_info->ext_data = frame->extended_data[0] = av_malloc (in_size);
465       frame->linesize[0] = in_size / channels;
466       for (i = 1; i < channels; i++)
467         frame->extended_data[i] =
468             frame->extended_data[i - 1] + frame->linesize[0];
469
470       switch (info->finfo->width) {
471         case 8:{
472           const guint8 *idata = (const guint8 *) audio_in;
473
474           for (i = 0; i < nsamples; i++) {
475             for (j = 0; j < channels; j++) {
476               ((guint8 *) frame->extended_data[j])[i] = idata[j];
477             }
478             idata += channels;
479           }
480           break;
481         }
482         case 16:{
483           const guint16 *idata = (const guint16 *) audio_in;
484
485           for (i = 0; i < nsamples; i++) {
486             for (j = 0; j < channels; j++) {
487               ((guint16 *) frame->extended_data[j])[i] = idata[j];
488             }
489             idata += channels;
490           }
491           break;
492         }
493         case 32:{
494           const guint32 *idata = (const guint32 *) audio_in;
495
496           for (i = 0; i < nsamples; i++) {
497             for (j = 0; j < channels; j++) {
498               ((guint32 *) frame->extended_data[j])[i] = idata[j];
499             }
500             idata += channels;
501           }
502
503           break;
504         }
505         case 64:{
506           const guint64 *idata = (const guint64 *) audio_in;
507
508           for (i = 0; i < nsamples; i++) {
509             for (j = 0; j < channels; j++) {
510               ((guint64 *) frame->extended_data[j])[i] = idata[j];
511             }
512             idata += channels;
513           }
514
515           break;
516         }
517         default:
518           g_assert_not_reached ();
519           break;
520       }
521
522       gst_buffer_unmap (buffer, &buffer_info->map);
523       gst_buffer_unref (buffer);
524       buffer_info->buffer = NULL;
525     } else {
526       frame->data[0] = audio_in;
527       frame->extended_data = frame->data;
528       frame->linesize[0] = in_size;
529       frame->nb_samples = nsamples = in_size / info->bpf;
530       frame->buf[0] =
531           av_buffer_create (NULL, 0, buffer_info_free, buffer_info, 0);
532     }
533
534     /* we have a frame to feed the encoder */
535     res = avcodec_send_frame (ctx, frame);
536
537     av_frame_unref (frame);
538   } else {
539     GstFFMpegAudEncClass *oclass =
540         (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
541
542     GST_LOG_OBJECT (ffmpegaudenc, "draining");
543     /* flushing the encoder */
544     res = avcodec_send_frame (ctx, NULL);
545
546     /* If AV_CODEC_CAP_ENCODER_FLUSH wasn't set, we need to re-open
547      * encoder */
548     if (!(oclass->in_plugin->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)) {
549       GST_DEBUG_OBJECT (ffmpegaudenc, "Encoder needs reopen later");
550
551       /* we will reopen later handle_frame() */
552       ffmpegaudenc->need_reopen = TRUE;
553     }
554   }
555
556   if (res == 0) {
557     ret = GST_FLOW_OK;
558   } else if (res == AVERROR_EOF) {
559     ret = GST_FLOW_EOS;
560   } else {                      /* Any other return value is an error in our context */
561     ret = GST_FLOW_OK;
562     GST_WARNING_OBJECT (ffmpegaudenc, "Failed to encode buffer");
563   }
564
565   return ret;
566 }
567
568 static GstFlowReturn
569 gst_ffmpegaudenc_receive_packet (GstFFMpegAudEnc * ffmpegaudenc,
570     gboolean * got_packet)
571 {
572   GstAudioEncoder *enc;
573   AVCodecContext *ctx;
574   gint res;
575   GstFlowReturn ret;
576   AVPacket *pkt;
577
578   enc = GST_AUDIO_ENCODER (ffmpegaudenc);
579
580   ctx = ffmpegaudenc->context;
581
582   pkt = g_slice_new0 (AVPacket);
583
584   res = avcodec_receive_packet (ctx, pkt);
585
586   if (res == 0) {
587     GstBuffer *outbuf;
588     const uint8_t *side_data;
589 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58,130,0)
590     size_t side_data_length = 0;
591 #else
592     int side_data_length = 0;
593 #endif
594
595     GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d", pkt->size);
596
597     outbuf =
598         gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, pkt->data,
599         pkt->size, 0, pkt->size, pkt, gst_ffmpegaudenc_free_avpacket);
600
601     if ((side_data =
602             av_packet_get_side_data (pkt, AV_PKT_DATA_SKIP_SAMPLES,
603                 &side_data_length)) && side_data_length == 10) {
604       GstByteReader reader = GST_BYTE_READER_INIT (pkt->data, pkt->size);
605       guint32 start, end;
606
607       start = gst_byte_reader_get_uint32_le_unchecked (&reader);
608       end = gst_byte_reader_get_uint32_le_unchecked (&reader);
609
610       GST_LOG_OBJECT (ffmpegaudenc,
611           "got skip samples side data with start %u and end %u", start, end);
612       gst_buffer_add_audio_clipping_meta (outbuf, GST_FORMAT_DEFAULT, start,
613           end);
614     }
615
616     ret =
617         gst_audio_encoder_finish_frame (enc, outbuf,
618         pkt->duration > 0 ? pkt->duration : -1);
619     *got_packet = TRUE;
620   } else {
621     GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
622     g_slice_free (AVPacket, pkt);
623     ret = GST_FLOW_OK;
624     *got_packet = FALSE;
625   }
626
627   return ret;
628 }
629
630 static GstFlowReturn
631 gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
632 {
633   GstFlowReturn ret = GST_FLOW_OK;
634   gboolean got_packet;
635
636   ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, NULL);
637
638   if (ret == GST_FLOW_OK) {
639     do {
640       ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
641       if (ret != GST_FLOW_OK)
642         break;
643     } while (got_packet);
644   }
645
646   /* NOTE: this may or may not work depending on capability */
647   avcodec_flush_buffers (ffmpegaudenc->context);
648
649   /* FFMpeg will return AVERROR_EOF if it's internal was fully drained
650    * then we are translating it to GST_FLOW_EOS. However, because this behavior
651    * is fully internal stuff of this implementation and gstaudioencoder
652    * baseclass doesn't convert this GST_FLOW_EOS to GST_FLOW_OK,
653    * convert this flow returned here */
654   if (ret == GST_FLOW_EOS)
655     ret = GST_FLOW_OK;
656
657   return ret;
658 }
659
660 static GstFlowReturn
661 gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
662 {
663   GstFFMpegAudEnc *ffmpegaudenc;
664   GstFlowReturn ret;
665   gboolean got_packet;
666
667   ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
668
669   if (G_UNLIKELY (!ffmpegaudenc->opened))
670     goto not_negotiated;
671
672   if (!inbuf)
673     return gst_ffmpegaudenc_drain (ffmpegaudenc);
674
675   /* endoder was drained or flushed, and ffmpeg encoder doesn't support
676    * flushing. We need to re-open encoder then */
677   if (ffmpegaudenc->need_reopen) {
678     GST_DEBUG_OBJECT (ffmpegaudenc, "Open encoder again");
679
680     if (!gst_ffmpegaudenc_set_format (encoder,
681             gst_audio_encoder_get_audio_info (encoder))) {
682       GST_ERROR_OBJECT (ffmpegaudenc, "Couldn't re-open encoder");
683       return GST_FLOW_NOT_NEGOTIATED;
684     }
685   }
686
687   inbuf = gst_buffer_ref (inbuf);
688
689   GST_DEBUG_OBJECT (ffmpegaudenc,
690       "Received time %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT
691       ", size %" G_GSIZE_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
692       GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), gst_buffer_get_size (inbuf));
693
694   /* Reorder channels to the GStreamer channel order */
695   if (ffmpegaudenc->needs_reorder) {
696     GstAudioInfo *info = gst_audio_encoder_get_audio_info (encoder);
697
698     inbuf = gst_buffer_make_writable (inbuf);
699     gst_audio_buffer_reorder_channels (inbuf, info->finfo->format,
700         info->channels, info->position, ffmpegaudenc->ffmpeg_layout);
701   }
702
703   ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, inbuf);
704
705   if (ret != GST_FLOW_OK)
706     goto send_frame_failed;
707
708   do {
709     ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
710   } while (got_packet);
711
712   return GST_FLOW_OK;
713
714   /* ERRORS */
715 not_negotiated:
716   {
717     GST_ELEMENT_ERROR (ffmpegaudenc, CORE, NEGOTIATION, (NULL),
718         ("not configured to input format before data start"));
719     gst_buffer_unref (inbuf);
720     return GST_FLOW_NOT_NEGOTIATED;
721   }
722 send_frame_failed:
723   {
724     GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to send frame %d (%s)", ret,
725         gst_flow_get_name (ret));
726     return ret;
727   }
728 }
729
730 static void
731 gst_ffmpegaudenc_set_property (GObject * object,
732     guint prop_id, const GValue * value, GParamSpec * pspec)
733 {
734   GstFFMpegAudEnc *ffmpegaudenc;
735
736   ffmpegaudenc = (GstFFMpegAudEnc *) (object);
737
738   if (ffmpegaudenc->opened) {
739     GST_WARNING_OBJECT (ffmpegaudenc,
740         "Can't change properties once encoder is setup !");
741     return;
742   }
743
744   switch (prop_id) {
745     default:
746       if (!gst_ffmpeg_cfg_set_property (ffmpegaudenc->refcontext, value, pspec))
747         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
748       break;
749   }
750 }
751
752 static void
753 gst_ffmpegaudenc_get_property (GObject * object,
754     guint prop_id, GValue * value, GParamSpec * pspec)
755 {
756   GstFFMpegAudEnc *ffmpegaudenc;
757
758   ffmpegaudenc = (GstFFMpegAudEnc *) (object);
759
760   switch (prop_id) {
761     default:
762       if (!gst_ffmpeg_cfg_get_property (ffmpegaudenc->refcontext, value, pspec))
763         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
764       break;
765   }
766 }
767
768 gboolean
769 gst_ffmpegaudenc_register (GstPlugin * plugin)
770 {
771   GTypeInfo typeinfo = {
772     sizeof (GstFFMpegAudEncClass),
773     (GBaseInitFunc) gst_ffmpegaudenc_base_init,
774     NULL,
775     (GClassInitFunc) gst_ffmpegaudenc_class_init,
776     NULL,
777     NULL,
778     sizeof (GstFFMpegAudEnc),
779     0,
780     (GInstanceInitFunc) gst_ffmpegaudenc_init,
781   };
782   GType type;
783   AVCodec *in_plugin;
784   void *i = 0;
785
786
787   GST_LOG ("Registering encoders");
788
789   while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
790     gchar *type_name;
791     guint rank;
792
793     /* Skip non-AV codecs */
794     if (in_plugin->type != AVMEDIA_TYPE_AUDIO)
795       continue;
796
797     /* no quasi codecs, please */
798     if (in_plugin->id == AV_CODEC_ID_PCM_S16LE_PLANAR ||
799         (in_plugin->id >= AV_CODEC_ID_PCM_S16LE &&
800             in_plugin->id <= AV_CODEC_ID_PCM_BLURAY) ||
801         (in_plugin->id >= AV_CODEC_ID_PCM_S8_PLANAR &&
802             in_plugin->id <= AV_CODEC_ID_PCM_F24LE)) {
803       continue;
804     }
805
806     /* No encoders depending on external libraries (we don't build them, but
807      * people who build against an external ffmpeg might have them.
808      * We have native gstreamer plugins for all of those libraries anyway. */
809     if (!strncmp (in_plugin->name, "lib", 3)) {
810       GST_DEBUG
811           ("Not using external library encoder %s. Use the gstreamer-native ones instead.",
812           in_plugin->name);
813       continue;
814     }
815
816     /* only encoders */
817     if (!av_codec_is_encoder (in_plugin)) {
818       continue;
819     }
820
821     /* FIXME : We should have a method to know cheaply whether we have a mapping
822      * for the given plugin or not */
823
824     GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name);
825
826     /* no codecs for which we're GUARANTEED to have better alternatives */
827     if (!strcmp (in_plugin->name, "vorbis")
828         || !strcmp (in_plugin->name, "flac")) {
829       GST_LOG ("Ignoring encoder %s", in_plugin->name);
830       continue;
831     }
832
833     /* construct the type */
834     type_name = g_strdup_printf ("avenc_%s", in_plugin->name);
835
836     type = g_type_from_name (type_name);
837
838     if (!type) {
839
840       /* create the glib type now */
841       type =
842           g_type_register_static (GST_TYPE_AUDIO_ENCODER, type_name, &typeinfo,
843           0);
844       g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin);
845
846       {
847         static const GInterfaceInfo preset_info = {
848           NULL,
849           NULL,
850           NULL
851         };
852         g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info);
853       }
854     }
855
856     switch (in_plugin->id) {
857         /* avenc_aac: see https://bugzilla.gnome.org/show_bug.cgi?id=691617 */
858       case AV_CODEC_ID_AAC:
859         rank = GST_RANK_NONE;
860         break;
861       default:
862         rank = GST_RANK_SECONDARY;
863         break;
864     }
865
866     if (!gst_element_register (plugin, type_name, rank, type)) {
867       g_free (type_name);
868       return FALSE;
869     }
870
871     g_free (type_name);
872   }
873
874   GST_LOG ("Finished registering encoders");
875
876   return TRUE;
877 }