OSDN Git Service

Merge from avformat branch
[handbrake-jp/handbrake-jp-git.git] / libhb / muxcommon.c
1 /* $Id: muxcommon.c,v 1.23 2005/03/30 17:27:19 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.m0k.org/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8
9 struct hb_mux_object_s
10 {
11     HB_MUX_COMMON;
12 };
13
14 typedef struct
15 {
16     hb_job_t * job;
17     uint64_t   pts;
18
19 } hb_mux_t;
20
21 typedef struct
22 {
23     hb_fifo_t     * fifo;
24     hb_mux_data_t * mux_data;
25     uint64_t        frames;
26     uint64_t        bytes;
27
28 } hb_track_t;
29
30 static hb_track_t * GetTrack( hb_list_t * list )
31 {
32     hb_buffer_t * buf;
33     hb_track_t  * track = NULL, * track2;
34     int64_t       pts = 0;
35     int           i;
36
37     for( i = 0; i < hb_list_count( list ); i++ )
38     {
39         track2 = hb_list_item( list, i );
40         buf    = hb_fifo_see( track2->fifo );
41         if( !buf )
42         {
43             return NULL;
44         }
45         if( !track || buf->start < pts )
46         {
47             track = track2;
48             pts   = buf->start;
49         }
50     }
51     return track;
52 }
53
54 static void MuxerFunc( void * _mux )
55 {
56     hb_mux_t    * mux = _mux;
57     hb_job_t    * job = mux->job;
58     hb_title_t  * title = job->title;
59     hb_audio_t  * audio;
60     hb_list_t   * list;
61     hb_buffer_t * buf;
62     hb_track_t  * track;
63     int           i;
64
65     hb_mux_object_t * m = NULL;
66
67     /* Get a real muxer */
68     if( job->pass != 1 )
69     {
70         switch( job->mux )
71         {
72             case HB_MUX_MP4:
73             case HB_MUX_PSP:
74                 m = hb_mux_mp4_init( job );
75                 break;
76             case HB_MUX_AVI:
77                 m = hb_mux_avi_init( job );
78                 break;
79             case HB_MUX_OGM:
80                 m = hb_mux_ogm_init( job );
81                 break;
82         }
83     }
84
85     /* Wait for one buffer for each track */
86     while( !*job->die && !job->done )
87     {
88         int ready;
89
90         ready = 1;
91         if( !hb_fifo_size( job->fifo_mpeg4 ) )
92         {
93             ready = 0;
94         }
95         for( i = 0; i < hb_list_count( title->list_audio ); i++ )
96         {
97             audio = hb_list_item( title->list_audio, i );
98             if( !hb_fifo_size( audio->fifo_out ) )
99             {
100                 ready = 0;
101                 break;
102             }
103         }
104
105         if( ready )
106         {
107             break;
108         }
109
110         hb_snooze( 50 );
111     }
112
113     /* Create file, write headers */
114     if( job->pass != 1 )
115     {
116         m->init( m );
117     }
118
119     /* Build list of fifos we're interested in */
120     list = hb_list_init();
121
122     track           = calloc( sizeof( hb_track_t ), 1 );
123     track->fifo     = job->fifo_mpeg4;
124     track->mux_data = job->mux_data;
125     hb_list_add( list, track );
126
127     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
128     {
129         audio           = hb_list_item( title->list_audio, i );
130         track           = calloc( sizeof( hb_track_t ), 1 );
131         track->fifo     = audio->fifo_out;
132         track->mux_data = audio->mux_data;
133         hb_list_add( list, track );
134     }
135
136     while( !*job->die && !job->done )
137     {
138         if( !( track = GetTrack( list ) ) )
139         {
140             hb_snooze( 50 );
141             continue;
142         }
143
144         buf = hb_fifo_get( track->fifo );
145         if( job->pass != 1 )
146         {
147             m->mux( m, track->mux_data, buf );
148             track->frames += 1;
149             track->bytes  += buf->size;
150             mux->pts = buf->stop;
151         }
152         hb_buffer_close( &buf );
153     }
154
155     if( job->pass != 1 )
156     {
157         struct stat sb;
158         uint64_t bytes_total, frames_total;
159
160         m->end( m );
161
162         if( !stat( job->file, &sb ) )
163         {
164             hb_log( "mux: file size, %lld bytes", (uint64_t) sb.st_size );
165
166             bytes_total  = 0;
167             frames_total = 0;
168             for( i = 0; i < hb_list_count( list ); i++ )
169             {
170                 track = hb_list_item( list, i );
171                 hb_log( "mux: track %d, %lld bytes, %.2f kbps",
172                         i, track->bytes,
173                         90000.0 * track->bytes / mux->pts / 125 );
174                 if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) )
175                 {
176                     /* Video */
177                     hb_log( "mux: video bitrate error, %+lld bytes",
178                             track->bytes - mux->pts * job->vbitrate *
179                             125 / 90000 );
180                 }
181                 bytes_total  += track->bytes;
182                 frames_total += track->frames;
183             }
184
185             if( bytes_total && frames_total )
186             {
187                 hb_log( "mux: overhead, %.2f bytes per frame",
188                         (float) ( sb.st_size - bytes_total ) /
189                         frames_total );
190             }
191         }
192     }
193
194     free( m );
195
196     for( i = 0; i < hb_list_count( list ); i++ )
197     {
198         track = hb_list_item( list, i );
199         if( track->mux_data )
200         {
201             free( track->mux_data );
202         }
203         free( track );
204     }
205     hb_list_close( &list );
206
207     free( mux );
208 }
209
210 hb_thread_t * hb_muxer_init( hb_job_t * job )
211 {
212     hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
213     mux->job = job;
214     return hb_thread_init( "muxer", MuxerFunc, mux,
215                            HB_NORMAL_PRIORITY );
216 }