OSDN Git Service

Fix a hang in sync
[handbrake-jp/handbrake-jp-git.git] / libhb / muxavi.c
index cd88d84..85839e1 100644 (file)
@@ -1,10 +1,11 @@
 /* $Id: muxavi.c,v 1.10 2005/03/30 18:17:29 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"
+#include "hbffmpeg.h"
 
 #define AVIF_HASINDEX  0x10
 #define AVIIF_KEYFRAME 0x10
@@ -57,6 +58,31 @@ typedef struct __attribute__((__packed__))
 {
     uint32_t FourCC;
     uint32_t BytesCount;
+    uint32_t VideoFormatToken;
+    uint32_t VideoStandard;
+    uint32_t dwVerticalRefreshRate;
+    uint32_t dwHTotalInT;
+    uint32_t dwVTotalInLines;
+    uint16_t dwFrameAspectRatioDen;
+    uint16_t dwFrameAspectRatioNum;
+    uint32_t dwFrameWidthInPixels;
+    uint32_t dwFrameHeightInLines;
+    uint32_t nbFieldPerFrame;
+    uint32_t CompressedBMHeight;
+    uint32_t CompressedBMWidth;
+    uint32_t ValidBMHeight;
+    uint32_t ValidBMWidth;
+    uint32_t ValidBMXOffset;
+    uint32_t ValidBMYOffset;
+    uint32_t VideoXOffsetInT;
+    uint32_t VideoYValidStartLine;
+
+} hb_avi_vprp_info_t;
+
+typedef struct __attribute__((__packed__))
+{
+    uint32_t FourCC;
+    uint32_t BytesCount;
     uint32_t Size;
     uint32_t Width;
     uint32_t Height;
@@ -203,6 +229,30 @@ static void WriteStreamHeader( FILE * file, hb_avi_stream_header_t * header )
     WriteInt16( file, header->Bottom );
 }
 
+static void WriteVprpInfo( FILE * file, hb_avi_vprp_info_t * info )
+{
+    WriteInt32( file, info->FourCC );
+    WriteInt32( file, info->BytesCount );
+    WriteInt32( file, info->VideoFormatToken );
+    WriteInt32( file, info->VideoStandard );
+    WriteInt32( file, info->dwVerticalRefreshRate );
+    WriteInt32( file, info->dwHTotalInT );
+    WriteInt32( file, info->dwVTotalInLines );
+    WriteInt16( file, info->dwFrameAspectRatioDen );
+    WriteInt16( file, info->dwFrameAspectRatioNum );
+    WriteInt32( file, info->dwFrameWidthInPixels );
+    WriteInt32( file, info->dwFrameHeightInLines );
+    WriteInt32( file, info->nbFieldPerFrame );
+    WriteInt32( file, info->CompressedBMHeight );
+    WriteInt32( file, info->CompressedBMWidth );
+    WriteInt32( file, info->ValidBMHeight );
+    WriteInt32( file, info->ValidBMWidth );
+    WriteInt32( file, info->ValidBMXOffset );
+    WriteInt32( file, info->ValidBMYOffset );
+    WriteInt32( file, info->VideoXOffsetInT );
+    WriteInt32( file, info->VideoYValidStartLine );
+}
+
 static void IndexAddInt32( hb_buffer_t * b, uint32_t val )
 {
     if( b->size + 16 > b->alloc )
@@ -233,8 +283,9 @@ struct hb_mux_object_s
 
 struct hb_mux_data_s
 {
-    uint32_t               fourcc;
-    hb_avi_stream_header_t header;
+    uint32_t                           fourcc;
+    hb_avi_stream_header_t     header;
+    hb_avi_vprp_info_t         vprp_header;
     union
     {
         hb_bitmap_info_t   v;
@@ -281,7 +332,8 @@ static int AVIInit( hb_mux_object_t * m )
     hb_mux_data_t * mux_data;
 
     int audio_count = hb_list_count( title->list_audio );
-    int is_ac3      = ( job->acodec & HB_ACODEC_AC3 );
+    int is_passthru = 0;
+    int is_ac3      = 0;
     int hdrl_bytes;
     int i;
 
@@ -314,9 +366,7 @@ static int AVIInit( hb_mux_object_t * m )
     h.Type       = FOURCC( "vids" );
 
     if( job->vcodec == HB_VCODEC_FFMPEG )
-        h.Handler = FOURCC( "fmp4" );
-    else if( job->vcodec == HB_VCODEC_XVID )
-        h.Handler = FOURCC( "xvid" );
+        h.Handler = FOURCC( "divx" );
     else if( job->vcodec == HB_VCODEC_X264 )
         h.Handler = FOURCC( "h264" );
 
@@ -334,20 +384,51 @@ static int AVIInit( hb_mux_object_t * m )
     f.Planes      = 1;
     f.BitCount    = 24;
     if( job->vcodec == HB_VCODEC_FFMPEG )
-        f.Compression = FOURCC( "FMP4" );
-    else if( job->vcodec == HB_VCODEC_XVID )
-        f.Compression = FOURCC( "XVID" );
+        f.Compression = FOURCC( "DX50" );
     else if( job->vcodec == HB_VCODEC_X264 )
         f.Compression = FOURCC( "H264" );
 #undef f
 
+#define g mux_data->vprp_header
+    /* Vprp video stream header */     
+    AVRational sample_aspect_ratio = ( AVRational ){ job->anamorphic.par_width, job->anamorphic.par_height };
+    AVRational dar = av_mul_q( sample_aspect_ratio, ( AVRational ){ job->width, job->height } );
+    int num, den;
+    av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
+
+    g.FourCC                = FOURCC( "vprp" );
+    g.BytesCount            = sizeof( hb_avi_vprp_info_t ) - 8;
+    g.VideoFormatToken      = 0;
+    g.VideoStandard         = 0;
+    g.dwVerticalRefreshRate = job->vrate / job->vrate_base;
+    g.dwHTotalInT           = job->width;
+    g.dwVTotalInLines       = job->height;
+    g.dwFrameAspectRatioDen = den;
+    g.dwFrameAspectRatioNum = num;
+    g.dwFrameWidthInPixels  = job->width;
+    g.dwFrameHeightInLines  = job->height;
+    g.nbFieldPerFrame       = 1;
+    g.CompressedBMHeight    = job->height;
+    g.CompressedBMWidth     = job->width;
+    g.ValidBMHeight         = job->height;
+    g.ValidBMWidth          = job->width;
+    g.ValidBMXOffset        = 0;
+    g.ValidBMYOffset        = 0;
+    g.VideoXOffsetInT       = 0;
+    g.VideoYValidStartLine  = 0;
+#undef g
+
     /* Audio tracks */
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
         audio = hb_list_item( title->list_audio, i );
 
+        is_ac3 = (audio->config.out.codec == HB_ACODEC_AC3);
+        is_passthru = (audio->config.out.codec == HB_ACODEC_AC3) ||
+                      (audio->config.out.codec == HB_ACODEC_DCA);
+
         mux_data = calloc( sizeof( hb_mux_data_t ), 1 );
-        audio->mux_data = mux_data;
+        audio->priv.mux_data = mux_data;
 
 #define h mux_data->header
 #define f mux_data->format.a.f
@@ -358,31 +439,31 @@ static int AVIInit( hb_mux_object_t * m )
         h.Type          = FOURCC( "auds" );
         h.InitialFrames = 1;
         h.Scale         = 1;
-        h.Rate          = is_ac3 ? ( audio->bitrate / 8 ) :
-                                   ( job->abitrate * 1000 / 8 );
+        h.Rate          = is_passthru ? ( audio->config.in.bitrate / 8 ) :
+                                   ( audio->config.out.bitrate * 1000 / 8 );
         h.Quality       = 0xFFFFFFFF;
         h.SampleSize    = 1;
 
         /* Audio stream format */
         f.FourCC         = FOURCC( "strf" );
-        if( is_ac3 )
+        if( is_passthru )
         {
             f.BytesCount     = sizeof( hb_wave_formatex_t ) - 8;
-            f.FormatTag      = 0x2000;
-            f.Channels       = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->input_channel_layout);
-            f.SamplesPerSec  = audio->rate;
+            f.FormatTag      = is_ac3 ? 0x2000 : 0x2001;
+            f.Channels       = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout);
+            f.SamplesPerSec  = audio->config.in.samplerate;
         }
         else
         {
             f.BytesCount     = sizeof( hb_wave_formatex_t ) +
                                sizeof( hb_wave_mp3_t ) - 8;
             f.FormatTag      = 0x55;
-            f.Channels       = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(job->audio_mixdowns[i]);
-            f.SamplesPerSec  = job->arate;
+            f.Channels       = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
+            f.SamplesPerSec  = audio->config.out.samplerate;
         }
         f.AvgBytesPerSec = h.Rate;
         f.BlockAlign     = 1;
-        if( is_ac3 )
+        if( is_passthru )
         {
             f.Size       = 0;
         }
@@ -391,7 +472,7 @@ static int AVIInit( hb_mux_object_t * m )
             f.Size           = sizeof( hb_wave_mp3_t );
             m.Id             = 1;
             m.Flags          = 2;
-            m.BlockSize      = 1152 * f.AvgBytesPerSec / job->arate;
+            m.BlockSize      = 1152 * f.AvgBytesPerSec / audio->config.out.samplerate;
             m.FramesPerBlock = 1;
             m.CodecDelay     = 1393;
         }
@@ -406,10 +487,12 @@ static int AVIInit( hb_mux_object_t * m )
         /* strh for video + audios */
         ( 1 + audio_count ) * ( 12 + sizeof( hb_avi_stream_header_t ) ) +
         /* video strf */
-        sizeof( hb_bitmap_info_t ) +
+               sizeof( hb_bitmap_info_t ) +
+        /* video vprp */
+        ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) +
         /* audios strf */
         audio_count * ( sizeof( hb_wave_formatex_t ) +
-                        ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) );
+                        ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) );
 
     /* Here we really start to write into the file */
 
@@ -428,10 +511,15 @@ static int AVIInit( hb_mux_object_t * m )
 
     WriteInt32( m->file, FOURCC( "LIST" ) );
     WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
-                sizeof( hb_bitmap_info_t ) );
+                sizeof( hb_bitmap_info_t )  +
+                ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) );
     WriteInt32( m->file, FOURCC( "strl" ) );
     WriteStreamHeader( m->file, &mux_data->header );
     WriteBitmapInfo( m->file, &mux_data->format.v );
+    if( job->anamorphic.mode )
+    {
+        WriteVprpInfo( m->file, &mux_data->vprp_header );
+    }
 
     /* Audio tracks */
     for( i = 0; i < audio_count; i++ )
@@ -439,7 +527,7 @@ static int AVIInit( hb_mux_object_t * m )
         char fourcc[4] = "00wb";
 
         audio    = hb_list_item( title->list_audio, i );
-        mux_data = audio->mux_data;
+        mux_data = audio->priv.mux_data;
 
         fourcc[1] = '1' + i; /* This is fine as we don't allow more
                                 than 8 tracks */
@@ -448,11 +536,11 @@ static int AVIInit( hb_mux_object_t * m )
         WriteInt32( m->file, FOURCC( "LIST" ) );
         WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
                              sizeof( hb_wave_formatex_t ) +
-                             ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) );
+                             ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) );
         WriteInt32( m->file, FOURCC( "strl" ) );
         WriteStreamHeader( m->file, &mux_data->header );
         WriteWaveFormatEx( m->file, &mux_data->format.a.f );
-        if( !is_ac3 )
+        if( !is_passthru )
         {
             WriteWaveMp3( m->file, &mux_data->format.a.m );
         }
@@ -511,11 +599,14 @@ static int AVIMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
     WriteInt32( m->file, job->mux_data->header.Length );
     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
+        int is_passthru;
         audio = hb_list_item( title->list_audio, i );
+        is_passthru = (audio->config.out.codec == HB_ACODEC_AC3) ||
+                      (audio->config.out.codec == HB_ACODEC_DCA);
         fseek( m->file, 264 + i *
-               ( 102 + ( ( job->acodec & HB_ACODEC_AC3 ) ? 0 :
+               ( 102 + ( is_passthru ? 0 :
                  sizeof( hb_wave_mp3_t ) ) ), SEEK_SET );
-        WriteInt32( m->file, audio->mux_data->header.Length );
+        WriteInt32( m->file, audio->priv.mux_data->header.Length );
     }
 
     /* movi size */