OSDN Git Service

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