35
39
#include "gstffmpeg.h"
36
40
#include "gstffmpegcodecmap.h"
41
#include "gstffmpegenc.h"
42
#include "gstffmpegcfg.h"
38
#define DEFAULT_VIDEO_BITRATE 300000 /* in bps */
44
#define DEFAULT_VIDEO_BITRATE 300000 /* in bps */
39
45
#define DEFAULT_VIDEO_GOP_SIZE 15
40
46
#define DEFAULT_AUDIO_BITRATE 128000
42
48
#define DEFAULT_WIDTH 352
43
49
#define DEFAULT_HEIGHT 288
45
typedef struct _GstFFMpegEnc GstFFMpegEnc;
51
/* We need to keep track of our pads, so we do so here. */
55
AVCodecContext *context;
65
gulong rtp_payload_size;
68
typedef struct _GstFFMpegEncClass GstFFMpegEncClass;
70
struct _GstFFMpegEncClass
72
GstElementClass parent_class;
75
GstPadTemplate *srctempl, *sinktempl;
82
GstCaps *srccaps, *sinkcaps;
83
} GstFFMpegEncClassParams;
85
#define GST_TYPE_FFMPEGENC \
86
(gst_ffmpegenc_get_type())
87
#define GST_FFMPEGENC(obj) \
88
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGENC,GstFFMpegEnc))
89
#define GST_FFMPEGENC_CLASS(klass) \
90
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGENC,GstFFMpegEncClass))
91
#define GST_IS_FFMPEGENC(obj) \
92
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGENC))
93
#define GST_IS_FFMPEGENC_CLASS(obj) \
94
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGENC))
96
52
#define VIDEO_BUFFER_SIZE (1024*1024)
142
98
static void gst_ffmpegenc_dispose (GObject * object);
144
100
static gboolean gst_ffmpegenc_setcaps (GstPad * pad, GstCaps * caps);
145
static GstCaps * gst_ffmpegenc_getcaps (GstPad * pad);
146
static GstFlowReturn gst_ffmpegenc_chain_video (GstPad * pad, GstBuffer *buffer);
147
static GstFlowReturn gst_ffmpegenc_chain_audio (GstPad * pad, GstBuffer *buffer);
101
static GstCaps *gst_ffmpegenc_getcaps (GstPad * pad);
102
static GstFlowReturn gst_ffmpegenc_chain_video (GstPad * pad,
104
static GstFlowReturn gst_ffmpegenc_chain_audio (GstPad * pad,
106
static gboolean gst_ffmpegenc_event_video (GstPad * pad, GstEvent * event);
149
108
static void gst_ffmpegenc_set_property (GObject * object,
150
109
guint prop_id, const GValue * value, GParamSpec * pspec);
221
180
if (klass->in_plugin->type == CODEC_TYPE_VIDEO) {
222
181
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BIT_RATE,
223
182
g_param_spec_ulong ("bitrate", "Bit Rate",
224
"Target Video Bitrate", 0, G_MAXULONG, DEFAULT_VIDEO_BITRATE, G_PARAM_READWRITE));
183
"Target Video Bitrate", 0, G_MAXULONG, DEFAULT_VIDEO_BITRATE,
225
185
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_GOP_SIZE,
226
186
g_param_spec_int ("gop_size", "GOP Size",
227
"Number of frames within one GOP",
228
0, G_MAXINT, DEFAULT_VIDEO_GOP_SIZE, G_PARAM_READWRITE));
187
"Number of frames within one GOP", 0, G_MAXINT,
188
DEFAULT_VIDEO_GOP_SIZE, G_PARAM_READWRITE));
229
189
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ME_METHOD,
230
g_param_spec_enum ("me_method", "ME Method",
231
"Motion Estimation Method",
232
GST_TYPE_ME_METHOD, ME_LOG, G_PARAM_READWRITE));
190
g_param_spec_enum ("me_method", "ME Method", "Motion Estimation Method",
191
GST_TYPE_ME_METHOD, ME_EPZS, G_PARAM_READWRITE));
233
192
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFSIZE,
234
193
g_param_spec_ulong ("buffer_size", "Buffer Size",
235
194
"Size of the video buffers", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
236
195
g_object_class_install_property (G_OBJECT_CLASS (klass),
237
ARG_RTP_PAYLOAD_SIZE,
238
g_param_spec_ulong ("rtp_payload_size", "RTP Payload Size",
239
"Target GOB length", 0, G_MAXULONG, 0, G_PARAM_READWRITE));
196
ARG_RTP_PAYLOAD_SIZE, g_param_spec_ulong ("rtp_payload_size",
197
"RTP Payload Size", "Target GOB length", 0, G_MAXULONG, 0,
200
/* register additional properties, possibly dependent on the exact CODEC */
201
gst_ffmpeg_cfg_install_property (klass, ARG_CFG_BASE);
240
202
} else if (klass->in_plugin->type == CODEC_TYPE_AUDIO) {
241
203
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BIT_RATE,
242
204
g_param_spec_ulong ("bitrate", "Bit Rate",
243
"Target Audio Bitrate", 0, G_MAXULONG, DEFAULT_AUDIO_BITRATE, G_PARAM_READWRITE));
205
"Target Audio Bitrate", 0, G_MAXULONG, DEFAULT_AUDIO_BITRATE,
246
209
gstelement_class->change_state = gst_ffmpegenc_change_state;
266
229
ffmpegenc->picture = avcodec_alloc_frame ();
267
230
ffmpegenc->opened = FALSE;
232
ffmpegenc->file = NULL;
233
ffmpegenc->delay = g_queue_new ();
269
235
if (oclass->in_plugin->type == CODEC_TYPE_VIDEO) {
270
236
gst_pad_set_chain_function (ffmpegenc->sinkpad, gst_ffmpegenc_chain_video);
237
/* so we know when to flush the buffers on EOS */
238
gst_pad_set_event_function (ffmpegenc->sinkpad, gst_ffmpegenc_event_video);
272
240
ffmpegenc->bitrate = DEFAULT_VIDEO_BITRATE;
241
ffmpegenc->me_method = ME_EPZS;
273
242
ffmpegenc->buffer_size = 512 * 1024;
274
243
ffmpegenc->gop_size = DEFAULT_VIDEO_GOP_SIZE;
275
244
ffmpegenc->rtp_payload_size = 0;
247
ffmpegenc->lmax = 31;
248
ffmpegenc->max_key_interval = 0;
250
gst_ffmpeg_cfg_set_defaults (ffmpegenc);
276
251
} else if (oclass->in_plugin->type == CODEC_TYPE_AUDIO) {
277
252
gst_pad_set_chain_function (ffmpegenc->sinkpad, gst_ffmpegenc_chain_audio);
336
314
/* makes it silent */
337
315
ctx->strict_std_compliance = -1;
339
/* shut up the logging while we autoprobe; we don't want warnings and
340
* errors about unsupported formats */
341
/* FIXME: if someone cares about this disabling the logging for other
342
* instances/threads/..., one could investigate if there is a way to
343
* set this as a struct member on the av context, and check it from the
317
/* shut up the logging while we autoprobe; we don't want warnings and
318
* errors about unsupported formats */
319
/* FIXME: if someone cares about this disabling the logging for other
320
* instances/threads/..., one could investigate if there is a way to
321
* set this as a struct member on the av context, and check it from the
345
323
#ifndef GST_DISABLE_GST_DEBUG
346
324
_shut_up_I_am_probing = TRUE;
348
326
for (pixfmt = 0; pixfmt < PIX_FMT_NB; pixfmt++) {
349
329
ctx->pix_fmt = pixfmt;
350
330
if (gst_ffmpeg_avcodec_open (ctx, oclass->in_plugin) >= 0 &&
351
331
ctx->pix_fmt == pixfmt) {
354
334
caps = gst_caps_new_empty ();
355
gst_caps_append (caps,
356
gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx));
335
tmpcaps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type, ctx);
337
gst_caps_append (caps, tmpcaps);
339
GST_LOG_OBJECT (ffmpegenc,
340
"Couldn't get caps for oclass->in_plugin->name:%s",
341
oclass->in_plugin->name);
357
342
gst_ffmpeg_avcodec_close (ctx);
359
344
if (ctx->priv_data)
402
387
ffmpegenc->context->bit_rate_tolerance = ffmpegenc->bitrate;
403
388
ffmpegenc->context->gop_size = ffmpegenc->gop_size;
404
389
ffmpegenc->context->me_method = ffmpegenc->me_method;
405
GST_DEBUG_OBJECT (ffmpegenc, "Setting avcontext with bitrate %d, gop_size %d",
390
GST_DEBUG_OBJECT (ffmpegenc, "Setting avcontext to bitrate %lu, gop_size %d",
406
391
ffmpegenc->bitrate, ffmpegenc->gop_size);
408
393
/* RTP payload used for GOB production (for Asterisk) */
409
394
if (ffmpegenc->rtp_payload_size) {
410
395
ffmpegenc->context->rtp_mode = 1;
411
396
ffmpegenc->context->rtp_payload_size = ffmpegenc->rtp_payload_size;
413
ffmpegenc->context->rtp_mode = 0;
414
ffmpegenc->context->rtp_payload_size = 512;
417
/* general properties */
418
ffmpegenc->context->qmin = 1;
419
ffmpegenc->context->qmax = 31;
420
ffmpegenc->context->max_qdiff = 15;
399
/* additional avcodec settings */
400
/* first fill in the majority by copying over */
401
gst_ffmpeg_cfg_fill_context (ffmpegenc, ffmpegenc->context);
403
/* then handle some special cases */
404
ffmpegenc->context->lmin = (ffmpegenc->lmin * FF_QP2LAMBDA + 0.5);
405
ffmpegenc->context->lmax = (ffmpegenc->lmax * FF_QP2LAMBDA + 0.5);
407
if (ffmpegenc->interlaced) {
408
ffmpegenc->context->flags |=
409
CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME;
410
ffmpegenc->picture->interlaced_frame = TRUE;
411
/* if this is not the case, a filter element should be used to swap fields */
412
ffmpegenc->picture->top_field_first = TRUE;
415
/* some other defaults */
416
ffmpegenc->context->rc_strategy = 2;
417
ffmpegenc->context->b_frame_strategy = 0;
418
ffmpegenc->context->coder_type = 0;
419
ffmpegenc->context->context_model = 0;
420
ffmpegenc->context->scenechange_threshold = 0;
421
ffmpegenc->context->inter_threshold = 0;
423
/* and last but not least the pass; CBR, 2-pass, etc */
424
ffmpegenc->context->flags |= ffmpegenc->pass;
425
switch (ffmpegenc->pass) {
426
/* some additional action depends on type of pass */
427
case CODEC_FLAG_QSCALE:
428
ffmpegenc->context->global_quality
429
= ffmpegenc->picture->quality = FF_QP2LAMBDA * ffmpegenc->quantizer;
431
case CODEC_FLAG_PASS1: /* need to prepare a stats file */
432
/* we don't close when changing caps, fingers crossed */
433
if (!ffmpegenc->file)
434
ffmpegenc->file = g_fopen (ffmpegenc->filename, "w");
435
if (!ffmpegenc->file) {
436
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, OPEN_WRITE,
437
(("Could not open file \"%s\" for writing."), ffmpegenc->filename),
442
case CODEC_FLAG_PASS2:
443
{ /* need to read the whole stats file ! */
446
if (!g_file_get_contents (ffmpegenc->filename,
447
&ffmpegenc->context->stats_in, &size, NULL)) {
448
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, READ,
449
(("Could not get contents of file \"%s\"."), ffmpegenc->filename),
422
460
/* fetch pix_fmt and so on */
423
461
gst_ffmpeg_caps_with_codectype (oclass->in_plugin->type,
425
463
if (!ffmpegenc->context->time_base.den) {
426
464
ffmpegenc->context->time_base.den = 25;
427
465
ffmpegenc->context->time_base.num = 1;
466
} else if ((oclass->in_plugin->id == CODEC_ID_MPEG4)
467
&& (ffmpegenc->context->time_base.den > 65535)) {
468
/* MPEG4 Standards do not support time_base denominator greater than
469
* (1<<16) - 1 . We therefore scale them down.
470
* Agreed, it will not be the exact framerate... but the difference
471
* shouldn't be that noticeable */
472
ffmpegenc->context->time_base.num =
473
(gint) gst_util_uint64_scale_int (ffmpegenc->context->time_base.num,
474
65535, ffmpegenc->context->time_base.den);
475
ffmpegenc->context->time_base.den = 65535;
476
GST_LOG_OBJECT (ffmpegenc, "MPEG4 : scaled down framerate to %d / %d",
477
ffmpegenc->context->time_base.den, ffmpegenc->context->time_base.num);
430
480
pix_fmt = ffmpegenc->context->pix_fmt;
482
/* max-key-interval may need the framerate set above */
483
if (ffmpegenc->max_key_interval) {
486
/* override gop-size */
487
ctx = ffmpegenc->context;
488
ctx->gop_size = (ffmpegenc->max_key_interval < 0) ?
489
(-ffmpegenc->max_key_interval
490
* (ctx->time_base.den / ctx->time_base.num))
491
: ffmpegenc->max_key_interval;
433
495
if (gst_ffmpeg_avcodec_open (ffmpegenc->context, oclass->in_plugin) < 0) {
434
496
if (ffmpegenc->context->priv_data)
435
497
gst_ffmpeg_avcodec_close (ffmpegenc->context);
498
if (ffmpegenc->context->stats_in)
499
g_free (ffmpegenc->context->stats_in);
436
500
GST_DEBUG_OBJECT (ffmpegenc, "ffenc_%s: Failed to open FFMPEG codec",
437
501
oclass->in_plugin->name);
505
/* second pass stats buffer no longer needed */
506
if (ffmpegenc->context->stats_in)
507
g_free (ffmpegenc->context->stats_in);
441
509
/* is the colourspace correct? */
442
510
if (pix_fmt != ffmpegenc->context->pix_fmt) {
443
511
gst_ffmpeg_avcodec_close (ffmpegenc->context);
444
GST_DEBUG_OBJECT (ffmpegenc, "ffenc_%s: AV wants different colourspace (%d given, %d wanted)",
512
GST_DEBUG_OBJECT (ffmpegenc,
513
"ffenc_%s: AV wants different colourspace (%d given, %d wanted)",
445
514
oclass->in_plugin->name, pix_fmt, ffmpegenc->context->pix_fmt);
453
522
GST_DEBUG_OBJECT (ffmpegenc, "... but no peer, using template caps");
454
523
/* we need to copy because get_allowed_caps returns a ref, and
455
524
* get_pad_template_caps doesn't */
456
allowed_caps = gst_caps_copy (
457
gst_pad_get_pad_template_caps (ffmpegenc->srcpad));
526
gst_caps_copy (gst_pad_get_pad_template_caps (ffmpegenc->srcpad));
459
528
GST_DEBUG_OBJECT (ffmpegenc, "chose caps %" GST_PTR_FORMAT, allowed_caps);
460
529
gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
523
590
ffmpegenc->picture->pts =
524
591
gst_ffmpeg_time_gst_to_ff (GST_BUFFER_TIMESTAMP (inbuf),
525
ffmpegenc->context->time_base);
592
ffmpegenc->context->time_base);
527
594
outbuf = gst_buffer_new_and_alloc (ffmpegenc->buffer_size);
528
595
ret_size = avcodec_encode_video (ffmpegenc->context,
529
GST_BUFFER_DATA (outbuf),
530
GST_BUFFER_SIZE (outbuf), ffmpegenc->picture);
596
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), ffmpegenc->picture);
532
598
if (ret_size < 0) {
599
#ifndef GST_DISABLE_GST_DEBUG
600
GstFFMpegEncClass *oclass =
601
(GstFFMpegEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc));
533
602
GST_ERROR_OBJECT (ffmpegenc,
534
603
"ffenc_%s: failed to encode buffer", oclass->in_plugin->name);
604
#endif /* GST_DISABLE_GST_DEBUG */
535
605
gst_buffer_unref (inbuf);
536
606
gst_buffer_unref (outbuf);
537
607
return GST_FLOW_OK;
610
/* handle b-frame delay when no output, so we don't output empty frames;
611
* timestamps and so can permute a bit between coding and display order
612
* but keyframes should still end up with the proper metadata */
613
g_queue_push_tail (ffmpegenc->delay, inbuf);
615
inbuf = g_queue_pop_head (ffmpegenc->delay);
619
/* save stats info if there is some as well as a stats file */
620
if (ffmpegenc->file && ffmpegenc->context->stats_out)
621
if (fprintf (ffmpegenc->file, "%s", ffmpegenc->context->stats_out) < 0)
622
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, WRITE,
623
(("Could not write to file \"%s\"."), ffmpegenc->filename),
540
626
GST_BUFFER_SIZE (outbuf) = ret_size;
541
627
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
542
628
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
732
gst_ffmpegenc_flush_buffers (GstFFMpegEnc * ffmpegenc, gboolean send)
734
GstBuffer *outbuf, *inbuf;
737
GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send);
739
/* no need to empty codec if there is none */
740
if (!ffmpegenc->opened)
743
while (!g_queue_is_empty (ffmpegenc->delay)) {
745
outbuf = gst_buffer_new_and_alloc (ffmpegenc->buffer_size);
746
ret_size = avcodec_encode_video (ffmpegenc->context,
747
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), NULL);
749
if (ret_size < 0) { /* there should be something, notify and give up */
750
#ifndef GST_DISABLE_GST_DEBUG
751
GstFFMpegEncClass *oclass =
752
(GstFFMpegEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc));
753
GST_WARNING_OBJECT (ffmpegenc,
754
"ffenc_%s: failed to flush buffer", oclass->in_plugin->name);
755
#endif /* GST_DISABLE_GST_DEBUG */
759
/* save stats info if there is some as well as a stats file */
760
if (ffmpegenc->file && ffmpegenc->context->stats_out)
761
if (fprintf (ffmpegenc->file, "%s", ffmpegenc->context->stats_out) < 0)
762
GST_ELEMENT_ERROR (ffmpegenc, RESOURCE, WRITE,
763
(("Could not write to file \"%s\"."), ffmpegenc->filename),
766
/* handle b-frame delay when no output, so we don't output empty frames */
767
inbuf = g_queue_pop_head (ffmpegenc->delay);
769
GST_BUFFER_SIZE (outbuf) = ret_size;
770
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
771
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
772
if (!ffmpegenc->context->coded_frame->key_frame)
773
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
774
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegenc->srcpad));
776
gst_buffer_unref (inbuf);
779
gst_pad_push (ffmpegenc->srcpad, outbuf);
781
gst_buffer_unref (outbuf);
786
/* make sure that we empty the queue, is still needed if we had to break */
787
while (!g_queue_is_empty (ffmpegenc->delay))
788
gst_buffer_unref (g_queue_pop_head (ffmpegenc->delay));
793
gst_ffmpegenc_event_video (GstPad * pad, GstEvent * event)
795
GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) (GST_PAD_PARENT (pad));
797
switch (GST_EVENT_TYPE (event)) {
799
gst_ffmpegenc_flush_buffers (ffmpegenc, TRUE);
801
/* no flushing if flush received,
802
* buffers in encoder are considered (in the) past */
807
return gst_pad_push_event (ffmpegenc->srcpad, event);
647
811
gst_ffmpegenc_set_property (GObject * object,
648
812
guint prop_id, const GValue * value, GParamSpec * pspec)
780
954
if (!gst_ffmpeg_get_codecid_longname (in_plugin->id)) {
781
g_warning ("Add encoder %s (%d) please",
782
in_plugin->name, in_plugin->id);
955
GST_INFO ("Add encoder %s (%d) please", in_plugin->name, in_plugin->id);
786
959
/* first make sure we've got a supported type */
787
960
srccaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, TRUE);
788
961
if (in_plugin->type == CODEC_TYPE_VIDEO) {
789
sinkcaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
964
("video/x-raw-rgb; video/x-raw-yuv; video/x-raw-gray");
791
966
sinkcaps = gst_ffmpeg_codectype_to_caps (in_plugin->type, NULL);