OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / libhb / encac3.c
1 /* $Id: encac3.c,v 1.23 2005/10/13 23:47:06 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8 #include "hbffmpeg.h"
9 #include "downmix.h"
10
11 struct hb_work_private_s
12 {
13     hb_job_t       * job;
14     AVCodecContext * context;
15
16     int              out_discrete_channels;
17     unsigned long    input_samples;
18     unsigned long    output_bytes;
19     hb_list_t      * list;
20     uint8_t        * buf;
21     float          * samples;
22 };
23
24 int  encac3Init( hb_work_object_t *, hb_job_t * );
25 int  encac3Work( hb_work_object_t *, hb_buffer_t **, hb_buffer_t ** );
26 void encac3Close( hb_work_object_t * );
27
28 #define AC3_SAMPLES_PER_FRAME 1536
29 #define AC3_MAX_CODED_FRAME_SIZE 3840
30
31 hb_work_object_t hb_encac3 =
32 {
33     WORK_ENCAC3,
34     "AC-3 encoder (libavcodec)",
35     encac3Init,
36     encac3Work,
37     encac3Close
38 };
39
40 int encac3Init( hb_work_object_t * w, hb_job_t * job )
41 {
42     AVCodec * codec;
43     AVCodecContext * context;
44     hb_audio_t * audio = w->audio;
45
46     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
47     w->private_data = pv;
48
49     pv->job = job;
50
51     pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);
52     pv->input_samples = AC3_SAMPLES_PER_FRAME * pv->out_discrete_channels;
53     pv->output_bytes = AC3_MAX_CODED_FRAME_SIZE;
54
55     pv->buf = malloc( pv->input_samples * sizeof( float ) );
56     pv->samples = malloc( pv->input_samples * sizeof( float ) );
57
58     codec = avcodec_find_encoder( CODEC_ID_AC3 );
59     if( !codec )
60     {
61         hb_log( "encac3Init: avcodec_find_encoder "
62                 "failed" );
63     }
64     context = avcodec_alloc_context();
65     avcodec_get_context_defaults3(context, codec);
66
67     context->channel_layout = CH_LAYOUT_STEREO;
68     switch( audio->config.out.mixdown )
69     {
70         case HB_AMIXDOWN_MONO:
71             context->channel_layout = CH_LAYOUT_MONO;
72             break;
73
74         case HB_AMIXDOWN_STEREO:
75         case HB_AMIXDOWN_DOLBY:
76         case HB_AMIXDOWN_DOLBYPLII:
77             context->channel_layout = CH_LAYOUT_STEREO;
78             break;
79
80         case HB_AMIXDOWN_6CH:
81             context->channel_layout = CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY;
82             break;
83
84         default:
85             hb_log(" encac3Init: bad mixdown" );
86             break;
87     }
88
89     context->bit_rate = audio->config.out.bitrate * 1000;
90     context->sample_rate = audio->config.out.samplerate;
91     context->channels = pv->out_discrete_channels;
92     context->sample_fmt = AV_SAMPLE_FMT_FLT;
93
94     if( hb_avcodec_open( context, codec ) )
95     {
96         hb_log( "encac3Init: avcodec_open failed" );
97     }
98     pv->context = context;
99
100     pv->list = hb_list_init();
101
102     return 0;
103 }
104
105 /***********************************************************************
106  * Close
107  ***********************************************************************
108  *
109  **********************************************************************/
110 void encac3Close( hb_work_object_t * w )
111 {
112     hb_work_private_t * pv = w->private_data;
113
114     if ( pv )
115     {
116         if( pv->context )
117         {
118             hb_deep_log( 2, "encac3: closing libavcodec" );
119             if ( pv->context->codec )
120                 avcodec_flush_buffers( pv->context );
121             hb_avcodec_close( pv->context );
122         }
123
124         if ( pv->buf )
125         {
126             free( pv->buf );
127             pv->buf = NULL;
128         }
129
130         if ( pv->samples )
131         {
132             free( pv->samples );
133             pv->samples = NULL;
134         }
135
136         if ( pv->list )
137             hb_list_empty( &pv->list );
138
139         free( pv );
140         w->private_data = NULL;
141     }
142 }
143
144 static hb_buffer_t * Encode( hb_work_object_t * w )
145 {
146     hb_work_private_t * pv = w->private_data;
147     uint64_t pts, pos;
148     hb_audio_t * audio = w->audio;
149     hb_buffer_t * buf;
150     int ii;
151
152     if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
153     {
154         return NULL;
155     }
156
157     hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
158                       &pts, &pos);
159
160     hb_chan_map_t *map = NULL;
161     if ( audio->config.in.codec == HB_ACODEC_AC3 )
162     {
163         map = &hb_ac3_chan_map;
164     }
165     else if ( audio->config.in.codec == HB_ACODEC_DCA )
166     {
167         map = &hb_qt_chan_map;
168     }
169     if ( map )
170     {
171         int layout;
172         switch (audio->config.out.mixdown)
173         {
174             case HB_AMIXDOWN_MONO:
175                 layout = HB_INPUT_CH_LAYOUT_MONO;
176                 break;
177             case HB_AMIXDOWN_STEREO:
178             case HB_AMIXDOWN_DOLBY:
179             case HB_AMIXDOWN_DOLBYPLII:
180                 layout = HB_INPUT_CH_LAYOUT_STEREO;
181                 break;
182             case HB_AMIXDOWN_6CH:
183             default:
184                 layout = HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE;
185                 break;
186         }
187         hb_layout_remap( map, &hb_smpte_chan_map, layout, 
188                         (float*)pv->buf, AC3_SAMPLES_PER_FRAME);
189     }
190     
191     for (ii = 0; ii < pv->input_samples; ii++)
192     {
193         // ffmpeg float samples are -1.0 to 1.0
194         pv->samples[ii] = ((float*)pv->buf)[ii] / 32768.0;
195     }
196
197     buf = hb_buffer_init( pv->output_bytes );
198     buf->size = avcodec_encode_audio( pv->context, buf->data, buf->alloc,
199                                       (short*)pv->samples );
200
201     buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
202     buf->stop  = buf->start + 90000 * AC3_SAMPLES_PER_FRAME / audio->config.out.samplerate;
203
204     buf->frametype = HB_FRAME_AUDIO;
205
206     if ( !buf->size )
207     {
208         hb_buffer_close( &buf );
209         return Encode( w );
210     }
211     else if (buf->size < 0)
212     {
213         hb_log( "encac3: avcodec_encode_audio failed" );
214         hb_buffer_close( &buf );
215         return NULL;
216     }
217
218     return buf;
219 }
220
221 /***********************************************************************
222  * Work
223  ***********************************************************************
224  *
225  **********************************************************************/
226 int encac3Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
227                     hb_buffer_t ** buf_out )
228 {
229     hb_work_private_t * pv = w->private_data;
230     hb_buffer_t * in = *buf_in, * buf;
231
232     if ( in->size <= 0 )
233     {
234         /* EOF on input - send it downstream & say we're done */
235         *buf_out = in;
236         *buf_in = NULL;
237        return HB_WORK_DONE;
238     }
239
240     if ( pv->context == NULL || pv->context->codec == NULL )
241     {
242         // No encoder context. Nothing we can do.
243         return HB_WORK_OK;
244     }
245
246     hb_list_add( pv->list, in );
247     *buf_in = NULL;
248
249     *buf_out = buf = Encode( w );
250
251     while ( buf )
252     {
253         buf->next = Encode( w );
254         buf = buf->next;
255     }
256
257     return HB_WORK_OK;
258 }
259
260