OSDN Git Service

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