OSDN Git Service

LinGui: change some preset keys to sync with mac presets
[handbrake-jp/handbrake-jp-git.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 "hbffmpeg.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_passthru = 0;
336     int is_ac3      = 0;
337     int hdrl_bytes;
338     int i;
339
340     /* Allocate index */
341     m->index       = hb_buffer_init( 1024 * 1024 );
342     m->index->size = 0;
343
344     /* Open destination file */
345     hb_log( "muxavi: opening %s", job->file );
346     m->file = fopen( job->file, "wb" );
347
348 #define m m->main_header
349     /* AVI main header */
350     m.FourCC           = FOURCC( "avih" );
351     m.BytesCount       = sizeof( hb_avi_main_header_t ) - 8;
352     m.MicroSecPerFrame = (uint64_t) 1000000 * job->vrate_base / job->vrate;
353     m.Streams          = 1 + audio_count;
354     m.Width            = job->width;
355     m.Height           = job->height;
356 #undef m
357
358     /* Video track */
359     mux_data = calloc( sizeof( hb_mux_data_t ), 1 );
360     job->mux_data = mux_data;
361
362 #define h mux_data->header
363     /* Video stream header */
364     h.FourCC     = FOURCC( "strh" );
365     h.BytesCount = sizeof( hb_avi_stream_header_t ) - 8;
366     h.Type       = FOURCC( "vids" );
367
368     if( job->vcodec == HB_VCODEC_FFMPEG )
369         h.Handler = FOURCC( "divx" );
370     else if( job->vcodec == HB_VCODEC_XVID )
371         h.Handler = FOURCC( "xvid" );
372     else if( job->vcodec == HB_VCODEC_X264 )
373         h.Handler = FOURCC( "h264" );
374
375     h.Scale      = job->vrate_base;
376     h.Rate       = job->vrate;
377 #undef h
378
379 #define f mux_data->format.v
380     /* Video stream format */
381     f.FourCC      = FOURCC( "strf" );
382     f.BytesCount  = sizeof( hb_bitmap_info_t ) - 8;
383     f.Size        = f.BytesCount;
384     f.Width       = job->width;
385     f.Height      = job->height;
386     f.Planes      = 1;
387     f.BitCount    = 24;
388     if( job->vcodec == HB_VCODEC_FFMPEG )
389         f.Compression = FOURCC( "DX50" );
390     else if( job->vcodec == HB_VCODEC_XVID )
391         f.Compression = FOURCC( "XVID" );
392     else if( job->vcodec == HB_VCODEC_X264 )
393         f.Compression = FOURCC( "H264" );
394 #undef f
395
396 #define g mux_data->vprp_header
397     /* Vprp video stream header */      
398     AVRational sample_aspect_ratio = ( AVRational ){ job->anamorphic.par_width, job->anamorphic.par_height };
399     AVRational dar = av_mul_q( sample_aspect_ratio, ( AVRational ){ job->width, job->height } );
400     int num, den;
401     av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
402
403     g.FourCC                = FOURCC( "vprp" );
404     g.BytesCount            = sizeof( hb_avi_vprp_info_t ) - 8;
405     g.VideoFormatToken      = 0;
406     g.VideoStandard         = 0;
407     g.dwVerticalRefreshRate = job->vrate / job->vrate_base;
408     g.dwHTotalInT           = job->width;
409     g.dwVTotalInLines       = job->height;
410     g.dwFrameAspectRatioDen = den;
411     g.dwFrameAspectRatioNum = num;
412     g.dwFrameWidthInPixels  = job->width;
413     g.dwFrameHeightInLines  = job->height;
414     g.nbFieldPerFrame       = 1;
415     g.CompressedBMHeight    = job->height;
416     g.CompressedBMWidth     = job->width;
417     g.ValidBMHeight         = job->height;
418     g.ValidBMWidth          = job->width;
419     g.ValidBMXOffset        = 0;
420     g.ValidBMYOffset        = 0;
421     g.VideoXOffsetInT       = 0;
422     g.VideoYValidStartLine  = 0;
423 #undef g
424
425     /* Audio tracks */
426     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
427     {
428         audio = hb_list_item( title->list_audio, i );
429
430         is_ac3 = (audio->config.out.codec == HB_ACODEC_AC3);
431         is_passthru = (audio->config.out.codec == HB_ACODEC_AC3) ||
432                       (audio->config.out.codec == HB_ACODEC_DCA);
433
434         mux_data = calloc( sizeof( hb_mux_data_t ), 1 );
435         audio->priv.mux_data = mux_data;
436
437 #define h mux_data->header
438 #define f mux_data->format.a.f
439 #define m mux_data->format.a.m
440         /* Audio stream header */
441         h.FourCC        = FOURCC( "strh" );
442         h.BytesCount    = sizeof( hb_avi_stream_header_t ) - 8;
443         h.Type          = FOURCC( "auds" );
444         h.InitialFrames = 1;
445         h.Scale         = 1;
446         h.Rate          = is_passthru ? ( audio->config.in.bitrate / 8 ) :
447                                    ( audio->config.out.bitrate * 1000 / 8 );
448         h.Quality       = 0xFFFFFFFF;
449         h.SampleSize    = 1;
450
451         /* Audio stream format */
452         f.FourCC         = FOURCC( "strf" );
453         if( is_passthru )
454         {
455             f.BytesCount     = sizeof( hb_wave_formatex_t ) - 8;
456             f.FormatTag      = is_ac3 ? 0x2000 : 0x2001;
457             f.Channels       = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout);
458             f.SamplesPerSec  = audio->config.in.samplerate;
459         }
460         else
461         {
462             f.BytesCount     = sizeof( hb_wave_formatex_t ) +
463                                sizeof( hb_wave_mp3_t ) - 8;
464             f.FormatTag      = 0x55;
465             f.Channels       = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
466             f.SamplesPerSec  = audio->config.out.samplerate;
467         }
468         f.AvgBytesPerSec = h.Rate;
469         f.BlockAlign     = 1;
470         if( is_passthru )
471         {
472             f.Size       = 0;
473         }
474         else
475         {
476             f.Size           = sizeof( hb_wave_mp3_t );
477             m.Id             = 1;
478             m.Flags          = 2;
479             m.BlockSize      = 1152 * f.AvgBytesPerSec / audio->config.out.samplerate;
480             m.FramesPerBlock = 1;
481             m.CodecDelay     = 1393;
482         }
483 #undef h
484 #undef f
485 #undef m
486     }
487
488     hdrl_bytes =
489         /* Main header */
490         4 + sizeof( hb_avi_main_header_t ) +
491         /* strh for video + audios */
492         ( 1 + audio_count ) * ( 12 + sizeof( hb_avi_stream_header_t ) ) +
493         /* video strf */
494                 sizeof( hb_bitmap_info_t ) +
495         /* video vprp */
496         ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) +
497         /* audios strf */
498         audio_count * ( sizeof( hb_wave_formatex_t ) +
499                         ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) );
500
501     /* Here we really start to write into the file */
502
503     /* Main headers */
504     WriteInt32( m->file, FOURCC( "RIFF" ) );
505     WriteInt32( m->file, 2040 );
506     WriteInt32( m->file, FOURCC( "AVI " ) );
507     WriteInt32( m->file, FOURCC( "LIST" ) );
508     WriteInt32( m->file, hdrl_bytes );
509     WriteInt32( m->file, FOURCC( "hdrl" ) );
510     WriteMainHeader( m->file, &m->main_header );
511
512     /* Video track */
513     mux_data          = job->mux_data;
514     mux_data->fourcc = FOURCC( "00dc" );
515
516     WriteInt32( m->file, FOURCC( "LIST" ) );
517     WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
518                 sizeof( hb_bitmap_info_t )  +
519                 ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) );
520     WriteInt32( m->file, FOURCC( "strl" ) );
521     WriteStreamHeader( m->file, &mux_data->header );
522     WriteBitmapInfo( m->file, &mux_data->format.v );
523     if( job->anamorphic.mode )
524     {
525         WriteVprpInfo( m->file, &mux_data->vprp_header );
526     }
527
528     /* Audio tracks */
529     for( i = 0; i < audio_count; i++ )
530     {
531         char fourcc[4] = "00wb";
532
533         audio    = hb_list_item( title->list_audio, i );
534         mux_data = audio->priv.mux_data;
535
536         fourcc[1] = '1' + i; /* This is fine as we don't allow more
537                                 than 8 tracks */
538         mux_data->fourcc = FOURCC( fourcc );
539
540         WriteInt32( m->file, FOURCC( "LIST" ) );
541         WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) +
542                              sizeof( hb_wave_formatex_t ) +
543                              ( is_passthru ? 0 : sizeof( hb_wave_mp3_t ) ) );
544         WriteInt32( m->file, FOURCC( "strl" ) );
545         WriteStreamHeader( m->file, &mux_data->header );
546         WriteWaveFormatEx( m->file, &mux_data->format.a.f );
547         if( !is_passthru )
548         {
549             WriteWaveMp3( m->file, &mux_data->format.a.m );
550         }
551     }
552
553     WriteInt32( m->file, FOURCC( "JUNK" ) );
554     WriteInt32( m->file, 2020 - hdrl_bytes );
555     for( i = 0; i < 2020 - hdrl_bytes; i++ )
556     {
557         WriteInt8( m->file, 0 );
558     }
559     WriteInt32( m->file, FOURCC( "LIST" ) );
560     WriteInt32( m->file, 4 );
561     WriteInt32( m->file, FOURCC( "movi" ) );
562
563     return 0;
564 }
565
566 static int AVIMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
567                    hb_buffer_t * buf )
568 {
569     hb_job_t   * job   = m->job;
570     hb_title_t * title = job->title;
571
572     hb_audio_t * audio;
573     int i;
574
575     /* Update index */
576     IndexAddInt32( m->index, mux_data->fourcc );
577     IndexAddInt32( m->index, (buf->frametype & HB_FRAME_KEY) ? AVIIF_KEYFRAME : 0 );
578     IndexAddInt32( m->index, 4 + m->size );
579     IndexAddInt32( m->index, buf->size );
580
581     /* Write the chunk to the file */
582     fseek( m->file, 0, SEEK_END );
583     WriteInt32( m->file, mux_data->fourcc );
584     WriteInt32( m->file, buf->size );
585     WriteBuffer( m->file, buf );
586
587     /* Chunks must be 2-bytes aligned */
588     if( buf->size & 1 )
589     {
590         WriteInt8( m->file, 0 );
591     }
592
593     /* Update headers */
594     m->size += 8 + EVEN( buf->size );
595     mux_data->header.Length++;
596
597     /* RIFF size */
598     fseek( m->file, 4, SEEK_SET );
599     WriteInt32( m->file, 2052 + m->size );
600
601     /* Mmmmh that's not nice */
602     fseek( m->file, 140, SEEK_SET );
603     WriteInt32( m->file, job->mux_data->header.Length );
604     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
605     {
606         int is_passthru;
607         audio = hb_list_item( title->list_audio, i );
608         is_passthru = (audio->config.out.codec == HB_ACODEC_AC3) ||
609                       (audio->config.out.codec == HB_ACODEC_DCA);
610         fseek( m->file, 264 + i *
611                ( 102 + ( is_passthru ? 0 :
612                  sizeof( hb_wave_mp3_t ) ) ), SEEK_SET );
613         WriteInt32( m->file, audio->priv.mux_data->header.Length );
614     }
615
616     /* movi size */
617     fseek( m->file, 2052, SEEK_SET );
618     WriteInt32( m->file, 4 + m->size );
619     return 0;
620 }
621
622 static int AVIEnd( hb_mux_object_t * m )
623 {
624     hb_job_t * job = m->job;
625
626     hb_log( "muxavi: writing index" );
627     AddIndex( m );
628
629     hb_log( "muxavi: closing %s", job->file );
630     fclose( m->file );
631
632     hb_buffer_close( &m->index );
633
634     return 0;
635 }
636
637 hb_mux_object_t * hb_mux_avi_init( hb_job_t * job )
638 {
639     hb_mux_object_t * m = calloc( sizeof( hb_mux_object_t ), 1 );
640     m->init      = AVIInit;
641     m->mux       = AVIMux;
642     m->end       = AVIEnd;
643     m->job       = job;
644     return m;
645 }
646