Reported by Fedora team for gcc-13 and Andrew created patch here
[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  *
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 #ifdef HAVE_LIBZMPEG
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         close_file();
63         delete mpg_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         return 0;
76 }
77
78 void FileAC3::get_parameters(BC_WindowBase *parent_window,
79                 Asset *asset, BC_WindowBase* &format_window,
80                 int audio_options, int video_options, EDL *edl)
81 {
82         if(audio_options)
83         {
84
85                 AC3ConfigAudio *window = new AC3ConfigAudio(parent_window, asset);
86                 format_window = window;
87                 window->create_objects();
88                 window->run_window();
89                 delete window;
90         }
91 }
92
93 int FileAC3::check_sig()
94 {
95 // Libmpeg3 does this in FileMPEG.
96         return 0;
97 }
98
99 int64_t FileAC3::get_channel_layout(int channels)
100 {
101         switch( channels ) {
102         case 1: return AV_CH_LAYOUT_MONO;
103         case 2: return AV_CH_LAYOUT_STEREO;
104         case 3: return AV_CH_LAYOUT_SURROUND;
105         case 4: return AV_CH_LAYOUT_QUAD;
106         case 5: return AV_CH_LAYOUT_5POINT0;
107         case 6: return AV_CH_LAYOUT_5POINT1;
108         case 8: return AV_CH_LAYOUT_7POINT1;
109         }
110         return 0;
111 }
112
113 int FileAC3::open_file(int rd, int wr)
114 {
115         int result = 0;
116
117         if(rd)
118         {
119                 if( !mpg_file )
120                         mpg_file = new FileMPEG(file->asset, file);
121                 result = mpg_file->open_file(1, 0);
122                 if( result ) {
123                         eprintf(_("Error while opening \"%s\" for reading. \n%m\n"), asset->path);
124                 }
125         }
126
127         if( !result && wr )
128         {
129                 codec = avcodec_find_encoder(AV_CODEC_ID_AC3);
130                 if(!codec)
131                 {
132                         eprintf(_("FileAC3::open_file codec not found.\n"));
133                         result = 1;
134                 }
135                 if( !result && !(fd = fopen(asset->path, "w")))
136                 {
137                         eprintf(_("Error while opening \"%s\" for writing. \n%m\n"), asset->path);
138                         result = 1;
139                 }
140                 if( !result ) {
141                         int channels = asset->channels;
142                         int sample_rate = asset->sample_rate;
143                         int64_t layout = get_channel_layout(channels);
144                         int bitrate = asset->ac3_bitrate * 1000;
145                         av_init_packet(&avpkt);
146                         codec_context = avcodec_alloc_context3(codec);
147                         codec_context->bit_rate = bitrate;
148                         codec_context->sample_rate = sample_rate;
149                         codec_context->channels = channels;
150                         codec_context->channel_layout = layout;
151                         codec_context->sample_fmt = codec->sample_fmts[0];
152                         resample_context = swr_alloc_set_opts(NULL,
153                                         layout, codec_context->sample_fmt, sample_rate,
154                                         layout, AV_SAMPLE_FMT_S16, sample_rate,
155                                         0, NULL);
156                         swr_init(resample_context);
157                         if(avcodec_open2(codec_context, codec, 0))
158                         {
159                                 eprintf(_("FileAC3::open_file failed to open codec.\n"));
160                                 result = 1;
161                         }
162                 }
163         }
164
165         return result;
166 }
167
168 int FileAC3::close_file()
169 {
170         if( mpg_file )
171         {
172                 delete mpg_file;
173                 mpg_file = 0;
174         }
175         if(codec_context)
176         {
177                 encode_flush();
178                 avcodec_close(codec_context);
179                 avcodec_free_context(&codec_context);
180                 codec = 0;
181         }
182         if( resample_context )
183                 swr_free(&resample_context);
184         if(fd)
185         {
186                 fclose(fd);
187                 fd = 0;
188         }
189         if(temp_raw)
190         {
191                 delete [] temp_raw;
192                 temp_raw = 0;
193         }
194         reset_parameters();
195         FileBase::close_file();
196         return 0;
197 }
198
199 int FileAC3::read_samples(double *buffer, int64_t len)
200 {
201         return !mpg_file ? 0 : mpg_file->read_samples(buffer, len);
202 }
203
204 int FileAC3::get_index(IndexFile *index_file, MainProgressBar *progress_bar)
205 {
206         return !mpg_file ? 1 : mpg_file->get_index(index_file, progress_bar);
207 }
208
209 // Channel conversion matrices because ffmpeg encodes a
210 // different channel order than liba52 decodes.
211 // Each row is an output channel.
212 // Each column is an input channel.
213 // static int channels5[] =
214 // {
215 //      { }
216 // };
217 //
218 // static int channels6[] =
219 // {
220 //      { }
221 // };
222
223 int FileAC3::write_packet()
224 {
225         AVCodecContext *&avctx = codec_context;
226         int ret = avcodec_receive_packet(avctx, &avpkt);
227         if( ret >= 0 ) {
228                 ret = 0;
229                 if( avpkt.data && avpkt.size > 0 ) {
230                         int sz = fwrite(avpkt.data, 1, avpkt.size, fd);
231                         if( sz == avpkt.size ) ret = 1;
232                 }
233                 if( !ret )
234                         eprintf(_("Error while writing samples. \n%m\n"));
235                 av_packet_unref(&avpkt);
236         }
237         else if( ret == AVERROR_EOF )
238                 ret = 0;
239         return ret;
240 }
241
242 int FileAC3::encode_frame(AVFrame *frame)
243 {
244         AVCodecContext *&avctx = codec_context;
245         int ret = 0, pkts = 0;
246         for( int retry=100; --retry>=0; ) {
247                 ret = avcodec_send_frame(avctx, frame);
248                 if( ret >= 0 ) return pkts;
249                 if( ret != AVERROR(EAGAIN) ) break;
250                 if( (ret=write_packet()) < 0 ) break;
251                 if( !ret ) return pkts;
252                 ++pkts;
253         }
254         if( ret < 0 ) {
255                 char errmsg[BCTEXTLEN];
256                 av_strerror(ret, errmsg, sizeof(errmsg));
257                 fprintf(stderr, "FileAC3::encode_frame: encode failed: %s\n", errmsg);
258         }
259         return ret;
260 }
261
262 int FileAC3::encode_flush()
263 {
264         AVCodecContext *&avctx = codec_context;
265         int ret = avcodec_send_frame(avctx, 0);
266         while( (ret=write_packet()) > 0 );
267         if( ret < 0 ) {
268                 char errmsg[BCTEXTLEN];
269                 av_strerror(ret, errmsg, sizeof(errmsg));
270                 fprintf(stderr, "FileAC3::encode_flush: encode failed: %s\n", errmsg);
271         }
272         return ret;
273 }
274
275 int FileAC3::write_samples(double **buffer, int64_t len)
276 {
277 // Convert buffer to encoder format
278         if(temp_raw_size + len > temp_raw_allocated)
279         {
280                 int new_allocated = temp_raw_size + len;
281                 int16_t *new_raw = new int16_t[new_allocated * asset->channels];
282                 if(temp_raw)
283                 {
284                         memcpy(new_raw,
285                                 temp_raw,
286                                 sizeof(int16_t) * temp_raw_size * asset->channels);
287                         delete [] temp_raw;
288                 }
289                 temp_raw = new_raw;
290                 temp_raw_allocated = new_allocated;
291         }
292
293 // Append buffer to temp raw
294         int16_t *out_ptr = temp_raw + temp_raw_size * asset->channels;
295         for(int i = 0; i < len; i++)
296         {
297                 for(int j = 0; j < asset->channels; j++)
298                 {
299                         int sample = (int)(buffer[j][i] * 32767);
300                         CLAMP(sample, -32768, 32767);
301                         *out_ptr++ = sample;
302                 }
303         }
304         temp_raw_size += len;
305
306         AVCodecContext *&avctx = codec_context;
307         int frame_size = avctx->frame_size;
308         int cur_sample = 0, ret = 0;
309         for(cur_sample = 0; ret >= 0 &&
310                 cur_sample + frame_size <= temp_raw_size;
311                 cur_sample += frame_size)
312         {
313                 AVFrame *frame = av_frame_alloc();
314                 frame->nb_samples = frame_size;
315                 frame->format = avctx->sample_fmt;
316                 frame->channel_layout = avctx->channel_layout;
317                 frame->sample_rate = avctx->sample_rate;
318                 ret = av_frame_get_buffer(frame, 0);
319                 if( ret >= 0 ) {
320                         const uint8_t *samples = (uint8_t *)temp_raw +
321                                 cur_sample * sizeof(int16_t) * asset->channels;
322                         ret = swr_convert(resample_context,
323                                 (uint8_t **)frame->extended_data, frame_size,
324                                 &samples, frame_size);
325                 }
326                 if( ret >= 0 ) {
327                         frame->pts = avctx->sample_rate && avctx->time_base.num ?
328                                 file->get_audio_position() : AV_NOPTS_VALUE ;
329                         ret = encode_frame(frame);
330                 }
331                 av_frame_free(&frame);
332         }
333
334 // Shift buffer back
335         memcpy(temp_raw,
336                 temp_raw + cur_sample * asset->channels,
337                 (temp_raw_size - cur_sample) * sizeof(int16_t) * asset->channels);
338         temp_raw_size -= cur_sample;
339
340         return 0;
341 }
342
343
344 AC3ConfigAudio::AC3ConfigAudio(BC_WindowBase *parent_window,
345         Asset *asset)
346  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
347         parent_window->get_abs_cursor_x(1),
348         parent_window->get_abs_cursor_y(1),
349         xS(500), BC_OKButton::calculate_h() + yS(100),
350         xS(500), BC_OKButton::calculate_h() + yS(100),
351         0, 0, 1)
352 {
353         this->parent_window = parent_window;
354         this->asset = asset;
355 // *** CONTEXT_HELP ***
356         context_help_set_keyword("Single File Rendering");
357 }
358
359 void AC3ConfigAudio::create_objects()
360 {
361         int x = xS(10), y = yS(10);
362         int x1 = xS(150);
363         lock_window("AC3ConfigAudio::create_objects");
364         add_tool(new BC_Title(x, y, _("Bitrate (kbps):")));
365         AC3ConfigAudioBitrate *bitrate;
366         add_tool(bitrate = new AC3ConfigAudioBitrate(this, x1, y));
367         bitrate->create_objects();
368
369         add_subwindow(new BC_OKButton(this));
370         show_window(1);
371         unlock_window();
372 }
373
374 int AC3ConfigAudio::close_event()
375 {
376         set_done(0);
377         return 1;
378 }
379
380
381 AC3ConfigAudioBitrate::AC3ConfigAudioBitrate(AC3ConfigAudio *gui, int x, int y)
382  : BC_PopupMenu(x, y, xS(150),
383         AC3ConfigAudioBitrate::bitrate_to_string(gui->string, gui->asset->ac3_bitrate))
384 {
385         this->gui = gui;
386 }
387
388 char* AC3ConfigAudioBitrate::bitrate_to_string(char *string, int bitrate)
389 {
390         sprintf(string, "%d", bitrate);
391         return string;
392 }
393
394 void AC3ConfigAudioBitrate::create_objects()
395 {
396         add_item(new BC_MenuItem("32"));
397         add_item(new BC_MenuItem("40"));
398         add_item(new BC_MenuItem("48"));
399         add_item(new BC_MenuItem("56"));
400         add_item(new BC_MenuItem("64"));
401         add_item(new BC_MenuItem("80"));
402         add_item(new BC_MenuItem("96"));
403         add_item(new BC_MenuItem("112"));
404         add_item(new BC_MenuItem("128"));
405         add_item(new BC_MenuItem("160"));
406         add_item(new BC_MenuItem("192"));
407         add_item(new BC_MenuItem("224"));
408         add_item(new BC_MenuItem("256"));
409         add_item(new BC_MenuItem("320"));
410         add_item(new BC_MenuItem("384"));
411         add_item(new BC_MenuItem("448"));
412         add_item(new BC_MenuItem("512"));
413         add_item(new BC_MenuItem("576"));
414         add_item(new BC_MenuItem("640"));
415 }
416
417 int AC3ConfigAudioBitrate::handle_event()
418 {
419         gui->asset->ac3_bitrate = atol(get_text());
420         return 1;
421 }
422
423 #endif
424 #endif //libzmpeg