mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-19 08:11:16 +00:00
ext/ffmpeg/gstffmpeg.c: Enable muxers (only mp4 muxer for now).
Original commit message from CVS: * ext/ffmpeg/gstffmpeg.c: (plugin_init): Enable muxers (only mp4 muxer for now). * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_formatid_get_codecids), (gst_ffmpeg_caps_to_codecid): * ext/ffmpeg/gstffmpegcodecmap.h: Fix a bunch of typos in codec-id lookup (false/true return value mixup), add a codec-id list retrieval function (because ffmpeg does not provide one). With that, we can make valid pad templates. * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_init), (gst_ffmpegmux_connect), (gst_ffmpegmux_loop), (gst_ffmpegmux_change_state), (gst_ffmpegmux_get_id_caps), (gst_ffmpegmux_register): Fix for whatever changed since I last tried this. Works for MP4 muxing. * ext/ffmpeg/gstffmpegprotocol.c: (gst_ffmpegdata_open), (gst_ffmpegdata_peek), (gst_ffmpegdata_write), (gst_ffmpegdata_seek), (gst_ffmpegdata_close): Update obviously-untested write code...
This commit is contained in:
parent
35bb7be72c
commit
c74a433d1d
6 changed files with 195 additions and 52 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
2005-03-14 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
|
* ext/ffmpeg/gstffmpeg.c: (plugin_init):
|
||||||
|
Enable muxers (only mp4 muxer for now).
|
||||||
|
* ext/ffmpeg/gstffmpegcodecmap.c:
|
||||||
|
(gst_ffmpeg_formatid_get_codecids), (gst_ffmpeg_caps_to_codecid):
|
||||||
|
* ext/ffmpeg/gstffmpegcodecmap.h:
|
||||||
|
Fix a bunch of typos in codec-id lookup (false/true return value
|
||||||
|
mixup), add a codec-id list retrieval function (because ffmpeg
|
||||||
|
does not provide one). With that, we can make valid pad templates.
|
||||||
|
* ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_init),
|
||||||
|
(gst_ffmpegmux_connect), (gst_ffmpegmux_loop),
|
||||||
|
(gst_ffmpegmux_change_state), (gst_ffmpegmux_get_id_caps),
|
||||||
|
(gst_ffmpegmux_register):
|
||||||
|
Fix for whatever changed since I last tried this. Works for MP4
|
||||||
|
muxing.
|
||||||
|
* ext/ffmpeg/gstffmpegprotocol.c: (gst_ffmpegdata_open),
|
||||||
|
(gst_ffmpegdata_peek), (gst_ffmpegdata_write),
|
||||||
|
(gst_ffmpegdata_seek), (gst_ffmpegdata_close):
|
||||||
|
Update obviously-untested write code...
|
||||||
|
|
||||||
2005-03-13 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
2005-03-13 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
* ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_chain_video):
|
* ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_chain_video):
|
||||||
|
|
|
@ -80,7 +80,7 @@ plugin_init (GstPlugin * plugin)
|
||||||
gst_ffmpegenc_register (plugin);
|
gst_ffmpegenc_register (plugin);
|
||||||
gst_ffmpegdec_register (plugin);
|
gst_ffmpegdec_register (plugin);
|
||||||
gst_ffmpegdemux_register (plugin);
|
gst_ffmpegdemux_register (plugin);
|
||||||
/*gst_ffmpegmux_register (plugin); */
|
gst_ffmpegmux_register (plugin);
|
||||||
gst_ffmpegcsp_register (plugin);
|
gst_ffmpegcsp_register (plugin);
|
||||||
|
|
||||||
register_protocol (&gstreamer_protocol);
|
register_protocol (&gstreamer_protocol);
|
||||||
|
|
|
@ -107,6 +107,8 @@ gst_ffmpeg_set_palette (GstCaps *caps, AVCodecContext *context)
|
||||||
__VA_ARGS__, NULL) \
|
__VA_ARGS__, NULL) \
|
||||||
: \
|
: \
|
||||||
gst_caps_new_simple (mimetype, \
|
gst_caps_new_simple (mimetype, \
|
||||||
|
"rate", GST_TYPE_INT_RANGE, 8000, 96000, \
|
||||||
|
"channels", GST_TYPE_INT_RANGE, 1, 2, \
|
||||||
__VA_ARGS__, NULL)
|
__VA_ARGS__, NULL)
|
||||||
|
|
||||||
/* Convert a FFMPEG codec ID and optional AVCodecContext
|
/* Convert a FFMPEG codec ID and optional AVCodecContext
|
||||||
|
@ -1325,6 +1327,24 @@ gst_ffmpeg_formatid_to_caps (const gchar * format_name)
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_ffmpeg_formatid_get_codecids (const gchar *format_name,
|
||||||
|
enum CodecID ** video_codec_list, enum CodecID ** audio_codec_list)
|
||||||
|
{
|
||||||
|
if (!strcmp (format_name, "mp4")) {
|
||||||
|
static enum CodecID mp4_video_list[] = { CODEC_ID_MPEG4, CODEC_ID_NONE };
|
||||||
|
static enum CodecID mp4_audio_list[] = { CODEC_ID_AAC, CODEC_ID_NONE };
|
||||||
|
|
||||||
|
*video_codec_list = mp4_video_list;
|
||||||
|
*audio_codec_list = mp4_audio_list;
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("Format %s not found", format_name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert a GstCaps to a FFMPEG codec ID. Size et all
|
/* Convert a GstCaps to a FFMPEG codec ID. Size et all
|
||||||
* are omitted, that can be queried by the user itself,
|
* are omitted, that can be queried by the user itself,
|
||||||
* we're not eating the GstCaps or anything
|
* we're not eating the GstCaps or anything
|
||||||
|
@ -1398,7 +1418,7 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context)
|
||||||
} else if (!strcmp (mimetype, "video/x-dv")) {
|
} else if (!strcmp (mimetype, "video/x-dv")) {
|
||||||
gboolean sys_strm;
|
gboolean sys_strm;
|
||||||
|
|
||||||
if (!gst_structure_get_boolean (structure, "systemstream", &sys_strm) &&
|
if (gst_structure_get_boolean (structure, "systemstream", &sys_strm) &&
|
||||||
!sys_strm) {
|
!sys_strm) {
|
||||||
id = CODEC_ID_DVVIDEO;
|
id = CODEC_ID_DVVIDEO;
|
||||||
video = TRUE;
|
video = TRUE;
|
||||||
|
@ -1419,8 +1439,8 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context)
|
||||||
gboolean sys_strm;
|
gboolean sys_strm;
|
||||||
gint mpegversion;
|
gint mpegversion;
|
||||||
|
|
||||||
if (!gst_structure_get_boolean (structure, "systemstream", &sys_strm) &&
|
if (gst_structure_get_boolean (structure, "systemstream", &sys_strm) &&
|
||||||
!gst_structure_get_int (structure, "mpegversion", &mpegversion) &&
|
gst_structure_get_int (structure, "mpegversion", &mpegversion) &&
|
||||||
!sys_strm) {
|
!sys_strm) {
|
||||||
switch (mpegversion) {
|
switch (mpegversion) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1468,7 +1488,7 @@ gst_ffmpeg_caps_to_codecid (const GstCaps * caps, AVCodecContext * context)
|
||||||
switch (mpegversion) {
|
switch (mpegversion) {
|
||||||
case 2: /* ffmpeg uses faad for both... */
|
case 2: /* ffmpeg uses faad for both... */
|
||||||
case 4:
|
case 4:
|
||||||
id = CODEC_ID_MPEG4AAC;
|
id = CODEC_ID_AAC;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (gst_structure_get_int (structure, "layer", &layer)) {
|
if (gst_structure_get_int (structure, "layer", &layer)) {
|
||||||
|
|
|
@ -87,6 +87,17 @@ gst_ffmpeg_caps_with_codectype (enum CodecType type,
|
||||||
GstCaps *
|
GstCaps *
|
||||||
gst_ffmpeg_formatid_to_caps (const gchar *format_name);
|
gst_ffmpeg_formatid_to_caps (const gchar *format_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _formatid_get_codecids () can be used to get the codecIDs
|
||||||
|
* (CODEC_ID_NONE-terminated list) that fit that specific
|
||||||
|
* output format.
|
||||||
|
*/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_ffmpeg_formatid_get_codecids (const gchar *format_name,
|
||||||
|
enum CodecID ** video_codec_list,
|
||||||
|
enum CodecID ** audio_codec_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since FFMpeg has such really cool and useful descriptions
|
* Since FFMpeg has such really cool and useful descriptions
|
||||||
* of its codecs, we use our own...
|
* of its codecs, we use our own...
|
||||||
|
@ -118,7 +129,8 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt,
|
gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt,
|
||||||
const AVPicture * src, int src_pix_fmt, int src_width, int src_height);
|
const AVPicture * src, int src_pix_fmt,
|
||||||
|
int src_width, int src_height);
|
||||||
|
|
||||||
#endif /* __GST_FFMPEG_CODECMAP_H__ */
|
#endif /* __GST_FFMPEG_CODECMAP_H__ */
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@ struct _GstFFMpegMux
|
||||||
AVFormatContext *context;
|
AVFormatContext *context;
|
||||||
gboolean opened;
|
gboolean opened;
|
||||||
|
|
||||||
|
GstTagList *tags;
|
||||||
|
|
||||||
GstPad *sinkpads[MAX_STREAMS];
|
GstPad *sinkpads[MAX_STREAMS];
|
||||||
gint videopads, audiopads;
|
gint videopads, audiopads;
|
||||||
GstBuffer *bufferqueue[MAX_STREAMS];
|
GstBuffer *bufferqueue[MAX_STREAMS];
|
||||||
|
@ -189,6 +191,8 @@ gst_ffmpegmux_init (GstFFMpegMux * ffmpegmux)
|
||||||
|
|
||||||
ffmpegmux->videopads = 0;
|
ffmpegmux->videopads = 0;
|
||||||
ffmpegmux->audiopads = 0;
|
ffmpegmux->audiopads = 0;
|
||||||
|
|
||||||
|
ffmpegmux->tags = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -269,7 +273,6 @@ gst_ffmpegmux_connect (GstPad * pad, const GstCaps * caps)
|
||||||
|
|
||||||
/*g_return_val_if_fail (ffmpegmux->opened == FALSE,
|
/*g_return_val_if_fail (ffmpegmux->opened == FALSE,
|
||||||
GST_PAD_LINK_REFUSED); */
|
GST_PAD_LINK_REFUSED); */
|
||||||
|
|
||||||
for (i = 0; i < ffmpegmux->context->nb_streams; i++) {
|
for (i = 0; i < ffmpegmux->context->nb_streams; i++) {
|
||||||
if (pad == ffmpegmux->sinkpads[i]) {
|
if (pad == ffmpegmux->sinkpads[i]) {
|
||||||
break;
|
break;
|
||||||
|
@ -318,6 +321,16 @@ gst_ffmpegmux_loop (GstElement * element)
|
||||||
ffmpegmux->eos[i] = TRUE;
|
ffmpegmux->eos[i] = TRUE;
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_TAG:
|
||||||
|
if (ffmpegmux->tags) {
|
||||||
|
gst_tag_list_insert (ffmpegmux->tags,
|
||||||
|
gst_event_tag_get_list (event), GST_TAG_MERGE_PREPEND);
|
||||||
|
} else {
|
||||||
|
ffmpegmux->tags =
|
||||||
|
gst_tag_list_copy (gst_event_tag_get_list (event));
|
||||||
|
}
|
||||||
|
gst_event_unref (event);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
break;
|
break;
|
||||||
|
@ -330,6 +343,8 @@ gst_ffmpegmux_loop (GstElement * element)
|
||||||
|
|
||||||
/* open "file" (gstreamer protocol to next element) */
|
/* open "file" (gstreamer protocol to next element) */
|
||||||
if (!ffmpegmux->opened) {
|
if (!ffmpegmux->opened) {
|
||||||
|
const GstTagList *iface_tags;
|
||||||
|
|
||||||
/* we do need all streams to have started capsnego,
|
/* we do need all streams to have started capsnego,
|
||||||
* or things will go horribly wrong */
|
* or things will go horribly wrong */
|
||||||
for (i = 0; i < ffmpegmux->context->nb_streams; i++) {
|
for (i = 0; i < ffmpegmux->context->nb_streams; i++) {
|
||||||
|
@ -343,6 +358,58 @@ gst_ffmpegmux_loop (GstElement * element)
|
||||||
"video" : "audio"));
|
"video" : "audio"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
|
||||||
|
st->codec.frame_size =
|
||||||
|
st->codec.sample_rate *
|
||||||
|
GST_BUFFER_DURATION (ffmpegmux->bufferqueue[i]) / GST_SECOND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tags */
|
||||||
|
iface_tags = gst_tag_setter_get_list (GST_TAG_SETTER (ffmpegmux));
|
||||||
|
if (ffmpegmux->tags || iface_tags) {
|
||||||
|
GstTagList *tags;
|
||||||
|
gint i;
|
||||||
|
gchar *s;
|
||||||
|
|
||||||
|
if (iface_tags && ffmpegmux->tags) {
|
||||||
|
gst_tag_list_merge (iface_tags, ffmpegmux->tags,
|
||||||
|
GST_TAG_MERGE_APPEND);
|
||||||
|
} else if (iface_tags) {
|
||||||
|
tags = gst_tag_list_copy (iface_tags);
|
||||||
|
} else {
|
||||||
|
tags = gst_tag_list_copy (ffmpegmux->tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the interesting ones */
|
||||||
|
if (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s)) {
|
||||||
|
strncpy (ffmpegmux->context->title, s,
|
||||||
|
sizeof (ffmpegmux->context->title));
|
||||||
|
}
|
||||||
|
if (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s)) {
|
||||||
|
strncpy (ffmpegmux->context->author, s,
|
||||||
|
sizeof (ffmpegmux->context->author));
|
||||||
|
}
|
||||||
|
if (gst_tag_list_get_string (tags, GST_TAG_COPYRIGHT, &s)) {
|
||||||
|
strncpy (ffmpegmux->context->copyright, s,
|
||||||
|
sizeof (ffmpegmux->context->copyright));
|
||||||
|
}
|
||||||
|
if (gst_tag_list_get_string (tags, GST_TAG_COMMENT, &s)) {
|
||||||
|
strncpy (ffmpegmux->context->comment, s,
|
||||||
|
sizeof (ffmpegmux->context->comment));
|
||||||
|
}
|
||||||
|
if (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s)) {
|
||||||
|
strncpy (ffmpegmux->context->album, s,
|
||||||
|
sizeof (ffmpegmux->context->album));
|
||||||
|
}
|
||||||
|
if (gst_tag_list_get_string (tags, GST_TAG_GENRE, &s)) {
|
||||||
|
strncpy (ffmpegmux->context->genre, s,
|
||||||
|
sizeof (ffmpegmux->context->genre));
|
||||||
|
}
|
||||||
|
if (gst_tag_list_get_uint (tags, GST_TAG_TRACK_NUMBER, &i)) {
|
||||||
|
ffmpegmux->context->track = i;
|
||||||
|
}
|
||||||
|
gst_tag_list_free (tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url_fopen (&ffmpegmux->context->pb,
|
if (url_fopen (&ffmpegmux->context->pb,
|
||||||
|
@ -352,7 +419,7 @@ gst_ffmpegmux_loop (GstElement * element)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av_set_parameters (ffmpegmux->context, NULL)) {
|
if (av_set_parameters (ffmpegmux->context, NULL) < 0) {
|
||||||
GST_ELEMENT_ERROR (element, LIBRARY, INIT, (NULL),
|
GST_ELEMENT_ERROR (element, LIBRARY, INIT, (NULL),
|
||||||
("Failed to initialize muxer"));
|
("Failed to initialize muxer"));
|
||||||
return;
|
return;
|
||||||
|
@ -362,7 +429,11 @@ gst_ffmpegmux_loop (GstElement * element)
|
||||||
ffmpegmux->opened = TRUE;
|
ffmpegmux->opened = TRUE;
|
||||||
|
|
||||||
/* now open the mux format */
|
/* now open the mux format */
|
||||||
av_write_header (ffmpegmux->context);
|
if (av_write_header (ffmpegmux->context) < 0) {
|
||||||
|
GST_ELEMENT_ERROR (element, LIBRARY, SETTINGS, (NULL),
|
||||||
|
("Failed to write file header - check codec settings"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* take the one with earliest timestamp,
|
/* take the one with earliest timestamp,
|
||||||
|
@ -401,6 +472,7 @@ gst_ffmpegmux_loop (GstElement * element)
|
||||||
|
|
||||||
/* set time */
|
/* set time */
|
||||||
pkt.pts = GST_BUFFER_TIMESTAMP (buf) * AV_TIME_BASE / GST_SECOND;
|
pkt.pts = GST_BUFFER_TIMESTAMP (buf) * AV_TIME_BASE / GST_SECOND;
|
||||||
|
pkt.dts = pkt.pts;
|
||||||
pkt.data = GST_BUFFER_DATA (buf);
|
pkt.data = GST_BUFFER_DATA (buf);
|
||||||
pkt.size = GST_BUFFER_SIZE (buf);
|
pkt.size = GST_BUFFER_SIZE (buf);
|
||||||
pkt.stream_index = bufnum;
|
pkt.stream_index = bufnum;
|
||||||
|
@ -430,6 +502,10 @@ gst_ffmpegmux_change_state (GstElement * element)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
|
if (ffmpegmux->tags) {
|
||||||
|
gst_tag_list_free (ffmpegmux->tags);
|
||||||
|
ffmpegmux->tags = NULL;
|
||||||
|
}
|
||||||
if (ffmpegmux->opened) {
|
if (ffmpegmux->opened) {
|
||||||
url_fclose (&ffmpegmux->context->pb);
|
url_fclose (&ffmpegmux->context->pb);
|
||||||
ffmpegmux->opened = FALSE;
|
ffmpegmux->opened = FALSE;
|
||||||
|
@ -443,6 +519,20 @@ gst_ffmpegmux_change_state (GstElement * element)
|
||||||
return GST_STATE_SUCCESS;
|
return GST_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_ffmpegmux_get_id_caps (enum CodecID * id_list)
|
||||||
|
{
|
||||||
|
GstCaps *caps, *t;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
caps = gst_caps_new_empty ();
|
||||||
|
for (i = 0; id_list[i] != CODEC_ID_NONE; i++) {
|
||||||
|
if ((t = gst_ffmpeg_codecid_to_caps (id_list[i], NULL, TRUE)))
|
||||||
|
gst_caps_append (caps, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_ffmpegmux_register (GstPlugin * plugin)
|
gst_ffmpegmux_register (GstPlugin * plugin)
|
||||||
|
@ -458,6 +548,9 @@ gst_ffmpegmux_register (GstPlugin * plugin)
|
||||||
0,
|
0,
|
||||||
(GInstanceInitFunc) gst_ffmpegmux_init,
|
(GInstanceInitFunc) gst_ffmpegmux_init,
|
||||||
};
|
};
|
||||||
|
static const GInterfaceInfo tag_setter_info = {
|
||||||
|
NULL, NULL, NULL
|
||||||
|
};
|
||||||
GType type;
|
GType type;
|
||||||
AVOutputFormat *in_plugin;
|
AVOutputFormat *in_plugin;
|
||||||
GstFFMpegMuxClassParams *params;
|
GstFFMpegMuxClassParams *params;
|
||||||
|
@ -471,35 +564,20 @@ gst_ffmpegmux_register (GstPlugin * plugin)
|
||||||
gchar *type_name;
|
gchar *type_name;
|
||||||
gchar *p;
|
gchar *p;
|
||||||
GstCaps *srccaps, *audiosinkcaps, *videosinkcaps;
|
GstCaps *srccaps, *audiosinkcaps, *videosinkcaps;
|
||||||
|
enum CodecID *video_ids = NULL, *audio_ids = NULL;
|
||||||
|
|
||||||
/* Try to find the caps that belongs here */
|
/* Try to find the caps that belongs here */
|
||||||
srccaps = gst_ffmpeg_formatid_to_caps (in_plugin->name);
|
srccaps = gst_ffmpeg_formatid_to_caps (in_plugin->name);
|
||||||
if (!srccaps) {
|
if (!srccaps) {
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
/* This is a bit ugly, but we just take all formats
|
if (!gst_ffmpeg_formatid_get_codecids (in_plugin->name,
|
||||||
* for the pad template. We'll get an exact match
|
&video_ids, &audio_ids)) {
|
||||||
* when we open the stream */
|
gst_caps_free (srccaps);
|
||||||
audiosinkcaps = gst_caps_new_empty ();
|
goto next;
|
||||||
videosinkcaps = gst_caps_new_empty ();
|
|
||||||
for (in_codec = first_avcodec; in_codec != NULL; in_codec = in_codec->next) {
|
|
||||||
GstCaps *temp = gst_ffmpeg_codecid_to_caps (in_codec->id, NULL, TRUE);
|
|
||||||
|
|
||||||
if (!temp) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (in_codec->type) {
|
|
||||||
case CODEC_TYPE_VIDEO:
|
|
||||||
gst_caps_append (videosinkcaps, temp);
|
|
||||||
break;
|
|
||||||
case CODEC_TYPE_AUDIO:
|
|
||||||
gst_caps_append (audiosinkcaps, temp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
gst_caps_free (temp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
videosinkcaps = video_ids ? gst_ffmpegmux_get_id_caps (video_ids) : NULL;
|
||||||
|
audiosinkcaps = audio_ids ? gst_ffmpegmux_get_id_caps (audio_ids) : NULL;
|
||||||
|
|
||||||
/* construct the type */
|
/* construct the type */
|
||||||
type_name = g_strdup_printf ("ffmux_%s", in_plugin->name);
|
type_name = g_strdup_printf ("ffmux_%s", in_plugin->name);
|
||||||
|
@ -515,6 +593,11 @@ gst_ffmpegmux_register (GstPlugin * plugin)
|
||||||
/* if it's already registered, drop it */
|
/* if it's already registered, drop it */
|
||||||
if (g_type_from_name (type_name)) {
|
if (g_type_from_name (type_name)) {
|
||||||
g_free (type_name);
|
g_free (type_name);
|
||||||
|
gst_caps_free (srccaps);
|
||||||
|
if (audiosinkcaps)
|
||||||
|
gst_caps_free (audiosinkcaps);
|
||||||
|
if (videosinkcaps)
|
||||||
|
gst_caps_free (videosinkcaps);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,8 +613,15 @@ gst_ffmpegmux_register (GstPlugin * plugin)
|
||||||
|
|
||||||
/* create the type now */
|
/* create the type now */
|
||||||
type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
|
type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
|
||||||
|
g_type_add_interface_static (type, GST_TYPE_TAG_SETTER,
|
||||||
|
&tag_setter_info);
|
||||||
if (!gst_element_register (plugin, type_name, GST_RANK_NONE, type)) {
|
if (!gst_element_register (plugin, type_name, GST_RANK_NONE, type)) {
|
||||||
g_free (type_name);
|
g_free (type_name);
|
||||||
|
gst_caps_free (srccaps);
|
||||||
|
if (audiosinkcaps)
|
||||||
|
gst_caps_free (audiosinkcaps);
|
||||||
|
if (videosinkcaps)
|
||||||
|
gst_caps_free (videosinkcaps);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ struct _GstProtocolInfo
|
||||||
{
|
{
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
|
|
||||||
int flags;
|
|
||||||
GstByteStream *bs;
|
GstByteStream *bs;
|
||||||
gboolean eos;
|
gboolean eos;
|
||||||
};
|
};
|
||||||
|
@ -53,7 +52,6 @@ gst_ffmpegdata_open (URLContext * h, const char *filename, int flags)
|
||||||
GST_LOG ("Opening %s", filename);
|
GST_LOG ("Opening %s", filename);
|
||||||
|
|
||||||
info = g_new0 (GstProtocolInfo, 1);
|
info = g_new0 (GstProtocolInfo, 1);
|
||||||
info->flags = flags;
|
|
||||||
|
|
||||||
/* we don't support R/W together */
|
/* we don't support R/W together */
|
||||||
if (flags != URL_RDONLY && flags != URL_WRONLY) {
|
if (flags != URL_RDONLY && flags != URL_WRONLY) {
|
||||||
|
@ -85,7 +83,6 @@ gst_ffmpegdata_open (URLContext * h, const char *filename, int flags)
|
||||||
|
|
||||||
h->priv_data = (void *) info;
|
h->priv_data = (void *) info;
|
||||||
h->is_streamed = FALSE;
|
h->is_streamed = FALSE;
|
||||||
h->flags = 0;
|
|
||||||
h->max_packet_size = 0;
|
h->max_packet_size = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -102,7 +99,7 @@ gst_ffmpegdata_peek (URLContext * h, unsigned char *buf, int size)
|
||||||
|
|
||||||
info = (GstProtocolInfo *) h->priv_data;
|
info = (GstProtocolInfo *) h->priv_data;
|
||||||
|
|
||||||
g_return_val_if_fail (info->flags == URL_RDONLY, AVERROR_IO);
|
g_return_val_if_fail (h->flags == URL_RDONLY, AVERROR_IO);
|
||||||
|
|
||||||
bs = info->bs;
|
bs = info->bs;
|
||||||
|
|
||||||
|
@ -202,7 +199,7 @@ gst_ffmpegdata_write (URLContext * h, unsigned char *buf, int size)
|
||||||
|
|
||||||
info = (GstProtocolInfo *) h->priv_data;
|
info = (GstProtocolInfo *) h->priv_data;
|
||||||
|
|
||||||
g_return_val_if_fail (info->flags == URL_WRONLY, -EIO);
|
g_return_val_if_fail (h->flags == URL_WRONLY, -EIO);
|
||||||
|
|
||||||
/* create buffer and push data further */
|
/* create buffer and push data further */
|
||||||
outbuf = gst_buffer_new_and_alloc (size);
|
outbuf = gst_buffer_new_and_alloc (size);
|
||||||
|
@ -225,20 +222,22 @@ gst_ffmpegdata_seek (URLContext * h, offset_t pos, int whence)
|
||||||
|
|
||||||
info = (GstProtocolInfo *) h->priv_data;
|
info = (GstProtocolInfo *) h->priv_data;
|
||||||
|
|
||||||
/* get data (typefind hack) */
|
if (h->flags == URL_RDONLY) {
|
||||||
if (gst_bytestream_tell (info->bs) != gst_bytestream_length (info->bs)) {
|
/* get data (typefind hack) */
|
||||||
gchar buf;
|
if (gst_bytestream_tell (info->bs) != gst_bytestream_length (info->bs)) {
|
||||||
gst_ffmpegdata_peek (h, &buf, 1);
|
gchar buf;
|
||||||
}
|
gst_ffmpegdata_peek (h, &buf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* hack in ffmpeg to get filesize... */
|
/* hack in ffmpeg to get filesize... */
|
||||||
if (whence == SEEK_END && pos == -1)
|
if (whence == SEEK_END && pos == -1)
|
||||||
return gst_bytestream_length (info->bs) - 1;
|
return gst_bytestream_length (info->bs) - 1;
|
||||||
else if (whence == SEEK_END && pos == 0)
|
else if (whence == SEEK_END && pos == 0)
|
||||||
return gst_bytestream_length (info->bs);
|
return gst_bytestream_length (info->bs);
|
||||||
/* another hack to get the current position... */
|
/* another hack to get the current position... */
|
||||||
else if (whence == SEEK_CUR && pos == 0)
|
else if (whence == SEEK_CUR && pos == 0)
|
||||||
return gst_bytestream_tell (info->bs);
|
return gst_bytestream_tell (info->bs);
|
||||||
|
}
|
||||||
|
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
|
@ -255,7 +254,7 @@ gst_ffmpegdata_seek (URLContext * h, offset_t pos, int whence)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (info->flags) {
|
switch (h->flags) {
|
||||||
case URL_RDONLY: {
|
case URL_RDONLY: {
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
|
@ -303,7 +302,8 @@ gst_ffmpegdata_seek (URLContext * h, offset_t pos, int whence)
|
||||||
}
|
}
|
||||||
|
|
||||||
case URL_WRONLY:
|
case URL_WRONLY:
|
||||||
gst_pad_push (info->pad, GST_DATA (gst_event_new_seek (seek_type, pos)));
|
gst_pad_push (info->pad,
|
||||||
|
GST_DATA (gst_event_new_seek (seek_type | GST_FORMAT_BYTES, pos)));
|
||||||
/* this is screwy because there might be queues or scheduler-queued
|
/* this is screwy because there might be queues or scheduler-queued
|
||||||
* buffers... Argh! */
|
* buffers... Argh! */
|
||||||
if (whence == SEEK_SET) {
|
if (whence == SEEK_SET) {
|
||||||
|
@ -331,7 +331,7 @@ gst_ffmpegdata_close (URLContext * h)
|
||||||
|
|
||||||
GST_LOG ("Closing file");
|
GST_LOG ("Closing file");
|
||||||
|
|
||||||
switch (info->flags) {
|
switch (h->flags) {
|
||||||
case URL_WRONLY:{
|
case URL_WRONLY:{
|
||||||
/* send EOS - that closes down the stream */
|
/* send EOS - that closes down the stream */
|
||||||
GstEvent *event = gst_event_new (GST_EVENT_EOS);
|
GstEvent *event = gst_event_new (GST_EVENT_EOS);
|
||||||
|
|
Loading…
Reference in a new issue