OSDN Git Service

added worker thread sleep throttling.
[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 #if 0
148                 if ((thread_sleep_interval <= 1) || (thread_sleep_interval > 100)) {
149                         hb_log("%s: %d", "Muxer", thread_sleep_interval);
150                 }
151 #endif
152
153         buf = hb_fifo_get( track->fifo );
154         if( job->pass != 1 )
155         {
156             m->mux( m, track->mux_data, buf );
157             track->frames += 1;
158             track->bytes  += buf->size;
159             mux->pts = buf->stop;
160         }
161         hb_buffer_close( &buf );
162     }
163
164     if( job->pass != 1 )
165     {
166         struct stat sb;
167         uint64_t bytes_total, frames_total;
168
169 #define p state.param.muxing
170         /* Update the UI */
171         hb_state_t state;
172         state.state   = HB_STATE_MUXING;
173                 p.progress = 0;
174         hb_set_state( job->h, &state );
175 #undef p
176         m->end( m );
177
178         if( !stat( job->file, &sb ) )
179         {
180             hb_log( "mux: file size, %lld bytes", (uint64_t) sb.st_size );
181
182             bytes_total  = 0;
183             frames_total = 0;
184             for( i = 0; i < hb_list_count( list ); i++ )
185             {
186                 track = hb_list_item( list, i );
187                 hb_log( "mux: track %d, %lld bytes, %.2f kbps",
188                         i, track->bytes,
189                         90000.0 * track->bytes / mux->pts / 125 );
190                 if( !i && ( job->vquality < 0.0 || job->vquality > 1.0 ) )
191                 {
192                     /* Video */
193                     hb_log( "mux: video bitrate error, %+lld bytes",
194                             track->bytes - mux->pts * job->vbitrate *
195                             125 / 90000 );
196                 }
197                 bytes_total  += track->bytes;
198                 frames_total += track->frames;
199             }
200
201             if( bytes_total && frames_total )
202             {
203                 hb_log( "mux: overhead, %.2f bytes per frame",
204                         (float) ( sb.st_size - bytes_total ) /
205                         frames_total );
206             }
207         }
208     }
209
210     free( m );
211
212     for( i = 0; i < hb_list_count( list ); i++ )
213     {
214         track = hb_list_item( list, i );
215         if( track->mux_data )
216         {
217             free( track->mux_data );
218         }
219         free( track );
220     }
221     hb_list_close( &list );
222
223     free( mux );
224 }
225
226 hb_thread_t * hb_muxer_init( hb_job_t * job )
227 {
228     hb_mux_t * mux = calloc( sizeof( hb_mux_t ), 1 );
229     mux->job = job;
230     return hb_thread_init( "muxer", MuxerFunc, mux,
231                            HB_NORMAL_PRIORITY );
232 }