xlat changes, layout changes
[goodguy/history.git] / cinelerra-5.1 / cinelerra / fileac3.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <ctype.h>
29 #include <limits.h>
30 // work around (centos) for __STDC_CONSTANT_MACROS
31 #include <lzma.h>
32 #ifndef INT64_MAX
33 #   define INT64_MAX 9223372036854775807LL
34 #endif
35
36 extern "C"
37 {
38 #include "libavcodec/avcodec.h"
39 }
40
41 #include "asset.h"
42 #include "clip.h"
43 #include "fileac3.h"
44 #include "file.h"
45 #include "filempeg.h"
46 #include "language.h"
47 #include "mainerror.h"
48
49
50
51 #include <string.h>
52
53 FileAC3::FileAC3(Asset *asset, File *file)
54  : FileBase(asset, file)
55 {
56         reset_parameters();
57         mpg_file = 0;
58 }
59
60 FileAC3::~FileAC3()
61 {
62         if( mpg_file ) delete mpg_file;
63         close_file();
64 }
65
66 int FileAC3::reset_parameters_derived()
67 {
68         codec = 0;
69         codec_context = 0;
70         resample_context = 0;
71         fd = 0;
72         temp_raw = 0;
73         temp_raw_size = 0;
74         temp_raw_allocated = 0;
75         temp_compressed = 0;
76         compressed_allocated = 0;
77         return 0;
78 }
79
80 void FileAC3::get_parameters(BC_WindowBase *parent_window,
81                 Asset *asset,
82                 BC_WindowBase* &format_window,
83                 int audio_options,
84                 int video_options)
85 {
86         if(audio_options)
87         {
88
89                 AC3ConfigAudio *window = new AC3ConfigAudio(parent_window, asset);
90                 format_window = window;
91                 window->create_objects();
92                 window->run_window();
93                 delete window;
94         }
95 }
96
97 int FileAC3::check_sig()
98 {
99 // Libmpeg3 does this in FileMPEG.
100         return 0;
101 }
102
103 int64_t FileAC3::get_channel_layout(int channels)
104 {
105         switch( channels ) {
106         case 1: return AV_CH_LAYOUT_MONO;
107         case 2: return AV_CH_LAYOUT_STEREO;
108         case 3: return AV_CH_LAYOUT_SURROUND;
109         case 4: return AV_CH_LAYOUT_QUAD;
110         case 5: return AV_CH_LAYOUT_5POINT0;
111         case 6: return AV_CH_LAYOUT_5POINT1;
112         case 8: return AV_CH_LAYOUT_7POINT1;
113         }
114         return 0;
115 }
116
117 int FileAC3::open_file(int rd, int wr)
118 {
119         int result = 0;
120
121         if(rd)
122         {
123                 if( !mpg_file )
124                         mpg_file = new FileMPEG(file->asset, file);
125                 result = mpg_file->open_file(1, 0);
126                 if( result ) {
127                         eprintf(_("Error while opening \"%s\" for reading. \n%m\n"), asset->path);
128                 }
129         }
130
131         if( !result && wr )
132         {
133                 //avcodec_init();
134                 avcodec_register_all();
135                 codec = avcodec_find_encoder(AV_CODEC_ID_AC3);
136                 if(!codec)
137                 {
138                         eprintf(_("FileAC3::open_file codec not found.\n"));
139                         result = 1;
140                 }
141                 if( !result && !(fd = fopen(asset->path, "w")))
142                 {
143                         eprintf(_("Error while opening \"%s\" for writing. \n%m\n"), asset->path);
144                         result = 1;
145                 }
146                 if( !result ) {
147                         int channels = asset->channels;
148                         int sample_rate = asset->sample_rate;
149                         int64_t layout = get_channel_layout(channels);
150                         int bitrate = asset->ac3_bitrate * 1000;
151                         codec_context = avcodec_alloc_context3(codec);
152                         codec_context->bit_rate = bitrate;
153                         codec_context->sample_rate = sample_rate;
154                         codec_context->channels = channels;
155                         codec_context->channel_layout = layout;
156                         codec_context->sample_fmt = codec->sample_fmts[0];
157                         resample_context = swr_alloc_set_opts(NULL,
158                                         layout, codec_context->sample_fmt, sample_rate,
159                                         layout, AV_SAMPLE_FMT_S16, sample_rate,
160                                         0, NULL);
161                         swr_init(resample_context);
162                         if(avcodec_open2(codec_context, codec, 0))
163                         {
164                                 eprintf(_("FileAC3::open_file failed to open codec.\n"));
165                                 result = 1;
166                         }
167                 }
168         }
169
170         return result;
171 }
172
173 int FileAC3::close_file()
174 {
175         if( mpg_file )
176         {
177                 delete mpg_file;
178                 mpg_file = 0;
179         }
180         if(codec_context)
181         {
182                 avcodec_close(codec_context);
183                 avcodec_free_context(&codec_context);
184                 codec = 0;
185         }
186         if( resample_context )
187                 swr_free(&resample_context);
188         if(fd)
189         {
190                 fclose(fd);
191                 fd = 0;
192         }
193         if(temp_raw)
194         {
195                 delete [] temp_raw;
196                 temp_raw = 0;
197         }
198         if(temp_compressed)
199         {
200                 delete [] temp_compressed;
201                 temp_compressed = 0;
202         }
203         reset_parameters();
204         FileBase::close_file();
205         return 0;
206 }
207
208 int FileAC3::read_samples(double *buffer, int64_t len)
209 {
210         return !mpg_file ? 0 : mpg_file->read_samples(buffer, len);
211 }
212
213 int FileAC3::get_index(IndexFile *index_file, MainProgressBar *progress_bar)
214 {
215         return !mpg_file ? 1 : mpg_file->get_index(index_file, progress_bar);
216 }
217
218 // Channel conversion matrices because ffmpeg encodes a
219 // different channel order than liba52 decodes.
220 // Each row is an output channel.
221 // Each column is an input channel.
222 // static int channels5[] =
223 // {
224 //      { }
225 // };
226 //
227 // static int channels6[] =
228 // {
229 //      { }
230 // };
231
232
233 int FileAC3::write_samples(double **buffer, int64_t len)
234 {
235 // Convert buffer to encoder format
236         if(temp_raw_size + len > temp_raw_allocated)
237         {
238                 int new_allocated = temp_raw_size + len;
239                 int16_t *new_raw = new int16_t[new_allocated * asset->channels];
240                 if(temp_raw)
241                 {
242                         memcpy(new_raw,
243                                 temp_raw,
244                                 sizeof(int16_t) * temp_raw_size * asset->channels);
245                         delete [] temp_raw;
246                 }
247                 temp_raw = new_raw;
248                 temp_raw_allocated = new_allocated;
249         }
250
251 // Allocate compressed data buffer
252         if(temp_raw_allocated * asset->channels * 2 > compressed_allocated)
253         {
254                 compressed_allocated = temp_raw_allocated * asset->channels * 2;
255                 delete [] temp_compressed;
256                 temp_compressed = new unsigned char[compressed_allocated];
257         }
258
259 // Append buffer to temp raw
260         int16_t *out_ptr = temp_raw + temp_raw_size * asset->channels;
261         for(int i = 0; i < len; i++)
262         {
263                 for(int j = 0; j < asset->channels; j++)
264                 {
265                         int sample = (int)(buffer[j][i] * 32767);
266                         CLAMP(sample, -32768, 32767);
267                         *out_ptr++ = sample;
268                 }
269         }
270         temp_raw_size += len;
271
272         AVCodecContext *&avctx = codec_context;
273         int frame_size = avctx->frame_size;
274         int output_size = 0, cur_sample = 0, ret = 0;
275         for(cur_sample = 0; !ret &&
276                 cur_sample + frame_size <= temp_raw_size;
277                 cur_sample += frame_size)
278         {
279                 AVPacket avpkt;
280                 av_init_packet(&avpkt);
281                 avpkt.data = temp_compressed + output_size;
282                 avpkt.size = compressed_allocated - output_size;
283                 AVFrame *frame = av_frame_alloc();
284                 frame->nb_samples = frame_size;
285                 frame->format = avctx->sample_fmt;
286                 frame->channel_layout = avctx->channel_layout;
287                 frame->sample_rate = avctx->sample_rate;
288                 ret = av_frame_get_buffer(frame, 0);
289                 if( ret >= 0 ) {
290                         const uint8_t *samples = (uint8_t *)temp_raw +
291                                 cur_sample * sizeof(int16_t) * asset->channels;
292                         ret = swr_convert(resample_context,
293                                 (uint8_t **)frame->extended_data, frame_size,
294                                 &samples, frame_size);
295                 }
296                 if( ret >= 0 ) {
297                         frame->pts = avctx->sample_rate && avctx->time_base.num ?
298                                 file->get_audio_position() : AV_NOPTS_VALUE ;
299                         int got_packet = 0;
300                         ret = avcodec_encode_audio2(avctx, &avpkt, frame, &got_packet);
301                         if( ret < 0 ) {
302                                 char errmsg[BCSTRLEN];
303                                 av_strerror(ret, errmsg, sizeof(errmsg));
304                                 fprintf(stderr, "avcodec_encode_audio2 failed. \n%s\n", errmsg);
305                         }
306                 }
307                 av_packet_free_side_data(&avpkt);
308                 output_size += avpkt.size;
309                 if(frame->extended_data != frame->data)
310                         av_freep(&frame->extended_data);
311                 av_frame_free(&frame);
312         }
313
314 // Shift buffer back
315         memcpy(temp_raw,
316                 temp_raw + cur_sample * asset->channels,
317                 (temp_raw_size - cur_sample) * sizeof(int16_t) * asset->channels);
318         temp_raw_size -= cur_sample;
319
320         int bytes_written = fwrite(temp_compressed, 1, output_size, fd);
321         if(bytes_written < output_size)
322         {
323                 eprintf(_("Error while writing samples. \n%m\n"));
324                 return 1;
325         }
326         return 0;
327 }
328
329
330
331
332
333
334
335 AC3ConfigAudio::AC3ConfigAudio(BC_WindowBase *parent_window,
336         Asset *asset)
337  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
338         parent_window->get_abs_cursor_x(1),
339         parent_window->get_abs_cursor_y(1),
340         500,
341         BC_OKButton::calculate_h() + 100,
342         500,
343         BC_OKButton::calculate_h() + 100,
344         0,
345         0,
346         1)
347 {
348         this->parent_window = parent_window;
349         this->asset = asset;
350 }
351
352 void AC3ConfigAudio::create_objects()
353 {
354         int x = 10, y = 10;
355         int x1 = 150;
356         lock_window("AC3ConfigAudio::create_objects");
357         add_tool(new BC_Title(x, y, _("Bitrate (kbps):")));
358         AC3ConfigAudioBitrate *bitrate;
359         add_tool(bitrate =
360                 new AC3ConfigAudioBitrate(this,
361                         x1,
362                         y));
363         bitrate->create_objects();
364
365         add_subwindow(new BC_OKButton(this));
366         show_window(1);
367         unlock_window();
368 }
369
370 int AC3ConfigAudio::close_event()
371 {
372         set_done(0);
373         return 1;
374 }
375
376
377
378
379
380
381 AC3ConfigAudioBitrate::AC3ConfigAudioBitrate(AC3ConfigAudio *gui,
382         int x,
383         int y)
384  : BC_PopupMenu(x,
385         y,
386         150,
387         AC3ConfigAudioBitrate::bitrate_to_string(gui->string, gui->asset->ac3_bitrate))
388 {
389         this->gui = gui;
390 }
391
392 char* AC3ConfigAudioBitrate::bitrate_to_string(char *string, int bitrate)
393 {
394         sprintf(string, "%d", bitrate);
395         return string;
396 }
397
398 void AC3ConfigAudioBitrate::create_objects()
399 {
400         add_item(new BC_MenuItem("32"));
401         add_item(new BC_MenuItem("40"));
402         add_item(new BC_MenuItem("48"));
403         add_item(new BC_MenuItem("56"));
404         add_item(new BC_MenuItem("64"));
405         add_item(new BC_MenuItem("80"));
406         add_item(new BC_MenuItem("96"));
407         add_item(new BC_MenuItem("112"));
408         add_item(new BC_MenuItem("128"));
409         add_item(new BC_MenuItem("160"));
410         add_item(new BC_MenuItem("192"));
411         add_item(new BC_MenuItem("224"));
412         add_item(new BC_MenuItem("256"));
413         add_item(new BC_MenuItem("320"));
414         add_item(new BC_MenuItem("384"));
415         add_item(new BC_MenuItem("448"));
416         add_item(new BC_MenuItem("512"));
417         add_item(new BC_MenuItem("576"));
418         add_item(new BC_MenuItem("640"));
419 }
420
421 int AC3ConfigAudioBitrate::handle_event()
422 {
423         gui->asset->ac3_bitrate = atol(get_text());
424         return 1;
425 }
426
427
428