OSDN Git Service

MacGui: When using x264 and rf 0 is selected show "Warning: Lossless" in the field...
[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     int16_t        * 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( int16_t ) );
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
66     context->channel_layout = CH_LAYOUT_STEREO;
67     switch( audio->config.out.mixdown )
68     {
69         case HB_AMIXDOWN_MONO:
70             context->channel_layout = CH_LAYOUT_MONO;
71             break;
72
73         case HB_AMIXDOWN_STEREO:
74         case HB_AMIXDOWN_DOLBY:
75         case HB_AMIXDOWN_DOLBYPLII:
76             context->channel_layout = CH_LAYOUT_STEREO;
77             break;
78
79         case HB_AMIXDOWN_6CH:
80             context->channel_layout = CH_LAYOUT_5POINT0|CH_LOW_FREQUENCY;
81             break;
82
83         default:
84             hb_log(" encac3Init: bad mixdown" );
85             break;
86     }
87
88     context->bit_rate = audio->config.out.bitrate * 1000;
89     context->sample_rate = audio->config.out.samplerate;
90     context->channels = pv->out_discrete_channels;
91
92     if( hb_avcodec_open( context, codec ) )
93     {
94         hb_log( "encac3Init: avcodec_open failed" );
95     }
96     pv->context = context;
97
98     pv->list = hb_list_init();
99
100     return 0;
101 }
102
103 /***********************************************************************
104  * Close
105  ***********************************************************************
106  *
107  **********************************************************************/
108 void encac3Close( hb_work_object_t * w )
109 {
110     hb_work_private_t * pv = w->private_data;
111
112     if ( pv )
113     {
114         if( pv->context )
115         {
116             hb_deep_log( 2, "encac3: closing libavcodec" );
117             if ( pv->context->codec )
118                 avcodec_flush_buffers( pv->context );
119             hb_avcodec_close( pv->context );
120         }
121
122         if ( pv->buf )
123         {
124             free( pv->buf );
125             pv->buf = NULL;
126         }
127
128         if ( pv->samples )
129         {
130             free( pv->samples );
131             pv->samples = NULL;
132         }
133
134         if ( pv->list )
135             hb_list_empty( &pv->list );
136
137         free( pv );
138         w->private_data = NULL;
139     }
140 }
141
142 static hb_buffer_t * Encode( hb_work_object_t * w )
143 {
144     hb_work_private_t * pv = w->private_data;
145     uint64_t pts, pos;
146     hb_audio_t * audio = w->audio;
147     hb_buffer_t * buf;
148     int ii;
149
150     if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
151     {
152         return NULL;
153     }
154
155     hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
156                       &pts, &pos);
157
158     hb_chan_map_t *map = NULL;
159     if ( audio->config.in.codec == HB_ACODEC_AC3 )
160     {
161         map = &hb_ac3_chan_map;
162     }
163     else if ( audio->config.in.codec == HB_ACODEC_DCA )
164     {
165         map = &hb_qt_chan_map;
166     }
167     if ( map )
168     {
169         int layout;
170         switch (audio->config.out.mixdown)
171         {
172             case HB_AMIXDOWN_MONO:
173                 layout = HB_INPUT_CH_LAYOUT_MONO;
174                 break;
175             case HB_AMIXDOWN_STEREO:
176             case HB_AMIXDOWN_DOLBY:
177             case HB_AMIXDOWN_DOLBYPLII:
178                 layout = HB_INPUT_CH_LAYOUT_STEREO;
179                 break;
180             case HB_AMIXDOWN_6CH:
181             default:
182                 layout = HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE;
183                 break;
184         }
185         hb_layout_remap( map, &hb_smpte_chan_map, layout, 
186                         (float*)pv->buf, AC3_SAMPLES_PER_FRAME);
187     }
188     
189     for (ii = 0; ii < pv->input_samples; ii++)
190     {
191         pv->samples[ii] = (int16_t)((float*)pv->buf)[ii];
192     }
193
194     buf = hb_buffer_init( pv->output_bytes );
195     buf->size = avcodec_encode_audio( pv->context, buf->data, buf->alloc,
196                                           pv->samples );
197
198     buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
199     buf->stop  = buf->start + 90000 * AC3_SAMPLES_PER_FRAME / audio->config.out.samplerate;
200
201     buf->frametype = HB_FRAME_AUDIO;
202
203     if ( !buf->size )
204     {
205         hb_buffer_close( &buf );
206         return Encode( w );
207     }
208     else if (buf->size < 0)
209     {
210         hb_log( "encac3: avcodec_encode_audio failed" );
211         hb_buffer_close( &buf );
212         return NULL;
213     }
214
215     return buf;
216 }
217
218 /***********************************************************************
219  * Work
220  ***********************************************************************
221  *
222  **********************************************************************/
223 int encac3Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
224                     hb_buffer_t ** buf_out )
225 {
226     hb_work_private_t * pv = w->private_data;
227     hb_buffer_t * in = *buf_in, * buf;
228
229     if ( in->size <= 0 )
230     {
231         /* EOF on input - send it downstream & say we're done */
232         *buf_out = in;
233         *buf_in = NULL;
234        return HB_WORK_DONE;
235     }
236
237     if ( pv->context == NULL || pv->context->codec == NULL )
238     {
239         // No encoder context. Nothing we can do.
240         return HB_WORK_OK;
241     }
242
243     hb_list_add( pv->list, in );
244     *buf_in = NULL;
245
246     *buf_out = buf = Encode( w );
247
248     while ( buf )
249     {
250         buf->next = Encode( w );
251         buf = buf->next;
252     }
253
254     return HB_WORK_OK;
255 }
256
257