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