2002-02-02 16:27:20 +00:00
/* AVI muxer plugin for GStreamer
* Copyright ( C ) 2002 Ronald Bultje < rbultje @ ronald . bitfreak . net >
2001-12-22 23:22:30 +00:00
*
* 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 .
*/
2002-02-02 16:27:20 +00:00
/* based on:
* - the old avimuxer ( by Wim Taymans )
* - xawtv ' s aviwriter ( by Gerd Knorr )
* - mjpegtools ' avilib ( by Rainer Johanni )
* - openDML large - AVI docs
*/
2001-12-22 23:22:30 +00:00
2003-06-29 19:46:12 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2001-12-22 23:22:30 +00:00
# include <stdlib.h>
# include <string.h>
2002-10-23 18:56:28 +00:00
# include <gst/video/video.h>
2001-12-22 23:22:30 +00:00
# include "gstavimux.h"
2002-02-02 16:27:20 +00:00
# ifndef LE_FROM_GUINT16
# define LE_FROM_GUINT16 GUINT16_FROM_LE
# endif
# ifndef LE_FROM_GUINT32
# define LE_FROM_GUINT32 GUINT32_FROM_LE
# endif
2001-12-22 23:22:30 +00:00
/* AviMux signals and args */
enum {
/* FILL ME */
LAST_SIGNAL
} ;
enum {
ARG_0 ,
2002-02-02 16:27:20 +00:00
ARG_BIGFILE ,
2001-12-22 23:22:30 +00:00
} ;
2002-04-11 20:42:25 +00:00
GST_PAD_TEMPLATE_FACTORY ( src_factory ,
2001-12-22 23:22:30 +00:00
" src " ,
GST_PAD_SRC ,
GST_PAD_ALWAYS ,
GST_CAPS_NEW (
2002-02-02 16:27:20 +00:00
" avimux_src_video " ,
2001-12-22 23:22:30 +00:00
" video/avi " ,
NULL
)
)
2002-04-11 20:42:25 +00:00
GST_PAD_TEMPLATE_FACTORY ( video_sink_factory ,
2002-03-06 16:17:14 +00:00
" video_%d " ,
2001-12-22 23:22:30 +00:00
GST_PAD_SINK ,
GST_PAD_REQUEST ,
2002-02-02 16:27:20 +00:00
GST_CAPS_NEW (
2003-05-30 23:05:29 +00:00
" avimux_sink_video_yuv " ,
2003-07-06 20:49:52 +00:00
" video/x-raw-yuv " ,
2002-02-02 16:27:20 +00:00
" format " , GST_PROPS_LIST (
GST_PROPS_FOURCC ( GST_MAKE_FOURCC ( ' Y ' , ' U ' , ' Y ' , ' 2 ' ) ) ,
2003-07-06 20:49:52 +00:00
GST_PROPS_FOURCC ( GST_MAKE_FOURCC ( ' I ' , ' 4 ' , ' 2 ' , ' 0 ' ) )
2002-02-02 16:27:20 +00:00
) ,
" width " , GST_PROPS_INT_RANGE ( 16 , 4096 ) ,
" height " , GST_PROPS_INT_RANGE ( 16 , 4096 )
) ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" 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 " ,
2002-02-02 16:27:20 +00:00
" width " , GST_PROPS_INT_RANGE ( 16 , 4096 ) ,
" height " , GST_PROPS_INT_RANGE ( 16 , 4096 ) ,
2003-07-06 20:49:52 +00:00
" divxversion " , GST_PROPS_INT_RANGE ( 3 , 5 )
2002-02-02 16:27:20 +00:00
) ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" avimux_sink_video_xvid " ,
" video/x-xvid " ,
2002-02-02 16:27:20 +00:00
" width " , GST_PROPS_INT_RANGE ( 16 , 4096 ) ,
" height " , GST_PROPS_INT_RANGE ( 16 , 4096 )
2003-05-30 23:05:29 +00:00
) ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" avimux_sink_video_3ivx " ,
" video/x-3ivx " ,
2003-05-30 23:05:29 +00:00
" width " , GST_PROPS_INT_RANGE ( 16 , 4096 ) ,
" height " , GST_PROPS_INT_RANGE ( 16 , 4096 )
) ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" 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 " ,
2003-05-30 23:05:29 +00:00
" width " , GST_PROPS_INT_RANGE ( 16 , 4096 ) ,
" height " , GST_PROPS_INT_RANGE ( 16 , 4096 )
2001-12-22 23:22:30 +00:00
)
)
2002-04-11 20:42:25 +00:00
GST_PAD_TEMPLATE_FACTORY ( audio_sink_factory ,
2002-03-06 16:17:14 +00:00
" audio_%d " ,
2001-12-22 23:22:30 +00:00
GST_PAD_SINK ,
GST_PAD_REQUEST ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" avimux_sink_audio_raw " ,
" audio/x-raw-int " ,
2003-05-14 22:04:20 +00:00
" endianness " , GST_PROPS_INT ( G_LITTLE_ENDIAN ) ,
2002-02-02 16:27:20 +00:00
" 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 )
) ,
2003-07-06 20:49:52 +00:00
" rate " , GST_PROPS_INT_RANGE ( 1000 , 96000 ) ,
" channels " , GST_PROPS_INT_RANGE ( 1 , 2 )
) ,
GST_CAPS_NEW (
" avimux_sink_audio_mpeg " ,
" audio/mpeg " ,
2003-11-07 12:47:01 +00:00
" mpegversion " , GST_PROPS_INT ( 1 ) ,
2003-07-06 20:49:52 +00:00
" layer " , GST_PROPS_INT_RANGE ( 1 , 3 ) ,
" rate " , GST_PROPS_INT_RANGE ( 1000 , 96000 ) ,
2002-02-02 16:27:20 +00:00
" channels " , GST_PROPS_INT_RANGE ( 1 , 2 )
) ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" avimux_sink_audio_vorbis " ,
" audio/x-vorbis " ,
" rate " , GST_PROPS_INT_RANGE ( 1000 , 96000 ) ,
" channels " , GST_PROPS_INT_RANGE ( 1 , 2 )
2002-10-27 18:08:43 +00:00
) ,
GST_CAPS_NEW (
2003-07-06 20:49:52 +00:00
" avimux_sink_audio_ac3 " ,
" audio/x-ac3 " ,
" rate " , GST_PROPS_INT_RANGE ( 1000 , 96000 ) ,
" channels " , GST_PROPS_INT_RANGE ( 1 , 6 )
2001-12-22 23:22:30 +00:00
)
)
2003-11-01 02:07:52 +00:00
static void gst_avimux_base_init ( gpointer g_class ) ;
2002-02-02 16:27:20 +00:00
static void gst_avimux_class_init ( GstAviMuxClass * klass ) ;
static void gst_avimux_init ( GstAviMux * avimux ) ;
2002-10-23 18:56:28 +00:00
static void gst_avimux_loop ( GstElement * element ) ;
2002-02-02 16:27:20 +00:00
static gboolean gst_avimux_handle_event ( GstPad * pad ,
GstEvent * event ) ;
static GstPad * gst_avimux_request_new_pad ( GstElement * element ,
GstPadTemplate * templ ,
const gchar * name ) ;
static void gst_avimux_set_property ( GObject * object ,
guint prop_id ,
const GValue * value ,
GParamSpec * pspec ) ;
static void gst_avimux_get_property ( GObject * object ,
guint prop_id ,
GValue * value ,
GParamSpec * pspec ) ;
static GstElementStateReturn gst_avimux_change_state ( GstElement * element ) ;
2001-12-22 23:22:30 +00:00
static GstElementClass * parent_class = NULL ;
2002-01-19 14:57:47 +00:00
/*static guint gst_avimux_signals[LAST_SIGNAL] = { 0 }; */
2001-12-22 23:22:30 +00:00
GType
gst_avimux_get_type ( void )
{
static GType avimux_type = 0 ;
if ( ! avimux_type ) {
static const GTypeInfo avimux_info = {
sizeof ( GstAviMuxClass ) ,
2003-11-01 02:07:52 +00:00
gst_avimux_base_init ,
2001-12-22 23:22:30 +00:00
NULL ,
( GClassInitFunc ) gst_avimux_class_init ,
NULL ,
NULL ,
sizeof ( GstAviMux ) ,
0 ,
( GInstanceInitFunc ) gst_avimux_init ,
} ;
avimux_type = g_type_register_static ( GST_TYPE_ELEMENT , " GstAviMux " , & avimux_info , 0 ) ;
}
return avimux_type ;
}
2003-11-01 02:07:52 +00:00
static void
gst_avimux_base_init ( gpointer g_class )
{
GstElementClass * element_class = GST_ELEMENT_CLASS ( g_class ) ;
static GstElementDetails gst_avimux_details = GST_ELEMENT_DETAILS (
" Avi multiplexer " ,
" Codec/Muxer " ,
" Muxes audio and video into an avi stream " ,
" Ronald Bultje <rbultje@ronald.bitfreak.net> "
) ;
gst_element_class_add_pad_template ( element_class ,
GST_PAD_TEMPLATE_GET ( src_factory ) ) ;
gst_element_class_add_pad_template ( element_class ,
GST_PAD_TEMPLATE_GET ( audio_sink_factory ) ) ;
gst_element_class_add_pad_template ( element_class ,
GST_PAD_TEMPLATE_GET ( video_sink_factory ) ) ;
gst_element_class_set_details ( element_class , & gst_avimux_details ) ;
}
2001-12-22 23:22:30 +00:00
static void
gst_avimux_class_init ( GstAviMuxClass * klass )
{
GObjectClass * gobject_class ;
GstElementClass * gstelement_class ;
gobject_class = ( GObjectClass * ) klass ;
gstelement_class = ( GstElementClass * ) klass ;
parent_class = g_type_class_ref ( GST_TYPE_ELEMENT ) ;
2002-02-02 16:27:20 +00:00
g_object_class_install_property ( G_OBJECT_CLASS ( klass ) , ARG_BIGFILE ,
2003-07-06 20:49:52 +00:00
g_param_spec_boolean ( " bigfile " , " Bigfile Support " ,
" Support for openDML-2.0 (big) AVI files " ,
2002-02-02 16:27:20 +00:00
0 , G_PARAM_READWRITE ) ) ;
2001-12-22 23:22:30 +00:00
gstelement_class - > request_new_pad = gst_avimux_request_new_pad ;
2002-02-02 16:27:20 +00:00
gstelement_class - > change_state = gst_avimux_change_state ;
gstelement_class - > get_property = gst_avimux_get_property ;
gstelement_class - > set_property = gst_avimux_set_property ;
2001-12-22 23:22:30 +00:00
}
2002-10-23 18:56:28 +00:00
static const GstEventMask *
2002-07-24 21:41:38 +00:00
gst_avimux_get_event_masks ( GstPad * pad )
{
2002-10-23 18:56:28 +00:00
static const GstEventMask gst_avimux_sink_event_masks [ ] = {
{ GST_EVENT_EOS , 0 } ,
{ 0 , }
} ;
2002-07-24 21:41:38 +00:00
2003-06-01 12:23:46 +00:00
return gst_avimux_sink_event_masks ;
2002-07-24 21:41:38 +00:00
}
2001-12-22 23:22:30 +00:00
static void
gst_avimux_init ( GstAviMux * avimux )
{
2003-11-09 13:48:36 +00:00
GstElementClass * klass = GST_ELEMENT_GET_CLASS ( avimux ) ;
2001-12-22 23:22:30 +00:00
avimux - > srcpad = gst_pad_new_from_template (
2003-11-09 13:48:36 +00:00
gst_element_class_get_pad_template ( klass , " src " ) , " src " ) ;
2001-12-22 23:22:30 +00:00
gst_element_add_pad ( GST_ELEMENT ( avimux ) , avimux - > srcpad ) ;
2002-02-02 16:27:20 +00:00
GST_FLAG_SET ( GST_ELEMENT ( avimux ) , GST_ELEMENT_EVENT_AWARE ) ;
2002-10-23 18:56:28 +00:00
avimux - > audiosinkpad = NULL ;
avimux - > audio_pad_connected = FALSE ;
avimux - > videosinkpad = NULL ;
avimux - > video_pad_connected = FALSE ;
avimux - > audio_buffer_queue = NULL ;
avimux - > video_buffer_queue = NULL ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
avimux - > num_frames = 0 ;
/* audio/video/AVI header initialisation */
memset ( & ( avimux - > avi_hdr ) , 0 , sizeof ( gst_riff_avih ) ) ;
memset ( & ( avimux - > vids_hdr ) , 0 , sizeof ( gst_riff_strh ) ) ;
memset ( & ( avimux - > vids ) , 0 , sizeof ( gst_riff_strf_vids ) ) ;
memset ( & ( avimux - > auds_hdr ) , 0 , sizeof ( gst_riff_strh ) ) ;
memset ( & ( avimux - > auds ) , 0 , sizeof ( gst_riff_strf_auds ) ) ;
avimux - > vids_hdr . type = GST_MAKE_FOURCC ( ' v ' , ' i ' , ' d ' , ' s ' ) ;
avimux - > vids_hdr . rate = 1000000 ;
2003-10-09 22:11:53 +00:00
avimux - > avi_hdr . max_bps = 10000000 ;
2002-02-02 16:27:20 +00:00
avimux - > auds_hdr . type = GST_MAKE_FOURCC ( ' a ' , ' u ' , ' d ' , ' s ' ) ;
2003-06-01 12:23:46 +00:00
avimux - > vids_hdr . quality = 0xFFFFFFFF ;
avimux - > auds_hdr . quality = 0xFFFFFFFF ;
2002-02-02 16:27:20 +00:00
avimux - > idx = NULL ;
avimux - > write_header = TRUE ;
avimux - > enable_large_avi = TRUE ;
2002-02-20 07:25:39 +00:00
2002-10-23 18:56:28 +00:00
gst_element_set_loop_function ( GST_ELEMENT ( avimux ) , gst_avimux_loop ) ;
2001-12-22 23:22:30 +00:00
}
2003-01-10 13:38:32 +00:00
static GstPadLinkReturn
2003-07-06 20:49:52 +00:00
gst_avimux_vidsinkconnect ( GstPad * pad , GstCaps * vscaps )
2001-12-22 23:22:30 +00:00
{
GstAviMux * avimux ;
2002-02-02 16:27:20 +00:00
GstCaps * caps ;
2001-12-22 23:22:30 +00:00
avimux = GST_AVIMUX ( gst_pad_get_parent ( pad ) ) ;
2002-02-04 19:44:08 +00:00
/* we are not going to act on variable caps */
if ( ! GST_CAPS_IS_FIXED ( vscaps ) )
2003-01-10 10:22:25 +00:00
return GST_PAD_LINK_DELAYED ;
2002-02-04 19:44:08 +00:00
2003-07-06 20:49:52 +00:00
GST_DEBUG ( " avimux: video sinkconnect triggered on %s " ,
gst_pad_get_name ( pad ) ) ;
2002-02-02 16:27:20 +00:00
for ( caps = vscaps ; caps ! = NULL ; caps = vscaps = vscaps - > next )
{
const gchar * mimetype = gst_caps_get_mime ( caps ) ;
2003-07-06 20:49:52 +00:00
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 " ) )
2002-02-02 16:27:20 +00:00
{
2002-03-30 17:06:26 +00:00
guint32 format ;
gst_caps_get_fourcc_int ( caps , " format " , & format ) ;
2003-07-06 20:49:52 +00:00
avimux - > vids . compression = format ;
2002-03-30 17:06:26 +00:00
switch ( format )
2002-02-02 16:27:20 +00:00
{
case GST_MAKE_FOURCC ( ' Y ' , ' U ' , ' Y ' , ' 2 ' ) :
2003-07-06 20:49:52 +00:00
avimux - > vids . bit_cnt = 16 ;
break ;
2002-02-02 16:27:20 +00:00
case GST_MAKE_FOURCC ( ' I ' , ' 4 ' , ' 2 ' , ' 0 ' ) :
2003-07-06 20:49:52 +00:00
avimux - > vids . bit_cnt = 12 ;
2002-02-02 16:27:20 +00:00
break ;
}
2003-07-06 20:49:52 +00:00
goto done ;
2002-02-02 16:27:20 +00:00
}
2003-07-06 20:49:52 +00:00
else
2002-02-02 16:27:20 +00:00
{
2003-07-06 20:49:52 +00:00
avimux - > vids . bit_cnt = 24 ;
avimux - > vids . compression = 0 ;
2003-05-30 23:05:29 +00:00
2003-07-06 20:49:52 +00:00
/* 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 " ) ) {
2003-05-30 23:05:29 +00:00
avimux - > vids . compression = GST_MAKE_FOURCC ( ' M ' , ' J ' , ' P ' , ' G ' ) ;
2003-07-06 20:49:52 +00:00
} 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 " ) ) {
2003-05-30 23:05:29 +00:00
avimux - > vids . compression = GST_MAKE_FOURCC ( ' X ' , ' V ' , ' I ' , ' D ' ) ;
2003-07-06 20:49:52 +00:00
} 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 ;
}
2003-05-30 23:05:29 +00:00
2002-02-02 16:27:20 +00:00
goto done ;
}
2003-07-06 20:49:52 +00:00
}
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 ;
}
2002-03-30 17:06:26 +00:00
2003-07-06 20:49:52 +00:00
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 " ) )
{
2002-02-02 16:27:20 +00:00
avimux - > auds . format = GST_RIFF_WAVE_FORMAT_PCM ;
2003-07-06 20:49:52 +00:00
gst_caps_get ( caps , " width " , & avimux - > auds . blockalign ,
2002-07-09 10:45:37 +00:00
" depth " , & avimux - > auds . size ,
NULL ) ;
2003-07-06 20:49:52 +00:00
/* 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 ;
2002-02-02 16:27:20 +00:00
goto done ;
}
2003-07-06 20:49:52 +00:00
else if ( ! strcmp ( mimetype , " audio/mpeg " ) | |
! strcmp ( mimetype , " audio/x-vorbis " ) | |
! strcmp ( mimetype , " audio/x-ac3 " ) )
2002-02-02 16:27:20 +00:00
{
2003-07-06 20:49:52 +00:00
avimux - > auds . format = 0 ;
2002-03-30 17:06:26 +00:00
2003-07-06 20:49:52 +00:00
if ( ! strcmp ( mimetype , " audio/mpeg " ) ) {
gint layer = 3 ;
2003-05-14 21:59:18 +00:00
gst_caps_get_int ( caps , " layer " , & layer ) ;
2003-07-06 20:49:52 +00:00
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 ;
2003-06-01 12:23:46 +00:00
avimux - > auds . size = 16 ;
2003-07-06 20:49:52 +00:00
if ( ! avimux - > auds . format ) {
continue ;
}
2002-10-27 18:08:43 +00:00
goto done ;
}
2001-12-22 23:22:30 +00:00
}
2003-01-10 10:22:25 +00:00
return GST_PAD_LINK_REFUSED ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
done :
2003-07-06 20:49:52 +00:00
avimux - > auds_hdr . rate = avimux - > auds . blockalign * avimux - > auds . rate ;
avimux - > auds_hdr . samplesize = avimux - > auds . blockalign ;
avimux - > auds_hdr . scale = avimux - > auds . blockalign ;
2003-01-10 10:22:25 +00:00
return GST_PAD_LINK_OK ;
2001-12-22 23:22:30 +00:00
}
2002-09-19 10:46:01 +00:00
static void
2003-01-28 20:02:14 +00:00
gst_avimux_pad_link ( GstPad * pad ,
GstPad * peer ,
gpointer data )
2002-09-19 10:46:01 +00:00
{
GstAviMux * avimux = GST_AVIMUX ( data ) ;
const gchar * padname = gst_pad_get_name ( pad ) ;
2002-10-23 18:56:28 +00:00
if ( pad = = avimux - > audiosinkpad )
2002-09-19 10:46:01 +00:00
{
2002-10-23 18:56:28 +00:00
avimux - > audio_pad_connected = TRUE ;
2002-09-19 10:46:01 +00:00
}
2002-10-23 18:56:28 +00:00
else if ( pad = = avimux - > videosinkpad )
2002-09-19 10:46:01 +00:00
{
2002-10-23 18:56:28 +00:00
avimux - > video_pad_connected = TRUE ;
2002-09-19 10:46:01 +00:00
}
else
{
g_warning ( " Unknown padname '%s' " , padname ) ;
return ;
}
2003-06-29 19:46:12 +00:00
GST_DEBUG ( " pad '%s' connected " , padname ) ;
2002-09-19 10:46:01 +00:00
}
static void
2003-01-10 10:22:25 +00:00
gst_avimux_pad_unlink ( GstPad * pad ,
2003-01-28 20:02:14 +00:00
GstPad * peer ,
gpointer data )
2002-09-19 10:46:01 +00:00
{
GstAviMux * avimux = GST_AVIMUX ( data ) ;
const gchar * padname = gst_pad_get_name ( pad ) ;
2002-10-23 18:56:28 +00:00
if ( pad = = avimux - > audiosinkpad )
2002-09-19 10:46:01 +00:00
{
2002-10-23 18:56:28 +00:00
avimux - > audio_pad_connected = FALSE ;
avimux - > audiosinkpad = NULL ;
2002-09-19 10:46:01 +00:00
}
2002-10-23 18:56:28 +00:00
else if ( pad = = avimux - > videosinkpad )
2002-09-19 10:46:01 +00:00
{
2002-10-23 18:56:28 +00:00
avimux - > video_pad_connected = FALSE ;
avimux - > videosinkpad = NULL ;
2002-09-19 10:46:01 +00:00
}
else
{
g_warning ( " Unknown padname '%s' " , padname ) ;
return ;
}
2003-06-29 19:46:12 +00:00
GST_DEBUG ( " pad '%s' unlinked " , padname ) ;
2002-09-19 10:46:01 +00:00
}
2001-12-22 23:22:30 +00:00
static GstPad *
gst_avimux_request_new_pad ( GstElement * element ,
GstPadTemplate * templ ,
const gchar * req_name )
{
GstAviMux * avimux ;
GstPad * newpad ;
2003-11-09 13:48:36 +00:00
GstElementClass * klass = GST_ELEMENT_GET_CLASS ( element ) ;
2002-03-06 16:17:14 +00:00
2001-12-22 23:22:30 +00:00
g_return_val_if_fail ( templ ! = NULL , NULL ) ;
if ( templ - > direction ! = GST_PAD_SINK ) {
g_warning ( " avimux: request pad that is not a SINK pad \n " ) ;
return NULL ;
}
g_return_val_if_fail ( GST_IS_AVIMUX ( element ) , NULL ) ;
avimux = GST_AVIMUX ( element ) ;
2003-11-09 13:48:36 +00:00
if ( templ = = gst_element_class_get_pad_template ( klass , " audio_%d " ) ) {
2002-10-23 18:56:28 +00:00
g_return_val_if_fail ( avimux - > audiosinkpad = = NULL , NULL ) ;
newpad = gst_pad_new_from_template ( templ , " audio_00 " ) ;
2003-07-06 20:49:52 +00:00
gst_pad_set_link_function ( newpad , gst_avimux_audsinkconnect ) ;
2002-10-23 18:56:28 +00:00
avimux - > audiosinkpad = newpad ;
2001-12-22 23:22:30 +00:00
}
2003-11-09 13:48:36 +00:00
else if ( templ = = gst_element_class_get_pad_template ( klass , " video_%d " ) ) {
2002-10-23 18:56:28 +00:00
g_return_val_if_fail ( avimux - > videosinkpad = = NULL , NULL ) ;
newpad = gst_pad_new_from_template ( templ , " video_00 " ) ;
2003-07-06 20:49:52 +00:00
gst_pad_set_link_function ( newpad , gst_avimux_vidsinkconnect ) ;
2002-10-23 18:56:28 +00:00
avimux - > videosinkpad = newpad ;
2001-12-22 23:22:30 +00:00
}
else {
g_warning ( " avimux: this is not our template! \n " ) ;
return NULL ;
}
2003-01-26 16:25:59 +00:00
g_signal_connect ( newpad , " linked " ,
2003-01-28 20:02:14 +00:00
G_CALLBACK ( gst_avimux_pad_link ) , ( gpointer ) avimux ) ;
2003-01-10 10:22:25 +00:00
g_signal_connect ( newpad , " unlinked " ,
G_CALLBACK ( gst_avimux_pad_unlink ) , ( gpointer ) avimux ) ;
2001-12-22 23:22:30 +00:00
gst_element_add_pad ( element , newpad ) ;
2002-10-23 18:56:28 +00:00
gst_pad_set_event_function ( newpad , gst_avimux_handle_event ) ;
gst_pad_set_event_mask_function ( newpad , gst_avimux_get_event_masks ) ;
2001-12-22 23:22:30 +00:00
return newpad ;
}
2002-02-02 16:27:20 +00:00
/* maybe some of these functions should be moved to riff.h? */
/* DISCLAIMER: this function is ugly. So be it (i.e. it makes the rest easier) */
static GstBuffer *
gst_avimux_riff_get_avi_header ( GstAviMux * avimux )
{
GstBuffer * buffer ;
guint8 * buffdata ;
guint16 temp16 ;
guint32 temp32 ;
buffer = gst_buffer_new ( ) ;
/* first, let's see what actually needs to be in the buffer */
GST_BUFFER_SIZE ( buffer ) = 0 ;
GST_BUFFER_SIZE ( buffer ) + = 32 + sizeof ( gst_riff_avih ) ; /* avi header */
2002-10-23 18:56:28 +00:00
if ( avimux - > video_pad_connected )
2002-02-02 16:27:20 +00:00
{ /* we have video */
GST_BUFFER_SIZE ( buffer ) + = 28 + sizeof ( gst_riff_strh ) + sizeof ( gst_riff_strf_vids ) ; /* vid hdr */
GST_BUFFER_SIZE ( buffer ) + = 24 ; /* odml header */
}
2002-10-23 18:56:28 +00:00
if ( avimux - > audio_pad_connected )
2002-02-02 16:27:20 +00:00
{ /* we have audio */
GST_BUFFER_SIZE ( buffer ) + = 28 + sizeof ( gst_riff_strh ) + sizeof ( gst_riff_strf_auds ) ; /* aud hdr */
}
/* this is the "riff size" */
avimux - > header_size = GST_BUFFER_SIZE ( buffer ) ;
GST_BUFFER_SIZE ( buffer ) + = 12 ; /* avi data header */
/* allocate the buffer */
buffdata = GST_BUFFER_DATA ( buffer ) = g_malloc ( GST_BUFFER_SIZE ( buffer ) ) ;
/* avi header metadata */
memcpy ( buffdata , " RIFF " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > header_size + avimux - > idx_size + avimux - > data_size ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " AVI " , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > header_size - 4 * 5 ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " hdrl " , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " avih " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_avih ) ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the AVI header itself */
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . us_frame ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . max_bps ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . pad_gran ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . flags ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . tot_frames ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . init_frames ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . streams ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . bufsize ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . width ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . height ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . scale ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . rate ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . start ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > avi_hdr . length ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
2002-10-23 18:56:28 +00:00
if ( avimux - > video_pad_connected )
2002-02-04 19:44:08 +00:00
{
/* video header metadata */
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_strh ) + sizeof ( gst_riff_strf_vids ) + 4 * 5 ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " strl " , 4 ) ; buffdata + = 4 ;
/* generic header */
memcpy ( buffdata , " strh " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_strh ) ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the actual header */
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . type ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . fcc_handler ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . flags ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . priority ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . init_frames ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . scale ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . rate ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . start ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . length ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . bufsize ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . quality ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids_hdr . samplesize ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the video header */
memcpy ( buffdata , " strf " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_strf_vids ) ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the actual header */
temp32 = LE_FROM_GUINT32 ( avimux - > vids . size ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . width ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . height ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp16 = LE_FROM_GUINT16 ( avimux - > vids . planes ) ;
memcpy ( buffdata , & temp16 , 2 ) ; buffdata + = 2 ;
temp16 = LE_FROM_GUINT16 ( avimux - > vids . bit_cnt ) ;
memcpy ( buffdata , & temp16 , 2 ) ; buffdata + = 2 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . compression ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . image_size ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . xpels_meter ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . ypels_meter ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . num_colors ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > vids . imp_colors ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
}
2002-02-02 16:27:20 +00:00
2002-10-23 18:56:28 +00:00
if ( avimux - > audio_pad_connected )
2002-02-04 19:44:08 +00:00
{
/* audio header */
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_strh ) + sizeof ( gst_riff_strf_auds ) + 4 * 5 ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " strl " , 4 ) ; buffdata + = 4 ;
/* generic header */
memcpy ( buffdata , " strh " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_strh ) ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the actual header */
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . type ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . fcc_handler ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . flags ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . priority ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . init_frames ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . scale ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . rate ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . start ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . length ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . bufsize ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . quality ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds_hdr . samplesize ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the audio header */
memcpy ( buffdata , " strf " , 4 ) ; buffdata + = 4 ;
2002-10-23 18:56:28 +00:00
temp32 = LE_FROM_GUINT32 ( sizeof ( gst_riff_strf_auds ) ) ;
2002-02-04 19:44:08 +00:00
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
/* the actual header */
temp16 = LE_FROM_GUINT16 ( avimux - > auds . format ) ;
memcpy ( buffdata , & temp16 , 2 ) ; buffdata + = 2 ;
temp16 = LE_FROM_GUINT16 ( avimux - > auds . channels ) ;
memcpy ( buffdata , & temp16 , 2 ) ; buffdata + = 2 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds . rate ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > auds . av_bps ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp16 = LE_FROM_GUINT16 ( avimux - > auds . blockalign ) ;
memcpy ( buffdata , & temp16 , 2 ) ; buffdata + = 2 ;
temp16 = LE_FROM_GUINT16 ( avimux - > auds . size ) ;
memcpy ( buffdata , & temp16 , 2 ) ; buffdata + = 2 ;
}
2002-02-02 16:27:20 +00:00
2002-10-23 18:56:28 +00:00
if ( avimux - > video_pad_connected )
2002-02-04 19:44:08 +00:00
{
/* odml header */
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( guint32 ) + 4 * 3 ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " odml " , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " dmlh " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( sizeof ( guint32 ) ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > total_frames ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
}
2002-02-02 16:27:20 +00:00
/* avi data header */
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( avimux - > data_size ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
2002-02-04 19:44:08 +00:00
memcpy ( buffdata , " movi " , 4 ) ;
2002-02-02 16:27:20 +00:00
return buffer ;
}
static GstBuffer *
gst_avimux_riff_get_avix_header ( guint32 datax_size )
{
GstBuffer * buffer ;
guint8 * buffdata ;
guint32 temp32 ;
buffer = gst_buffer_new ( ) ;
GST_BUFFER_SIZE ( buffer ) = 24 ;
buffdata = GST_BUFFER_DATA ( buffer ) = g_malloc ( GST_BUFFER_SIZE ( buffer ) ) ;
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( datax_size + 4 * 4 ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " AVIX " , 4 ) ; buffdata + = 4 ;
memcpy ( buffdata , " LIST " , 4 ) ; buffdata + = 4 ;
temp32 = LE_FROM_GUINT32 ( datax_size ) ;
memcpy ( buffdata , & temp32 , 4 ) ; buffdata + = 4 ;
2002-02-04 19:44:08 +00:00
memcpy ( buffdata , " movi " , 4 ) ;
2002-02-02 16:27:20 +00:00
return buffer ;
}
static GstBuffer *
gst_avimux_riff_get_video_header ( guint32 video_frame_size )
{
GstBuffer * buffer ;
guint32 temp32 ;
buffer = gst_buffer_new ( ) ;
GST_BUFFER_DATA ( buffer ) = g_malloc ( 8 ) ;
GST_BUFFER_SIZE ( buffer ) = 8 ;
memcpy ( GST_BUFFER_DATA ( buffer ) , " 00db " , 4 ) ;
temp32 = LE_FROM_GUINT32 ( video_frame_size ) ;
memcpy ( GST_BUFFER_DATA ( buffer ) + 4 , & temp32 , 4 ) ;
return buffer ;
}
static GstBuffer *
gst_avimux_riff_get_audio_header ( guint32 audio_sample_size )
{
GstBuffer * buffer ;
guint32 temp32 ;
buffer = gst_buffer_new ( ) ;
GST_BUFFER_DATA ( buffer ) = g_malloc ( 8 ) ;
GST_BUFFER_SIZE ( buffer ) = 8 ;
memcpy ( GST_BUFFER_DATA ( buffer ) , " 01wb " , 4 ) ;
temp32 = LE_FROM_GUINT32 ( audio_sample_size ) ;
memcpy ( GST_BUFFER_DATA ( buffer ) + 4 , & temp32 , 4 ) ;
return buffer ;
}
/* some other usable functions (thankyou xawtv ;-) ) */
2001-12-22 23:22:30 +00:00
static void
2002-09-19 10:46:01 +00:00
gst_avimux_add_index ( GstAviMux * avimux , guchar * code , guint32 flags , guint32 size )
2001-12-22 23:22:30 +00:00
{
2002-02-02 16:27:20 +00:00
if ( avimux - > idx_index = = avimux - > idx_count )
{
avimux - > idx_count + = 256 ;
avimux - > idx = realloc ( avimux - > idx , avimux - > idx_count * sizeof ( gst_riff_index_entry ) ) ;
}
2002-09-19 10:46:01 +00:00
memcpy ( & ( avimux - > idx [ avimux - > idx_index ] . id ) , code , 4 ) ;
2002-02-02 16:27:20 +00:00
avimux - > idx [ avimux - > idx_index ] . flags = LE_FROM_GUINT32 ( flags ) ;
2002-09-19 16:52:11 +00:00
avimux - > idx [ avimux - > idx_index ] . offset = LE_FROM_GUINT32 ( avimux - > idx_offset ) ;
2002-02-02 16:27:20 +00:00
avimux - > idx [ avimux - > idx_index ] . size = LE_FROM_GUINT32 ( size ) ;
avimux - > idx_index + + ;
}
static void
gst_avimux_write_index ( GstAviMux * avimux )
{
GstBuffer * buffer ;
guint32 temp32 ;
buffer = gst_buffer_new ( ) ;
GST_BUFFER_SIZE ( buffer ) = 8 ;
GST_BUFFER_DATA ( buffer ) = g_malloc ( 8 ) ;
memcpy ( GST_BUFFER_DATA ( buffer ) , " idx1 " , 4 ) ;
temp32 = LE_FROM_GUINT32 ( avimux - > idx_index * sizeof ( gst_riff_index_entry ) ) ;
memcpy ( GST_BUFFER_DATA ( buffer ) + 4 , & temp32 , 4 ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( buffer ) ) ;
2002-02-02 16:27:20 +00:00
buffer = gst_buffer_new ( ) ;
GST_BUFFER_SIZE ( buffer ) = avimux - > idx_index * sizeof ( gst_riff_index_entry ) ;
GST_BUFFER_DATA ( buffer ) = ( unsigned char * ) avimux - > idx ;
2002-02-04 19:44:08 +00:00
avimux - > idx = NULL ; /* will be free()'ed by gst_buffer_unref() */
2002-02-02 16:27:20 +00:00
avimux - > total_data + = GST_BUFFER_SIZE ( buffer ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( buffer ) ) ;
2002-02-02 16:27:20 +00:00
avimux - > idx_size + = avimux - > idx_index * sizeof ( gst_riff_index_entry ) + 8 ;
/* update header */
avimux - > avi_hdr . flags | = GST_RIFF_AVIH_HASINDEX ;
}
static void
gst_avimux_bigfile ( GstAviMux * avimux , gboolean last )
{
GstBuffer * header ;
GstEvent * event ;
2003-10-09 22:11:53 +00:00
if ( avimux - > is_bigfile )
2002-02-02 16:27:20 +00:00
{
/* sarch back */
2002-05-26 21:59:22 +00:00
event = gst_event_new_seek ( GST_FORMAT_BYTES |
GST_SEEK_METHOD_SET |
GST_SEEK_FLAG_FLUSH ,
avimux - > avix_start ) ;
/* if the event succeeds */
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( event ) ) ;
2003-09-12 11:39:29 +00:00
/* rewrite AVIX header */
header = gst_avimux_riff_get_avix_header ( avimux - > datax_size ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( header ) ) ;
2003-09-12 11:39:29 +00:00
/* go back to current location */
event = gst_event_new_seek ( GST_FORMAT_BYTES |
GST_SEEK_METHOD_SET |
GST_SEEK_FLAG_FLUSH ,
avimux - > total_data ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( event ) ) ;
2002-02-02 16:27:20 +00:00
}
avimux - > avix_start = avimux - > total_data ;
if ( last )
return ;
avimux - > is_bigfile = TRUE ;
avimux - > numx_frames = 0 ;
avimux - > datax_size = 0 ;
header = gst_avimux_riff_get_avix_header ( 0 ) ;
avimux - > total_data + = GST_BUFFER_SIZE ( header ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( header ) ) ;
2002-02-02 16:27:20 +00:00
}
/* enough header blabla now, let's go on to actually writing the headers */
static void
gst_avimux_start_file ( GstAviMux * avimux )
{
GstBuffer * header ;
avimux - > total_data = 0 ;
avimux - > total_frames = 0 ;
avimux - > data_size = 4 ; /* ? */
avimux - > datax_size = 0 ;
avimux - > num_frames = 0 ;
avimux - > numx_frames = 0 ;
avimux - > audio_size = 0 ;
2003-05-30 23:05:29 +00:00
avimux - > audio_time = 0 ;
2002-09-19 16:52:11 +00:00
avimux - > avix_start = 0 ;
2002-02-02 16:27:20 +00:00
avimux - > idx_index = 0 ;
2002-09-19 16:52:11 +00:00
avimux - > idx_offset = 0 ; /* see 10 lines below */
2002-02-02 16:27:20 +00:00
avimux - > idx_size = 0 ;
avimux - > idx_count = 0 ;
avimux - > idx = NULL ;
2002-02-04 19:44:08 +00:00
/* header */
2003-01-28 20:02:14 +00:00
avimux - > avi_hdr . streams = ( avimux - > video_pad_connected ? 1 : 0 ) + ( avimux - > audio_pad_connected ? 1 : 0 ) ;
2002-02-02 16:27:20 +00:00
avimux - > is_bigfile = FALSE ;
2002-02-04 19:44:08 +00:00
2002-02-02 16:27:20 +00:00
header = gst_avimux_riff_get_avi_header ( avimux ) ;
avimux - > total_data + = GST_BUFFER_SIZE ( header ) ;
2003-07-22 20:55:08 +00:00
avimux - > idx_offset = avimux - > total_data ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( header ) ) ;
2002-02-02 16:27:20 +00:00
avimux - > write_header = FALSE ;
2002-02-03 15:47:02 +00:00
avimux - > restart = FALSE ;
2002-02-02 16:27:20 +00:00
}
static void
gst_avimux_stop_file ( GstAviMux * avimux )
{
GstEvent * event ;
GstBuffer * header ;
/* if bigfile, rewrite header, else write indexes */
2002-10-23 18:56:28 +00:00
if ( avimux - > video_pad_connected )
2002-02-02 16:27:20 +00:00
{
if ( avimux - > is_bigfile )
{
gst_avimux_bigfile ( avimux , TRUE ) ;
avimux - > idx_size = 0 ;
}
else
{
gst_avimux_write_index ( avimux ) ;
}
}
/* statistics/total_frames/... */
avimux - > avi_hdr . tot_frames = avimux - > num_frames ;
2003-06-01 12:23:46 +00:00
if ( avimux - > video_pad_connected ) {
2002-02-04 19:44:08 +00:00
avimux - > vids_hdr . length = avimux - > num_frames ;
2003-06-01 12:23:46 +00:00
}
2003-07-06 20:49:52 +00:00
if ( avimux - > audio_pad_connected ) {
2003-07-22 20:55:08 +00:00
avimux - > auds_hdr . length = ( avimux - > audio_time * avimux - > auds . rate ) / GST_SECOND ;
2002-10-24 19:32:11 +00:00
}
2002-02-02 16:27:20 +00:00
2002-10-23 18:56:28 +00:00
/* set rate and everything having to do with that */
2002-02-04 19:44:08 +00:00
avimux - > avi_hdr . max_bps = 0 ;
2003-05-14 21:59:18 +00:00
if ( avimux - > audio_pad_connected ) {
/* calculate bps if needed */
if ( ! avimux - > auds . av_bps ) {
2003-09-12 11:39:29 +00:00
if ( avimux - > audio_time ) {
avimux - > auds_hdr . rate = ( GST_SECOND * avimux - > audio_size ) / avimux - > audio_time ;
} else {
2003-09-16 10:00:02 +00:00
gst_element_error ( GST_ELEMENT ( avimux ) , " Audio stream available, but no audio data transferred (or data with invalid timestamps). Resulting AVI will be corrupt " ) ;
2003-09-12 11:39:29 +00:00
avimux - > auds_hdr . rate = 0 ;
}
2003-06-01 12:23:46 +00:00
avimux - > auds . av_bps = avimux - > auds_hdr . rate * avimux - > auds_hdr . scale ;
2003-05-14 21:59:18 +00:00
}
2002-02-04 19:44:08 +00:00
avimux - > avi_hdr . max_bps + = avimux - > auds . av_bps ;
2003-05-14 21:59:18 +00:00
}
2003-06-01 12:23:46 +00:00
if ( avimux - > video_pad_connected ) {
2002-09-19 16:52:11 +00:00
avimux - > avi_hdr . max_bps + = ( ( avimux - > vids . bit_cnt + 7 ) / 8 ) *
2003-07-22 20:55:08 +00:00
( 1000000. / avimux - > avi_hdr . us_frame ) *
2002-09-19 16:52:11 +00:00
avimux - > vids . image_size ;
2003-06-01 12:23:46 +00:00
}
2002-02-04 19:44:08 +00:00
2002-02-02 16:27:20 +00:00
/* seek and rewrite the header */
2003-10-09 22:11:53 +00:00
header = gst_avimux_riff_get_avi_header ( avimux ) ;
event = gst_event_new_seek ( GST_FORMAT_BYTES |
GST_SEEK_METHOD_SET , 0 ) ;
gst_pad_push ( avimux - > srcpad , GST_DATA ( event ) ) ;
gst_pad_push ( avimux - > srcpad , GST_DATA ( header ) ) ;
event = gst_event_new_seek ( GST_FORMAT_BYTES |
GST_SEEK_METHOD_SET , avimux - > total_data ) ;
gst_pad_push ( avimux - > srcpad , GST_DATA ( event ) ) ;
2002-02-02 16:27:20 +00:00
avimux - > write_header = TRUE ;
}
static void
gst_avimux_restart_file ( GstAviMux * avimux )
{
GstEvent * event ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
gst_avimux_stop_file ( avimux ) ;
2001-12-22 23:22:30 +00:00
2003-06-01 12:23:46 +00:00
event = gst_event_new ( GST_EVENT_EOS ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( event ) ) ;
2002-02-02 16:27:20 +00:00
2002-02-04 19:44:08 +00:00
gst_avimux_start_file ( avimux ) ;
2002-02-02 16:27:20 +00:00
}
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
/* handle events (search) */
static gboolean
gst_avimux_handle_event ( GstPad * pad , GstEvent * event )
{
GstAviMux * avimux ;
GstEventType type ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
avimux = GST_AVIMUX ( gst_pad_get_parent ( pad ) ) ;
type = event ? GST_EVENT_TYPE ( event ) : GST_EVENT_UNKNOWN ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
switch ( type ) {
2002-10-23 18:56:28 +00:00
case GST_EVENT_EOS :
/* is this allright? */
2003-06-01 12:23:46 +00:00
if ( pad = = avimux - > videosinkpad ) {
2002-10-23 18:56:28 +00:00
avimux - > video_pad_eos = TRUE ;
2003-06-01 12:23:46 +00:00
} else if ( pad = = avimux - > audiosinkpad ) {
2002-10-23 18:56:28 +00:00
avimux - > audio_pad_eos = TRUE ;
2003-06-01 12:23:46 +00:00
} else {
2002-10-23 18:56:28 +00:00
g_warning ( " Unknown pad for EOS! " ) ;
2003-06-01 12:23:46 +00:00
}
2002-10-23 18:56:28 +00:00
break ;
2002-02-02 16:27:20 +00:00
default :
break ;
2001-12-22 23:22:30 +00:00
}
2002-02-02 16:27:20 +00:00
return TRUE ;
2001-12-22 23:22:30 +00:00
}
2002-10-23 18:56:28 +00:00
/* fill the internal queue for each available pad */
2001-12-22 23:22:30 +00:00
static void
2002-10-23 18:56:28 +00:00
gst_avimux_fill_queue ( GstAviMux * avimux )
2001-12-22 23:22:30 +00:00
{
2002-10-23 18:56:28 +00:00
GstBuffer * buffer ;
2001-12-22 23:22:30 +00:00
2003-06-01 12:23:46 +00:00
while ( ! avimux - > audio_buffer_queue & &
avimux - > audiosinkpad & &
avimux - > audio_pad_connected & &
GST_PAD_IS_USABLE ( avimux - > audiosinkpad ) & &
! avimux - > audio_pad_eos )
2002-02-02 16:27:20 +00:00
{
2003-10-08 16:08:18 +00:00
buffer = GST_BUFFER ( gst_pad_pull ( avimux - > audiosinkpad ) ) ;
2003-06-01 12:23:46 +00:00
if ( GST_IS_EVENT ( buffer ) ) {
gst_avimux_handle_event ( avimux - > audiosinkpad , GST_EVENT ( buffer ) ) ;
} else {
avimux - > audio_buffer_queue = buffer ;
break ;
2002-10-23 18:56:28 +00:00
}
2002-02-02 16:27:20 +00:00
}
2001-12-22 23:22:30 +00:00
2003-06-01 12:23:46 +00:00
while ( ! avimux - > video_buffer_queue & &
avimux - > videosinkpad & &
avimux - > video_pad_connected & &
GST_PAD_IS_USABLE ( avimux - > videosinkpad ) & &
! avimux - > video_pad_eos )
2002-02-02 16:27:20 +00:00
{
2003-10-08 16:08:18 +00:00
buffer = GST_BUFFER ( gst_pad_pull ( avimux - > videosinkpad ) ) ;
2003-06-01 12:23:46 +00:00
if ( GST_IS_EVENT ( buffer ) ) {
gst_avimux_handle_event ( avimux - > videosinkpad , GST_EVENT ( buffer ) ) ;
} else {
avimux - > video_buffer_queue = buffer ;
break ;
2002-02-02 16:27:20 +00:00
}
2002-10-23 18:56:28 +00:00
}
}
2002-02-02 16:27:20 +00:00
2002-10-24 19:32:11 +00:00
/* send extra 'padding' data */
static void
gst_avimux_send_pad_data ( GstAviMux * avimux ,
gulong num_bytes )
{
GstBuffer * buffer ;
buffer = gst_buffer_new ( ) ;
GST_BUFFER_SIZE ( buffer ) = num_bytes ;
GST_BUFFER_DATA ( buffer ) = g_malloc ( num_bytes ) ;
memset ( GST_BUFFER_DATA ( buffer ) , 0 , num_bytes ) ;
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( buffer ) ) ;
2002-10-24 19:32:11 +00:00
}
2002-10-23 18:56:28 +00:00
/* do audio buffer */
static void
gst_avimux_do_audio_buffer ( GstAviMux * avimux )
{
GstBuffer * data = avimux - > audio_buffer_queue , * header ;
2003-07-22 20:55:08 +00:00
gulong total_size , pad_bytes = 0 ;
2002-10-23 18:56:28 +00:00
/* write a audio header + index entry */
2003-07-22 20:55:08 +00:00
if ( GST_BUFFER_SIZE ( data ) & 1 ) {
pad_bytes = 2 - ( GST_BUFFER_SIZE ( data ) & 1 ) ;
}
header = gst_avimux_riff_get_audio_header ( GST_BUFFER_SIZE ( data ) ) ;
total_size = GST_BUFFER_SIZE ( header ) + GST_BUFFER_SIZE ( data ) + pad_bytes ;
2002-10-23 18:56:28 +00:00
if ( avimux - > is_bigfile )
{
avimux - > datax_size + = total_size ;
2002-02-02 16:27:20 +00:00
}
2002-10-23 18:56:28 +00:00
else
2002-02-02 16:27:20 +00:00
{
2002-10-23 18:56:28 +00:00
avimux - > data_size + = total_size ;
avimux - > audio_size + = GST_BUFFER_SIZE ( data ) ;
2003-05-30 23:05:29 +00:00
avimux - > audio_time + = GST_BUFFER_DURATION ( data ) ;
2003-07-22 20:55:08 +00:00
gst_avimux_add_index ( avimux , " 01wb " , 0x0 , GST_BUFFER_SIZE ( data ) ) ;
2002-10-23 18:56:28 +00:00
}
2002-02-03 15:47:02 +00:00
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( header ) ) ;
gst_pad_push ( avimux - > srcpad , GST_DATA ( data ) ) ;
2003-07-22 20:55:08 +00:00
if ( pad_bytes ) {
2002-10-24 19:32:11 +00:00
gst_avimux_send_pad_data ( avimux , pad_bytes ) ;
2003-07-22 20:55:08 +00:00
}
avimux - > total_data + = total_size ;
avimux - > idx_offset + = total_size ;
2002-10-23 18:56:28 +00:00
avimux - > audio_buffer_queue = NULL ;
}
2002-02-02 16:27:20 +00:00
2002-10-23 18:56:28 +00:00
/* do video buffer */
static void
gst_avimux_do_video_buffer ( GstAviMux * avimux )
{
GstBuffer * data = avimux - > video_buffer_queue , * header ;
2003-07-22 20:55:08 +00:00
gulong total_size , pad_bytes = 0 ;
2002-02-02 16:27:20 +00:00
2002-10-23 18:56:28 +00:00
if ( avimux - > restart )
gst_avimux_restart_file ( avimux ) ;
/* write a video header + index entry */
if ( ( avimux - > is_bigfile ? avimux - > datax_size : avimux - > data_size ) + GST_BUFFER_SIZE ( data ) > 1024 * 1024 * 2000 )
{
if ( avimux - > enable_large_avi )
gst_avimux_bigfile ( avimux , FALSE ) ;
2002-02-02 16:27:20 +00:00
else
2002-10-23 18:56:28 +00:00
gst_avimux_restart_file ( avimux ) ;
}
2002-02-02 16:27:20 +00:00
2003-07-22 20:55:08 +00:00
if ( GST_BUFFER_SIZE ( data ) & 1 ) {
pad_bytes = 2 - ( GST_BUFFER_SIZE ( data ) & 1 ) ;
}
header = gst_avimux_riff_get_video_header ( GST_BUFFER_SIZE ( data ) ) ;
total_size = GST_BUFFER_SIZE ( header ) + GST_BUFFER_SIZE ( data ) + pad_bytes ;
2002-10-23 18:56:28 +00:00
avimux - > total_frames + + ;
if ( avimux - > is_bigfile )
{
avimux - > datax_size + = total_size ;
avimux - > numx_frames + + ;
2002-02-02 16:27:20 +00:00
}
else
{
2003-09-30 21:06:43 +00:00
guint flags = 0x2 ;
if ( GST_BUFFER_FLAG_IS_SET ( data , GST_BUFFER_KEY_UNIT ) )
flags | = 0x10 ;
2002-10-23 18:56:28 +00:00
avimux - > data_size + = total_size ;
avimux - > num_frames + + ;
2003-09-30 21:06:43 +00:00
gst_avimux_add_index ( avimux , " 00db " , flags , GST_BUFFER_SIZE ( data ) ) ;
2001-12-22 23:22:30 +00:00
}
2003-10-08 16:08:18 +00:00
gst_pad_push ( avimux - > srcpad , GST_DATA ( header ) ) ;
gst_pad_push ( avimux - > srcpad , GST_DATA ( data ) ) ;
2003-07-22 20:55:08 +00:00
if ( pad_bytes ) {
2002-10-24 19:32:11 +00:00
gst_avimux_send_pad_data ( avimux , pad_bytes ) ;
2003-07-22 20:55:08 +00:00
}
avimux - > total_data + = total_size ;
avimux - > idx_offset + = total_size ;
2002-10-23 18:56:28 +00:00
avimux - > video_buffer_queue = NULL ;
}
/* take the oldest buffer in our internal queue and push-it */
static gboolean
gst_avimux_do_one_buffer ( GstAviMux * avimux )
{
if ( avimux - > video_buffer_queue & &
avimux - > audio_buffer_queue )
{
if ( GST_BUFFER_TIMESTAMP ( avimux - > video_buffer_queue ) < =
GST_BUFFER_TIMESTAMP ( avimux - > audio_buffer_queue ) )
gst_avimux_do_video_buffer ( avimux ) ;
else
gst_avimux_do_audio_buffer ( avimux ) ;
}
else if ( avimux - > video_buffer_queue | |
avimux - > audio_buffer_queue )
{
if ( avimux - > video_buffer_queue )
gst_avimux_do_video_buffer ( avimux ) ;
else
gst_avimux_do_audio_buffer ( avimux ) ;
}
2003-05-30 23:05:29 +00:00
else {
/* simply finish off the file and send EOS */
gst_avimux_stop_file ( avimux ) ;
gst_pad_push ( avimux - > srcpad ,
2003-10-08 16:08:18 +00:00
GST_DATA ( gst_event_new ( GST_EVENT_EOS ) ) ) ;
2003-05-30 23:05:29 +00:00
gst_element_set_eos ( GST_ELEMENT ( avimux ) ) ;
2002-10-23 18:56:28 +00:00
return FALSE ;
2003-05-30 23:05:29 +00:00
}
2002-10-23 18:56:28 +00:00
return TRUE ;
}
static void
gst_avimux_loop ( GstElement * element )
{
GstAviMux * avimux ;
avimux = GST_AVIMUX ( element ) ;
/* first fill queue (some elements only set caps when
* flowing data ) , then write header */
gst_avimux_fill_queue ( avimux ) ;
if ( avimux - > write_header )
gst_avimux_start_file ( avimux ) ;
gst_avimux_do_one_buffer ( avimux ) ;
2001-12-22 23:22:30 +00:00
}
2002-02-02 16:27:20 +00:00
static void
gst_avimux_get_property ( GObject * object ,
guint prop_id ,
GValue * value ,
GParamSpec * pspec )
2001-12-22 23:22:30 +00:00
{
2002-02-02 16:27:20 +00:00
GstAviMux * avimux ;
2001-12-22 23:22:30 +00:00
/* it's not null if we got it, but it might not be ours */
g_return_if_fail ( GST_IS_AVIMUX ( object ) ) ;
2002-02-02 16:27:20 +00:00
avimux = GST_AVIMUX ( object ) ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
switch ( prop_id )
{
case ARG_BIGFILE :
g_value_set_boolean ( value , avimux - > enable_large_avi ) ;
break ;
2001-12-22 23:22:30 +00:00
default :
2002-02-02 16:27:20 +00:00
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , prop_id , pspec ) ;
2001-12-22 23:22:30 +00:00
break ;
}
}
2002-02-02 16:27:20 +00:00
static void
gst_avimux_set_property ( GObject * object ,
guint prop_id ,
const GValue * value ,
GParamSpec * pspec )
2001-12-22 23:22:30 +00:00
{
2002-02-02 16:27:20 +00:00
GstAviMux * avimux ;
2001-12-22 23:22:30 +00:00
/* it's not null if we got it, but it might not be ours */
g_return_if_fail ( GST_IS_AVIMUX ( object ) ) ;
2002-02-02 16:27:20 +00:00
avimux = GST_AVIMUX ( object ) ;
2001-12-22 23:22:30 +00:00
2002-02-02 16:27:20 +00:00
switch ( prop_id )
{
case ARG_BIGFILE :
avimux - > enable_large_avi = g_value_get_boolean ( value ) ;
break ;
2001-12-22 23:22:30 +00:00
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , prop_id , pspec ) ;
break ;
}
}
2002-02-02 16:27:20 +00:00
static GstElementStateReturn
gst_avimux_change_state ( GstElement * element )
{
GstAviMux * avimux ;
gint transition = GST_STATE_TRANSITION ( element ) ;
g_return_val_if_fail ( GST_IS_AVIMUX ( element ) , GST_STATE_FAILURE ) ;
avimux = GST_AVIMUX ( element ) ;
switch ( transition ) {
case GST_STATE_PAUSED_TO_PLAYING :
2002-10-23 18:56:28 +00:00
avimux - > video_pad_eos = avimux - > audio_pad_eos = FALSE ;
2002-02-02 16:27:20 +00:00
break ;
}
if ( GST_ELEMENT_CLASS ( parent_class ) - > change_state )
return GST_ELEMENT_CLASS ( parent_class ) - > change_state ( element ) ;
return GST_STATE_SUCCESS ;
}