]> git.sesse.net Git - vlc/blobdiff - modules/mux/avi.c
* modules/gui/wxwindows/preferences.cpp: windows can't have open _and_ save file...
[vlc] / modules / mux / avi.c
index e2d9068eb17d84679c78e8dc925765100a18d5c4..60a7ea22ec32cce0b5a21b7238520e7e89e09b9e 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: avi.c,v 1.10 2003/03/11 19:02:30 fenrir Exp $
+ * $Id: avi.c,v 1.13 2003/05/02 00:33:42 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -106,6 +106,7 @@ typedef struct avi_stream_s
 
     char fcc[4];
 
+    //mtime_t i_first_pts;
     mtime_t i_duration;       // in µs
 
     int     i_frames;        // total frame count
@@ -138,6 +139,8 @@ typedef struct avi_idx1_s
 
 struct sout_mux_sys_t
 {
+    vlc_bool_t b_write_header;
+
     int i_streams;
     int i_stream_video;
 
@@ -156,7 +159,7 @@ static int Open( vlc_object_t *p_this )
 {
     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
     sout_mux_sys_t  *p_sys = p_mux->p_sys;
-    sout_buffer_t   *p_hdr;
+    //sout_buffer_t   *p_hdr;
 
     p_sys = malloc( sizeof( sout_mux_sys_t ) );
     p_sys->i_streams = 0;
@@ -166,6 +169,7 @@ static int Open( vlc_object_t *p_this )
     p_sys->idx1.i_entry_count = 0;
     p_sys->idx1.i_entry_max = 10000;
     p_sys->idx1.entry = calloc( p_sys->idx1.i_entry_max, sizeof( avi_idx1_entry_t ) );
+    p_sys->b_write_header = VLC_TRUE;
 
     msg_Info( p_mux, "Open" );
 
@@ -176,10 +180,12 @@ static int Open( vlc_object_t *p_this )
     p_mux->p_sys        = p_sys;
     p_mux->i_preheader  = 8; // (fourcc,length) header
 
+#if 0
     /* room to add header at the end */
     p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE );
     memset( p_hdr->p_buffer, 0, HDR_SIZE );
     sout_AccessOutWrite( p_mux->p_access, p_hdr );
+#endif
 
     return VLC_SUCCESS;
 }
@@ -225,11 +231,12 @@ static void Close( vlc_object_t * p_this )
                     (uint64_t)p_stream->i_totalsize /
                     (uint64_t)p_stream->i_duration;
         }
-        msg_Err( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
-                 i_stream,
-                 p_stream->i_duration/1000000, p_stream->i_totalsize,
-                 p_stream->i_frames,
-                 p_stream->f_fps, p_stream->i_bitrate/1024 );
+        msg_Info( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
+                  i_stream,
+                  (int64_t)p_stream->i_duration / (int64_t)1000000,
+                  p_stream->i_totalsize,
+                  p_stream->i_frames,
+                  p_stream->f_fps, p_stream->i_bitrate/1024 );
     }
 
     p_hdr = avi_HeaderCreateRIFF( p_mux );
@@ -242,7 +249,7 @@ static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_ans
    switch( i_query )
    {
         case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
-            *(vlc_bool_t*)p_answer = VLC_TRUE;
+            *(vlc_bool_t*)p_answer = VLC_FALSE;
             return( SOUT_MUX_CAP_ERR_OK );
         default:
             return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
@@ -259,11 +266,6 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         msg_Err( p_mux, "too many streams" );
         return( -1 );
     }
-    if( p_input->input_format.p_format == NULL )
-    {
-        msg_Err( p_mux, "stream descriptor missing" );
-        return( -1 );
-    }
 
     msg_Dbg( p_mux, "adding input" );
     p_input->p_sys = malloc( sizeof( int ) );
@@ -271,56 +273,130 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
     *((int*)p_input->p_sys) = p_sys->i_streams;
     p_stream = &p_sys->stream[p_sys->i_streams];
 
-    switch( p_input->input_format.i_cat )
+    switch( p_input->p_fmt->i_cat )
     {
         case AUDIO_ES:
+            p_stream->i_cat = AUDIO_ES;
+            p_stream->fcc[0] = '0' + p_sys->i_streams / 10;
+            p_stream->fcc[1] = '0' + p_sys->i_streams % 10;
+            p_stream->fcc[2] = 'w';
+            p_stream->fcc[3] = 'b';
+
+            p_stream->p_bih = NULL;
+
+            p_stream->p_wf  = malloc( sizeof( WAVEFORMATEX ) + p_input->p_fmt->i_extra_data );
+#define p_wf p_stream->p_wf
+            p_wf->cbSize = p_input->p_fmt->i_extra_data;
+            if( p_wf->cbSize > 0 )
+            {
+                memcpy( &p_wf[1],
+                        p_input->p_fmt->p_extra_data,
+                        p_input->p_fmt->i_extra_data );
+            }
+            p_wf->nChannels      = p_input->p_fmt->i_channels;
+            p_wf->nSamplesPerSec = p_input->p_fmt->i_sample_rate;
+            p_wf->nBlockAlign    = p_input->p_fmt->i_block_align;
+            p_wf->nAvgBytesPerSec= p_input->p_fmt->i_bitrate / 8;
+            p_wf->wBitsPerSample = 0;
+
+            switch( p_input->p_fmt->i_fourcc )
             {
-                WAVEFORMATEX *p_wf =
-                    (WAVEFORMATEX*)p_input->input_format.p_format;
-
-                p_stream->i_cat = AUDIO_ES;
-                p_stream->fcc[0] = '0' + p_sys->i_streams / 10;
-                p_stream->fcc[1] = '0' + p_sys->i_streams % 10;
-                p_stream->fcc[2] = 'w';
-                p_stream->fcc[3] = 'b';
-
-                p_stream->p_bih = NULL;
-                p_stream->p_wf  = malloc( sizeof( WAVEFORMATEX ) + p_wf->cbSize );
-                memcpy( p_stream->p_wf,
-                        p_wf,
-                        sizeof( WAVEFORMATEX ) + p_wf->cbSize);
+                case VLC_FOURCC( 'a', '5', '2', ' ' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_A52;
+                    break;
+                case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_MPEGLAYER3;
+                    break;
+                case VLC_FOURCC( 'w', 'm', 'a', '1' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_WMA1;
+                    break;
+                case VLC_FOURCC( 'w', 'm', 'a', '2' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_WMA2;
+                    break;
+                case VLC_FOURCC( 'w', 'm', 'a', '3' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_WMA3;
+                    break;
+                    /* raw codec */
+                case VLC_FOURCC( 'u', '8', ' ', ' ' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_PCM;
+                    p_wf->nBlockAlign= p_wf->nChannels;
+                    p_wf->wBitsPerSample = 8;
+                    break;
+                case VLC_FOURCC( 's', '1', '6', 'l' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_PCM;
+                    p_wf->nBlockAlign= 2 * p_wf->nChannels;
+                    p_wf->wBitsPerSample = 16;
+                    break;
+                case VLC_FOURCC( 's', '2', '4', 'l' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_PCM;
+                    p_wf->nBlockAlign= 3 * p_wf->nChannels;
+                    p_wf->wBitsPerSample = 24;
+                    break;
+                case VLC_FOURCC( 's', '3', '2', 'l' ):
+                    p_wf->wFormatTag = WAVE_FORMAT_PCM;
+                    p_wf->nBlockAlign= 4 * p_wf->nChannels;
+                    p_wf->wBitsPerSample = 32;
+                    break;
+                default:
+                    return VLC_EGENERIC;
             }
+#undef p_wf
             break;
         case VIDEO_ES:
+            p_stream->i_cat = VIDEO_ES;
+            p_stream->fcc[0] = '0' + p_sys->i_streams / 10;
+            p_stream->fcc[1] = '0' + p_sys->i_streams % 10;
+            p_stream->fcc[2] = 'd';
+            p_stream->fcc[3] = 'c';
+            if( p_sys->i_stream_video < 0 )
             {
-                BITMAPINFOHEADER *p_bih =
-                    (BITMAPINFOHEADER*)p_input->input_format.p_format;;
-
-                p_stream->i_cat = VIDEO_ES;
-                p_stream->fcc[0] = '0' + p_sys->i_streams / 10;
-                p_stream->fcc[1] = '0' + p_sys->i_streams % 10;
-                p_stream->fcc[2] = 'd';
-                p_stream->fcc[3] = 'c';
-                if( p_sys->i_stream_video < 0 )
-                {
-                    p_sys->i_stream_video = p_sys->i_streams;
-                }
-                p_stream->p_wf  = NULL;
-                p_stream->p_bih = malloc( p_bih->biSize );
-                memcpy( p_stream->p_bih,
-                        p_bih,
-                        p_bih->biSize );
+                p_sys->i_stream_video = p_sys->i_streams;
+            }
+            p_stream->p_wf  = NULL;
+            p_stream->p_bih = malloc( sizeof( BITMAPINFOHEADER ) + p_input->p_fmt->i_extra_data );
+#define p_bih p_stream->p_bih
+            p_bih->biSize  = sizeof( BITMAPINFOHEADER ) + p_input->p_fmt->i_extra_data;
+            if( p_input->p_fmt->i_extra_data > 0 )
+            {
+                memcpy( &p_bih[1],
+                        p_input->p_fmt->p_extra_data,
+                        p_input->p_fmt->i_extra_data );
+            }
+            p_bih->biWidth = p_input->p_fmt->i_width;
+            p_bih->biHeight= p_input->p_fmt->i_height;
+            p_bih->biPlanes= 1;
+            p_bih->biBitCount       = 24;
+            p_bih->biSizeImage      = 0;
+            p_bih->biXPelsPerMeter  = 0;
+            p_bih->biYPelsPerMeter  = 0;
+            p_bih->biClrUsed        = 0;
+            p_bih->biClrImportant   = 0;
+            switch( p_input->p_fmt->i_fourcc )
+            {
+                case VLC_FOURCC( 'm', 'p', '4', 'v' ):
+                    p_bih->biCompression = VLC_FOURCC( 'X', 'V', 'I', 'D' );
+                    break;
+                default:
+                    p_bih->biCompression = p_input->p_fmt->i_fourcc;
+                    break;
             }
+#undef p_bih
             break;
         default:
-            return( -1 );
+            return( VLC_EGENERIC );
     }
     p_stream->i_totalsize = 0;
-    p_stream->i_frames     = 0;
+    p_stream->i_frames    = 0;
     p_stream->i_duration  = 0;
+    //p_stream->i_first_pts = 0;
+
+    /* fixed later */
+    p_stream->f_fps = 25;
+    p_stream->i_bitrate = 128 * 1024;
+
 
     p_sys->i_streams++;
-    return( 0 );
+    return( VLC_SUCCESS );
 }
 
 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
@@ -340,6 +416,18 @@ static int Mux      ( sout_mux_t *p_mux )
     int i_stream;
     int i;
 
+    if( p_sys->b_write_header )
+    {
+        sout_buffer_t *p_hdr;
+
+        msg_Dbg( p_mux, "writing header" );
+
+        p_hdr = avi_HeaderCreateRIFF( p_mux );
+        sout_AccessOutWrite( p_mux->p_access, p_hdr );
+
+        p_sys->b_write_header = VLC_FALSE;
+    }
+
     for( i = 0; i < p_mux->i_nb_inputs; i++ )
     {
         int i_count;
@@ -358,6 +446,13 @@ static int Mux      ( sout_mux_t *p_mux )
             p_data = sout_FifoGet( p_fifo );
 
             p_stream->i_frames++;
+            if( p_data->i_length < 0 )
+            {
+                msg_Warn( p_mux, "argg length < 0 l" );
+                sout_BufferDelete( p_mux->p_sout, p_data );
+                i_count--;
+                continue;
+            }
             p_stream->i_duration  += p_data->i_length;
             p_stream->i_totalsize += p_data->i_size;
 
@@ -401,8 +496,8 @@ static int Mux      ( sout_mux_t *p_mux )
                 p_data->i_size += 1;
             }
 
-            sout_AccessOutWrite( p_mux->p_access, p_data );
             p_sys->i_movi_size += p_data->i_size;
+            sout_AccessOutWrite( p_mux->p_access, p_data );
 
             i_count--;
         }
@@ -527,7 +622,7 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux,
         p_video = &p_sys->stream[p_sys->i_stream_video];
         if( p_video->i_frames <= 0 )
         {
-            p_video = NULL;
+        //    p_video = NULL;
         }
     }
 
@@ -540,14 +635,14 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux,
     }
     else
     {
-        msg_Warn( p_mux, "avi file without audio video track isn't a good idea..." );
+        msg_Warn( p_mux, "avi file without video track isn't a good idea..." );
         i_microsecperframe = 0;
         i_totalframes = 0;
     }
 
     for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ )
     {
-        if( p_sys->stream[p_sys->i_stream_video].i_duration > 0 )
+        if( p_sys->stream[i_stream].i_duration > 0 )
         {
             i_maxbytespersec +=
                 p_sys->stream[p_sys->i_stream_video].i_totalsize /
@@ -619,7 +714,7 @@ static int avi_HeaderAdd_strh( sout_mux_t   *p_mux,
                 if( i_samplesize > 1 )
                 {
                     i_scale = i_samplesize;
-                    i_rate = i_scale * p_stream->i_bitrate / 8;
+                    i_rate = /*i_scale **/ p_stream->i_bitrate / 8;
                 }
                 else
                 {