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>
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.
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.
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.
28 /* for stats file handling */
30 #include <glib/gstdio.h>
33 #include <libavcodec/avcodec.h>
34 #include <libavutil/opt.h>
37 #include <gst/base/base.h>
41 #include "gstavcodecmap.h"
42 #include "gstavutils.h"
43 #include "gstavaudenc.h"
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);
56 static gboolean gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder,
58 static GstFlowReturn gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder,
60 static gboolean gst_ffmpegaudenc_start (GstAudioEncoder * encoder);
61 static gboolean gst_ffmpegaudenc_stop (GstAudioEncoder * encoder);
62 static void gst_ffmpegaudenc_flush (GstAudioEncoder * encoder);
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);
69 #define GST_FFENC_PARAMS_QDATA g_quark_from_static_string("avenc-params")
71 static GstElementClass *parent_class = NULL;
74 gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass)
76 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
78 GstPadTemplate *srctempl = NULL, *sinktempl = NULL;
79 GstCaps *srccaps = NULL, *sinkcaps = NULL;
80 gchar *longname, *description;
83 (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
84 GST_FFENC_PARAMS_QDATA);
85 g_assert (in_plugin != NULL);
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>");
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");
102 sinkcaps = gst_ffmpeg_codectype_to_audio_caps (NULL,
103 in_plugin->id, TRUE, in_plugin);
105 GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name);
106 sinkcaps = gst_caps_new_empty_simple ("unknown/unknown");
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);
114 gst_element_class_add_pad_template (element_class, srctempl);
115 gst_element_class_add_pad_template (element_class, sinktempl);
117 gst_caps_unref (sinkcaps);
118 gst_caps_unref (srccaps);
120 klass->in_plugin = in_plugin;
121 klass->srctempl = srctempl;
122 klass->sinktempl = sinktempl;
128 gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass)
130 GObjectClass *gobject_class;
131 GstAudioEncoderClass *gstaudioencoder_class;
133 gobject_class = (GObjectClass *) klass;
134 gstaudioencoder_class = (GstAudioEncoderClass *) klass;
136 parent_class = g_type_class_peek_parent (klass);
138 gobject_class->set_property = gst_ffmpegaudenc_set_property;
139 gobject_class->get_property = gst_ffmpegaudenc_get_property;
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);
144 gobject_class->finalize = gst_ffmpegaudenc_finalize;
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);
156 gst_ffmpegaudenc_init (GstFFMpegAudEnc * ffmpegaudenc)
158 GstFFMpegAudEncClass *klass =
159 (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
161 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (ffmpegaudenc));
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 ();
169 gst_audio_encoder_set_drainable (GST_AUDIO_ENCODER (ffmpegaudenc), TRUE);
173 gst_ffmpegaudenc_finalize (GObject * object)
175 GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) object;
177 /* clean up remaining allocated data */
178 av_frame_free (&ffmpegaudenc->frame);
179 avcodec_free_context (&ffmpegaudenc->context);
180 avcodec_free_context (&ffmpegaudenc->refcontext);
182 G_OBJECT_CLASS (parent_class)->finalize (object);
186 gst_ffmpegaudenc_start (GstAudioEncoder * encoder)
188 GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
189 GstFFMpegAudEncClass *oclass =
190 (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
192 ffmpegaudenc->opened = FALSE;
193 ffmpegaudenc->need_reopen = FALSE;
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");
206 gst_ffmpegaudenc_stop (GstAudioEncoder * encoder)
208 GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
210 /* close old session */
211 gst_ffmpeg_avcodec_close (ffmpegaudenc->context);
212 ffmpegaudenc->opened = FALSE;
213 ffmpegaudenc->need_reopen = FALSE;
219 gst_ffmpegaudenc_flush (GstAudioEncoder * encoder)
221 GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
223 if (ffmpegaudenc->opened) {
224 avcodec_flush_buffers (ffmpegaudenc->context);
229 gst_ffmpegaudenc_set_format (GstAudioEncoder * encoder, GstAudioInfo * info)
231 GstFFMpegAudEnc *ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
233 GstCaps *allowed_caps;
236 GstFFMpegAudEncClass *oclass =
237 (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
239 ffmpegaudenc->need_reopen = FALSE;
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");
252 gst_ffmpeg_cfg_fill_context (G_OBJECT (ffmpegaudenc), ffmpegaudenc->context);
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;
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);
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));
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 */
279 gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (encoder));
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);
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");
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"));
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);
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");
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);
329 icaps = gst_caps_fixate (icaps);
331 if (!gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (ffmpegaudenc),
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");
340 gst_caps_unref (icaps);
342 frame_size = ffmpegaudenc->context->frame_size;
343 if (frame_size > 1) {
344 gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
346 gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
348 gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 1);
350 gst_audio_encoder_set_frame_samples_min (GST_AUDIO_ENCODER (ffmpegaudenc),
352 gst_audio_encoder_set_frame_samples_max (GST_AUDIO_ENCODER (ffmpegaudenc),
354 gst_audio_encoder_set_frame_max (GST_AUDIO_ENCODER (ffmpegaudenc), 0);
357 /* Store some tags */
359 GstTagList *tags = gst_tag_list_new_empty ();
362 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_NOMINAL_BITRATE,
363 (guint) ffmpegaudenc->context->bit_rate, NULL);
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,
370 gst_audio_encoder_merge_tags (encoder, tags, GST_TAG_MERGE_REPLACE);
371 gst_tag_list_unref (tags);
375 ffmpegaudenc->opened = TRUE;
376 ffmpegaudenc->need_reopen = FALSE;
382 gst_ffmpegaudenc_free_avpacket (gpointer pkt)
384 av_packet_unref ((AVPacket *) pkt);
385 g_slice_free (AVPacket, pkt);
393 guint8 **ext_data_array, *ext_data;
397 buffer_info_free (void *opaque, guint8 * data)
399 BufferInfo *info = opaque;
402 gst_buffer_unmap (info->buffer, &info->map);
403 gst_buffer_unref (info->buffer);
405 av_freep (&info->ext_data);
406 av_freep (&info->ext_data_array);
408 g_slice_free (BufferInfo, info);
412 gst_ffmpegaudenc_send_frame (GstFFMpegAudEnc * ffmpegaudenc, GstBuffer * buffer)
414 GstAudioEncoder *enc;
419 AVFrame *frame = ffmpegaudenc->frame;
423 enc = GST_AUDIO_ENCODER (ffmpegaudenc);
425 ctx = ffmpegaudenc->context;
427 if (buffer != NULL) {
428 BufferInfo *buffer_info = g_slice_new0 (BufferInfo);
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;
437 GST_LOG_OBJECT (ffmpegaudenc, "encoding buffer %p size:%u", audio_in,
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;
447 if (planar && info->channels > 1) {
451 nsamples = frame->nb_samples = in_size / info->bpf;
452 channels = info->channels;
455 av_buffer_create (NULL, 0, buffer_info_free, buffer_info, 0);
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 *));
461 frame->extended_data = frame->data;
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];
470 switch (info->finfo->width) {
472 const guint8 *idata = (const guint8 *) audio_in;
474 for (i = 0; i < nsamples; i++) {
475 for (j = 0; j < channels; j++) {
476 ((guint8 *) frame->extended_data[j])[i] = idata[j];
483 const guint16 *idata = (const guint16 *) audio_in;
485 for (i = 0; i < nsamples; i++) {
486 for (j = 0; j < channels; j++) {
487 ((guint16 *) frame->extended_data[j])[i] = idata[j];
494 const guint32 *idata = (const guint32 *) audio_in;
496 for (i = 0; i < nsamples; i++) {
497 for (j = 0; j < channels; j++) {
498 ((guint32 *) frame->extended_data[j])[i] = idata[j];
506 const guint64 *idata = (const guint64 *) audio_in;
508 for (i = 0; i < nsamples; i++) {
509 for (j = 0; j < channels; j++) {
510 ((guint64 *) frame->extended_data[j])[i] = idata[j];
518 g_assert_not_reached ();
522 gst_buffer_unmap (buffer, &buffer_info->map);
523 gst_buffer_unref (buffer);
524 buffer_info->buffer = NULL;
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;
531 av_buffer_create (NULL, 0, buffer_info_free, buffer_info, 0);
534 /* we have a frame to feed the encoder */
535 res = avcodec_send_frame (ctx, frame);
537 av_frame_unref (frame);
539 GstFFMpegAudEncClass *oclass =
540 (GstFFMpegAudEncClass *) G_OBJECT_GET_CLASS (ffmpegaudenc);
542 GST_LOG_OBJECT (ffmpegaudenc, "draining");
543 /* flushing the encoder */
544 res = avcodec_send_frame (ctx, NULL);
546 /* If AV_CODEC_CAP_ENCODER_FLUSH wasn't set, we need to re-open
548 if (!(oclass->in_plugin->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)) {
549 GST_DEBUG_OBJECT (ffmpegaudenc, "Encoder needs reopen later");
551 /* we will reopen later handle_frame() */
552 ffmpegaudenc->need_reopen = TRUE;
558 } else if (res == AVERROR_EOF) {
560 } else { /* Any other return value is an error in our context */
562 GST_WARNING_OBJECT (ffmpegaudenc, "Failed to encode buffer");
569 gst_ffmpegaudenc_receive_packet (GstFFMpegAudEnc * ffmpegaudenc,
570 gboolean * got_packet)
572 GstAudioEncoder *enc;
578 enc = GST_AUDIO_ENCODER (ffmpegaudenc);
580 ctx = ffmpegaudenc->context;
582 pkt = g_slice_new0 (AVPacket);
584 res = avcodec_receive_packet (ctx, pkt);
588 const uint8_t *side_data;
589 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58,130,0)
590 size_t side_data_length = 0;
592 int side_data_length = 0;
595 GST_LOG_OBJECT (ffmpegaudenc, "pushing size %d", pkt->size);
598 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, pkt->data,
599 pkt->size, 0, pkt->size, pkt, gst_ffmpegaudenc_free_avpacket);
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);
607 start = gst_byte_reader_get_uint32_le_unchecked (&reader);
608 end = gst_byte_reader_get_uint32_le_unchecked (&reader);
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,
617 gst_audio_encoder_finish_frame (enc, outbuf,
618 pkt->duration > 0 ? pkt->duration : -1);
621 GST_LOG_OBJECT (ffmpegaudenc, "no output produced");
622 g_slice_free (AVPacket, pkt);
631 gst_ffmpegaudenc_drain (GstFFMpegAudEnc * ffmpegaudenc)
633 GstFlowReturn ret = GST_FLOW_OK;
636 ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, NULL);
638 if (ret == GST_FLOW_OK) {
640 ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
641 if (ret != GST_FLOW_OK)
643 } while (got_packet);
646 /* NOTE: this may or may not work depending on capability */
647 avcodec_flush_buffers (ffmpegaudenc->context);
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)
661 gst_ffmpegaudenc_handle_frame (GstAudioEncoder * encoder, GstBuffer * inbuf)
663 GstFFMpegAudEnc *ffmpegaudenc;
667 ffmpegaudenc = (GstFFMpegAudEnc *) encoder;
669 if (G_UNLIKELY (!ffmpegaudenc->opened))
673 return gst_ffmpegaudenc_drain (ffmpegaudenc);
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");
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;
687 inbuf = gst_buffer_ref (inbuf);
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));
694 /* Reorder channels to the GStreamer channel order */
695 if (ffmpegaudenc->needs_reorder) {
696 GstAudioInfo *info = gst_audio_encoder_get_audio_info (encoder);
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);
703 ret = gst_ffmpegaudenc_send_frame (ffmpegaudenc, inbuf);
705 if (ret != GST_FLOW_OK)
706 goto send_frame_failed;
709 ret = gst_ffmpegaudenc_receive_packet (ffmpegaudenc, &got_packet);
710 } while (got_packet);
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;
724 GST_DEBUG_OBJECT (ffmpegaudenc, "Failed to send frame %d (%s)", ret,
725 gst_flow_get_name (ret));
731 gst_ffmpegaudenc_set_property (GObject * object,
732 guint prop_id, const GValue * value, GParamSpec * pspec)
734 GstFFMpegAudEnc *ffmpegaudenc;
736 ffmpegaudenc = (GstFFMpegAudEnc *) (object);
738 if (ffmpegaudenc->opened) {
739 GST_WARNING_OBJECT (ffmpegaudenc,
740 "Can't change properties once encoder is setup !");
746 if (!gst_ffmpeg_cfg_set_property (ffmpegaudenc->refcontext, value, pspec))
747 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
753 gst_ffmpegaudenc_get_property (GObject * object,
754 guint prop_id, GValue * value, GParamSpec * pspec)
756 GstFFMpegAudEnc *ffmpegaudenc;
758 ffmpegaudenc = (GstFFMpegAudEnc *) (object);
762 if (!gst_ffmpeg_cfg_get_property (ffmpegaudenc->refcontext, value, pspec))
763 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
769 gst_ffmpegaudenc_register (GstPlugin * plugin)
771 GTypeInfo typeinfo = {
772 sizeof (GstFFMpegAudEncClass),
773 (GBaseInitFunc) gst_ffmpegaudenc_base_init,
775 (GClassInitFunc) gst_ffmpegaudenc_class_init,
778 sizeof (GstFFMpegAudEnc),
780 (GInstanceInitFunc) gst_ffmpegaudenc_init,
787 GST_LOG ("Registering encoders");
789 while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
793 /* Skip non-AV codecs */
794 if (in_plugin->type != AVMEDIA_TYPE_AUDIO)
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)) {
805 #ifdef TIZEN_PRODUCT_TV
806 if (in_plugin->id != AV_CODEC_ID_AAC)
810 /* No encoders depending on external libraries (we don't build them, but
811 * people who build against an external ffmpeg might have them.
812 * We have native gstreamer plugins for all of those libraries anyway. */
813 if (!strncmp (in_plugin->name, "lib", 3)) {
815 ("Not using external library encoder %s. Use the gstreamer-native ones instead.",
821 if (!av_codec_is_encoder (in_plugin)) {
825 /* FIXME : We should have a method to know cheaply whether we have a mapping
826 * for the given plugin or not */
828 GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name);
830 /* no codecs for which we're GUARANTEED to have better alternatives */
831 if (!strcmp (in_plugin->name, "vorbis")
832 || !strcmp (in_plugin->name, "flac")) {
833 GST_LOG ("Ignoring encoder %s", in_plugin->name);
837 /* construct the type */
838 type_name = g_strdup_printf ("avenc_%s", in_plugin->name);
840 type = g_type_from_name (type_name);
844 /* create the glib type now */
846 g_type_register_static (GST_TYPE_AUDIO_ENCODER, type_name, &typeinfo,
848 g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin);
851 static const GInterfaceInfo preset_info = {
856 g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info);
860 switch (in_plugin->id) {
861 /* avenc_aac: see https://bugzilla.gnome.org/show_bug.cgi?id=691617 */
862 case AV_CODEC_ID_AAC:
863 #ifdef TIZEN_FEATURE_LIBAV
864 rank = GST_RANK_MARGINAL;
866 rank = GST_RANK_NONE;
870 rank = GST_RANK_SECONDARY;
874 if (!gst_element_register (plugin, type_name, rank, type)) {
882 GST_LOG ("Finished registering encoders");