mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
More ffmpeg wrapping going on here
Original commit message from CVS: More ffmpeg wrapping going on here
This commit is contained in:
parent
4996d4c7d2
commit
ba9ed9b9e4
7 changed files with 318 additions and 97 deletions
|
@ -3,12 +3,13 @@ plugindir = $(libdir)/gst
|
||||||
plugin_LTLIBRARIES = libgstffmpeg.la
|
plugin_LTLIBRARIES = libgstffmpeg.la
|
||||||
|
|
||||||
libgstffmpeg_la_SOURCES = gstffmpeg.c \
|
libgstffmpeg_la_SOURCES = gstffmpeg.c \
|
||||||
gstffmpegenc.c \
|
gstffmpegcodecmap.c \
|
||||||
gstffmpegdec.c \
|
gstffmpegdec.c \
|
||||||
gstffmpegdemux.c \
|
gstffmpegdemux.c \
|
||||||
|
gstffmpegenc.c \
|
||||||
gstffmpegmux.c \
|
gstffmpegmux.c \
|
||||||
gstffmpegprotocol.c \
|
gstffmpegprotocol.c \
|
||||||
gstffmpegcodecmap.c
|
gstffmpegtypes.c
|
||||||
|
|
||||||
libgstffmpeg_la_CFLAGS = $(GST_CFLAGS) -I/opt/src/sourceforge/ffmpeg/ -I/opt/src/sourceforge/ffmpeg/libavcodec/
|
libgstffmpeg_la_CFLAGS = $(GST_CFLAGS) -I/opt/src/sourceforge/ffmpeg/ -I/opt/src/sourceforge/ffmpeg/libavcodec/
|
||||||
libgstffmpeg_la_LIBADD =
|
libgstffmpeg_la_LIBADD =
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
extern gboolean gst_ffmpegdemux_register (GstPlugin *plugin);
|
extern gboolean gst_ffmpegdemux_register (GstPlugin *plugin);
|
||||||
extern gboolean gst_ffmpegdec_register (GstPlugin *plugin);
|
extern gboolean gst_ffmpegdec_register (GstPlugin *plugin);
|
||||||
extern gboolean gst_ffmpegenc_register (GstPlugin *plugin);
|
extern gboolean gst_ffmpegenc_register (GstPlugin *plugin);
|
||||||
|
extern gboolean gst_ffmpegtypes_register (GstPlugin *plugin);
|
||||||
|
|
||||||
|
extern URLProtocol gstreamer_protocol;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GModule *module, GstPlugin *plugin)
|
plugin_init (GModule *module, GstPlugin *plugin)
|
||||||
|
@ -43,6 +46,9 @@ plugin_init (GModule *module, 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_ffmpegtypes_register (plugin);
|
||||||
|
|
||||||
|
register_protocol (&gstreamer_protocol);
|
||||||
|
|
||||||
/* Now we can return the pointer to the newly created Plugin object. */
|
/* Now we can return the pointer to the newly created Plugin object. */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
GstCaps *
|
GstCaps *
|
||||||
gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context, int codec_id)
|
||||||
{
|
{
|
||||||
switch (context->codec_id) {
|
switch (codec_id) {
|
||||||
case CODEC_ID_NONE:
|
case CODEC_ID_NONE:
|
||||||
return GST_CAPS_NEW ("ffmpeg_none",
|
return GST_CAPS_NEW ("ffmpeg_none",
|
||||||
"unkown/unkown",
|
"unkown/unkown",
|
||||||
|
@ -72,13 +72,24 @@ gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MPEG4:
|
case CODEC_ID_MPEG4:
|
||||||
return GST_CAPS_NEW ("ffmpeg_mpeg4",
|
if (context) {
|
||||||
"video/avi",
|
return GST_CAPS_NEW ("ffmpeg_mpeg4",
|
||||||
"format", GST_PROPS_STRING ("strf_vids"),
|
"video/avi",
|
||||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
"width", GST_PROPS_INT (context->width),
|
"compression", GST_PROPS_FOURCC (context->fourcc),
|
||||||
"height", GST_PROPS_INT (context->height)
|
"width", GST_PROPS_INT (context->width),
|
||||||
);
|
"height", GST_PROPS_INT (context->height)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return GST_CAPS_NEW ("ffmpeg_mpeg4",
|
||||||
|
"video/avi",
|
||||||
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("DIV3")),
|
||||||
|
"width", GST_PROPS_INT_RANGE (0, 4096),
|
||||||
|
"height", GST_PROPS_INT_RANGE (0, 4096)
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_RAWVIDEO:
|
case CODEC_ID_RAWVIDEO:
|
||||||
return GST_CAPS_NEW ("ffmpeg_rawvideo",
|
return GST_CAPS_NEW ("ffmpeg_rawvideo",
|
||||||
|
@ -86,40 +97,81 @@ gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MSMPEG4V1:
|
case CODEC_ID_MSMPEG4V1:
|
||||||
return GST_CAPS_NEW ("ffmpeg_msmpeg4v1",
|
if (context) {
|
||||||
"video/avi",
|
return GST_CAPS_NEW ("ffmpeg_msmpeg4v1",
|
||||||
"format", GST_PROPS_STRING ("strf_vids"),
|
"video/avi",
|
||||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
"width", GST_PROPS_INT (context->width),
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("MPG4")),
|
||||||
"height", GST_PROPS_INT (context->height)
|
"width", GST_PROPS_INT (context->width),
|
||||||
);
|
"height", GST_PROPS_INT (context->height)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return GST_CAPS_NEW ("ffmpeg_msmpeg4v1",
|
||||||
|
"video/avi",
|
||||||
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("MPG4")),
|
||||||
|
"width", GST_PROPS_INT_RANGE (0, 4096),
|
||||||
|
"height", GST_PROPS_INT_RANGE (0, 4096)
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MSMPEG4V2:
|
case CODEC_ID_MSMPEG4V2:
|
||||||
return GST_CAPS_NEW ("ffmpeg_msmpeg4v2",
|
if (context) {
|
||||||
"video/avi",
|
return GST_CAPS_NEW ("ffmpeg_msmpeg4v2",
|
||||||
"format", GST_PROPS_STRING ("strf_vids"),
|
"video/avi",
|
||||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
"width", GST_PROPS_INT (context->width),
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("MP42")),
|
||||||
"height", GST_PROPS_INT (context->height)
|
"width", GST_PROPS_INT (context->width),
|
||||||
);
|
"height", GST_PROPS_INT (context->height)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return GST_CAPS_NEW ("ffmpeg_msmpeg4v2",
|
||||||
|
"video/avi",
|
||||||
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("MP42")),
|
||||||
|
"width", GST_PROPS_INT_RANGE (0, 4096),
|
||||||
|
"height", GST_PROPS_INT_RANGE (0, 4096)
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_MSMPEG4V3:
|
case CODEC_ID_MSMPEG4V3:
|
||||||
return GST_CAPS_NEW ("ffmpeg_msmpeg4v3",
|
if (context) {
|
||||||
"video/avi",
|
return GST_CAPS_NEW ("ffmpeg_msmpeg4v3",
|
||||||
"format", GST_PROPS_STRING ("strf_vids"),
|
"video/avi",
|
||||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
"width", GST_PROPS_INT (context->width),
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("DIV3")),
|
||||||
"height", GST_PROPS_INT (context->height)
|
"width", GST_PROPS_INT (context->width),
|
||||||
);
|
"height", GST_PROPS_INT (context->height)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return GST_CAPS_NEW ("ffmpeg_msmpeg4v3",
|
||||||
|
"video/avi",
|
||||||
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("DIV3")),
|
||||||
|
"width", GST_PROPS_INT_RANGE (0, 4096),
|
||||||
|
"height", GST_PROPS_INT_RANGE (0, 4096)
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_WMV1:
|
case CODEC_ID_WMV1:
|
||||||
return GST_CAPS_NEW ("ffmpeg_wmv1",
|
if (context) {
|
||||||
"video/avi",
|
return GST_CAPS_NEW ("ffmpeg_wmv1",
|
||||||
"format", GST_PROPS_STRING ("strf_vids"),
|
"video/avi",
|
||||||
"fourcc", GST_PROPS_FOURCC (GST_STR_FOURCC ("WMV1")),
|
"format", GST_PROPS_STRING ("strf_vids"),
|
||||||
"width", GST_PROPS_INT (context->width),
|
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("WMV1")),
|
||||||
"height", GST_PROPS_INT (context->height)
|
"width", GST_PROPS_INT (context->width),
|
||||||
);
|
"height", GST_PROPS_INT (context->height)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return GST_CAPS_NEW ("ffmpeg_wmv1",
|
||||||
|
"video/x-wmv1",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_WMV2:
|
case CODEC_ID_WMV2:
|
||||||
return GST_CAPS_NEW ("ffmpeg_wmv2",
|
return GST_CAPS_NEW ("ffmpeg_wmv2",
|
||||||
|
@ -229,7 +281,7 @@ gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_warning ("no caps found for codec id %d\n", context->codec_id);
|
g_warning ("no caps found for codec id %d\n", codec_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
extern GstCaps* gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *ctx, int id);
|
||||||
|
|
||||||
|
|
||||||
typedef struct _GstFFMpegDec GstFFMpegDec;
|
typedef struct _GstFFMpegDec GstFFMpegDec;
|
||||||
|
|
||||||
struct _GstFFMpegDec {
|
struct _GstFFMpegDec {
|
||||||
|
@ -42,8 +45,14 @@ struct _GstFFMpegDecClass {
|
||||||
GstElementClass parent_class;
|
GstElementClass parent_class;
|
||||||
|
|
||||||
AVCodec *in_plugin;
|
AVCodec *in_plugin;
|
||||||
|
GstPadTemplate *templ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AVCodec *in_plugin;
|
||||||
|
GstPadTemplate *templ;
|
||||||
|
} GstFFMpegClassParams;
|
||||||
|
|
||||||
#define GST_TYPE_FFMPEGDEC \
|
#define GST_TYPE_FFMPEGDEC \
|
||||||
(gst_ffmpegdec_get_type())
|
(gst_ffmpegdec_get_type())
|
||||||
#define GST_FFMPEGDEC(obj) \
|
#define GST_FFMPEGDEC(obj) \
|
||||||
|
@ -65,23 +74,6 @@ enum {
|
||||||
/* FILL ME */
|
/* FILL ME */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This factory is much simpler, and defines the source pad. */
|
|
||||||
GST_PAD_TEMPLATE_FACTORY (gst_ffmpegdec_sink_factory,
|
|
||||||
"sink",
|
|
||||||
GST_PAD_SINK,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_CAPS_NEW (
|
|
||||||
"ffmpegdec_sink",
|
|
||||||
"video/avi",
|
|
||||||
"format", GST_PROPS_STRING ("strf_vids")
|
|
||||||
),
|
|
||||||
GST_CAPS_NEW (
|
|
||||||
"ffmpegdec_sink",
|
|
||||||
"video/mpeg",
|
|
||||||
NULL
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* This factory is much simpler, and defines the source pad. */
|
/* This factory is much simpler, and defines the source pad. */
|
||||||
GST_PAD_TEMPLATE_FACTORY (gst_ffmpegdec_audio_src_factory,
|
GST_PAD_TEMPLATE_FACTORY (gst_ffmpegdec_audio_src_factory,
|
||||||
"src",
|
"src",
|
||||||
|
@ -140,15 +132,19 @@ gst_ffmpegdec_class_init (GstFFMpegDecClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class;
|
GObjectClass *gobject_class;
|
||||||
GstElementClass *gstelement_class;
|
GstElementClass *gstelement_class;
|
||||||
|
GstFFMpegClassParams *params;
|
||||||
|
|
||||||
gobject_class = (GObjectClass*)klass;
|
gobject_class = (GObjectClass*)klass;
|
||||||
gstelement_class = (GstElementClass*)klass;
|
gstelement_class = (GstElementClass*)klass;
|
||||||
|
|
||||||
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
|
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
klass->in_plugin = g_hash_table_lookup (global_plugins,
|
params = g_hash_table_lookup (global_plugins,
|
||||||
GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class)));
|
GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class)));
|
||||||
|
|
||||||
|
klass->in_plugin = params->in_plugin;
|
||||||
|
klass->templ = params->templ;
|
||||||
|
|
||||||
gobject_class->set_property = gst_ffmpegdec_set_property;
|
gobject_class->set_property = gst_ffmpegdec_set_property;
|
||||||
gobject_class->get_property = gst_ffmpegdec_get_property;
|
gobject_class->get_property = gst_ffmpegdec_get_property;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +164,6 @@ gst_ffmpegdec_sinkconnect (GstPad *pad, GstCaps *caps)
|
||||||
gst_caps_get_int (caps, "height", &ffmpegdec->context->height);
|
gst_caps_get_int (caps, "height", &ffmpegdec->context->height);
|
||||||
|
|
||||||
ffmpegdec->context->pix_fmt = PIX_FMT_YUV420P;
|
ffmpegdec->context->pix_fmt = PIX_FMT_YUV420P;
|
||||||
ffmpegdec->context->frame_rate = 23 * FRAME_RATE_BASE;
|
|
||||||
ffmpegdec->context->bit_rate = 0;
|
ffmpegdec->context->bit_rate = 0;
|
||||||
|
|
||||||
/* FIXME bug in ffmpeg */
|
/* FIXME bug in ffmpeg */
|
||||||
|
@ -191,8 +186,7 @@ gst_ffmpegdec_init(GstFFMpegDec *ffmpegdec)
|
||||||
|
|
||||||
ffmpegdec->context = g_malloc0 (sizeof (AVCodecContext));
|
ffmpegdec->context = g_malloc0 (sizeof (AVCodecContext));
|
||||||
|
|
||||||
ffmpegdec->sinkpad = gst_pad_new_from_template (
|
ffmpegdec->sinkpad = gst_pad_new_from_template (oclass->templ, "sink");
|
||||||
GST_PAD_TEMPLATE_GET (gst_ffmpegdec_sink_factory), "sink");
|
|
||||||
gst_pad_set_connect_function (ffmpegdec->sinkpad, gst_ffmpegdec_sinkconnect);
|
gst_pad_set_connect_function (ffmpegdec->sinkpad, gst_ffmpegdec_sinkconnect);
|
||||||
|
|
||||||
if (oclass->in_plugin->type == CODEC_TYPE_VIDEO) {
|
if (oclass->in_plugin->type == CODEC_TYPE_VIDEO) {
|
||||||
|
@ -367,6 +361,9 @@ gst_ffmpegdec_register (GstPlugin *plugin)
|
||||||
while (in_plugin) {
|
while (in_plugin) {
|
||||||
gchar *type_name;
|
gchar *type_name;
|
||||||
gchar *codec_type;
|
gchar *codec_type;
|
||||||
|
GstPadTemplate *sinktempl;
|
||||||
|
GstCaps *sinkcaps;
|
||||||
|
GstFFMpegClassParams *params;
|
||||||
|
|
||||||
if (in_plugin->decode) {
|
if (in_plugin->decode) {
|
||||||
codec_type = "dec";
|
codec_type = "dec";
|
||||||
|
@ -396,18 +393,23 @@ gst_ffmpegdec_register (GstPlugin *plugin)
|
||||||
details->author = g_strdup("The FFMPEG crew, GStreamer plugin by Wim Taymans <wim.taymans@chello.be>");
|
details->author = g_strdup("The FFMPEG crew, GStreamer plugin by Wim Taymans <wim.taymans@chello.be>");
|
||||||
details->copyright = g_strdup("(c) 2001");
|
details->copyright = g_strdup("(c) 2001");
|
||||||
|
|
||||||
g_hash_table_insert (global_plugins,
|
|
||||||
GINT_TO_POINTER (type),
|
|
||||||
(gpointer) in_plugin);
|
|
||||||
|
|
||||||
/* register the plugin with gstreamer */
|
/* register the plugin with gstreamer */
|
||||||
factory = gst_element_factory_new(type_name,type,details);
|
factory = gst_element_factory_new(type_name,type,details);
|
||||||
g_return_val_if_fail(factory != NULL, FALSE);
|
g_return_val_if_fail(factory != NULL, FALSE);
|
||||||
|
|
||||||
gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_NONE);
|
gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_NONE);
|
||||||
|
|
||||||
gst_element_factory_add_pad_template (factory,
|
sinkcaps = gst_ffmpegcodec_codec_context_to_caps (NULL, in_plugin->id);
|
||||||
GST_PAD_TEMPLATE_GET (gst_ffmpegdec_sink_factory));
|
sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sinkcaps, NULL);
|
||||||
|
gst_element_factory_add_pad_template (factory, sinktempl);
|
||||||
|
|
||||||
|
params = g_new0 (GstFFMpegClassParams, 1);
|
||||||
|
params->in_plugin = in_plugin;
|
||||||
|
params->templ = sinktempl;
|
||||||
|
|
||||||
|
g_hash_table_insert (global_plugins,
|
||||||
|
GINT_TO_POINTER (type),
|
||||||
|
(gpointer) params);
|
||||||
|
|
||||||
if (in_plugin->type == CODEC_TYPE_VIDEO) {
|
if (in_plugin->type == CODEC_TYPE_VIDEO) {
|
||||||
gst_element_factory_add_pad_template (factory,
|
gst_element_factory_add_pad_template (factory,
|
||||||
|
|
|
@ -23,13 +23,11 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
extern URLProtocol gstreamer_protocol;
|
extern GstCaps* gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context, int codec_id);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
STATE_OPEN,
|
STATE_OPEN,
|
||||||
STATE_STREAM_INFO,
|
|
||||||
STATE_DEMUX,
|
STATE_DEMUX,
|
||||||
STATE_END,
|
|
||||||
} DemuxState;
|
} DemuxState;
|
||||||
|
|
||||||
typedef struct _GstFFMpegDemux GstFFMpegDemux;
|
typedef struct _GstFFMpegDemux GstFFMpegDemux;
|
||||||
|
@ -164,9 +162,6 @@ gst_ffmpegdemux_loop (GstElement *element)
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/* this doesn't work */
|
|
||||||
av_set_pts_info (ffmpegdemux->context, 33, 1, 100000);
|
|
||||||
|
|
||||||
ffmpegdemux->state = STATE_DEMUX;
|
ffmpegdemux->state = STATE_DEMUX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -180,44 +175,53 @@ gst_ffmpegdemux_loop (GstElement *element)
|
||||||
|
|
||||||
res = av_read_packet(ct, &pkt);
|
res = av_read_packet(ct, &pkt);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
gint i;
|
if (url_feof (&ct->pb)) {
|
||||||
|
gint i;
|
||||||
|
|
||||||
for (i = 0; i < ct->nb_streams; i++) {
|
for (i = 0; i < ct->nb_streams; i++) {
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
|
|
||||||
pad = ffmpegdemux->srcpads[i];
|
pad = ffmpegdemux->srcpads[i];
|
||||||
|
|
||||||
if (GST_PAD_IS_USABLE (pad)) {
|
if (GST_PAD_IS_USABLE (pad)) {
|
||||||
gst_pad_push (pad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
|
gst_pad_push (pad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
gst_element_set_eos (element);
|
||||||
}
|
}
|
||||||
gst_element_set_eos (element);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
st = ct->streams[pkt.stream_index];
|
st = ct->streams[pkt.stream_index];
|
||||||
|
|
||||||
if (st->codec_info_state == 0) {
|
if (st->codec_info_state == 0) {
|
||||||
gchar *padname = NULL;
|
gchar *templname = NULL;
|
||||||
GstPadTemplate *templ = NULL;
|
|
||||||
|
|
||||||
st->codec_info_state = 1;
|
st->codec_info_state = 1;
|
||||||
|
|
||||||
if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
|
if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
|
||||||
padname = g_strdup_printf ("video_%02d", pkt.stream_index);
|
templname = "video_%02d";
|
||||||
templ = GST_PAD_TEMPLATE_GET (gst_ffmpegdemux_video_src_factory);
|
|
||||||
}
|
}
|
||||||
else if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
|
else if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
|
||||||
padname = g_strdup_printf ("audio_%02d", pkt.stream_index);
|
templname = "audio_%02d";
|
||||||
templ = GST_PAD_TEMPLATE_GET (gst_ffmpegdemux_audio_src_factory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (padname != NULL) {
|
if (templname != NULL) {
|
||||||
|
gchar *padname;
|
||||||
|
GstCaps *caps;
|
||||||
|
GstPadTemplate *templ;
|
||||||
|
|
||||||
|
caps = gst_ffmpegcodec_codec_context_to_caps (&st->codec, st->codec.codec_id);
|
||||||
|
templ = gst_pad_template_new (templname,
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_SOMETIMES,
|
||||||
|
caps, NULL);
|
||||||
|
|
||||||
|
padname = g_strdup_printf (templname, pkt.stream_index);
|
||||||
pad = gst_pad_new_from_template (templ, padname);
|
pad = gst_pad_new_from_template (templ, padname);
|
||||||
|
|
||||||
ffmpegdemux->srcpads[pkt.stream_index] = pad;
|
ffmpegdemux->srcpads[pkt.stream_index] = pad;
|
||||||
gst_element_add_pad (GST_ELEMENT (ffmpegdemux), pad);
|
gst_element_add_pad (GST_ELEMENT (ffmpegdemux), pad);
|
||||||
g_print ("new pad\n");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g_warning ("unkown pad type %d", st->codec.codec_type);
|
g_warning ("unkown pad type %d", st->codec.codec_type);
|
||||||
|
@ -234,8 +238,9 @@ gst_ffmpegdemux_loop (GstElement *element)
|
||||||
outbuf = gst_buffer_new ();
|
outbuf = gst_buffer_new ();
|
||||||
GST_BUFFER_DATA (outbuf) = pkt.data;
|
GST_BUFFER_DATA (outbuf) = pkt.data;
|
||||||
GST_BUFFER_SIZE (outbuf) = pkt.size;
|
GST_BUFFER_SIZE (outbuf) = pkt.size;
|
||||||
if (pkt.pts != 0) {
|
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = pkt.pts * GST_SECOND / 90000LL;
|
if (pkt.pts != AV_NOPTS_VALUE && ct->pts_den) {
|
||||||
|
GST_BUFFER_TIMESTAMP (outbuf) = pkt.pts * GST_SECOND * ct->pts_num / ct->pts_den;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = -1;
|
GST_BUFFER_TIMESTAMP (outbuf) = -1;
|
||||||
|
@ -364,7 +369,5 @@ next:
|
||||||
in_plugin = in_plugin->next;
|
in_plugin = in_plugin->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_protocol (&gstreamer_protocol);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,11 @@ typedef struct _GstProtocolInfo GstProtocolInfo;
|
||||||
|
|
||||||
struct _GstProtocolInfo
|
struct _GstProtocolInfo
|
||||||
{
|
{
|
||||||
GstPad *pad;
|
GstPad *pad;
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
GstByteStream *bs;
|
GstByteStream *bs;
|
||||||
|
gboolean eos;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -54,6 +55,7 @@ gst_open (URLContext *h, const char *filename, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
info->bs = gst_bytestream_new (pad);
|
info->bs = gst_bytestream_new (pad);
|
||||||
|
info->eos = FALSE;
|
||||||
|
|
||||||
h->priv_data = (void *) info;
|
h->priv_data = (void *) info;
|
||||||
|
|
||||||
|
@ -71,10 +73,36 @@ gst_read (URLContext *h, unsigned char *buf, int size)
|
||||||
info = (GstProtocolInfo *) h->priv_data;
|
info = (GstProtocolInfo *) h->priv_data;
|
||||||
bs = info->bs;
|
bs = info->bs;
|
||||||
|
|
||||||
total = gst_bytestream_peek_bytes (bs, &data, size);
|
if (info->eos)
|
||||||
memcpy (buf, data, total);
|
return 0;
|
||||||
|
|
||||||
gst_bytestream_flush_fast (bs, total);
|
total = gst_bytestream_peek_bytes (bs, &data, size);
|
||||||
|
|
||||||
|
if (total < size) {
|
||||||
|
GstEvent *event;
|
||||||
|
guint32 remaining;
|
||||||
|
|
||||||
|
gst_bytestream_get_status (bs, &remaining, &event);
|
||||||
|
|
||||||
|
if (!event) {
|
||||||
|
g_warning ("gstffmpegprotocol: no bytestream event");
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
gst_bytestream_flush_fast (bs, remaining);
|
||||||
|
case GST_EVENT_EOS:
|
||||||
|
info->eos = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gst_event_unref (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (buf, data, total);
|
||||||
|
gst_bytestream_flush (bs, total);
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
129
ext/ffmpeg/gstffmpegtypes.c
Normal file
129
ext/ffmpeg/gstffmpegtypes.c
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libav/avformat.h>
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
static GHashTable *global_types = NULL;
|
||||||
|
|
||||||
|
extern GstCaps* gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *ctx, int id);
|
||||||
|
|
||||||
|
static GstCaps*
|
||||||
|
gst_ffmpegtypes_typefind (GstBuffer *buffer, gpointer priv)
|
||||||
|
{
|
||||||
|
AVInputFormat *in_plugin;
|
||||||
|
AVInputFormat *highest = NULL;
|
||||||
|
gint max = 0;
|
||||||
|
gint res = 0;
|
||||||
|
|
||||||
|
in_plugin = first_iformat;
|
||||||
|
|
||||||
|
while (in_plugin) {
|
||||||
|
if (in_plugin->read_probe) {
|
||||||
|
AVProbeData probe_data;
|
||||||
|
|
||||||
|
probe_data.filename = "";
|
||||||
|
probe_data.buf = GST_BUFFER_DATA (buffer);
|
||||||
|
probe_data.buf_size = GST_BUFFER_SIZE (buffer);
|
||||||
|
|
||||||
|
res = in_plugin->read_probe (&probe_data);
|
||||||
|
if (res > max) {
|
||||||
|
max = res;
|
||||||
|
highest = in_plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in_plugin = in_plugin->next;
|
||||||
|
}
|
||||||
|
if (highest) {
|
||||||
|
GstCaps *caps;
|
||||||
|
caps = g_hash_table_lookup (global_types, highest->name);
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_TYPE(key,caps) g_hash_table_insert (global_types, (key), (caps))
|
||||||
|
|
||||||
|
static void
|
||||||
|
register_standard_formats (void)
|
||||||
|
{
|
||||||
|
global_types = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
|
||||||
|
ADD_TYPE ("avi", GST_CAPS_NEW ("ffmpeg_type_avi", "video/avi", NULL));
|
||||||
|
ADD_TYPE ("mpeg", GST_CAPS_NEW ("ffmpeg_type_mpeg", "video/mpeg",
|
||||||
|
"systemstream", GST_PROPS_BOOLEAN (TRUE)));
|
||||||
|
ADD_TYPE ("mpegts", GST_CAPS_NEW ("ffmpeg_type_mpegts", "video/x-mpegts",
|
||||||
|
"systemstream", GST_PROPS_BOOLEAN (TRUE)));
|
||||||
|
ADD_TYPE ("rm", GST_CAPS_NEW ("ffmpeg_type_rm", "audio/x-pn-realaudio", NULL));
|
||||||
|
ADD_TYPE ("asf", GST_CAPS_NEW ("ffmpeg_type_asf", "video/x-ms-asf", NULL));
|
||||||
|
ADD_TYPE ("avi", GST_CAPS_NEW ("ffmpeg_type_avi", "video/avi",
|
||||||
|
"format", GST_PROPS_STRING ("AVI")));
|
||||||
|
ADD_TYPE ("mov", GST_CAPS_NEW ("ffmpeg_type_mov", "video/quicktime", NULL));
|
||||||
|
ADD_TYPE ("swf", GST_CAPS_NEW ("ffmpeg_type_swf", "application/x-shockwave-flash", NULL));
|
||||||
|
ADD_TYPE ("au", GST_CAPS_NEW ("ffmpeg_type_au", "audio/basic", NULL));
|
||||||
|
ADD_TYPE ("mov", GST_CAPS_NEW ("ffmpeg_type_mov", "video/quicktime", NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_ffmpegtypes_register (GstPlugin *plugin)
|
||||||
|
{
|
||||||
|
AVInputFormat *in_plugin;
|
||||||
|
GstTypeFactory *factory;
|
||||||
|
GstTypeDefinition *definition;
|
||||||
|
|
||||||
|
in_plugin = first_iformat;
|
||||||
|
|
||||||
|
while (in_plugin) {
|
||||||
|
gchar *type_name;
|
||||||
|
gchar *p;
|
||||||
|
|
||||||
|
if (!in_plugin->read_probe)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
/* construct the type */
|
||||||
|
type_name = g_strdup_printf("fftype_%s", in_plugin->name);
|
||||||
|
|
||||||
|
p = type_name;
|
||||||
|
|
||||||
|
while (*p) {
|
||||||
|
if (*p == '.') *p = '_';
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
definition = g_new0 (GstTypeDefinition, 1);
|
||||||
|
definition->name = type_name;
|
||||||
|
definition->mime = type_name;
|
||||||
|
definition->exts = g_strdup (in_plugin->extensions);
|
||||||
|
definition->typefindfunc = gst_ffmpegtypes_typefind;
|
||||||
|
|
||||||
|
factory = gst_type_factory_new (definition);
|
||||||
|
|
||||||
|
/* The very last thing is to register the elementfactory with the plugin. */
|
||||||
|
gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
|
||||||
|
next:
|
||||||
|
in_plugin = in_plugin->next;
|
||||||
|
}
|
||||||
|
register_standard_formats ();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
Loading…
Reference in a new issue