Credit Andrew - updating patches for FFmpeg 7.0 as needed since 6.1, now at 7.0,...
[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                         AVChannelLayout ch_layout;
146                         av_channel_layout_default(&ch_layout, channels);
147                         if(!ch_layout.nb_channels) {
148                         printf ("av_ch_layut_default failed! \n"); }
149                         int bitrate = asset->ac3_bitrate * 1000;
150                         av_init_packet(&avpkt);
151                         codec_context = avcodec_alloc_context3(codec);
152                         codec_context->bit_rate = bitrate;
153                         codec_context->sample_rate = sample_rate;
154                         codec_context->ch_layout.nb_channels = channels;
155                         codec_context->ch_layout.u.mask = layout;
156                         av_channel_layout_copy(&codec_context->ch_layout, &ch_layout);
157                         codec_context->sample_fmt = codec->sample_fmts[0];
158                         SwrContext *tmp_resample_context = NULL;
159                         int ret = swr_alloc_set_opts2(&tmp_resample_context,
160                                         &ch_layout, codec_context->sample_fmt, sample_rate,
161                                         &ch_layout, AV_SAMPLE_FMT_S16, sample_rate,
162                                         0, NULL);
163                         if(ret <0) printf("swr_alloc eror: %i \n", ret );
164                         if(tmp_resample_context){
165                         resample_context = tmp_resample_context;
166                         if(swr_init(resample_context))
167                         {
168                                 eprintf(_("FileAC3::open_file failed to init swr.\n"));
169                                 result = 1;
170                         }
171                         }
172                         if(avcodec_open2(codec_context, codec, 0))
173                         {
174                                 eprintf(_("FileAC3::open_file failed to open codec.\n"));
175                                 result = 1;
176                         }
177                         av_channel_layout_uninit(&ch_layout);
178                 }
179         }
180
181         return result;
182 }
183
184 int FileAC3::close_file()
185 {
186         if( mpg_file )
187         {
188                 delete mpg_file;
189                 mpg_file = 0;
190         }
191         if(codec_context)
192         {
193                 encode_flush();
194                 avcodec_close(codec_context);
195                 avcodec_free_context(&codec_context);
196                 codec = 0;
197         }
198         if( resample_context )
199                 swr_free(&resample_context);
200         if(fd)
201         {
202                 fclose(fd);
203                 fd = 0;
204         }
205         if(temp_raw)
206         {
207                 delete [] temp_raw;
208                 temp_raw = 0;
209         }
210         reset_parameters();
211         FileBase::close_file();
212         return 0;
213 }
214
215 int FileAC3::read_samples(double *buffer, int64_t len)
216 {
217         return !mpg_file ? 0 : mpg_file->read_samples(buffer, len);
218 }
219
220 int FileAC3::get_index(IndexFile *index_file, MainProgressBar *progress_bar)
221 {
222         return !mpg_file ? 1 : mpg_file->get_index(index_file, progress_bar);
223 }
224
225 // Channel conversion matrices because ffmpeg encodes a
226 // different channel order than liba52 decodes.
227 // Each row is an output channel.
228 // Each column is an input channel.
229 // static int channels5[] =
230 // {
231 //      { }
232 // };
233 //
234 // static int channels6[] =
235 // {
236 //      { }
237 // };
238
239 int FileAC3::write_packet()
240 {
241         AVCodecContext *&avctx = codec_context;
242         int ret = avcodec_receive_packet(avctx, &avpkt);
243         if( ret >= 0 ) {
244                 ret = 0;
245                 if( avpkt.data && avpkt.size > 0 ) {
246                         int sz = fwrite(avpkt.data, 1, avpkt.size, fd);
247                         if( sz == avpkt.size ) ret = 1;
248                 }
249                 if( !ret )
250                         eprintf(_("Error while writing samples. \n%m\n"));
251                 av_packet_unref(&avpkt);
252         }
253         else if( ret == AVERROR_EOF )
254                 ret = 0;
255         return ret;
256 }
257
258 int FileAC3::encode_frame(AVFrame *frame)
259 {
260         AVCodecContext *&avctx = codec_context;
261         int ret = 0, pkts = 0;
262         for( int retry=100; --retry>=0; ) {
263                 ret = avcodec_send_frame(avctx, frame);
264                 if( ret >= 0 ) return pkts;
265                 if( ret != AVERROR(EAGAIN) ) break;
266                 if( (ret=write_packet()) < 0 ) break;
267                 if( !ret ) return pkts;
268                 ++pkts;
269         }
270         if( ret < 0 ) {
271                 char errmsg[BCTEXTLEN];
272                 av_strerror(ret, errmsg, sizeof(errmsg));
273                 fprintf(stderr, "FileAC3::encode_frame: encode failed: %s\n", errmsg);
274         }
275         return ret;
276 }
277
278 int FileAC3::encode_flush()
279 {
280         AVCodecContext *&avctx = codec_context;
281         int ret = avcodec_send_frame(avctx, 0);
282         while( (ret=write_packet()) > 0 );
283         if( ret < 0 ) {
284                 char errmsg[BCTEXTLEN];
285                 av_strerror(ret, errmsg, sizeof(errmsg));
286                 fprintf(stderr, "FileAC3::encode_flush: encode failed: %s\n", errmsg);
287         }
288         return ret;
289 }
290
291 int FileAC3::write_samples(double **buffer, int64_t len)
292 {
293 // Convert buffer to encoder format
294         if(temp_raw_size + len > temp_raw_allocated)
295         {
296                 int new_allocated = temp_raw_size + len;
297                 int16_t *new_raw = new int16_t[new_allocated * asset->channels];
298                 if(temp_raw)
299                 {
300                         memcpy(new_raw,
301                                 temp_raw,
302                                 sizeof(int16_t) * temp_raw_size * asset->channels);
303                         delete [] temp_raw;
304                 }
305                 temp_raw = new_raw;
306                 temp_raw_allocated = new_allocated;
307         }
308
309 // Append buffer to temp raw
310         int16_t *out_ptr = temp_raw + temp_raw_size * asset->channels;
311         for(int i = 0; i < len; i++)
312         {
313                 for(int j = 0; j < asset->channels; j++)
314                 {
315                         int sample = (int)(buffer[j][i] * 32767);
316                         CLAMP(sample, -32768, 32767);
317                         *out_ptr++ = sample;
318                 }
319         }
320         temp_raw_size += len;
321
322         AVCodecContext *&avctx = codec_context;
323         int frame_size = avctx->frame_size;
324         int cur_sample = 0, ret = 0;
325         for(cur_sample = 0; ret >= 0 &&
326                 cur_sample + frame_size <= temp_raw_size;
327                 cur_sample += frame_size)
328         {
329                 AVFrame *frame = av_frame_alloc();
330                 frame->nb_samples = frame_size;
331                 frame->format = avctx->sample_fmt;
332                 av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout);
333                 frame->sample_rate = avctx->sample_rate;
334
335                 ret = av_frame_get_buffer(frame, 0);
336                 if( ret >= 0 ) {
337                         const uint8_t *samples = (uint8_t *)temp_raw +
338                                 cur_sample * sizeof(int16_t) * asset->channels;
339                         ret = swr_convert(resample_context,
340                                 (uint8_t **)frame->extended_data, frame_size,
341                                 &samples, frame_size);
342                 } else { printf("fileAC3: av_frame_get_buffer failed!\n"); }
343                 if( ret >= 0 ) {
344                         frame->pts = avctx->sample_rate && avctx->time_base.num ?
345                                 file->get_audio_position() : AV_NOPTS_VALUE ;
346                         ret = encode_frame(frame);
347                 }
348                 av_frame_free(&frame);
349         }
350
351 // Shift buffer back
352         memcpy(temp_raw,
353                 temp_raw + cur_sample * asset->channels,
354                 (temp_raw_size - cur_sample) * sizeof(int16_t) * asset->channels);
355         temp_raw_size -= cur_sample;
356
357         return 0;
358 }
359
360
361 AC3ConfigAudio::AC3ConfigAudio(BC_WindowBase *parent_window,
362         Asset *asset)
363  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
364         parent_window->get_abs_cursor_x(1),
365         parent_window->get_abs_cursor_y(1),
366         xS(500), BC_OKButton::calculate_h() + yS(100),
367         xS(500), BC_OKButton::calculate_h() + yS(100),
368         0, 0, 1)
369 {
370         this->parent_window = parent_window;
371         this->asset = asset;
372 // *** CONTEXT_HELP ***
373         context_help_set_keyword("Single File Rendering");
374 }
375
376 void AC3ConfigAudio::create_objects()
377 {
378         int x = xS(10), y = yS(10);
379         int x1 = xS(150);
380         lock_window("AC3ConfigAudio::create_objects");
381         add_tool(new BC_Title(x, y, _("Bitrate (kbps):")));
382         AC3ConfigAudioBitrate *bitrate;
383         add_tool(bitrate = new AC3ConfigAudioBitrate(this, x1, y));
384         bitrate->create_objects();
385
386         add_subwindow(new BC_OKButton(this));
387         show_window(1);
388         unlock_window();
389 }
390
391 int AC3ConfigAudio::close_event()
392 {
393         set_done(0);
394         return 1;
395 }
396
397
398 AC3ConfigAudioBitrate::AC3ConfigAudioBitrate(AC3ConfigAudio *gui, int x, int y)
399  : BC_PopupMenu(x, y, xS(150),
400         AC3ConfigAudioBitrate::bitrate_to_string(gui->string, gui->asset->ac3_bitrate))
401 {
402         this->gui = gui;
403 }
404
405 char* AC3ConfigAudioBitrate::bitrate_to_string(char *string, int bitrate)
406 {
407         sprintf(string, "%d", bitrate);
408         return string;
409 }
410
411 void AC3ConfigAudioBitrate::create_objects()
412 {
413         add_item(new BC_MenuItem("32"));
414         add_item(new BC_MenuItem("40"));
415         add_item(new BC_MenuItem("48"));
416         add_item(new BC_MenuItem("56"));
417         add_item(new BC_MenuItem("64"));
418         add_item(new BC_MenuItem("80"));
419         add_item(new BC_MenuItem("96"));
420         add_item(new BC_MenuItem("112"));
421         add_item(new BC_MenuItem("128"));
422         add_item(new BC_MenuItem("160"));
423         add_item(new BC_MenuItem("192"));
424         add_item(new BC_MenuItem("224"));
425         add_item(new BC_MenuItem("256"));
426         add_item(new BC_MenuItem("320"));
427         add_item(new BC_MenuItem("384"));
428         add_item(new BC_MenuItem("448"));
429         add_item(new BC_MenuItem("512"));
430         add_item(new BC_MenuItem("576"));
431         add_item(new BC_MenuItem("640"));
432 }
433
434 int AC3ConfigAudioBitrate::handle_event()
435 {
436         gui->asset->ac3_bitrate = atol(get_text());
437         return 1;
438 }
439
440 #endif
441 #endif //libzmpeg