OSDN Git Service

Fix a hang in sync
[handbrake-jp/handbrake-jp-git.git] / libhb / muxogm.c
index 6a3b1ec..885dcca 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id: muxogm.c,v 1.4 2005/02/20 00:41:56 titer Exp $
 
    This file is part of the HandBrake source code.
-   Homepage: <http://handbrake.m0k.org/>.
+   Homepage: <http://handbrake.fr/>.
    It may be used under the terms of the GNU General Public License. */
 
 #include "hb.h"
@@ -21,7 +21,7 @@ struct hb_mux_data_s
 {
     int              codec;
     ogg_stream_state os;
-    int              i_packet_no;                                               
+    int              i_packet_no;
 };
 
 typedef struct __attribute__((__packed__))
@@ -96,7 +96,7 @@ static int OGMFlush( hb_mux_object_t * m, hb_mux_data_t * mux_data )
         }
     }
     return 0;
-}                                                                               
+}
 
 /**********************************************************************
  * OGMInit
@@ -107,7 +107,7 @@ static int OGMInit( hb_mux_object_t * m )
 {
     hb_job_t   * job   = m->job;
     hb_title_t * title = job->title;
-    
+
     hb_audio_t    * audio;
     hb_mux_data_t * mux_data;
     int i;
@@ -135,57 +135,69 @@ static int OGMInit( hb_mux_object_t * m )
     {
         audio                 = hb_list_item( title->list_audio, i );
         mux_data              = malloc( sizeof( hb_mux_data_t ) );
-        mux_data->codec       = job->acodec;
+        mux_data->codec       = audio->config.out.codec;
         mux_data->i_packet_no = 0;
-        audio->mux_data       = mux_data;
+        audio->priv.mux_data       = mux_data;
         ogg_stream_init( &mux_data->os, i + 1 );
     }
 
 
     /* First pass: all b_o_s packets */
-
+    hb_log("muxogm: Writing b_o_s header packets");
     /* Video */
     mux_data = job->mux_data;
-    memset( &h, 0, sizeof( ogg_stream_header_t ) );
-    h.i_packet_type = 0x01;
-    memcpy( h.stream_type, "video    ", 8 );
-    if( mux_data->codec == HB_VCODEC_X264 )
-    {
-        memcpy( h.sub_type, "H264", 4 );
-    }
-    else if( mux_data->codec == HB_VCODEC_XVID )
-    {
-        memcpy( h.sub_type, "XVID", 4 );
-    }
-    else
+    switch( job->vcodec )
     {
-        memcpy( h.sub_type, "DX50", 4 );
+        case HB_VCODEC_THEORA:
+            memcpy(&op, job->config.theora.headers[0], sizeof(op));
+            op.packet = job->config.theora.headers[0] + sizeof(op);
+            ogg_stream_packetin( &mux_data->os, &op );
+            break;
+        case HB_VCODEC_X264:
+        case HB_VCODEC_FFMPEG:
+        {
+                memset( &h, 0, sizeof( ogg_stream_header_t ) );
+                h.i_packet_type = 0x01;
+                memcpy( h.stream_type, "video    ", 8 );
+                if( mux_data->codec == HB_VCODEC_X264 )
+                {
+                    memcpy( h.sub_type, "H264", 4 );
+                }
+                else
+                {
+                    memcpy( h.sub_type, "DX50", 4 );
+                }
+                SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
+                SetQWLE( &h.i_time_unit, (int64_t) 10 * 1000 * 1000 *
+                         (int64_t) job->vrate_base / (int64_t) job->vrate );
+                SetQWLE( &h.i_samples_per_unit, 1 );
+                SetDWLE( &h.i_default_len, 0 );
+                SetDWLE( &h.i_buffer_size, 1024*1024 );
+                SetWLE ( &h.i_bits_per_sample, 0 );
+                SetDWLE( &h.header.video.i_width,  job->width );
+                SetDWLE( &h.header.video.i_height, job->height );
+                op.packet   = (unsigned char*)&h;
+                op.bytes    = sizeof( ogg_stream_header_t );
+                op.b_o_s    = 1;
+                op.e_o_s    = 0;
+                op.granulepos = 0;
+                op.packetno = mux_data->i_packet_no++;
+                ogg_stream_packetin( &mux_data->os, &op );
+                break;
+            }
+        default:
+            hb_error( "muxogm: unhandled video codec" );
+            *job->die = 1;
     }
-    SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
-    SetQWLE( &h.i_time_unit, (int64_t) 10 * 1000 * 1000 *
-             (int64_t) job->vrate_base / (int64_t) job->vrate );
-    SetQWLE( &h.i_samples_per_unit, 1 );
-    SetDWLE( &h.i_default_len, 0 );
-    SetDWLE( &h.i_buffer_size, 1024*1024 );
-    SetWLE ( &h.i_bits_per_sample, 0 );
-    SetDWLE( &h.header.video.i_width,  job->width );
-    SetDWLE( &h.header.video.i_height, job->height );
-    op.packet   = (unsigned char*)&h;
-    op.bytes    = sizeof( ogg_stream_header_t );
-    op.b_o_s    = 1;
-    op.e_o_s    = 0;
-    op.granulepos = 0;
-    op.packetno = mux_data->i_packet_no++;
-    ogg_stream_packetin( &mux_data->os, &op );
     OGMFlush( m, mux_data );
 
     /* Audio */
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
         audio   = hb_list_item( title->list_audio, i );
-        mux_data = audio->mux_data;
+        mux_data = audio->priv.mux_data;
         memset( &h, 0, sizeof( ogg_stream_header_t ) );
-        switch( job->acodec )
+        switch( audio->config.out.codec )
         {
             case HB_ACODEC_LAME:
             {
@@ -195,17 +207,17 @@ static int OGMInit( hb_mux_object_t * m )
 
                 SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
                 SetQWLE( &h.i_time_unit, 0 );
-                SetQWLE( &h.i_samples_per_unit, job->arate );
+                SetQWLE( &h.i_samples_per_unit, audio->config.out.samplerate );
                 SetDWLE( &h.i_default_len, 1 );
                 SetDWLE( &h.i_buffer_size, 30 * 1024 );
                 SetWLE ( &h.i_bits_per_sample, 0 );
 
-                SetDWLE( &h.header.audio.i_channels, 2 ); 
+                SetDWLE( &h.header.audio.i_channels, 2 );
                 SetDWLE( &h.header.audio.i_block_align, 0 );
                 SetDWLE( &h.header.audio.i_avgbytespersec,
-                         job->abitrate / 8 );
+                         audio->config.out.bitrate / 8 );
 
-                op.packet   = (char*) &h;
+                op.packet   = (unsigned char*) &h;
                 op.bytes    = sizeof( ogg_stream_header_t );
                 op.b_o_s    = 1;
                 op.e_o_s    = 0;
@@ -216,9 +228,9 @@ static int OGMInit( hb_mux_object_t * m )
             }
             case HB_ACODEC_VORBIS:
             {
-                memcpy( &op, audio->config.vorbis.headers[0],
+                memcpy( &op, audio->priv.config.vorbis.headers[0],
                         sizeof( ogg_packet ) );
-                op.packet = audio->config.vorbis.headers[0] +
+                op.packet = audio->priv.config.vorbis.headers[0] +
                                 sizeof( ogg_packet );
                 ogg_stream_packetin( &mux_data->os, &op );
                 break;
@@ -231,19 +243,42 @@ static int OGMInit( hb_mux_object_t * m )
     }
 
     /* second pass: all non b_o_s packets */
+    hb_log("muxogm: Writing non b_o_s header packets");
+    /* Video */
+    mux_data = job->mux_data;
+    switch( job->vcodec )
+    {
+        case HB_VCODEC_THEORA:
+            for (i = 1; i < 3; i++)
+            {
+                memcpy(&op, job->config.theora.headers[i], sizeof(op));
+                op.packet = job->config.theora.headers[i] + sizeof(op);
+                ogg_stream_packetin( &mux_data->os, &op );
+                OGMFlush( m, mux_data );
+            }
+            break;
+        case HB_VCODEC_X264:
+        case HB_VCODEC_FFMPEG:
+            break;
+        default:
+            hb_error( "muxogm: unhandled video codec" );
+            *job->die = 1;
+    }
+
+    /* Audio */
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
         audio = hb_list_item( title->list_audio, i );
-        if( job->acodec == HB_ACODEC_VORBIS )
+        if( audio->config.out.codec == HB_ACODEC_VORBIS )
         {
             int       j;
-            mux_data = audio->mux_data;
+            mux_data = audio->priv.mux_data;
 
             for( j = 1; j < 3; j++ )
             {
-                memcpy( &op, audio->config.vorbis.headers[j],
+                memcpy( &op, audio->priv.config.vorbis.headers[j],
                         sizeof( ogg_packet ) );
-                op.packet = audio->config.vorbis.headers[j] +
+                op.packet = audio->priv.config.vorbis.headers[j] +
                                 sizeof( ogg_packet );
                 ogg_stream_packetin( &mux_data->os, &op );
 
@@ -263,12 +298,16 @@ static int OGMMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
 
     switch( mux_data->codec )
     {
+        case HB_VCODEC_THEORA:
+            memcpy( &op, buf->data, sizeof( ogg_packet ) );
+            op.packet = malloc( op.bytes );
+            memcpy( op.packet, buf->data + sizeof( ogg_packet ), op.bytes );
+            break;
         case HB_VCODEC_FFMPEG:
-        case HB_VCODEC_XVID:
         case HB_VCODEC_X264:
             op.bytes  = buf->size + 1;
             op.packet = malloc( op.bytes );
-            op.packet[0] = buf->key ? 0x08 : 0x00;
+            op.packet[0] = (buf->frametype & HB_FRAME_KEY) ? 0x08 : 0x00;
             memcpy( &op.packet[1], buf->data, buf->size );
             op.b_o_s       = 0;
             op.e_o_s       = 0;
@@ -319,7 +358,7 @@ static int OGMMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
         }
         free( op.packet );
     }
-    return 0; 
+    return 0;
 }
 
 static int OGMEnd( hb_mux_object_t * m )
@@ -336,19 +375,22 @@ static int OGMEnd( hb_mux_object_t * m )
     {
         return -1;
     }
+    ogg_stream_clear( &mux_data->os );
+
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
         audio = hb_list_item( title->list_audio, i );
-        mux_data = audio->mux_data;
+        mux_data = audio->priv.mux_data;
         if( OGMFlush( m, mux_data ) < 0 )
         {
             return -1;
         }
+        ogg_stream_clear( &mux_data->os );
     }
 
     fclose( m->file );
     hb_log( "muxogm: `%s' closed", job->file );
-    
+
     return 0;
 }