OSDN Git Service

Applied and committed saintdev's patch to fix multi-track audio. Only in the CLI...
[handbrake-jp/handbrake-jp-git.git] / libhb / deca52.c
1 /* $Id: deca52.c,v 1.14 2005/03/03 17:21:57 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 #include "a52dec/a52.h"
10
11 struct hb_work_private_s
12 {
13     hb_job_t    * job;
14
15     /* liba52 handle */
16     a52_state_t * state;
17
18     int           flags_in;
19     int           flags_out;
20     int           rate;
21     int           bitrate;
22     float         level;
23     
24     int           error;
25     int           sync;
26     int           size;
27
28     uint8_t       frame[3840];
29
30     hb_list_t   * list;
31         
32         int           channelsused;
33         
34 };
35
36 int  deca52Init( hb_work_object_t *, hb_job_t * );
37 int  deca52Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
38 void deca52Close( hb_work_object_t * );
39
40 hb_work_object_t hb_deca52 =
41 {
42     WORK_DECA52,
43     "AC3 decoder",
44     deca52Init,
45     deca52Work,
46     deca52Close
47 };
48
49 /***********************************************************************
50  * Local prototypes
51  **********************************************************************/
52 static hb_buffer_t * Decode( hb_work_object_t * w );
53
54 /***********************************************************************
55  * hb_work_deca52_init
56  ***********************************************************************
57  * Allocate the work object, initialize liba52
58  **********************************************************************/
59 int deca52Init( hb_work_object_t * w, hb_job_t * job )
60 {
61     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
62     w->private_data = pv;
63
64     pv->job   = job;
65
66     pv->list      = hb_list_init();
67     pv->state     = a52_init( 0 );
68
69         /* Decide what format we want out of a52dec
70         work.c has already done some of this deduction for us in do_job() */
71         
72         if (w->config->a52.channelsused == 6) {
73                 /* we're going to be encoding to AAC,
74                 and have turned on the "preserve 5.1" flag */
75                 pv->flags_out = A52_3F2R | A52_LFE;
76         } else if (w->config->a52.channelsused == 1) {
77                 /* we're going to be encoding to AAC, */
78                 /* and want to keep the mono-ness of the source audio */
79                 pv->flags_out = A52_MONO;
80         } else if (w->config->a52.channelsused == 2 && w->config->a52.channels == 5 && w->config->a52.lfechannels == 1) {
81                 /* we are mixing a 5.1 source down to stereo, so use dolby surround */
82                 pv->flags_out = A52_DOLBY;
83         } else if (w->config->a52.channelsused == 2 && ((w->config->a52.ac3flags & A52_CHANNEL_MASK) == A52_DOLBY)) {
84                 /* we have a dolby stereo surround source, so preserve it */
85                 pv->flags_out = A52_DOLBY;
86         } else {
87                 /* mix everything else down to plain stereo */
88                 pv->flags_out = A52_STEREO;
89         }
90
91         /* pass the number of channels used into the private work data */
92         pv->channelsused = w->config->a52.channelsused;
93
94     pv->level     = 32768.0;
95
96     return 0;
97 }
98
99 /***********************************************************************
100  * Close
101  ***********************************************************************
102  * Free memory
103  **********************************************************************/
104 void deca52Close( hb_work_object_t * w )
105 {
106     hb_work_private_t * pv = w->private_data;
107     a52_free( pv->state );
108 }
109
110 /***********************************************************************
111  * Work
112  ***********************************************************************
113  * Add the given buffer to the data we already have, and decode as much
114  * as we can
115  **********************************************************************/
116 int deca52Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
117                 hb_buffer_t ** buf_out )
118 {
119     hb_work_private_t * pv = w->private_data;
120     hb_buffer_t * buf;
121
122     hb_list_add( pv->list, *buf_in );
123     *buf_in = NULL;
124
125     /* If we got more than a frame, chain raw buffers */
126     *buf_out = buf = Decode( w );
127     while( buf )
128     {
129         buf->next = Decode( w );
130         buf       = buf->next;
131     }
132
133     return HB_WORK_OK;
134 }
135
136 /***********************************************************************
137  * Decode
138  ***********************************************************************
139  * 
140  **********************************************************************/
141 static hb_buffer_t * Decode( hb_work_object_t * w )
142 {
143     hb_work_private_t * pv = w->private_data;
144     hb_buffer_t * buf;
145     int           i, j, k;
146     uint64_t      pts, pos;
147
148     /* Get a frame header if don't have one yet */
149     if( !pv->sync )
150     {
151         while( hb_list_bytes( pv->list ) >= 7 )
152         {
153             /* We have 7 bytes, check if this is a correct header */
154             hb_list_seebytes( pv->list, pv->frame, 7 );
155             pv->size = a52_syncinfo( pv->frame, &pv->flags_in, &pv->rate,
156                                     &pv->bitrate );
157             if( pv->size )
158             {
159                 /* It is. W00t. */
160                 if( pv->error )
161                 {
162                     hb_log( "a52_syncinfo ok" );
163                 }
164                 pv->error = 0;
165                 pv->sync  = 1;
166                 break;
167             }
168
169             /* It is not */
170             if( !pv->error )
171             {
172                 hb_log( "a52_syncinfo failed" );
173                 pv->error = 1;
174             }
175
176             /* Try one byte later */
177             hb_list_getbytes( pv->list, pv->frame, 1, NULL, NULL );
178         }
179     }
180
181     if( !pv->sync ||
182         hb_list_bytes( pv->list ) < pv->size )
183     {
184         /* Need more data */
185         return NULL;
186     }
187
188     /* Get the whole frame */
189     hb_list_getbytes( pv->list, pv->frame, pv->size, &pts, &pos );
190
191     /* AC3 passthrough: don't decode the AC3 frame */
192     if( pv->job->acodec & HB_ACODEC_AC3 )
193     {
194         buf = hb_buffer_init( pv->size );
195         memcpy( buf->data, pv->frame, pv->size );
196         buf->start = pts + ( pos / pv->size ) * 6 * 256 * 90000 / pv->rate;
197         buf->stop  = buf->start + 6 * 256 * 90000 / pv->rate;
198         pv->sync = 0;
199         return buf;
200     }
201
202     /* Feed liba52 */
203     a52_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 );
204
205     /* 6 blocks per frame, 256 samples per block, channelsused channels */
206     buf        = hb_buffer_init( 6 * 256 * pv->channelsused * sizeof( float ) );
207     buf->start = pts + ( pos / pv->size ) * 6 * 256 * 90000 / pv->rate;
208     buf->stop  = buf->start + 6 * 256 * 90000 / pv->rate;
209
210     for( i = 0; i < 6; i++ )
211     {
212         sample_t * samples_in;
213         float    * samples_out;
214
215         a52_block( pv->state );
216         samples_in  = a52_samples( pv->state );
217         samples_out = ((float *) buf->data) + 256 * pv->channelsused * i;
218
219         /* Interleave */
220         for( j = 0; j < 256; j++ )
221         {
222                         for ( k = 0; k < pv->channelsused; k++ )
223                         {
224                                 samples_out[(pv->channelsused*j)+k]   = samples_in[(256*k)+j]; // DJA
225                         }
226         }
227     }
228
229     pv->sync = 0;
230     return buf;
231 }
232