OSDN Git Service

Adds extra, user-selectable dynamic range compression to the liba52 interface, making...
[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     float         dynamic_range_compression;
24     
25     int           error;
26     int           sync;
27     int           size;
28
29     int64_t       next_expected_pts;
30
31     int64_t       sequence;
32
33     uint8_t       frame[3840];
34
35     hb_list_t   * list;
36         
37         int           out_discrete_channels;
38         
39 };
40
41 int  deca52Init( hb_work_object_t *, hb_job_t * );
42 int  deca52Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
43 void deca52Close( hb_work_object_t * );
44
45 hb_work_object_t hb_deca52 =
46 {
47     WORK_DECA52,
48     "AC3 decoder",
49     deca52Init,
50     deca52Work,
51     deca52Close
52 };
53
54 /***********************************************************************
55  * Local prototypes
56  **********************************************************************/
57 static hb_buffer_t * Decode( hb_work_object_t * w );
58
59 /***********************************************************************
60  * dynrng_call
61  ***********************************************************************
62  * Boosts soft audio -- taken from gbooker's work in A52Decoder, comment and all..
63  * Two cases 
64  * 1) The user requested a compression of 1 or less, return the typical power rule 
65  * 2) The user requested a compression of more than 1 (decompression): 
66  *    If the stream's requested compression is less than 1.0 (loud sound), return the normal compression 
67  *    If the stream's requested compression is more than 1.0 (soft sound), use power rule (which will make
68  *   it louder in this case). 
69  * 
70  **********************************************************************/
71 static sample_t dynrng_call (sample_t c, void *data)
72 {        
73         double *level = (double *)data;
74         float levelToUse = (float)*level;
75         if(c > 1.0 || levelToUse <= 1.0)
76         {
77             return powf(c, levelToUse);
78         }
79         else
80                 return c;
81 }
82  
83 /***********************************************************************
84  * hb_work_deca52_init
85  ***********************************************************************
86  * Allocate the work object, initialize liba52
87  **********************************************************************/
88 int deca52Init( hb_work_object_t * w, hb_job_t * job )
89 {
90     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
91     w->private_data = pv;
92
93     pv->job   = job;
94
95     pv->list      = hb_list_init();
96     pv->state     = a52_init( 0 );
97
98         /* Decide what format we want out of a52dec
99         work.c has already done some of this deduction for us in do_job() */
100         
101         pv->flags_out = HB_AMIXDOWN_GET_A52_FORMAT(w->amixdown);
102
103         /* pass the number of channels used into the private work data */
104         /* will only be actually used if we're not doing AC3 passthru */
105         pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(w->amixdown);
106
107     pv->level     = 32768.0;
108     pv->dynamic_range_compression = job->dynamic_range_compression;
109     
110     pv->next_expected_pts = 0;
111     pv->sequence = 0;
112     
113     return 0;
114 }
115
116 /***********************************************************************
117  * Close
118  ***********************************************************************
119  * Free memory
120  **********************************************************************/
121 void deca52Close( hb_work_object_t * w )
122 {
123     hb_work_private_t * pv = w->private_data;
124     a52_free( pv->state );
125     hb_list_empty( &pv->list );
126     free( pv );
127     w->private_data = NULL;
128 }
129
130 /***********************************************************************
131  * Work
132  ***********************************************************************
133  * Add the given buffer to the data we already have, and decode as much
134  * as we can
135  **********************************************************************/
136 int deca52Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
137                 hb_buffer_t ** buf_out )
138 {
139     hb_work_private_t * pv = w->private_data;
140     hb_buffer_t * buf;
141
142     if( buf_in && *buf_in )
143     {
144         pv->sequence = (*buf_in)->sequence;
145     }
146
147     hb_list_add( pv->list, *buf_in );
148     *buf_in = NULL;
149
150     /* If we got more than a frame, chain raw buffers */
151     *buf_out = buf = Decode( w );
152     while( buf )
153     { 
154         buf->sequence = pv->sequence;
155         buf->next = Decode( w );
156         buf       = buf->next;
157     }
158
159     return HB_WORK_OK;
160 }
161
162 /***********************************************************************
163  * Decode
164  ***********************************************************************
165  * 
166  **********************************************************************/
167 static hb_buffer_t * Decode( hb_work_object_t * w )
168 {
169     hb_work_private_t * pv = w->private_data;
170     hb_buffer_t * buf;
171     int           i, j, k;
172     uint64_t      pts, pos;
173
174     /* Get a frame header if don't have one yet */
175     if( !pv->sync )
176     {
177         while( hb_list_bytes( pv->list ) >= 7 )
178         {
179             /* We have 7 bytes, check if this is a correct header */
180             hb_list_seebytes( pv->list, pv->frame, 7 );
181             pv->size = a52_syncinfo( pv->frame, &pv->flags_in, &pv->rate,
182                                     &pv->bitrate );
183             if( pv->size )
184             {
185                 /* It is. W00t. */
186                 if( pv->error )
187                 {
188                     hb_log( "a52_syncinfo ok" );
189                 }
190                 pv->error = 0;
191                 pv->sync  = 1;
192                 break;
193             }
194
195             /* It is not */
196             if( !pv->error )
197             {
198                 hb_log( "a52_syncinfo failed" );
199                 pv->error = 1;
200             }
201
202             /* Try one byte later */
203             hb_list_getbytes( pv->list, pv->frame, 1, NULL, NULL );
204         }
205     }
206
207     if( !pv->sync ||
208         hb_list_bytes( pv->list ) < pv->size )
209     {
210         /* Need more data */
211         return NULL;
212     }
213
214     /* Get the whole frame */
215     hb_list_getbytes( pv->list, pv->frame, pv->size, &pts, &pos );
216
217     /* AC3 passthrough: don't decode the AC3 frame */
218     if( pv->job->acodec & HB_ACODEC_AC3 )
219     {
220         buf = hb_buffer_init( pv->size );
221         memcpy( buf->data, pv->frame, pv->size );
222         buf->start = pts + ( pos / pv->size ) * 6 * 256 * 90000 / pv->rate;
223         buf->stop  = buf->start + 6 * 256 * 90000 / pv->rate;
224         pv->sync = 0;
225         return buf;
226     }
227
228     /* Feed liba52 */
229     a52_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 );
230
231     if ( pv->dynamic_range_compression )
232     {
233         a52_dynrng( pv->state, dynrng_call, &pv->dynamic_range_compression);        
234     }
235     
236     /* 6 blocks per frame, 256 samples per block, channelsused channels */
237     buf        = hb_buffer_init( 6 * 256 * pv->out_discrete_channels * sizeof( float ) );
238     if (pts == -1)
239     {
240       pts = pv->next_expected_pts;
241     }
242     buf->start = pts + ( pos / pv->size ) * 6 * 256 * 90000 / pv->rate;
243     buf->stop  = buf->start + 6 * 256 * 90000 / pv->rate;
244
245     /*
246        * To track AC3 PTS add this back in again.
247         *hb_log("AC3: pts is %lld, buf->start %lld buf->stop %lld", pts, buf->start, buf->stop); 
248         */
249     
250     pv->next_expected_pts = buf->stop;
251     
252     for( i = 0; i < 6; i++ )
253     {
254         sample_t * samples_in;
255         float    * samples_out;
256
257         a52_block( pv->state );
258         samples_in  = a52_samples( pv->state );
259         samples_out = ((float *) buf->data) + 256 * pv->out_discrete_channels * i;
260
261         /* Interleave */
262         for( j = 0; j < 256; j++ )
263         {
264                         for ( k = 0; k < pv->out_discrete_channels; k++ )
265                         {
266                                 samples_out[(pv->out_discrete_channels*j)+k]   = samples_in[(256*k)+j];
267                         }
268         }
269
270     }
271
272     pv->sync = 0;
273     return buf;
274 }
275