OSDN Git Service

HandBrake 0.7.0
[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_object_s
12 {
13     HB_WORK_COMMON;
14
15     hb_job_t    * job;
16     hb_audio_t  * audio;
17
18     /* liba52 handle */
19     a52_state_t * state;
20
21     int           flags_in;
22     int           flags_out;
23     int           rate;
24     int           bitrate;
25     float         level;
26     
27     int           error;
28     int           sync;
29     int           size;
30
31     uint8_t       frame[3840];
32
33     hb_list_t   * list;
34 };
35
36 /***********************************************************************
37  * Local prototypes
38  **********************************************************************/
39 static void          Close( hb_work_object_t ** _w );
40 static int           Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
41                            hb_buffer_t ** buf_out );
42 static hb_buffer_t * Decode( hb_work_object_t * w );
43
44 /***********************************************************************
45  * hb_work_deca52_init
46  ***********************************************************************
47  * Allocate the work object, initialize liba52
48  **********************************************************************/
49 hb_work_object_t * hb_work_deca52_init( hb_job_t * job, hb_audio_t * audio )
50 {
51     hb_work_object_t * w = calloc( sizeof( hb_work_object_t ), 1 );
52     w->name  = strdup( "AC3 decoder" );
53     w->work  = Work;
54     w->close = Close;
55
56     w->job   = job;
57     w->audio = audio;
58
59     w->list      = hb_list_init();
60     w->state     = a52_init( 0 );
61     w->flags_out = A52_STEREO;
62     w->level     = 32768.0;
63
64     return w;
65 }
66
67 /***********************************************************************
68  * Close
69  ***********************************************************************
70  * Free memory
71  **********************************************************************/
72 static void Close( hb_work_object_t ** _w )
73 {
74     hb_work_object_t * w = *_w;
75     a52_free( w->state );
76     free( w->name );
77     free( w );
78     *_w = NULL;
79 }
80
81 /***********************************************************************
82  * Work
83  ***********************************************************************
84  * Add the given buffer to the data we already have, and decode as much
85  * as we can
86  **********************************************************************/
87 static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
88                  hb_buffer_t ** buf_out )
89 {
90     hb_buffer_t * buf;
91
92     hb_list_add( w->list, *buf_in );
93     *buf_in = NULL;
94
95     /* If we got more than a frame, chain raw buffers */
96     *buf_out = buf = Decode( w );
97     while( buf )
98     {
99         buf->next = Decode( w );
100         buf       = buf->next;
101     }
102
103     return HB_WORK_OK;
104 }
105
106 /***********************************************************************
107  * Decode
108  ***********************************************************************
109  * 
110  **********************************************************************/
111 static hb_buffer_t * Decode( hb_work_object_t * w )
112 {
113     hb_buffer_t * buf;
114     int           i, j;
115     uint64_t      pts;
116     int           pos;
117
118     /* Get a frame header if don't have one yet */
119     if( !w->sync )
120     {
121         while( hb_list_bytes( w->list ) >= 7 )
122         {
123             /* We have 7 bytes, check if this is a correct header */
124             hb_list_seebytes( w->list, w->frame, 7 );
125             w->size = a52_syncinfo( w->frame, &w->flags_in, &w->rate,
126                                     &w->bitrate );
127             if( w->size )
128             {
129                 /* It is. W00t. */
130                 if( w->error )
131                 {
132                     hb_log( "a52_syncinfo ok" );
133                 }
134                 w->error = 0;
135                 w->sync  = 1;
136                 break;
137             }
138
139             /* It is not */
140             if( !w->error )
141             {
142                 hb_log( "a52_syncinfo failed" );
143                 w->error = 1;
144             }
145
146             /* Try one byte later */
147             hb_list_getbytes( w->list, w->frame, 1, NULL, NULL );
148         }
149     }
150
151     if( !w->sync ||
152         hb_list_bytes( w->list ) < w->size )
153     {
154         /* Need more data */
155         return NULL;
156     }
157
158     /* Get the whole frame */
159     hb_list_getbytes( w->list, w->frame, w->size, &pts, &pos );
160
161     /* AC3 passthrough: don't decode the AC3 frame */
162     if( w->job->acodec & HB_ACODEC_AC3 )
163     {
164         buf = hb_buffer_init( w->size );
165         memcpy( buf->data, w->frame, w->size );
166         buf->start = pts + ( pos / w->size ) * 6 * 256 * 90000 / w->rate;
167         buf->stop  = buf->start + 6 * 256 * 90000 / w->rate;
168         w->sync = 0;
169         return buf;
170     }
171
172     /* Feed liba52 */
173     a52_frame( w->state, w->frame, &w->flags_out, &w->level, 0 );
174
175     /* 6 blocks per frame, 256 samples per block, 2 channels */
176     buf        = hb_buffer_init( 3072 * sizeof( float ) );
177     buf->start = pts + ( pos / w->size ) * 6 * 256 * 90000 / w->rate;
178     buf->stop  = buf->start + 6 * 256 * 90000 / w->rate;
179
180     for( i = 0; i < 6; i++ )
181     {
182         sample_t * samples_in;
183         float    * samples_out;
184
185         a52_block( w->state );
186         samples_in  = a52_samples( w->state );
187         samples_out = ((float *) buf->data) + 512 * i;
188
189         /* Interleave */
190         for( j = 0; j < 256; j++ )
191         {
192             samples_out[2*j]   = samples_in[j];
193             samples_out[2*j+1] = samples_in[256+j];
194         }
195     }
196
197     w->sync = 0;
198     return buf;
199 }
200