mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 02:01:12 +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
|
||||
|
||||
libgstffmpeg_la_SOURCES = gstffmpeg.c \
|
||||
gstffmpegenc.c \
|
||||
gstffmpegcodecmap.c \
|
||||
gstffmpegdec.c \
|
||||
gstffmpegdemux.c \
|
||||
gstffmpegenc.c \
|
||||
gstffmpegmux.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_LIBADD =
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
extern gboolean gst_ffmpegdemux_register (GstPlugin *plugin);
|
||||
extern gboolean gst_ffmpegdec_register (GstPlugin *plugin);
|
||||
extern gboolean gst_ffmpegenc_register (GstPlugin *plugin);
|
||||
extern gboolean gst_ffmpegtypes_register (GstPlugin *plugin);
|
||||
|
||||
extern URLProtocol gstreamer_protocol;
|
||||
|
||||
static gboolean
|
||||
plugin_init (GModule *module, GstPlugin *plugin)
|
||||
|
@ -43,6 +46,9 @@ plugin_init (GModule *module, GstPlugin *plugin)
|
|||
gst_ffmpegenc_register (plugin);
|
||||
gst_ffmpegdec_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. */
|
||||
return TRUE;
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
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:
|
||||
return GST_CAPS_NEW ("ffmpeg_none",
|
||||
"unkown/unkown",
|
||||
|
@ -72,13 +72,24 @@ gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
|||
NULL);
|
||||
break;
|
||||
case CODEC_ID_MPEG4:
|
||||
if (context) {
|
||||
return GST_CAPS_NEW ("ffmpeg_mpeg4",
|
||||
"video/avi",
|
||||
"format", GST_PROPS_STRING ("strf_vids"),
|
||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
||||
"compression", GST_PROPS_FOURCC (context->fourcc),
|
||||
"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;
|
||||
case CODEC_ID_RAWVIDEO:
|
||||
return GST_CAPS_NEW ("ffmpeg_rawvideo",
|
||||
|
@ -86,40 +97,81 @@ gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
|||
NULL);
|
||||
break;
|
||||
case CODEC_ID_MSMPEG4V1:
|
||||
if (context) {
|
||||
return GST_CAPS_NEW ("ffmpeg_msmpeg4v1",
|
||||
"video/avi",
|
||||
"format", GST_PROPS_STRING ("strf_vids"),
|
||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
||||
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("MPG4")),
|
||||
"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;
|
||||
case CODEC_ID_MSMPEG4V2:
|
||||
if (context) {
|
||||
return GST_CAPS_NEW ("ffmpeg_msmpeg4v2",
|
||||
"video/avi",
|
||||
"format", GST_PROPS_STRING ("strf_vids"),
|
||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
||||
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("MP42")),
|
||||
"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;
|
||||
case CODEC_ID_MSMPEG4V3:
|
||||
if (context) {
|
||||
return GST_CAPS_NEW ("ffmpeg_msmpeg4v3",
|
||||
"video/avi",
|
||||
"format", GST_PROPS_STRING ("strf_vids"),
|
||||
"fourcc", GST_PROPS_FOURCC (context->fourcc),
|
||||
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("DIV3")),
|
||||
"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;
|
||||
case CODEC_ID_WMV1:
|
||||
if (context) {
|
||||
return GST_CAPS_NEW ("ffmpeg_wmv1",
|
||||
"video/avi",
|
||||
"format", GST_PROPS_STRING ("strf_vids"),
|
||||
"fourcc", GST_PROPS_FOURCC (GST_STR_FOURCC ("WMV1")),
|
||||
"compression", GST_PROPS_FOURCC (GST_STR_FOURCC ("WMV1")),
|
||||
"width", GST_PROPS_INT (context->width),
|
||||
"height", GST_PROPS_INT (context->height)
|
||||
);
|
||||
}
|
||||
else {
|
||||
return GST_CAPS_NEW ("ffmpeg_wmv1",
|
||||
"video/x-wmv1",
|
||||
NULL
|
||||
);
|
||||
}
|
||||
break;
|
||||
case CODEC_ID_WMV2:
|
||||
return GST_CAPS_NEW ("ffmpeg_wmv2",
|
||||
|
@ -229,7 +281,7 @@ gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context)
|
|||
NULL);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
extern GstCaps* gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *ctx, int id);
|
||||
|
||||
|
||||
typedef struct _GstFFMpegDec GstFFMpegDec;
|
||||
|
||||
struct _GstFFMpegDec {
|
||||
|
@ -42,8 +45,14 @@ struct _GstFFMpegDecClass {
|
|||
GstElementClass parent_class;
|
||||
|
||||
AVCodec *in_plugin;
|
||||
GstPadTemplate *templ;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
AVCodec *in_plugin;
|
||||
GstPadTemplate *templ;
|
||||
} GstFFMpegClassParams;
|
||||
|
||||
#define GST_TYPE_FFMPEGDEC \
|
||||
(gst_ffmpegdec_get_type())
|
||||
#define GST_FFMPEGDEC(obj) \
|
||||
|
@ -65,23 +74,6 @@ enum {
|
|||
/* 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. */
|
||||
GST_PAD_TEMPLATE_FACTORY (gst_ffmpegdec_audio_src_factory,
|
||||
"src",
|
||||
|
@ -140,15 +132,19 @@ gst_ffmpegdec_class_init (GstFFMpegDecClass *klass)
|
|||
{
|
||||
GObjectClass *gobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
GstFFMpegClassParams *params;
|
||||
|
||||
gobject_class = (GObjectClass*)klass;
|
||||
gstelement_class = (GstElementClass*)klass;
|
||||
|
||||
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)));
|
||||
|
||||
klass->in_plugin = params->in_plugin;
|
||||
klass->templ = params->templ;
|
||||
|
||||
gobject_class->set_property = gst_ffmpegdec_set_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);
|
||||
|
||||
ffmpegdec->context->pix_fmt = PIX_FMT_YUV420P;
|
||||
ffmpegdec->context->frame_rate = 23 * FRAME_RATE_BASE;
|
||||
ffmpegdec->context->bit_rate = 0;
|
||||
|
||||
/* FIXME bug in ffmpeg */
|
||||
|
@ -191,8 +186,7 @@ gst_ffmpegdec_init(GstFFMpegDec *ffmpegdec)
|
|||
|
||||
ffmpegdec->context = g_malloc0 (sizeof (AVCodecContext));
|
||||
|
||||
ffmpegdec->sinkpad = gst_pad_new_from_template (
|
||||
GST_PAD_TEMPLATE_GET (gst_ffmpegdec_sink_factory), "sink");
|
||||
ffmpegdec->sinkpad = gst_pad_new_from_template (oclass->templ, "sink");
|
||||
gst_pad_set_connect_function (ffmpegdec->sinkpad, gst_ffmpegdec_sinkconnect);
|
||||
|
||||
if (oclass->in_plugin->type == CODEC_TYPE_VIDEO) {
|
||||
|
@ -367,6 +361,9 @@ gst_ffmpegdec_register (GstPlugin *plugin)
|
|||
while (in_plugin) {
|
||||
gchar *type_name;
|
||||
gchar *codec_type;
|
||||
GstPadTemplate *sinktempl;
|
||||
GstCaps *sinkcaps;
|
||||
GstFFMpegClassParams *params;
|
||||
|
||||
if (in_plugin->decode) {
|
||||
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->copyright = g_strdup("(c) 2001");
|
||||
|
||||
g_hash_table_insert (global_plugins,
|
||||
GINT_TO_POINTER (type),
|
||||
(gpointer) in_plugin);
|
||||
|
||||
/* register the plugin with gstreamer */
|
||||
factory = gst_element_factory_new(type_name,type,details);
|
||||
g_return_val_if_fail(factory != NULL, FALSE);
|
||||
|
||||
gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_NONE);
|
||||
|
||||
gst_element_factory_add_pad_template (factory,
|
||||
GST_PAD_TEMPLATE_GET (gst_ffmpegdec_sink_factory));
|
||||
sinkcaps = gst_ffmpegcodec_codec_context_to_caps (NULL, in_plugin->id);
|
||||
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) {
|
||||
gst_element_factory_add_pad_template (factory,
|
||||
|
|
|
@ -23,13 +23,11 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
extern URLProtocol gstreamer_protocol;
|
||||
extern GstCaps* gst_ffmpegcodec_codec_context_to_caps (AVCodecContext *context, int codec_id);
|
||||
|
||||
typedef enum {
|
||||
STATE_OPEN,
|
||||
STATE_STREAM_INFO,
|
||||
STATE_DEMUX,
|
||||
STATE_END,
|
||||
} DemuxState;
|
||||
|
||||
typedef struct _GstFFMpegDemux GstFFMpegDemux;
|
||||
|
@ -164,9 +162,6 @@ gst_ffmpegdemux_loop (GstElement *element)
|
|||
0,
|
||||
NULL);
|
||||
|
||||
/* this doesn't work */
|
||||
av_set_pts_info (ffmpegdemux->context, 33, 1, 100000);
|
||||
|
||||
ffmpegdemux->state = STATE_DEMUX;
|
||||
break;
|
||||
}
|
||||
|
@ -180,6 +175,7 @@ gst_ffmpegdemux_loop (GstElement *element)
|
|||
|
||||
res = av_read_packet(ct, &pkt);
|
||||
if (res < 0) {
|
||||
if (url_feof (&ct->pb)) {
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < ct->nb_streams; i++) {
|
||||
|
@ -192,32 +188,40 @@ gst_ffmpegdemux_loop (GstElement *element)
|
|||
}
|
||||
}
|
||||
gst_element_set_eos (element);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
st = ct->streams[pkt.stream_index];
|
||||
|
||||
if (st->codec_info_state == 0) {
|
||||
gchar *padname = NULL;
|
||||
GstPadTemplate *templ = NULL;
|
||||
gchar *templname = NULL;
|
||||
|
||||
st->codec_info_state = 1;
|
||||
|
||||
if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
|
||||
padname = g_strdup_printf ("video_%02d", pkt.stream_index);
|
||||
templ = GST_PAD_TEMPLATE_GET (gst_ffmpegdemux_video_src_factory);
|
||||
templname = "video_%02d";
|
||||
}
|
||||
else if (st->codec.codec_type == CODEC_TYPE_AUDIO) {
|
||||
padname = g_strdup_printf ("audio_%02d", pkt.stream_index);
|
||||
templ = GST_PAD_TEMPLATE_GET (gst_ffmpegdemux_audio_src_factory);
|
||||
templname = "audio_%02d";
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ffmpegdemux->srcpads[pkt.stream_index] = pad;
|
||||
gst_element_add_pad (GST_ELEMENT (ffmpegdemux), pad);
|
||||
g_print ("new pad\n");
|
||||
}
|
||||
else {
|
||||
g_warning ("unkown pad type %d", st->codec.codec_type);
|
||||
|
@ -234,8 +238,9 @@ gst_ffmpegdemux_loop (GstElement *element)
|
|||
outbuf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (outbuf) = pkt.data;
|
||||
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 {
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = -1;
|
||||
|
@ -364,7 +369,5 @@ next:
|
|||
in_plugin = in_plugin->next;
|
||||
}
|
||||
|
||||
register_protocol (&gstreamer_protocol);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ struct _GstProtocolInfo
|
|||
|
||||
int flags;
|
||||
GstByteStream *bs;
|
||||
gboolean eos;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -54,6 +55,7 @@ gst_open (URLContext *h, const char *filename, int flags)
|
|||
}
|
||||
|
||||
info->bs = gst_bytestream_new (pad);
|
||||
info->eos = FALSE;
|
||||
|
||||
h->priv_data = (void *) info;
|
||||
|
||||
|
@ -71,10 +73,36 @@ gst_read (URLContext *h, unsigned char *buf, int size)
|
|||
info = (GstProtocolInfo *) h->priv_data;
|
||||
bs = info->bs;
|
||||
|
||||
total = gst_bytestream_peek_bytes (bs, &data, size);
|
||||
memcpy (buf, data, total);
|
||||
if (info->eos)
|
||||
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;
|
||||
}
|
||||
|
|
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