OSDN Git Service

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