OSDN Git Service

99604335d22df652bf73437d88ec80d8f081d504
[handbrake-jp/handbrake-jp.git] / libhb / muxavi.c
1 /* $Id: muxavi.c,v 1.10 2005/03/30 18:17:29 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8 #include "libavcodec/avcodec.h"
9
10 #define AVIF_HASINDEX  0x10
11 #define AVIIF_KEYFRAME 0x10
12 #define FOURCC(a)      ((a[3]<<24)|(a[2]<<16)|(a[1]<<8)|a[0])
13
14 /* Structures definitions */
15 typedef struct __attribute__((__packed__))
16 {
17     uint32_t FourCC;
18     uint32_t BytesCount;
19     uint32_t MicroSecPerFrame;
20     uint32_t MaxBytesPerSec;
21     uint32_t PaddingGranularity;
22     uint32_t Flags;
23     uint32_t TotalFrames;
24     uint32_t InitialFrames;
25     uint32_t Streams;
26     uint32_t SuggestedBufferSize;
27     uint32_t Width;
28     uint32_t Height;
29     uint32_t Reserved[4];
30
31 } hb_avi_main_header_t;
32
33 typedef struct __attribute__((__packed__))
34 {
35     uint32_t FourCC;
36     uint32_t BytesCount;
37     uint32_t Type;
38     uint32_t Handler;
39     uint32_t Flags;
40     uint16_t Priority;
41     uint16_t Language;
42     uint32_t InitialFrames;
43     uint32_t Scale;
44     uint32_t Rate;
45     uint32_t Start;
46     uint32_t Length;
47     uint32_t SuggestedBufferSize;
48     uint32_t Quality;
49     uint32_t SampleSize;
50     int16_t  Left;
51     int16_t  Top;
52     int16_t  Right;
53     int16_t  Bottom;
54
55 } hb_avi_stream_header_t;
56
57 typedef struct __attribute__((__packed__))
58 {
59     uint32_t FourCC;
60     uint32_t BytesCount;
61     uint32_t VideoFormatToken;
62     uint32_t VideoStandard;
63     uint32_t dwVerticalRefreshRate;
64     uint32_t dwHTotalInT;
65     uint32_t dwVTotalInLines;
66     uint16_t dwFrameAspectRatioDen;
67     uint16_t dwFrameAspectRatioNum;
68     uint32_t dwFrameWidthInPixels;
69     uint32_t dwFrameHeightInLines;
70     uint32_t nbFieldPerFrame;
71     uint32_t CompressedBMHeight;
72     uint32_t CompressedBMWidth;
73     uint32_t ValidBMHeight;
74     uint32_t ValidBMWidth;
75     uint32_t ValidBMXOffset;
76     uint32_t ValidBMYOffset;
77     uint32_t VideoXOffsetInT;
78     uint32_t VideoYValidStartLine;
79
80 } hb_avi_vprp_info_t;
81
82 typedef struct __attribute__((__packed__))
83 {
84     uint32_t FourCC;
85     uint32_t BytesCount;
86     uint32_t Size;
87     uint32_t Width;
88     uint32_t Height;
89     uint16_t Planes;
90     uint16_t BitCount;
91     uint32_t Compression;
92     uint32_t SizeImage;
93     uint32_t XPelsPerMeter;
94     uint32_t YPelsPerMeter;
95     uint32_t ClrUsed;
96     uint32_t ClrImportant;
97
98 } hb_bitmap_info_t;
99
100 typedef struct __attribute__((__packed__))
101 {
102     uint32_t FourCC;
103     uint32_t BytesCount;
104     uint16_t FormatTag;
105     uint16_t Channels;
106     uint32_t SamplesPerSec;
107     uint32_t AvgBytesPerSec;
108     uint16_t BlockAlign;
109     uint16_t BitsPerSample;
110     uint16_t Size;
111
112 } hb_wave_formatex_t;
113
114 typedef struct __attribute__((__packed__))
115 {
116     uint16_t Id;
117     uint32_t Flags;
118     uint16_t BlockSize;
119     uint16_t FramesPerBlock;
120     uint16_t CodecDelay;
121
122 } hb_wave_mp3_t;
123
124 static void WriteBuffer( FILE * file, hb_buffer_t * buf )
125 {
126     fwrite( buf->data, buf->size, 1, file );
127 }
128
129 /* Little-endian write routines */
130
131 static void WriteInt8( FILE * file, uint8_t val )
132 {
133     fputc( val, file );
134 }
135
136 static void WriteInt16( FILE * file, uint16_t val )
137 {
138     fputc( val & 0xFF, file );
139     fputc( val >> 8, file );
140 }
141
142 static void WriteInt32( FILE * file, uint32_t val )
143 {
144     fputc( val & 0xFF, file );
145     fputc( ( val >> 8 ) & 0xFF, file );
146     fputc( ( val >> 16 ) & 0xFF, file );
147     fputc( val >> 24, file );
148 }
149
150 static void WriteBitmapInfo( FILE * file, hb_bitmap_info_t * info )
151 {
152     WriteInt32( file, info->FourCC );
153     WriteInt32( file, info->BytesCount );
154     WriteInt32( file, info->Size );
155     WriteInt32( file, info->Width );
156     WriteInt32( file, info->Height );
157     WriteInt16( file, info->Planes );
158     WriteInt16( file, info->BitCount );
159     WriteInt32( file, info->Compression );
160     WriteInt32( file, info->SizeImage );
161     WriteInt32( file, info->XPelsPerMeter );
162     WriteInt32( file, info->YPelsPerMeter );
163     WriteInt32( file, info->ClrUsed );
164     WriteInt32( file, info->ClrImportant );
165 }
166
167 static void WriteWaveFormatEx( FILE * file, hb_wave_formatex_t * format )
168 {
169     WriteInt32( file, format->FourCC );
170     WriteInt32( file, format->BytesCount );
171     WriteInt16( file, format->FormatTag );
172     WriteInt16( file, format->Channels );
173     WriteInt32( file, format->SamplesPerSec );
174     WriteInt32( file, format->AvgBytesPerSec );
175     WriteInt16( file, format->BlockAlign );
176     WriteInt16( file, format->BitsPerSample );
177     WriteInt16( file, format->Size );
178 }
179
180 static void WriteWaveMp3( FILE * file, hb_wave_mp3_t * mp3 )
181 {
182     WriteInt16( file, mp3->Id );
183     WriteInt32( file, mp3->Flags );
184     WriteInt16( file, mp3->BlockSize );
185     WriteInt16( file, mp3->FramesPerBlock );
186     WriteInt16( file, mp3->CodecDelay );
187 }
188
189 static void WriteMainHeader( FILE * file, hb_avi_main_header_t * header )
190 {
191     WriteInt32( file, header->FourCC );
192     WriteInt32( file, header->BytesCount );
193     WriteInt32( file, header->MicroSecPerFrame );
194     WriteInt32( file, header->MaxBytesPerSec );
195     WriteInt32( file, header->PaddingGranularity );
196     WriteInt32( file, header->Flags );
197     WriteInt32( file, header->TotalFrames );
198     WriteInt32( file, header->InitialFrames );
199     WriteInt32( file, header->Streams );
200     WriteInt32( file, header->SuggestedBufferSize );
201     WriteInt32( file, header->Width );
202     WriteInt32( file, header->Height );
203     WriteInt32( file, header->Reserved[0] );
204     WriteInt32( file, header->Reserved[1] );
205     WriteInt32( file, header->Reserved[2] );
206     WriteInt32( file, header->Reserved[3] );
207 }
208
209 static void WriteStreamHeader( FILE * file, hb_avi_stream_header_t * header )
210 {
211     WriteInt32( file, header->FourCC );
212     WriteInt32( file, header->BytesCount );
213     WriteInt32( file, header->Type );
214     WriteInt32( file, header->Handler );
215     WriteInt32( file, header->Flags );
216     WriteInt16( file, header->Priority );
217     WriteInt16( file, header->Language );
218     WriteInt32( file, header->InitialFrames );
219     WriteInt32( file, header->Scale );
220     WriteInt32( file, header->Rate );
221     WriteInt32( file, header->Start );
222     WriteInt32( file, header->Length );
223     WriteInt32( file, header->SuggestedBufferSize );
224     WriteInt32( file, header->Quality );
225     WriteInt32( file, header->SampleSize );
226     WriteInt16( file, header->Left );
227     WriteInt16( file, header->Top );
228     WriteInt16( file, header->Right );
229     WriteInt16( file, header->Bottom );
230 }
231
232 static void WriteVprpInfo( FILE * file, hb_avi_vprp_info_t * info )
233 {
234     WriteInt32( file, info->FourCC );
235     WriteInt32( file, info->BytesCount );
236     WriteInt32( file, info->VideoFormatToken );
237     WriteInt32( file, info->VideoStandard );
238     WriteInt32( file, info->dwVerticalRefreshRate );
239     WriteInt32( file, info->dwHTotalInT );
240     WriteInt32( file, info->dwVTotalInLines );
241     WriteInt16( file, info->dwFrameAspectRatioDen );
242     WriteInt16( file, info->dwFrameAspectRatioNum );
243     WriteInt32( file, info->dwFrameWidthInPixels );
244     WriteInt32( file, info->dwFrameHeightInLines );
245     WriteInt32( file, info->nbFieldPerFrame );
246     WriteInt32( file, info->CompressedBMHeight );
247     WriteInt32( file, info->CompressedBMWidth );
248     WriteInt32( file, info->ValidBMHeight );
249     WriteInt32( file, info->ValidBMWidth );
250     WriteInt32( file, info->ValidBMXOffset );
251     WriteInt32( file, info->ValidBMYOffset );
252     WriteInt32( file, info->VideoXOffsetInT );
253     WriteInt32( file, info->VideoYValidStartLine );
254 }
255
256 static void IndexAddInt32( hb_buffer_t * b, uint32_t val )
257 {
258     if( b->size + 16 > b->alloc )
259     {
260         hb_log( "muxavi: reallocing index (%d MB)",
261                 1 + b->alloc / 1024 / 1024 );
262         hb_buffer_realloc( b, b->alloc + 1024 * 1024 );
263     }
264
265     b->data[b->size++] = val & 0xFF;
266     b->data[b->size++] = ( val >> 8 ) & 0xFF;
267     b->data[b->size++] = ( val >> 16 ) & 0xFF;
268     b->data[b->size++] = val >> 24;
269 }
270
271 struct hb_mux_object_s
272 {
273     HB_MUX_COMMON;
274
275     hb_job_t * job;
276
277     /* Data size in bytes, not including headers */
278     unsigned               size;
279     FILE                 * file;
280     hb_buffer_t          * index;
281     hb_avi_main_header_t   main_header;
282 };
283
284 struct hb_mux_data_s
285 {
286     uint32_t                            fourcc;
287     hb_avi_stream_header_t      header;
288     hb_avi_vprp_info_t          vprp_header;
289     union
290     {
291         hb_bitmap_info_t   v;
292         struct
293         {
294             hb_wave_formatex_t f;
295             hb_wave_mp3_t      m;
296         } a;
297     } format;
298 };
299
300 static void AddIndex( hb_mux_object_t * m )
301 {
302     fseek( m->file, 0, SEEK_END );
303
304     /* Write the index at the end of the file */
305     WriteInt32( m->file, FOURCC( "idx1" ) );
306     WriteInt32( m->file, m->index->size );
307     WriteBuffer( m->file, m->index );
308
309     /* Update file size */
310     m->size += 8 + m->index->size;
311     fseek( m->file, 4, SEEK_SET );
312     WriteInt32( m->file, 2040 + m->size );
313
314     /* Update HASINDEX flag */
315     m->main_header.Flags |= AVIF_HASINDEX;
316     fseek( m->file, 24, SEEK_SET );
317     WriteMainHeader( m->file, &m->main_header );
318 }
319
320
321 /**********************************************************************
322  * AVIInit
323  **********************************************************************
324  * Allocates things, create file, initialize and write headers
325  *********************************************************************/
326 static int AVIInit( hb_mux_object_t * m )
327 {
328     hb_job_t   * job   = m->job;
329     hb_title_t * title = job->title;
330
331     hb_audio_t    * audio;
332     hb_mux_data_t * mux_data;
333
334     int audio_count = hb_list_count( title->list_audio );
335     int is_ac3      = 0;
336     int hdrl_bytes;
337     int i;
338
339     /* Allocate index */
340     m->index       = hb_buffer_init( 1024 * 1024 );
341     m->index->size = 0;
342
343     /* Open destination file */
344     hb_log( "muxavi: opening %s", job->file );
345     m->file = fopen( job->file, "wb" );
346
347 #define m m->main_header
348     /* AVI main header */
349     m.FourCC           = FOURCC( "avih" );
350     m.BytesCount       = sizeof( hb_avi_main_header_t ) - 8;
351     m.MicroSecPerFrame = (uint64_t) 1000000 * job->vrate_base / job->vrate;
352     m.Streams          = 1 + audio_count;
353     m.Width            = job->width;
354     m.Height           = job->height;
355 #undef m
356
357     /* Video track */
358     mux_data = calloc( sizeof( hb_mux_data_t ), 1 );
359     job->mux_data = mux_data;
360
361 #define h mux_data->header
362     /* Video stream header */
363     h.FourCC     = FOURCC( "strh" );
364     h.BytesCount = sizeof( hb_avi_stream_header_t ) - 8;
365     h.Type       = FOURCC( "vids" );
366
367     if( job->vcodec == HB_VCODEC_FFMPEG )
368         h.Handler = FOURCC( "divx" );
369     else if( job->vcodec == HB_VCODEC_XVID )
370         h.Handler = FOURCC( "xvid" );
371     else if( job->vcodec == HB_VCODEC_X264 )
372         h.Handler = FOURCC( "h264" );
373
374     h.Scale      = job->vrate_base;
375     h.Rate       = job->vrate;
376 #undef h
377
378 #define f mux_data->format.v
379     /* Video stream format */
380     f.FourCC      = FOURCC( "strf" );
381     f.BytesCount  = sizeof( hb_bitmap_info_t ) - 8;
382     f.Size        = f.BytesCount;
383     f.Width       = job->width;
384     f.Height      = job->height;
385     f.Planes      = 1;
386     f.BitCount    = 24;
387     if( job->vcodec == HB_VCODEC_FFMPEG )
388         f.Compression = FOURCC( "DX50" );
389     else if( job->vcodec == HB_VCODEC_XVID )
390         f.Compression = FOURCC( "XVID" );
391     else if( job->vcodec == HB_VCODEC_X264 )
392         f.Compression = FOURCC( "H264" );
393 #undef f
394
395 #define g mux_data->vprp_header
396     /* Vprp video stream header */      
397     AVRational sample_aspect_ratio = ( AVRational ){ job->pixel_aspect_width, job->pixel_aspect_height };
398     AVRational dar = av_mul_q( sample_aspect_ratio, ( AVRational ){ job->width, job->height } );
399     int num, den;
400     av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
401
402     g.FourCC                = FOURCC( "vprp" );
403     g.BytesCount            = sizeof( hb_avi_vprp_info_t ) - 8;
404     g.VideoFormatToken      = 0;
405     g.VideoStandard         = 0;
406     g.dwVerticalRefreshRate = job->vrate / job->vrate_base;
407     g.dwHTotalInT           = job->width;
408     g.dwVTotalInLines       = job->height;
409     g.dwFrameAspectRatioDen = den;
410     g.dwFrameAspectRatioNum = num;
411     g.dwFrameWidthInPixels  = job->width;
412     g.dwFrameHeightInLines  = job->height;
413     g.nbFieldPerFrame       = 1;
414     g.CompressedBMHeight    = job->height;
415     g.CompressedBMWidth     = job->width;
416     g.ValidBMHeight         = job->height;
417     g.ValidBMWidth          = job->width;
418     g.ValidBMXOffset        = 0;
419     g.ValidBMYOffset        = 0;
420     g.VideoXOffsetInT       = 0;
421     g.VideoYValidStartLine  = 0;
422 #undef g
423
424     /* Audio tracks */
425     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
426     {
427         audio = hb_list_item( title->list_audio, i );
428
429         is_ac3 = (audio->config.out.codec == HB_ACODEC_AC3);
430
431         mux_data = calloc( sizeof( hb_mux_data_t ), 1 );
432         audio->priv.mux_data = mux_data;
433
434 #define h mux_data->header
435 #define f mux_data->format.a.f
436 #define m mux_data->format.a.m
437         /* Audio stream header */
438         h.FourCC        = FOURCC( "strh" );
439         h.BytesCount    = sizeof( hb_avi_stream_header_t ) - 8;
440         h.Type          = FOURCC( "auds" );
441         h.InitialFrames = 1;
442         h.Scale         = 1;
443         h.Rate          = is_ac3 ? ( audio->config.in.bitrate / 8 ) :
444                                    ( audio->config.out.bitrate * 1000 / 8 );
445         h.Quality       = 0xFFFFFFFF;
446         h.SampleSize    = 1;
447
448         /* Audio stream format */
449         f.FourCC         = FOURCC( "strf" );
450         if( is_ac3 )
451         {
452             f.BytesCount     = sizeof( hb_wave_formatex_t ) - 8;
453             f.FormatTag      = 0x2000;
454             f.Channels       = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout);
455             f.SamplesPerSec  = audio->config.in.samplerate;
456         }
457         else
458         {
459             f.BytesCount     = sizeof( hb_wave_formatex_t ) +
460                                sizeof( hb_wave_mp3_t ) - 8;
461             f.FormatTag      = 0x55;
462             f.Channels       = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
463             f.SamplesPerSec  = audio->config.out.samplerate;
464         }
465         f.AvgBytesPerSec = h.Rate;
466         f.BlockAlign     = 1;
467         if( is_ac3 )
468         {
469             f.Size       = 0;
470         }
471         else
472         {
473             f.Size           = sizeof( hb_wave_mp3_t );
474             m.Id             = 1;
475             m.Flags          = 2;
476             m.BlockSize      = 1152 * f.AvgBytesPerSec / audio->config.out.samplerate;
477             m.FramesPerBlock = 1;
478             m.CodecDelay     = 1393;
479         }
480 #undef h
481 #undef f
482 #undef m
483     }
484
485     hdrl_bytes =
486         /* Main header */
487         4 + sizeof( hb_avi_main_header_t ) +
488         /* strh for video + audios */
489         ( 1 + audio_count ) * ( 12 + sizeof( hb_avi_stream_header_t ) ) +
490         /* video strf */
491                 sizeof( hb_bitmap_info_t ) +
492         /* video vprp */
493         ( job->pixel_ratio ? sizeof( hb_avi_vprp_info_t ) : 0 ) +
494         /* audios strf */
495         audio_count * ( sizeof( hb_wave_formatex_t ) +
496                         ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) );
497
498     /* Here we really start to write into the file */
499
500     /* Main headers */
501     WriteInt32( m->file, FOURCC( "RIFF" ) );
502     WriteInt32( m->file, 2040 );
503     WriteInt32( m->file, FOURCC( "AVI " ) );
504     WriteInt32( m->file, FOURCC( "LIST" ) );
505     WriteInt32( m->file, hdrl_bytes );
506     WriteInt32( m->file, FOURCC( "hdrl" ) );
507     WriteMainHeader( m->file, &m->main_header );
508
509     /* Video track */
510     mux_data          = job->mux_data;
511     mux_data->fourcc = FOURCC( "00dc" );
512
513     WriteInt32( m->file, FOURCC( "LIST" ) );
514     WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
515                 sizeof( hb_bitmap_info_t )  +
516                 ( job->pixel_ratio ? sizeof( hb_avi_vprp_info_t ) : 0 ) );
517     WriteInt32( m->file, FOURCC( "strl" ) );
518     WriteStreamHeader( m->file, &mux_data->header );
519     WriteBitmapInfo( m->file, &mux_data->format.v );
520     if( job->pixel_ratio )
521     {
522         WriteVprpInfo( m->file, &mux_data->vprp_header );
523     }
524
525     /* Audio tracks */
526     for( i = 0; i < audio_count; i++ )
527     {
528         char fourcc[4] = "00wb";
529
530         audio    = hb_list_item( title->list_audio, i );
531         mux_data = audio->priv.mux_data;
532
533         fourcc[1] = '1' + i; /* This is fine as we don't allow more
534                                 than 8 tracks */
535         mux_data->fourcc = FOURCC( fourcc );
536
537         WriteInt32( m->file, FOURCC( "LIST" ) );
538         WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
539                              sizeof( hb_wave_formatex_t ) +
540                              ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) );
541         WriteInt32( m->file, FOURCC( "strl" ) );
542         WriteStreamHeader( m->file, &mux_data->header );
543         WriteWaveFormatEx( m->file, &mux_data->format.a.f );
544         if( !is_ac3 )
545         {
546             WriteWaveMp3( m->file, &mux_data->format.a.m );
547         }
548     }
549
550     WriteInt32( m->file, FOURCC( "JUNK" ) );
551     WriteInt32( m->file, 2020 - hdrl_bytes );
552     for( i = 0; i < 2020 - hdrl_bytes; i++ )
553     {
554         WriteInt8( m->file, 0 );
555     }
556     WriteInt32( m->file, FOURCC( "LIST" ) );
557     WriteInt32( m->file, 4 );
558     WriteInt32( m->file, FOURCC( "movi" ) );
559
560     return 0;
561 }
562
563 static int AVIMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
564                    hb_buffer_t * buf )
565 {
566     hb_job_t   * job   = m->job;
567     hb_title_t * title = job->title;
568
569     hb_audio_t * audio;
570     int i;
571
572     /* Update index */
573     IndexAddInt32( m->index, mux_data->fourcc );
574     IndexAddInt32( m->index, (buf->frametype & HB_FRAME_KEY) ? AVIIF_KEYFRAME : 0 );
575     IndexAddInt32( m->index, 4 + m->size );
576     IndexAddInt32( m->index, buf->size );
577
578     /* Write the chunk to the file */
579     fseek( m->file, 0, SEEK_END );
580     WriteInt32( m->file, mux_data->fourcc );
581     WriteInt32( m->file, buf->size );
582     WriteBuffer( m->file, buf );
583
584     /* Chunks must be 2-bytes aligned */
585     if( buf->size & 1 )
586     {
587         WriteInt8( m->file, 0 );
588     }
589
590     /* Update headers */
591     m->size += 8 + EVEN( buf->size );
592     mux_data->header.Length++;
593
594     /* RIFF size */
595     fseek( m->file, 4, SEEK_SET );
596     WriteInt32( m->file, 2052 + m->size );
597
598     /* Mmmmh that's not nice */
599     fseek( m->file, 140, SEEK_SET );
600     WriteInt32( m->file, job->mux_data->header.Length );
601     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
602     {
603         audio = hb_list_item( title->list_audio, i );
604         fseek( m->file, 264 + i *
605                ( 102 + ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? 0 :
606                  sizeof( hb_wave_mp3_t ) ) ), SEEK_SET );
607         WriteInt32( m->file, audio->priv.mux_data->header.Length );
608     }
609
610     /* movi size */
611     fseek( m->file, 2052, SEEK_SET );
612     WriteInt32( m->file, 4 + m->size );
613     return 0;
614 }
615
616 static int AVIEnd( hb_mux_object_t * m )
617 {
618     hb_job_t * job = m->job;
619
620     hb_log( "muxavi: writing index" );
621     AddIndex( m );
622
623     hb_log( "muxavi: closing %s", job->file );
624     fclose( m->file );
625
626     hb_buffer_close( &m->index );
627
628     return 0;
629 }
630
631 hb_mux_object_t * hb_mux_avi_init( hb_job_t * job )
632 {
633     hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );
634     m->init      = AVIInit;
635     m->mux       = AVIMux;
636     m->end       = AVIEnd;
637     m->job       = job;
638     return m;
639 }
640