示例#1
0
bool TRIFFWriter::InitAVIFile()
{	
	
	//	We cannot write out if all elements are not initialized...
	
	off_t	savePos;	
	bool 	retVal 	= true;
	ssize_t size 	= 0x4949;
	
	//	Rewind the file
	m_File->Seek(0, SEEK_SET);
		
	//	Write RIFF header
	WriteRIFFChunk(size);
	
	//	Write AVIHeader LIST chunk
	retVal = WriteLISTChunk(size);
	if (retVal == false)
		return retVal;
	
	//	Save position for later calculation.  Back over size...
	off_t listHeaderPos = m_File->Position();
	listHeaderPos -= sizeof(uint32);

	WriteIntMsb(m_File, kRiff_hdrl_Chunk, sizeof(uint32)); 	

	//	Write AVIHeader chunk
	retVal = WriteavihChunk();
	if (retVal == false)
		return retVal;
	
	//
	//	Write stream data List Chunk
	//
	
	//	Make sure we have streams to write
	if ( (m_StreamCount == 0) || (m_StreamCount > kRiffWriteMaxStreams) )
		return false;
	
	//
	//	Write out first stream
	//
		
	retVal = WriteLISTChunk(size);
	if (retVal == false)
		return retVal;
			
	//	Save position for later size calculation
	off_t streamOnePos = m_File->Position();

	//	Write out 'strl' chunk
	WriteIntMsb(m_File, kRiff_strl_Chunk, sizeof(uint32));
		
	//	First stream header
	retVal = WriteStreamHeader(&m_StreamHeaderOne);
	
	//	First stream format
	retVal = WriteStreamFormat(&m_StreamHeaderOne);
	
	//	Update streamOne chunk size
	savePos = m_File->Position();
	uint32 streamOneSize = (uint32)(savePos - streamOnePos);
	
	//	Update list header chunk size
	B_HOST_TO_LENDIAN_INT32(streamOneSize);
	streamOnePos -= sizeof(uint32);
	m_File->WriteAt(streamOnePos, &streamOneSize, sizeof(uint32));
	
	//	Return to saved postion
	m_File->Seek(savePos, SEEK_SET);
	
	//
	//	Write out second stream
	//
	
	if (m_StreamCount == 2)
	{
		retVal = WriteLISTChunk(size);
		if (retVal == false)
			return retVal;
	
		//	Save position for later size calculation
		off_t streamTwoPos = m_File->Position();

		//	Write out 'strl' chunk
		WriteIntMsb(m_File, kRiff_strl_Chunk, sizeof(uint32)); 	
		
		//	Second stream header
		retVal = WriteStreamHeader(&m_StreamHeaderTwo);
		
		//	Second stream format
		retVal = WriteStreamFormat(&m_StreamHeaderTwo);
		
		//	Update streamTwo chunk size
		savePos = m_File->Position();
		uint32 streamTwoSize = savePos - streamTwoPos;
		
		//	Update list header chunk size
		B_HOST_TO_LENDIAN_INT32(streamTwoSize);
		streamTwoPos -= sizeof(uint32);
		m_File->WriteAt(streamTwoPos, &streamTwoSize, sizeof(uint32));
		
		//	Restore position
		m_File->Seek(savePos, SEEK_SET);
	}
			
	//	Save position and go back and update unitialized chunk sizes
	savePos = m_File->Position();
	uint32 listHeaderSize = savePos - listHeaderPos;
	
	//	Update list header chunk size
	B_HOST_TO_LENDIAN_INT32(listHeaderSize);
	m_File->WriteAt(listHeaderPos, &listHeaderSize, sizeof(uint32));
	
	//	Restore position
	m_File->Seek(savePos, SEEK_SET);
	
	//
	//	Write movi Chunk.  We don't know the true size yet...
	//
	
	retVal = WriteLISTChunk(size);
	if (retVal == false)
		return retVal;
		
	WriteIntMsb(m_File, kRiff_movi_Chunk, sizeof(uint32)); 	
	
	//	Save offset for later index chunk calculation
	m_MoviChunkOffset = m_File->Position();
	
	//	All done
	return retVal;
	
}
示例#2
0
/**********************************************************************
 * AVIInit
 **********************************************************************
 * Allocates things, create file, initialize and write headers
 *********************************************************************/
static int AVIInit( 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 audio_count = hb_list_count( title->list_audio );
    int is_passthru = 0;
    int is_ac3      = 0;
    int hdrl_bytes;
    int i;

    /* Allocate index */
    m->index       = hb_buffer_init( 1024 * 1024 );
    m->index->size = 0;

    /* Open destination file */
    hb_log( "muxavi: opening %s", job->file );
    m->file = fopen( job->file, "wb" );

#define m m->main_header
    /* AVI main header */
    m.FourCC           = FOURCC( "avih" );
    m.BytesCount       = sizeof( hb_avi_main_header_t ) - 8;
    m.MicroSecPerFrame = (uint64_t) 1000000 * job->vrate_base / job->vrate;
    m.Streams          = 1 + audio_count;
    m.Width            = job->width;
    m.Height           = job->height;
#undef m

    /* Video track */
    mux_data = calloc( sizeof( hb_mux_data_t ), 1 );
    job->mux_data = mux_data;

#define h mux_data->header
    /* Video stream header */
    h.FourCC     = FOURCC( "strh" );
    h.BytesCount = sizeof( hb_avi_stream_header_t ) - 8;
    h.Type       = FOURCC( "vids" );

    if( job->vcodec == HB_VCODEC_FFMPEG )
        h.Handler = FOURCC( "divx" );
    else if( job->vcodec == HB_VCODEC_X264 )
        h.Handler = FOURCC( "h264" );

    h.Scale      = job->vrate_base;
    h.Rate       = job->vrate;
#undef h

#define f mux_data->format.v
    /* Video stream format */
    f.FourCC      = FOURCC( "strf" );
    f.BytesCount  = sizeof( hb_bitmap_info_t ) - 8;
    f.Size        = f.BytesCount;
    f.Width       = job->width;
    f.Height      = job->height;
    f.Planes      = 1;
    f.BitCount    = 24;
    if( job->vcodec == HB_VCODEC_FFMPEG )
        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->priv.mux_data = mux_data;

#define h mux_data->header
#define f mux_data->format.a.f
#define m mux_data->format.a.m
        /* Audio stream header */
        h.FourCC        = FOURCC( "strh" );
        h.BytesCount    = sizeof( hb_avi_stream_header_t ) - 8;
        h.Type          = FOURCC( "auds" );
        h.InitialFrames = 1;
        h.Scale         = 1;
        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_passthru )
        {
            f.BytesCount     = sizeof( hb_wave_formatex_t ) - 8;
            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(audio->config.out.mixdown);
            f.SamplesPerSec  = audio->config.out.samplerate;
        }
        f.AvgBytesPerSec = h.Rate;
        f.BlockAlign     = 1;
        if( is_passthru )
        {
            f.Size       = 0;
        }
        else
        {
            f.Size           = sizeof( hb_wave_mp3_t );
            m.Id             = 1;
            m.Flags          = 2;
            m.BlockSize      = 1152 * f.AvgBytesPerSec / audio->config.out.samplerate;
            m.FramesPerBlock = 1;
            m.CodecDelay     = 1393;
        }
#undef h
#undef f
#undef m
    }

    hdrl_bytes =
        /* Main header */
        4 + sizeof( hb_avi_main_header_t ) +
        /* strh for video + audios */
        ( 1 + audio_count ) * ( 12 + sizeof( hb_avi_stream_header_t ) ) +
        /* video strf */
		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_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) );

    /* Here we really start to write into the file */

    /* Main headers */
    WriteInt32( m->file, FOURCC( "RIFF" ) );
    WriteInt32( m->file, 2040 );
    WriteInt32( m->file, FOURCC( "AVI " ) );
    WriteInt32( m->file, FOURCC( "LIST" ) );
    WriteInt32( m->file, hdrl_bytes );
    WriteInt32( m->file, FOURCC( "hdrl" ) );
    WriteMainHeader( m->file, &m->main_header );

    /* Video track */
    mux_data          = job->mux_data;
    mux_data->fourcc = FOURCC( "00dc" );

    WriteInt32( m->file, FOURCC( "LIST" ) );
    WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_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++ )
    {
        char fourcc[4] = "00wb";

        audio    = hb_list_item( title->list_audio, i );
        mux_data = audio->priv.mux_data;

        fourcc[1] = '1' + i; /* This is fine as we don't allow more
                                than 8 tracks */
        mux_data->fourcc = FOURCC( fourcc );

        WriteInt32( m->file, FOURCC( "LIST" ) );
        WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
                             sizeof( hb_wave_formatex_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_passthru )
        {
            WriteWaveMp3( m->file, &mux_data->format.a.m );
        }
    }

    WriteInt32( m->file, FOURCC( "JUNK" ) );
    WriteInt32( m->file, 2020 - hdrl_bytes );
    for( i = 0; i < 2020 - hdrl_bytes; i++ )
    {
        WriteInt8( m->file, 0 );
    }
    WriteInt32( m->file, FOURCC( "LIST" ) );
    WriteInt32( m->file, 4 );
    WriteInt32( m->file, FOURCC( "movi" ) );

    return 0;
}