OSDN Git Service

Merge the 5.1 branch into the trunk.
[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                         case HB_MUX_IPOD:
75                 m = hb_mux_mp4_init( job );
76                 break;
77             case HB_MUX_AVI:
78                 m = hb_mux_avi_init( job );
79                 break;
80             case HB_MUX_OGM:
81                 m = hb_mux_ogm_init( job );
82                 break;
83         }
84     }
85
86     /* Wait for one buffer for each track */
87     while( !*job->die && !job->done )
88     {
89         int ready;
90
91         ready = 1;
92         if( !hb_fifo_size( job->fifo_mpeg4 ) )
93         {
94             ready = 0;
95         }
96         for( i = 0; i < hb_list_count( title->list_audio ); i++ )
97         {
98             audio = hb_list_item( title->list_audio, i );
99             if( !hb_fifo_size( audio->fifo_out ) )
100             {
101                 ready = 0;
102                 break;
103             }
104         }
105
106         if( ready )
107         {
108             break;
109         }
110
111         hb_snooze( 200 );
112     }
113
114     /* Create file, write headers */
115     if( job->pass != 1 )
116     {
117         m->init( m );
118     }
119
120     /* Build list of fifos we're interested in */
121     list = hb_list_init();
122
123     track           = calloc( sizeof( hb_track_t ), 1 );
124     track->fifo     = job->fifo_mpeg4;
125     track->mux_data = job->mux_data;
126     hb_list_add( list, track );
127
128     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
129     {
130         audio           = hb_list_item( title->list_audio, i );
131         track           = calloc( sizeof( hb_track_t ), 1 );
132         track->fifo     = audio->fifo_out;
133         track->mux_data = audio->mux_data;
134         hb_list_add( list, track );
135     }
136
137         int thread_sleep_interval = 50;
138         while( !*job->die && !job->done )
139     {
140         if( !( track = GetTrack( list ) ) )
141         {
142             hb_snooze( thread_sleep_interval );
143 //                      thread_sleep_interval += 1;
144             continue;
145         }
146 //              thread_sleep_interval = MAX(1, (thread_sleep_interval - 1));
147
148         buf = hb_fifo_get( track->fifo );
149         if( job->pass != 1 )
150         {
151             m->mux( m, track->mux_data, buf );
152             track->frames += 1;
153             track->bytes  += buf->size;
154             mux->pts = buf->stop;
155         }
156         hb_buffer_close( &buf );
157     }
158
159     if( job->pass != 1 )
160     {
161         struct stat sb;
162         uint64_t bytes_total, frames_total;
163
164 #define p state.param.muxing
165         /* Update the UI */
166         hb_state_t state;
167         state.state   = HB_STATE_MUXING;
168                 p.progress = 0;
169         hb_set_state( job->h, &state );
170 #undef p
171         m->end( m );
172
173         if( !stat( job->file, &sb ) )
174         {
175             hb_log( "mux: file size, %lld bytes", (uint64_t) sb.st_size );
176
177             bytes_total  = 0;
178             frames_total = 0;
179             for( i = 0; i < hb_list_count( list ); i++ )
180             {
181                 track = hb_list_item( list, i );
182                 hb_log( "mux: track %d, %lld bytes, %.2f kbps",
183                         i, track->bytes,
184                         90000.0 * track->bytes / mux->pts / 125 );
185                 if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) )
186                 {
187                     /* Video */
188                     hb_log( "mux: video bitrate error, %+lld bytes",
189                             track->bytes - mux->pts * job->vbitrate *
190                             125 / 90000 );
191                 }
192                 bytes_total  += track->bytes;
193                 frames_total += track->frames;
194             }
195
196             if( bytes_total && frames_total )
197             {
198                 hb_log( "mux: overhead, %.2f bytes per frame",
199                         (float) ( sb.st_size - bytes_total ) /
200                         frames_total );
201             }
202         }
203     }
204
205     free( m );
206
207     for( i = 0; i < hb_list_count( list ); i++ )
208     {
209         track = hb_list_item( list, i );
210         if( track->mux_data )
211         {
212             free( track->mux_data );
213         }
214         free( track );
215     }
216     hb_list_close( &list );
217
218     free( mux );
219 }
220
221 hb_thread_t * hb_muxer_init( hb_job_t * job )
222 {
223     hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
224     mux->job = job;
225     return hb_thread_init( "muxer", MuxerFunc, mux,
226                            HB_NORMAL_PRIORITY );
227 }