diff options
Diffstat (limited to 'gst/avi')
-rw-r--r-- | gst/avi/gstavidemux.c | 846 | ||||
-rw-r--r-- | gst/avi/gstavimux.c | 406 |
2 files changed, 695 insertions, 557 deletions
diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 77ff97f6..ad0b1ef3 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -68,138 +68,46 @@ GST_PAD_TEMPLATE_FACTORY (sink_templ, GST_PAD_ALWAYS, GST_CAPS_NEW ( "avidemux_sink", - "video/avi", - "format", GST_PROPS_STRING ("AVI") - ) -) - -GST_PAD_TEMPLATE_FACTORY (src_video_templ, - "video_%02d", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_CAPS_NEW ( - "avidemux_src_video_avi", - "video/avi", - "format", GST_PROPS_LIST ( - GST_PROPS_STRING ("strf_vids"), - GST_PROPS_STRING ("strf_iavs") - ), - "width", GST_PROPS_INT_RANGE (16, 4096), - "height", GST_PROPS_INT_RANGE (16, 4096) - - ), - GST_CAPS_NEW ( - "avidemux_src_video_raw", - "video/raw", - "format", GST_PROPS_LIST ( - GST_PROPS_FOURCC (GST_MAKE_FOURCC('Y','U','Y','2')), - GST_PROPS_FOURCC (GST_MAKE_FOURCC('I','4','2','0')) - ), - "width", GST_PROPS_INT_RANGE (16, 4096), - "height", GST_PROPS_INT_RANGE (16, 4096) - ), - GST_CAPS_NEW ( - "avidemux_src_video_jpeg", - "video/jpeg", - "width", GST_PROPS_INT_RANGE (16, 4096), - "height", GST_PROPS_INT_RANGE (16, 4096) - ), - GST_CAPS_NEW ( - "avidemux_src_video_dv", - "video/dv", - "format", GST_PROPS_LIST ( - GST_PROPS_STRING ("NTSC"), - GST_PROPS_STRING ("PAL") - ), - "width", GST_PROPS_INT_RANGE (16, 4096), - "height", GST_PROPS_INT_RANGE (16, 4096) - ), - GST_CAPS_NEW ( - "avidemux_src_video_divx", - "video/divx", - "width", GST_PROPS_INT_RANGE (16, 4096), - "height", GST_PROPS_INT_RANGE (16, 4096) - ), - GST_CAPS_NEW ( - "avidemux_src_video_xvid", - "video/xvid", - "width", GST_PROPS_INT_RANGE (16, 4096), - "height", GST_PROPS_INT_RANGE (16, 4096) - ) -) - -GST_PAD_TEMPLATE_FACTORY (src_audio_templ, - "audio_%02d", - GST_PAD_SRC, - GST_PAD_SOMETIMES, - GST_CAPS_NEW ( - "avidemux_src_audio_avi", "video/avi", - "format", GST_PROPS_STRING ("strf_auds") - ), - GST_CAPS_NEW ( - "avidemux_src_audio_raw", - "audio/raw", - "format", GST_PROPS_STRING ("int"), - "law", GST_PROPS_INT (0), - "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN), - "signed", GST_PROPS_LIST ( - GST_PROPS_BOOLEAN (TRUE), - GST_PROPS_BOOLEAN (FALSE) - ), - "width", GST_PROPS_LIST ( - GST_PROPS_INT (8), - GST_PROPS_INT (16) - ), - "depth", GST_PROPS_LIST ( - GST_PROPS_INT (8), - GST_PROPS_INT (16) - ), - "rate", GST_PROPS_INT_RANGE (11025, 44100), - "channels", GST_PROPS_INT_RANGE (1, 2) - ), - GST_CAPS_NEW ( - "avidemux_src_audio_mp3", - "audio/x-mp3", - NULL - ), - GST_CAPS_NEW ( - "avidemux_src_audio_ac3", - "audio/a52", NULL - ), - GST_CAPS_NEW ( - "avidemux_src_audio_vorbis", - "application/x-ogg", - NULL ) -) - -static void gst_avi_demux_class_init (GstAviDemuxClass *klass); -static void gst_avi_demux_init (GstAviDemux *avi_demux); - -static void gst_avi_demux_loop (GstElement *element); - -static gboolean gst_avi_demux_send_event (GstElement *element, GstEvent *event); - -static const GstEventMask* - gst_avi_demux_get_event_mask (GstPad *pad); -static gboolean gst_avi_demux_handle_src_event (GstPad *pad, GstEvent *event); -static const GstFormat* gst_avi_demux_get_src_formats (GstPad *pad); -static const GstQueryType* - gst_avi_demux_get_src_query_types (GstPad *pad); -static gboolean gst_avi_demux_handle_src_query (GstPad *pad, GstQueryType type, - GstFormat *format, gint64 *value); -static gboolean gst_avi_demux_src_convert (GstPad *pad, GstFormat src_format, gint64 src_value, - GstFormat *dest_format, gint64 *dest_value); +); + +static void gst_avi_demux_class_init (GstAviDemuxClass *klass); +static void gst_avi_demux_init (GstAviDemux *avi_demux); + +static void gst_avi_demux_loop (GstElement *element); + +static gboolean gst_avi_demux_send_event (GstElement *element, + GstEvent *event); + +static const GstEventMask * + gst_avi_demux_get_event_mask (GstPad *pad); +static gboolean gst_avi_demux_handle_src_event (GstPad *pad, + GstEvent *event); +static const GstFormat * + gst_avi_demux_get_src_formats (GstPad *pad); +static const GstQueryType * + gst_avi_demux_get_src_query_types (GstPad *pad); +static gboolean gst_avi_demux_handle_src_query (GstPad *pad, + GstQueryType type, + GstFormat *format, + gint64 *value); +static gboolean gst_avi_demux_src_convert (GstPad *pad, + GstFormat src_format, + gint64 src_value, + GstFormat *dest_format, + gint64 *dest_value); static GstElementStateReturn - gst_avi_demux_change_state (GstElement *element); - -static void gst_avi_demux_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); + gst_avi_demux_change_state (GstElement *element); +static void gst_avi_demux_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static GstPadTemplate *videosrctempl, *audiosrctempl; static GstElementClass *parent_class = NULL; /*static guint gst_avi_demux_signals[LAST_SIGNAL] = { 0 }; */ @@ -280,7 +188,7 @@ avi_type_find (GstBuffer *buf, new = GST_CAPS_NEW ("avi_type_find", "video/avi", - "format", GST_PROPS_STRING ("AVI")); + NULL); return new; } @@ -524,7 +432,7 @@ gst_avi_demux_metadata (GstAviDemux *avi_demux, gint len) type = "Subject"; break; case GST_RIFF_INFO_ISFT: - type = "Encoder"; /* "Sotware" */ + type = "Encoder"; /* "Software" */ break; case GST_RIFF_INFO_ISHP: type = "Sharpness"; @@ -577,102 +485,91 @@ gst_avi_demux_streaminfo (GstAviDemux *avi_demux) /*g_object_notify(G_OBJECT(avi_demux), "streaminfo");*/ } -static void -gst_avi_demux_strf_vids (GstAviDemux *avi_demux) +/* video/audio pad/caps stuff */ + +#define GST_AVI_VID_CAPS_NEW(name, mimetype, props...) \ + (strf != NULL) ? \ + GST_CAPS_NEW (name, \ + mimetype, \ + "width", GST_PROPS_INT (width), \ + "height", GST_PROPS_INT (height), \ + "framerate", GST_PROPS_FLOAT (framerate), \ + ##props) \ + : \ + GST_CAPS_NEW (name, \ + mimetype, \ + "width", GST_PROPS_INT_RANGE (16, 4096), \ + "height", GST_PROPS_INT_RANGE (16, 4096), \ + "framerate", GST_PROPS_FLOAT_RANGE (0., G_MAXFLOAT), \ + ##props) + +static GstCaps * +gst_avi_demux_video_caps (guint32 codec_fcc, + gst_riff_strh *strh, + gst_riff_strf_vids *strf, + GstAviDemux *avi_demux) { - gst_riff_strf_vids *strf; - guint8 *strfdata; - GstPad *srcpad; - GstCaps *newcaps = NULL, *capslist = NULL; - avi_stream_context *stream; - GstByteStream *bs = avi_demux->bs; - guint32 got_bytes; - gchar *codecname; - GstPropsEntry *entry; - - got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_vids)); - strf = (gst_riff_strf_vids *) strfdata; - if (got_bytes != sizeof (gst_riff_strf_vids)) - return; - - GST_INFO ( "gst_avi_demux: strf tag found in context vids"); - GST_INFO ( "gst_avi_demux: size %d", GUINT32_FROM_LE (strf->size)); - GST_INFO ( "gst_avi_demux: width %d", GUINT32_FROM_LE (strf->width)); - GST_INFO ( "gst_avi_demux: height %d", GUINT32_FROM_LE (strf->height)); - GST_INFO ( "gst_avi_demux: planes %d", GUINT16_FROM_LE (strf->planes)); - GST_INFO ( "gst_avi_demux: bit_cnt %d", GUINT16_FROM_LE (strf->bit_cnt)); - GST_INFO ( "gst_avi_demux: compression 0x%08x (%s)", - GUINT32_FROM_LE (strf->compression), gst_riff_id_to_fourcc (strf->compression)); - GST_INFO ( "gst_avi_demux: image_size %d", GUINT32_FROM_LE (strf->image_size)); - GST_INFO ( "gst_avi_demux: xpels_meter %d", GUINT32_FROM_LE (strf->xpels_meter)); - GST_INFO ( "gst_avi_demux: ypels_meter %d", GUINT32_FROM_LE (strf->ypels_meter)); - GST_INFO ( "gst_avi_demux: num_colors %d", GUINT32_FROM_LE (strf->num_colors)); - GST_INFO ( "gst_avi_demux: imp_colors %d", GUINT32_FROM_LE (strf->imp_colors)); - - srcpad = gst_pad_new_from_template ( - GST_PAD_TEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d", - avi_demux->num_v_streams)); - - capslist = gst_caps_append(NULL, GST_CAPS_NEW ( - "avidemux_video_src", - "video/avi", - "format", GST_PROPS_STRING ("strf_vids"), - "size", GST_PROPS_INT (GUINT32_FROM_LE (strf->size)), - "width", GST_PROPS_INT (GUINT32_FROM_LE (strf->width)), - "height", GST_PROPS_INT (GUINT32_FROM_LE (strf->height)), - "planes", GST_PROPS_INT (GUINT16_FROM_LE (strf->planes)), - "bit_cnt", GST_PROPS_INT (GUINT16_FROM_LE (strf->bit_cnt)), - "compression", GST_PROPS_FOURCC (GUINT32_FROM_LE (strf->compression)), - "image_size", GST_PROPS_INT (GUINT32_FROM_LE (strf->image_size)), - "xpels_meter", GST_PROPS_INT (GUINT32_FROM_LE (strf->xpels_meter)), - "ypels_meter", GST_PROPS_INT (GUINT32_FROM_LE (strf->ypels_meter)), - "num_colors", GST_PROPS_INT (GUINT32_FROM_LE (strf->num_colors)), - "imp_colors", GST_PROPS_INT (GUINT32_FROM_LE (strf->imp_colors)) - )); + GstCaps *caps = NULL; + gchar *codecname = NULL; + gint width = -1, height = -1; + gdouble framerate = 0.; + + if (strf != NULL) { + width = GUINT32_FROM_LE (strf->width); + height = GUINT32_FROM_LE (strf->height); + } + if (strh != NULL) { + framerate = 1. * GUINT32_FROM_LE (strh->rate) / + GUINT32_FROM_LE (strh->scale); /* fps */ + } - /* let's try some gstreamer-like mime-type caps */ - switch (GUINT32_FROM_LE(strf->compression)) - { + switch (codec_fcc) { case GST_MAKE_FOURCC('I','4','2','0'): case GST_MAKE_FOURCC('Y','U','Y','2'): - newcaps = GST_CAPS_NEW ( - "avidemux_video_src", - "video/raw", - "format", GST_PROPS_FOURCC(GUINT32_FROM_LE(strf->compression)), - "width", GST_PROPS_INT(strf->width), - "height", GST_PROPS_INT(strf->height) + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_raw", + "video/x-raw-yuv", + "format", GST_PROPS_FOURCC (codec_fcc) ); - codecname = g_strdup_printf("Raw Video (%4.4s)", - (char *) &strf->compression); + codecname = g_strdup_printf("Raw Video (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('M','J','P','G'): /* YUY2 MJPEG */ case GST_MAKE_FOURCC('J','P','E','G'): /* generic (mostly RGB) MJPEG */ case GST_MAKE_FOURCC('P','I','X','L'): /* Miro/Pinnacle fourccs */ case GST_MAKE_FOURCC('V','I','X','L'): /* Miro/Pinnacle fourccs */ - newcaps = GST_CAPS_NEW ( - "avidemux_video_src", - "video/jpeg", - "width", GST_PROPS_INT(strf->width), - "height", GST_PROPS_INT(strf->height) + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_jpeg", + "video/x-jpeg", + NULL ); - codecname = g_strdup_printf("Motion-JPEG (%4.4s)", - (char *) &strf->compression); + codecname = g_strdup_printf("Motion-JPEG (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('H','F','Y','U'): - codecname = g_strdup_printf("HuffYUV (%4.4s)", - (char *) &strf->compression); + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_hfyu", + "video/x-huffyuv", + NULL + ); + codecname = g_strdup_printf("HuffYUV (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('M','P','E','G'): case GST_MAKE_FOURCC('M','P','G','I'): - newcaps = GST_CAPS_NEW ( - "avidemux_video_src", + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_mpeg", "video/mpeg", - "width", GST_PROPS_INT(strf->width), - "height", GST_PROPS_INT(strf->height) + "systemstream", GST_PROPS_BOOLEAN (FALSE), + "mpegversion", GST_PROPS_BOOLEAN (1) ); - codecname = g_strdup_printf("MPEG-1 (%4.4s)", - (char *) &strf->compression); + codecname = g_strdup_printf("MPEG-1 (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('H','2','6','3'): case GST_MAKE_FOURCC('i','2','6','3'): case GST_MAKE_FOURCC('L','2','6','3'): @@ -680,67 +577,174 @@ gst_avi_demux_strf_vids (GstAviDemux *avi_demux) case GST_MAKE_FOURCC('V','D','O','W'): case GST_MAKE_FOURCC('V','I','V','O'): case GST_MAKE_FOURCC('x','2','6','3'): - codecname = g_strdup_printf("H263-compatible (%4.4s)", - (char *) &strf->compression); + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_263", + "video/x-h263", + NULL + ); + codecname = g_strdup_printf("H263-compatible (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; - case GST_MAKE_FOURCC('d','i','v','x'): + case GST_MAKE_FOURCC('D','I','V','3'): case GST_MAKE_FOURCC('D','I','V','4'): case GST_MAKE_FOURCC('D','I','V','5'): + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_divx3", + "video/x-divx", + "divxversion", GST_PROPS_INT(3) + ); + codecname = g_strdup_printf("DivX-3.x (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); + break; + + case GST_MAKE_FOURCC('d','i','v','x'): case GST_MAKE_FOURCC('D','I','V','X'): case GST_MAKE_FOURCC('D','X','5','0'): - newcaps = GST_CAPS_NEW ( - "avidemux_video_src", - "video/divx", - "width", GST_PROPS_INT(strf->width), - "height", GST_PROPS_INT(strf->height) + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_divx5", + "video/x-divx", + "divxversion", GST_PROPS_INT(5) ); - codecname = g_strdup_printf("DivX/MPEG-4 (%4.4s)", - (char *) &strf->compression); + codecname = g_strdup_printf("DivX 4.x/5.x (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('X','V','I','D'): case GST_MAKE_FOURCC('x','v','i','d'): - newcaps = GST_CAPS_NEW ( + caps = GST_AVI_VID_CAPS_NEW ( "avidemux_video_src", - "video/xvid", - "width", GST_PROPS_INT(strf->width), - "height", GST_PROPS_INT(strf->height) + "video/x-xvid", + NULL ); - codecname = g_strdup_printf("XviD/MPEG-4 (%4.4s)", - (char *) &strf->compression); + codecname = g_strdup_printf("XviD (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('M','P','G','4'): + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src", + "video/x-msmpeg", + "msmpegversion", GST_PROPS_INT (41) + ); + codecname = g_strdup_printf("MS MPEG-4.1 (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); + break; + case GST_MAKE_FOURCC('M','P','4','2'): + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src", + "video/x-msmpeg", + "msmpegversion", GST_PROPS_INT (42) + ); + codecname = g_strdup_printf("MS MPEG-4.2 (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); + break; + case GST_MAKE_FOURCC('M','P','4','3'): - codecname = g_strdup_printf("MS MPEG-4 (%4.4s)", - (char *) &strf->compression); + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src", + "video/x-msmpeg", + "msmpegversion", GST_PROPS_INT (43) + ); + codecname = g_strdup_printf("MS MPEG-4.3 (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); + break; + + case GST_MAKE_FOURCC('3','I','V','1'): + case GST_MAKE_FOURCC('3','I','V','2'): + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_3ivx", + "video/x-3ivx", + NULL + ); + codecname = g_strdup_printf("3ivX (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + case GST_MAKE_FOURCC('D','V','S','D'): case GST_MAKE_FOURCC('d','v','s','d'): - newcaps = GST_CAPS_NEW ( + caps = GST_AVI_VID_CAPS_NEW ( "avidemux_video_src", - "video/dv", - "format", GST_PROPS_STRING("NTSC"), /* FIXME??? */ - "width", GST_PROPS_INT(strf->width), - "height", GST_PROPS_INT(strf->height) + "video/x-dv", + "systemstream", GST_PROPS_BOOLEAN (FALSE) + ); + codecname = g_strdup_printf("Digital Video (" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); + break; + + case GST_MAKE_FOURCC('W','M','V','1'): + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_wmv1", + "video/x-wmv", + "wmvversion", GST_PROPS_INT (1) + ); + codecname = g_strdup_printf("Windows Media Format 1 (" + GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); + break; + + case GST_MAKE_FOURCC('W','M','V','2'): + caps = GST_AVI_VID_CAPS_NEW ( + "avidemux_video_src_wmv2", + "video/x-wmv", + "wmvversion", GST_PROPS_INT (2) ); - codecname = g_strdup_printf("Digital Video (%4.4s)", - (char *) &strf->compression); + codecname = g_strdup_printf("Windows Media Format 2 (" + GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS(codec_fcc)); break; + default: - codecname = g_strdup_printf("Unknown (%4.4s)", - (char *) &strf->compression); + g_warning ("avidemux: unkown video format " GST_FOURCC_FORMAT, + GST_FOURCC_ARGS(codec_fcc)); break; } - if (newcaps) capslist = gst_caps_append (capslist, newcaps); - /* set video codec info on streaminfo caps */ - entry = gst_props_entry_new("videocodec", GST_PROPS_STRING(codecname)); - gst_props_add_entry(avi_demux->streaminfo->properties, entry); - g_free(codecname); + if (strf != NULL && codecname != NULL) { + GstPropsEntry *entry; + entry = gst_props_entry_new("videocodec", + GST_PROPS_STRING(codecname)); + gst_props_add_entry(avi_demux->streaminfo->properties, entry); + } + if (codecname != NULL) { + g_free(codecname); + } + + return caps; +} + +static void +gst_avi_demux_strf_vids (GstAviDemux *avi_demux) +{ + gst_riff_strf_vids *strf; + gst_riff_strh *strh; + guint8 *strfdata; + GstPad *srcpad; + GstCaps *caps = NULL; + avi_stream_context *stream; + GstByteStream *bs = avi_demux->bs; + guint32 got_bytes; + gchar *padname; + + got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_vids)); + strf = (gst_riff_strf_vids *) strfdata; + if (got_bytes != sizeof (gst_riff_strf_vids)) + return; + + padname = g_strdup_printf ("video_%02d", avi_demux->num_v_streams); + srcpad = gst_pad_new_from_template (videosrctempl, padname); + g_free (padname); - gst_pad_try_set_caps (srcpad, capslist); + /* let's try some gstreamer-like mime-type caps */ + strh = &avi_demux->stream[avi_demux->num_streams].strh; + caps = gst_avi_demux_video_caps (GUINT32_FROM_LE(strf->compression), + strh, strf, avi_demux); + + if (caps != NULL) { + gst_pad_try_set_caps (srcpad, caps); + } gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats); gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask); gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event); @@ -757,130 +761,195 @@ gst_avi_demux_strf_vids (GstAviDemux *avi_demux) gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad); } -static void -gst_avi_demux_strf_auds (GstAviDemux *avi_demux) +#define GST_AVI_AUD_CAPS_NEW(name, mimetype, props...) \ + (strf != NULL) ? \ + GST_CAPS_NEW (name, \ + mimetype, \ + "rate", GST_PROPS_INT (rate), \ + "channels", GST_PROPS_INT (channels), \ + ##props) \ + : \ + GST_CAPS_NEW (name, \ + mimetype, \ + "rate", GST_PROPS_INT_RANGE (8000, 96000), \ + "channels", GST_PROPS_INT_RANGE (1, 2), \ + ##props) + + +static GstCaps * +gst_avi_demux_audio_caps (guint16 codec_id, + gst_riff_strf_auds *strf, + GstAviDemux *avi_demux) { - gst_riff_strf_auds *strf; - guint8 *strfdata; - GstPad *srcpad; - GstCaps *newcaps = NULL, *capslist = NULL; - avi_stream_context *stream; - GstByteStream *bs = avi_demux->bs; - guint32 got_bytes; - gchar *codecname; - GstPropsEntry *entry; + GstCaps *caps = NULL; + gchar *codecname = NULL; + gint rate = -1, channels = -1; - got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_auds)); - strf = (gst_riff_strf_auds *) strfdata; - if (got_bytes != sizeof (gst_riff_strf_auds)) - return; + if (strf != NULL) { + rate = GUINT32_FROM_LE (strf->rate); + channels = GUINT16_FROM_LE (strf->channels); + } - GST_INFO ( "gst_avi_demux: strf tag found in context auds"); - GST_INFO ( "gst_avi_demux: format %d", GUINT16_FROM_LE (strf->format)); - GST_INFO ( "gst_avi_demux: channels %d", GUINT16_FROM_LE (strf->channels)); - GST_INFO ( "gst_avi_demux: rate %d", GUINT32_FROM_LE (strf->rate)); - GST_INFO ( "gst_avi_demux: av_bps %d", GUINT32_FROM_LE (strf->av_bps)); - GST_INFO ( "gst_avi_demux: blockalign %d", GUINT16_FROM_LE (strf->blockalign)); - GST_INFO ( "gst_avi_demux: size %d", GUINT16_FROM_LE (strf->size)); + switch (codec_id) { + case GST_RIFF_WAVE_FORMAT_MPEGL3: /* mp3 */ + caps = GST_AVI_AUD_CAPS_NEW ("avi_demux_audio_src_mp3", + "audio/mpeg", + "layer", GST_PROPS_INT (3)); + codecname = g_strdup_printf("MPEG-1 layer 3 audio (0x%04x)", + codec_id); + break; - srcpad = gst_pad_new_from_template ( - GST_PAD_TEMPLATE_GET (src_audio_templ), g_strdup_printf ("audio_%02d", - avi_demux->num_a_streams)); - - capslist = gst_caps_append(NULL, GST_CAPS_NEW ( - "avidemux_audio_src", - "video/avi", - "format", GST_PROPS_STRING ("strf_auds"), - "fmt", GST_PROPS_INT (GUINT16_FROM_LE (strf->format)), - "channels", GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)), - "rate", GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)), - "av_bps", GST_PROPS_INT (GUINT32_FROM_LE (strf->av_bps)), - "blockalign", GST_PROPS_INT (GUINT16_FROM_LE (strf->blockalign)), - "size", GST_PROPS_INT (GUINT16_FROM_LE (strf->size)) - )); - - /* let's try some gstreamer-formatted mime types */ - switch (GUINT16_FROM_LE(strf->format)) - { - case GST_RIFF_WAVE_FORMAT_MPEGL3: - case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp3 */ - newcaps = gst_caps_new ("avidemux_audio_src", - "audio/x-mp3", - NULL); - codecname = g_strdup_printf("MPEG/audio (0x%04x)", - strf->format); + case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp1 or mp2 */ + caps = GST_AVI_AUD_CAPS_NEW ("avi_demux_audio_src_mp12", + "audio/mpeg", + "layer", GST_PROPS_INT (2)); + codecname = g_strdup_printf("MPEG-1 layer 1/2 audio (0x%04x)", + codec_id); break; - case GST_RIFF_WAVE_FORMAT_PCM: /* PCM/wav */ - newcaps = gst_caps_new ("avidemux_audio_src", - "audio/raw", - gst_props_new ( - "format", GST_PROPS_STRING ("int"), - "law", GST_PROPS_INT (0), - "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN), - "signed", GST_PROPS_BOOLEAN ((GUINT16_FROM_LE (strf->size) != 8)), - "width", GST_PROPS_INT ((GUINT16_FROM_LE (strf->blockalign)*8) / - GUINT16_FROM_LE (strf->channels)), - "depth", GST_PROPS_INT (GUINT16_FROM_LE (strf->size)), - "rate", GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)), - "channels", GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)), - NULL - )); + + case GST_RIFF_WAVE_FORMAT_PCM: /* PCM/wav */ { + GstPropsEntry *width = NULL, *depth = NULL, *signedness = NULL; + + if (strf != NULL) { + gint ba = GUINT16_FROM_LE (strf->blockalign); + gint ch = GUINT16_FROM_LE (strf->channels); + gint ws = GUINT16_FROM_LE (strf->size); + + width = gst_props_entry_new ("width", + GST_PROPS_INT (ba * 8 / ch)); + depth = gst_props_entry_new ("depth", + GST_PROPS_INT (ws)); + signedness = gst_props_entry_new ("signed", + GST_PROPS_BOOLEAN (ws != 8)); + } else { + signedness = gst_props_entry_new ("signed", + GST_PROPS_LIST ( + GST_PROPS_BOOLEAN (TRUE), + GST_PROPS_BOOLEAN (FALSE))); + width = gst_props_entry_new ("width", + GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16))); + depth = gst_props_entry_new ("depth", + GST_PROPS_LIST ( + GST_PROPS_INT (8), + GST_PROPS_INT (16))); + } + + caps = GST_AVI_AUD_CAPS_NEW ("avi_demux_audio_src_pcm", + "audio/x-raw-int", + "endianness", + GST_PROPS_INT (G_LITTLE_ENDIAN)); + gst_props_add_entry (caps->properties, width); + gst_props_add_entry (caps->properties, depth); + gst_props_add_entry (caps->properties, signedness); + codecname = g_strdup_printf("Raw PCM/WAV (0x%04x)", - strf->format); + codec_id); + } break; + case GST_RIFF_WAVE_FORMAT_MULAW: + if (strf != NULL && strf->size != 8) { + g_warning ("invalid depth (%d) of mulaw audio, overwriting.", + strf->size); + } + caps = GST_AVI_AUD_CAPS_NEW ("avidemux_audio_src", + "audio/x-mulaw", + NULL); + codecname = g_strdup_printf("A-law encoded (0x%04x)", + codec_id); + break; + case GST_RIFF_WAVE_FORMAT_ALAW: - if (strf->size != 8) - g_warning ("invalid depth (%d) of mulaw/alaw audio, overwriting.", strf->size); - newcaps = gst_caps_new ("avidemux_audio_src", - "audio/raw", - gst_props_new ( - "format", GST_PROPS_STRING ("int"), - "law", GST_PROPS_INT (GUINT16_FROM_LE(strf->format) == GST_RIFF_WAVE_FORMAT_ALAW ? 2 : 1), - "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN), - "width", GST_PROPS_INT (8), - "depth", GST_PROPS_INT (8), - "rate", GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)), - "channels", GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)), - NULL - )); - codecname = g_strdup_printf("%s-law encoded (0x%04x)", - GUINT16_FROM_LE(strf->format) == GST_RIFF_WAVE_FORMAT_ALAW ? "A" : "Mu", strf->format); + if (strf != NULL && strf->size != 8) { + g_warning ("invalid depth (%d) of alaw audio, overwriting.", + strf->size); + } + caps = GST_AVI_AUD_CAPS_NEW ("avidemux_audio_src", + "audio/x-alaw", + NULL); + codecname = g_strdup_printf("A-law encoded (0x%04x)", + codec_id); break; + case GST_RIFF_WAVE_FORMAT_VORBIS1: /* ogg/vorbis mode 1 */ case GST_RIFF_WAVE_FORMAT_VORBIS2: /* ogg/vorbis mode 2 */ case GST_RIFF_WAVE_FORMAT_VORBIS3: /* ogg/vorbis mode 3 */ case GST_RIFF_WAVE_FORMAT_VORBIS1PLUS: /* ogg/vorbis mode 1+ */ case GST_RIFF_WAVE_FORMAT_VORBIS2PLUS: /* ogg/vorbis mode 2+ */ case GST_RIFF_WAVE_FORMAT_VORBIS3PLUS: /* ogg/vorbis mode 3+ */ - newcaps = gst_caps_new ("avidemux_audio_src", - "application/x-ogg", - NULL); - codecname = g_strdup_printf("Ogg/Vorbis (0x%04x)", - strf->format); + caps = GST_AVI_AUD_CAPS_NEW ("asf_demux_audio_src_vorbis", + "audio/x-vorbis", + NULL); + codecname = g_strdup_printf("Vorbis (0x%04x)", + codec_id); break; + case GST_RIFF_WAVE_FORMAT_A52: - newcaps = gst_caps_new ("avidemux_audio_src", - "audio/a52", - NULL); - codecname = g_strdup_printf("AC3/AC52 (0x%04x)", - strf->format); + caps = GST_AVI_AUD_CAPS_NEW ("asf_demux_audio_src_ac3", + "audio/x-ac3", + NULL); + codecname = g_strdup_printf("AC-3 (0x%04x)", + codec_id); break; + default: - g_warning ("avidemux: unkown audio format %d", GUINT16_FROM_LE(strf->format)); - codecname = g_strdup_printf("Unknown (0x%04x)", - strf->format); + g_warning ("avidemux: unkown audio format 0x%04x", + codec_id); break; } - if (newcaps) capslist = gst_caps_append(capslist, newcaps); + if (strf != NULL && codecname != NULL) { + /* set audio codec in streaminfo */ + GstPropsEntry *entry; + entry = gst_props_entry_new("audiocodec", + GST_PROPS_STRING(codecname)); + gst_props_add_entry(avi_demux->streaminfo->properties, entry); + } + if (codecname != NULL) { + g_free (codecname); + } + + return caps; +} - /* set audio codec in streaminfo */ - entry = gst_props_entry_new("audiocodec", GST_PROPS_STRING(codecname)); - gst_props_add_entry(avi_demux->streaminfo->properties, entry); - g_free(codecname); +static void +gst_avi_demux_strf_auds (GstAviDemux *avi_demux) +{ + gst_riff_strf_auds *strf; + guint8 *strfdata; + GstPad *srcpad; + GstCaps *caps = NULL; + avi_stream_context *stream; + GstByteStream *bs = avi_demux->bs; + guint32 got_bytes; + gchar *padname; + + got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_auds)); + strf = (gst_riff_strf_auds *) strfdata; + if (got_bytes != sizeof (gst_riff_strf_auds)) + return; - gst_pad_try_set_caps(srcpad, capslist); + GST_INFO ( "gst_avi_demux: strf tag found in context auds"); + GST_INFO ( "gst_avi_demux: format %d", GUINT16_FROM_LE (strf->format)); + GST_INFO ( "gst_avi_demux: channels %d", GUINT16_FROM_LE (strf->channels)); + GST_INFO ( "gst_avi_demux: rate %d", GUINT32_FROM_LE (strf->rate)); + GST_INFO ( "gst_avi_demux: av_bps %d", GUINT32_FROM_LE (strf->av_bps)); + GST_INFO ( "gst_avi_demux: blockalign %d", GUINT16_FROM_LE (strf->blockalign)); + GST_INFO ( "gst_avi_demux: size %d", GUINT16_FROM_LE (strf->size)); + + padname = g_strdup_printf ("audio_%02d", + avi_demux->num_a_streams); + srcpad = gst_pad_new_from_template (audiosrctempl, padname); + g_free (padname); + + caps = gst_avi_demux_audio_caps (GUINT16_FROM_LE (strf->format), + strf, avi_demux); + + if (caps != NULL) { + gst_pad_try_set_caps(srcpad, caps); + } gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats); gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask); gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event); @@ -897,16 +966,25 @@ gst_avi_demux_strf_auds (GstAviDemux *avi_demux) gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad); } +static GstCaps * +gst_avi_demux_iavs_caps (void) +{ + return GST_CAPS_NEW ("avi_type_dv", + "video/x-dv", + "systemstream", GST_PROPS_BOOLEAN (TRUE)); +} + static void gst_avi_demux_strf_iavs (GstAviDemux *avi_demux) { gst_riff_strf_iavs *strf; guint8 *strfdata; GstPad *srcpad; - GstCaps *newcaps = NULL, *capslist = NULL; + GstCaps *caps = NULL; avi_stream_context *stream; GstByteStream *bs = avi_demux->bs; guint32 got_bytes; + gchar *padname; got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_iavs)); strf = (gst_riff_strf_iavs *) strfdata; @@ -923,33 +1001,16 @@ gst_avi_demux_strf_iavs (GstAviDemux *avi_demux) GST_INFO ( "gst_avi_demux: DVReserved1 %08x", GUINT32_FROM_LE (strf->DVReserved1)); GST_INFO ( "gst_avi_demux: DVReserved2 %08x", GUINT32_FROM_LE (strf->DVReserved2)); - srcpad = gst_pad_new_from_template ( - GST_PAD_TEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d", - avi_demux->num_v_streams)); - - capslist = gst_caps_append(NULL, GST_CAPS_NEW ( - "avidemux_video_src", - "video/avi", - "format", GST_PROPS_STRING ("strf_iavs"), - "DVAAuxSrc", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc)), - "DVAAuxCtl", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl)), - "DVAAuxSrc1", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc1)), - "DVAAuxCtl1", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl1)), - "DVVAuxSrc", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxSrc)), - "DVVAuxCtl", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxCtl)), - "DVReserved1", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved1)), - "DVReserved2", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved2)) - )); - - newcaps = gst_caps_new ("avi_type_dv", - "video/dv", - gst_props_new ( - "format", GST_PROPS_STRING ("NTSC"), /* FIXME??? */ - NULL)); - - if (newcaps) capslist = gst_caps_append(capslist, newcaps); - - gst_pad_try_set_caps(srcpad, capslist); + padname = g_strdup_printf ("video_%02d", + avi_demux->num_v_streams); + srcpad = gst_pad_new_from_template (videosrctempl, padname); + g_free (padname); + + caps = gst_avi_demux_iavs_caps (); + + if (caps != NULL) { + gst_pad_try_set_caps(srcpad, caps); + } gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats); gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask); gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event); @@ -1821,6 +1882,37 @@ plugin_init (GModule *module, GstPlugin *plugin) { GstElementFactory *factory; GstTypeFactory *type; + gint i = 0; + GstCaps *audcaps = NULL, *vidcaps = NULL, *temp; + guint32 vid_list[] = { + GST_MAKE_FOURCC('I','4','2','0'), + GST_MAKE_FOURCC('Y','U','Y','2'), + GST_MAKE_FOURCC('M','J','P','G'), + GST_MAKE_FOURCC('D','V','S','D'), + GST_MAKE_FOURCC('W','M','V','1'), + GST_MAKE_FOURCC('W','M','V','2'), + GST_MAKE_FOURCC('M','P','G','4'), + GST_MAKE_FOURCC('M','P','4','2'), + GST_MAKE_FOURCC('M','P','4','3'), + GST_MAKE_FOURCC('H','F','Y','U'), + GST_MAKE_FOURCC('D','I','V','3'), + GST_MAKE_FOURCC('M','P','E','G'), + GST_MAKE_FOURCC('H','2','6','3'), + GST_MAKE_FOURCC('D','I','V','X'), + GST_MAKE_FOURCC('X','V','I','D'), + GST_MAKE_FOURCC('3','I','V','1'), + 0 /* end */ + }; + gint aud_list[] = { + GST_RIFF_WAVE_FORMAT_MPEGL3, + GST_RIFF_WAVE_FORMAT_MPEGL12, + GST_RIFF_WAVE_FORMAT_PCM, + GST_RIFF_WAVE_FORMAT_VORBIS1, + GST_RIFF_WAVE_FORMAT_A52, + GST_RIFF_WAVE_FORMAT_ALAW, + GST_RIFF_WAVE_FORMAT_MULAW, + -1 /* end */ + }; /* this filter needs the riff parser */ if (!gst_library_load ("gstbytestream")) @@ -1835,9 +1927,28 @@ plugin_init (GModule *module, GstPlugin *plugin) g_return_val_if_fail (factory != NULL, FALSE); gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_PRIMARY); - gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_audio_templ)); - gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_video_templ)); - gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_templ)); + for (i = 0; aud_list[i] != -1; i++) { + temp = gst_avi_demux_audio_caps (aud_list[i], NULL, NULL); + audcaps = gst_caps_append (audcaps, temp); + } + audiosrctempl = gst_pad_template_new ("audio_%02d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + audcaps, NULL); + for (i = 0; vid_list[i] != 0; i++) { + temp = gst_avi_demux_video_caps (vid_list[i], NULL, NULL, NULL); + vidcaps = gst_caps_append (vidcaps, temp); + } + vidcaps = gst_caps_append (vidcaps, + gst_avi_demux_iavs_caps ()); + videosrctempl = gst_pad_template_new ("video_%02d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + vidcaps, NULL); + gst_element_factory_add_pad_template (factory, audiosrctempl); + gst_element_factory_add_pad_template (factory, videosrctempl); + gst_element_factory_add_pad_template (factory, + GST_PAD_TEMPLATE_GET (sink_templ)); type = gst_type_factory_new (&avidefinition); gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type)); @@ -1853,4 +1964,3 @@ GstPluginDesc plugin_desc = { "avidemux", plugin_init }; - diff --git a/gst/avi/gstavimux.c b/gst/avi/gstavimux.c index 8dfa50fa..6b3a442b 100644 --- a/gst/avi/gstavimux.c +++ b/gst/avi/gstavimux.c @@ -84,55 +84,74 @@ GST_PAD_TEMPLATE_FACTORY (video_sink_factory, GST_PAD_SINK, GST_PAD_REQUEST, GST_CAPS_NEW ( - "avimux_sink_video_avi", - "video/avi", - "format", GST_PROPS_STRING ("strf_vids") - ), - GST_CAPS_NEW ( "avimux_sink_video_yuv", - "video/raw", + "video/x-raw-yuv", "format", GST_PROPS_LIST ( GST_PROPS_FOURCC (GST_MAKE_FOURCC('Y','U','Y','2')), - GST_PROPS_FOURCC (GST_MAKE_FOURCC('I','4','2','0')), - GST_PROPS_FOURCC (GST_MAKE_FOURCC('Y','4','1','P')) + GST_PROPS_FOURCC (GST_MAKE_FOURCC('I','4','2','0')) ), "width", GST_PROPS_INT_RANGE (16, 4096), "height", GST_PROPS_INT_RANGE (16, 4096) ), GST_CAPS_NEW ( - "avimux_sink_video_rgb", - "video/raw", - "format", GST_PROPS_FOURCC (GST_MAKE_FOURCC('R','G','B',' ')), + "avimux_sink_video_jpeg", + "video/x-jpeg", + "width", GST_PROPS_INT_RANGE (16, 4096), + "height", GST_PROPS_INT_RANGE (16, 4096) + ), + GST_CAPS_NEW ( + "avimux_sink_video_divx", + "video/x-divx", "width", GST_PROPS_INT_RANGE (16, 4096), "height", GST_PROPS_INT_RANGE (16, 4096), - "depth", GST_PROPS_LIST( - GST_PROPS_INT(16), - GST_PROPS_INT(16), - GST_PROPS_INT(24), - GST_PROPS_INT(32) - ), - "bpp", GST_PROPS_LIST( - GST_PROPS_INT(15), - GST_PROPS_INT(16), - GST_PROPS_INT(24), - GST_PROPS_INT(32) - ) + "divxversion", GST_PROPS_INT_RANGE (3, 5) ), GST_CAPS_NEW ( - "avimux_sink_video_jpeg", - "video/jpeg", + "avimux_sink_video_xvid", + "video/x-xvid", "width", GST_PROPS_INT_RANGE (16, 4096), "height", GST_PROPS_INT_RANGE (16, 4096) ), GST_CAPS_NEW ( - "avimux_sink_video_divx", - "video/divx", + "avimux_sink_video_3ivx", + "video/x-3ivx", "width", GST_PROPS_INT_RANGE (16, 4096), "height", GST_PROPS_INT_RANGE (16, 4096) ), GST_CAPS_NEW ( - "avimux_sink_video_xvid", - "video/xvid", + "avimux_sink_video_msmpeg", + "video/x-msmpeg", + "width", GST_PROPS_INT_RANGE (16, 4096), + "height", GST_PROPS_INT_RANGE (16, 4096), + "msmpegversion", GST_PROPS_INT_RANGE (41, 43) + ), + GST_CAPS_NEW ( + "avimux_sink_video_mpeg", + "video/mpeg", + "width", GST_PROPS_INT_RANGE (16, 4096), + "height", GST_PROPS_INT_RANGE (16, 4096), + "mpegversion", GST_PROPS_INT (1), + "systemstream", GST_PROPS_BOOLEAN (FALSE) + ), + GST_CAPS_NEW ( + "avimux_sink_video_h263", + "video/x-h263", + "width", GST_PROPS_INT_RANGE (16, 4096), + "height", GST_PROPS_INT_RANGE (16, 4096) + ), + GST_CAPS_NEW ( + "avimux_sink_video_dv", + "video/x-dv", + "width", GST_PROPS_INT (720), + "height", GST_PROPS_LIST ( + GST_PROPS_INT (576), + GST_PROPS_INT (480) + ), + "systemstream", GST_PROPS_BOOLEAN (FALSE) + ), + GST_CAPS_NEW ( + "avimux_sink_video_hfyu", + "video/x-huffyuv", "width", GST_PROPS_INT_RANGE (16, 4096), "height", GST_PROPS_INT_RANGE (16, 4096) ) @@ -143,15 +162,8 @@ GST_PAD_TEMPLATE_FACTORY (audio_sink_factory, GST_PAD_SINK, GST_PAD_REQUEST, GST_CAPS_NEW ( - "avimux_sink_audio", - "video/avi", - "format", GST_PROPS_STRING ("strf_auds") - ), - GST_CAPS_NEW ( - "avimux_sink_audio", - "audio/raw", - "format", GST_PROPS_STRING ("int"), - "law", GST_PROPS_INT (0), + "avimux_sink_audio_raw", + "audio/x-raw-int", "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN), "signed", GST_PROPS_LIST ( GST_PROPS_BOOLEAN (TRUE), @@ -165,18 +177,27 @@ GST_PAD_TEMPLATE_FACTORY (audio_sink_factory, GST_PROPS_INT (8), GST_PROPS_INT (16) ), - "rate", GST_PROPS_INT_RANGE (1000, 48000), + "rate", GST_PROPS_INT_RANGE (1000, 96000), + "channels", GST_PROPS_INT_RANGE (1, 2) + ), + GST_CAPS_NEW ( + "avimux_sink_audio_mpeg", + "audio/mpeg", + "layer", GST_PROPS_INT_RANGE (1, 3), + "rate", GST_PROPS_INT_RANGE (1000, 96000), "channels", GST_PROPS_INT_RANGE (1, 2) ), GST_CAPS_NEW ( - "avimux_sink_audio", - "audio/x-mp3", - NULL + "avimux_sink_audio_vorbis", + "audio/x-vorbis", + "rate", GST_PROPS_INT_RANGE (1000, 96000), + "channels", GST_PROPS_INT_RANGE (1, 2) ), GST_CAPS_NEW ( - "avimux_sink_audio", - "application/x-ogg", - NULL + "avimux_sink_audio_ac3", + "audio/x-ac3", + "rate", GST_PROPS_INT_RANGE (1000, 96000), + "channels", GST_PROPS_INT_RANGE (1, 6) ) ) @@ -237,7 +258,8 @@ gst_avimux_class_init (GstAviMuxClass *klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BIGFILE, - g_param_spec_boolean("bigfile","Bigfile Support","Whether to capture large or small AVI files", + g_param_spec_boolean("bigfile","Bigfile Support", + "Support for openDML-2.0 (big) AVI files", 0,G_PARAM_READWRITE)); gstelement_class->request_new_pad = gst_avimux_request_new_pad; @@ -300,7 +322,7 @@ gst_avimux_init (GstAviMux *avimux) } static GstPadLinkReturn -gst_avimux_sinkconnect (GstPad *pad, GstCaps *vscaps) +gst_avimux_vidsinkconnect (GstPad *pad, GstCaps *vscaps) { GstAviMux *avimux; GstCaps *caps; @@ -311,170 +333,188 @@ gst_avimux_sinkconnect (GstPad *pad, GstCaps *vscaps) if (!GST_CAPS_IS_FIXED (vscaps)) return GST_PAD_LINK_DELAYED; - GST_DEBUG ("avimux: sinkconnect triggered on %s", gst_pad_get_name (pad)); + GST_DEBUG ("avimux: video sinkconnect triggered on %s", + gst_pad_get_name (pad)); for (caps = vscaps; caps != NULL; caps = vscaps = vscaps->next) { const gchar* mimetype = gst_caps_get_mime(caps); - - if (!strcmp (mimetype, "video/avi")) - { - const gchar* format; - - gst_caps_get_string (caps, "format", &format); - - if (!strncmp (format, "strf_vids", 9)) { - avimux->vids.size = sizeof(gst_riff_strf_vids); - gst_caps_get (caps, - "width", &avimux->vids.width, - "height", &avimux->vids.height, - "planes", &avimux->vids.planes, - "bit_cnt", &avimux->vids.bit_cnt, - "compression", &avimux->vids.compression, - "image_size", &avimux->vids.image_size, - "xpels_meter", &avimux->vids.xpels_meter, - "ypels_meter", &avimux->vids.ypels_meter, - "num_colors", &avimux->vids.num_colors, - "imp_colors", &avimux->vids.imp_colors, - NULL); - avimux->vids_hdr.fcc_handler = avimux->vids.compression; - avimux->avi_hdr.width = avimux->vids.width; - avimux->avi_hdr.height = avimux->vids.height; - goto done; - } - else if (!strncmp (format, "strf_auds", 9)) { - gst_caps_get (caps, - "format", &avimux->auds.format, - "channels", &avimux->auds.channels, - "rate", &avimux->auds.rate, - "av_bps", &avimux->auds.av_bps, - "blockalign", &avimux->auds.blockalign, - "size", &avimux->auds.size, - NULL); - avimux->auds_hdr.samplesize = avimux->auds_hdr.scale = avimux->auds.blockalign; - avimux->auds_hdr.rate = avimux->auds.av_bps; - goto done; - } - } - else if (!strcmp (mimetype, "video/raw")) + gfloat fps = 0.; + + /* global */ + avimux->vids.size = sizeof(gst_riff_strf_vids); + avimux->vids.planes = 1; + gst_caps_get (caps, "width", &avimux->vids.width, + "height", &avimux->vids.height, + "framerate", &fps, + NULL); + if (fps != 0.) + avimux->vids_hdr.scale = avimux->vids_hdr.rate / fps; + + if (!strcmp (mimetype, "video/x-raw-yuv")) { guint32 format; - gint temp; gst_caps_get_fourcc_int (caps, "format", &format); + avimux->vids.compression = format; switch (format) { case GST_MAKE_FOURCC('Y','U','Y','2'): + avimux->vids.bit_cnt = 16; + break; case GST_MAKE_FOURCC('I','4','2','0'): - case GST_MAKE_FOURCC('Y','4','1','P'): - case GST_MAKE_FOURCC('R','G','B',' '): - avimux->vids.size = sizeof(gst_riff_strf_vids); - gst_caps_get (caps, "width", &avimux->vids.width, - "height", &avimux->vids.height, NULL); - avimux->vids.planes = 1; - switch (format) - { - case GST_MAKE_FOURCC('Y','U','Y','2'): - avimux->vids.bit_cnt = 16; /* YUY2 */ - break; - case GST_MAKE_FOURCC('R','G','B',' '): - gst_caps_get_int (caps, "bpp", &temp); /* RGB */ - avimux->vids.bit_cnt = temp; - break; - case GST_MAKE_FOURCC('Y','4','1','P'): - case GST_MAKE_FOURCC('I','4','2','0'): - avimux->vids.bit_cnt = 12; /* Y41P or I420 */ - break; - } - gst_caps_get_fourcc_int(caps, "format", &avimux->vids.compression); - avimux->vids_hdr.fcc_handler = avimux->vids.compression; - avimux->vids.image_size = avimux->vids.height * avimux->vids.width; - avimux->avi_hdr.width = avimux->vids.width; - avimux->avi_hdr.height = avimux->vids.height; - goto done; - default: + avimux->vids.bit_cnt = 12; break; } + + goto done; } - else if (!strcmp (mimetype, "video/jpeg") || - !strcmp (mimetype, "video/xvid") || - !strcmp (mimetype, "video/divx")) + else { - avimux->vids.size = sizeof(gst_riff_strf_vids); - gst_caps_get (caps, "width", &avimux->vids.width, - "height", &avimux->vids.height, NULL); - avimux->vids.planes = 1; - avimux->vids.bit_cnt = 24; + avimux->vids.bit_cnt = 24; + avimux->vids.compression = 0; - if (!strcmp (mimetype, "video/jpeg")) + /* find format */ + if (!strcmp (mimetype, "video/x-huffyuv")) { + avimux->vids.compression = GST_MAKE_FOURCC('H','F','Y','U'); + } else if (!strcmp (mimetype, "video/x-jpeg")) { avimux->vids.compression = GST_MAKE_FOURCC('M','J','P','G'); - else if (!strcmp (mimetype, "video/divx")) - avimux->vids.compression = GST_MAKE_FOURCC('D','I','V','X'); - else if (!strcmp (mimetype, "video/xvid")) + } else if (!strcmp (mimetype, "video/x-divx")) { + gint divxversion; + gst_caps_get_int (caps, "divxversion", &divxversion); + switch (divxversion) { + case 3: + avimux->vids.compression = GST_MAKE_FOURCC('D','I','V','3'); + break; + case 4: + avimux->vids.compression = GST_MAKE_FOURCC('D','I','V','X'); + break; + case 5: + avimux->vids.compression = GST_MAKE_FOURCC('D','X','5','0'); + break; + } + } else if (!strcmp (mimetype, "video/x-xvid")) { avimux->vids.compression = GST_MAKE_FOURCC('X','V','I','D'); + } else if (!strcmp (mimetype, "video/x-3ivx")) { + avimux->vids.compression = GST_MAKE_FOURCC('3','I','V','2'); + } else if (!strcmp (mimetype, "video/x-msmpeg")) { + gint msmpegversion; + gst_caps_get_int (caps, "msmpegversion", &msmpegversion); + switch (msmpegversion) { + case 41: + avimux->vids.compression = GST_MAKE_FOURCC('M','P','G','4'); + break; + case 42: + avimux->vids.compression = GST_MAKE_FOURCC('M','P','4','2'); + break; + case 43: + avimux->vids.compression = GST_MAKE_FOURCC('M','P','4','3'); + break; + } + } else if (!strcmp (mimetype, "video/x-dv")) { + avimux->vids.compression = GST_MAKE_FOURCC('D','V','S','D'); + } else if (!strcmp (mimetype, "video/x-h263")) { + avimux->vids.compression = GST_MAKE_FOURCC('H','2','6','3'); + } else if (!strcmp (mimetype, "video/mpeg")) { + avimux->vids.compression = GST_MAKE_FOURCC('M','P','E','G'); + } + + if (!avimux->vids.compression) { + continue; + } - avimux->vids_hdr.fcc_handler = avimux->vids.compression; - avimux->avi_hdr.width = avimux->vids.width; - avimux->avi_hdr.height = avimux->vids.height; - avimux->vids.image_size = avimux->vids.height * avimux->vids.width; goto done; } - else if (!strcmp (mimetype, "audio/raw")) - { - gint width; + } + return GST_PAD_LINK_REFUSED; + +done: + avimux->vids_hdr.fcc_handler = avimux->vids.compression; + avimux->vids.image_size = avimux->vids.height * avimux->vids.width; + avimux->avi_hdr.width = avimux->vids.width; + avimux->avi_hdr.height = avimux->vids.height; + avimux->avi_hdr.us_frame = avimux->vids_hdr.scale; + return GST_PAD_LINK_OK; +} +static GstPadLinkReturn +gst_avimux_audsinkconnect (GstPad *pad, GstCaps *vscaps) +{ + GstAviMux *avimux; + GstCaps *caps; + + avimux = GST_AVIMUX (gst_pad_get_parent (pad)); + + /* we are not going to act on variable caps */ + if (!GST_CAPS_IS_FIXED (vscaps)) + return GST_PAD_LINK_DELAYED; + + GST_DEBUG ("avimux: audio sinkconnect triggered on %s", + gst_pad_get_name (pad)); + + for (caps = vscaps; caps != NULL; caps = vscaps = vscaps->next) + { + const gchar* mimetype = gst_caps_get_mime(caps); + + /* we want these for all */ + gst_caps_get (caps, "channels", &avimux->auds.channels, + "rate", &avimux->auds.rate, + NULL); + + if (!strcmp (mimetype, "audio/x-raw-int")) + { avimux->auds.format = GST_RIFF_WAVE_FORMAT_PCM; - gst_caps_get (caps, "channels", &avimux->auds.channels, - "rate", &avimux->auds.rate, - "width", &width, + + gst_caps_get (caps, "width", &avimux->auds.blockalign, "depth", &avimux->auds.size, NULL); - avimux->auds_hdr.rate = avimux->auds.av_bps = width * avimux->auds.rate * avimux->auds.channels / 8; - avimux->auds_hdr.samplesize = avimux->auds_hdr.scale = avimux->auds.blockalign = width * avimux->auds.channels/8; + + /* set some more info straight */ + avimux->auds.blockalign /= 8; + avimux->auds.blockalign *= avimux->auds.channels; + avimux->auds.av_bps = avimux->auds.blockalign * avimux->auds.rate; goto done; } - else if (!strcmp (mimetype, "audio/x-mp3")) + else if (!strcmp (mimetype, "audio/mpeg") || + !strcmp (mimetype, "audio/x-vorbis") || + !strcmp (mimetype, "audio/x-ac3")) { - gint layer = 3; + avimux->auds.format = 0; - if (GST_CAPS_PROPERTIES(caps) != NULL && - gst_caps_has_property(caps, "layer")) + if (!strcmp (mimetype, "audio/mpeg")) { + gint layer = 3; gst_caps_get_int(caps, "layer", &layer); - else - GST_DEBUG ( - "No layer specified, assuming layer 3"); - - /* we don't need to do anything here, compressed mp3 contains it all */ - avimux->auds.format = (layer == 3? - GST_RIFF_WAVE_FORMAT_MPEGL3 : - GST_RIFF_WAVE_FORMAT_MPEGL12); - avimux->auds_hdr.scale = avimux->auds_hdr.samplesize = - avimux->auds.blockalign = 1; - avimux->auds_hdr.rate = avimux->auds.av_bps = 0; - avimux->auds.size = 16; - /* nobody cares about this valus, but is has to be set (regardless of - * whether the value is correct) */ - avimux->auds.channels = 1; - /* we'll request this later on from the earlier pads */ - avimux->auds.rate = 0; - goto done; - } - else if (!strcmp (mimetype, "application/x-ogg")) - { - avimux->auds.format = GST_RIFF_WAVE_FORMAT_VORBIS1; - avimux->auds_hdr.scale = avimux->auds_hdr.samplesize = - avimux->auds.blockalign = 1; - avimux->auds_hdr.rate = avimux->auds.av_bps = 0; + switch (layer) { + case 3: + avimux->auds.format = GST_RIFF_WAVE_FORMAT_MPEGL3; + break; + case 1: case 2: + avimux->auds.format = GST_RIFF_WAVE_FORMAT_MPEGL12; + break; + } + } else if (!strcmp (mimetype, "audio/x-vorbis")) { + avimux->auds.format = GST_RIFF_WAVE_FORMAT_VORBIS3; + } else if (!strcmp (mimetype, "audio/x-ac3")) { + avimux->auds.format = GST_RIFF_WAVE_FORMAT_A52; + } + + avimux->auds.blockalign = 1; + avimux->auds.av_bps = 0; avimux->auds.size = 16; - /* see above */ - avimux->auds.channels = 1; - avimux->auds.rate = 0; + + if (!avimux->auds.format) { + continue; + } + goto done; } } return GST_PAD_LINK_REFUSED; done: + avimux->auds_hdr.rate = avimux->auds.blockalign * avimux->auds.rate; + avimux->auds_hdr.samplesize = avimux->auds.blockalign; + avimux->auds_hdr.scale = avimux->auds.blockalign; return GST_PAD_LINK_OK; } @@ -552,11 +592,13 @@ gst_avimux_request_new_pad (GstElement *element, if (templ == GST_PAD_TEMPLATE_GET (audio_sink_factory)) { g_return_val_if_fail(avimux->audiosinkpad == NULL, NULL); newpad = gst_pad_new_from_template (templ, "audio_00"); + gst_pad_set_link_function (newpad, gst_avimux_audsinkconnect); avimux->audiosinkpad = newpad; } else if (templ == GST_PAD_TEMPLATE_GET (video_sink_factory)) { g_return_val_if_fail(avimux->videosinkpad == NULL, NULL); newpad = gst_pad_new_from_template (templ, "video_00"); + gst_pad_set_link_function (newpad, gst_avimux_vidsinkconnect); avimux->videosinkpad = newpad; } else { @@ -568,7 +610,6 @@ gst_avimux_request_new_pad (GstElement *element, G_CALLBACK(gst_avimux_pad_link), (gpointer)avimux); g_signal_connect(newpad, "unlinked", G_CALLBACK(gst_avimux_pad_unlink), (gpointer)avimux); - gst_pad_set_link_function (newpad, gst_avimux_sinkconnect); gst_element_add_pad (element, newpad); gst_pad_set_event_function(newpad, gst_avimux_handle_event); gst_pad_set_event_mask_function(newpad, gst_avimux_get_event_masks); @@ -997,25 +1038,12 @@ gst_avimux_stop_file (GstAviMux *avimux) avimux->avi_hdr.tot_frames = avimux->num_frames; if (avimux->video_pad_connected) { avimux->vids_hdr.length = avimux->num_frames; - - /* get fps */ - framerate = gst_video_frame_rate(GST_PAD_PEER(avimux->videosinkpad)); - avimux->vids_hdr.scale = 1000000 / framerate; } - if (avimux->audio_pad_connected) - { - if (avimux->auds_hdr.scale) - avimux->auds_hdr.length = avimux->audio_size/(avimux->auds.channels*avimux->auds.size/8); - else - avimux->auds_hdr.length = 0; /* urm...? FIXME! ;-) */ - - /* sampling rate, if known - yes this is a hack */ - if (!avimux->auds.rate) - avimux->auds.rate = gst_video_frame_rate(GST_PAD_PEER(avimux->audiosinkpad)); + if (avimux->audio_pad_connected) { + avimux->auds_hdr.length = avimux->audio_size/avimux->auds.blockalign; } /* set rate and everything having to do with that */ - avimux->avi_hdr.us_frame = avimux->vids_hdr.scale; avimux->avi_hdr.max_bps = 0; if (avimux->audio_pad_connected) { /* calculate bps if needed */ |