r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / cinelerra / fileac3.C
blob2ba9235d2276333b7af59282cd172f7d97e33d2e
1 #include "asset.h"
2 #include "clip.h"
3 #include "fileac3.h"
4 #include "language.h"
5 #include "mwindow.inc"
6 #include "mainerror.h"
10 #include <string.h>
12 FileAC3::FileAC3(Asset *asset, File *file)
13  : FileBase(asset, file)
15         reset_parameters();
18 FileAC3::~FileAC3()
20         close_file();
23 int FileAC3::reset_parameters_derived()
25         codec = 0;
26         codec_context = 0;
27         fd = 0;
28         temp_raw = 0;
29         temp_raw_size = 0;
30         temp_raw_allocated = 0;
31         temp_compressed = 0;
32         compressed_allocated = 0;
35 void FileAC3::get_parameters(BC_WindowBase *parent_window, 
36                 Asset *asset, 
37                 BC_WindowBase* &format_window,
38                 int audio_options,
39                 int video_options)
41         if(audio_options)
42         {
44                 AC3ConfigAudio *window = new AC3ConfigAudio(parent_window, asset);
45                 format_window = window;
46                 window->create_objects();
47                 window->run_window();
48                 delete window;
49         }
52 int FileAC3::check_sig()
54 // Libmpeg3 does this in FileMPEG.
55         return 0;
58 int FileAC3::open_file(int rd, int wr)
60         this->wr = wr;
61         this->rd = rd;
64         if(wr)
65         {
66                 avcodec_init();
67                 avcodec_register_all();
68                 codec = avcodec_find_encoder(CODEC_ID_AC3);
69                 if(!codec)
70                 {
71                         eprintf("codec not found.\n");
72                         return 1;
73                 }
74                 codec_context = avcodec_alloc_context();
75                 codec_context->bit_rate = asset->ac3_bitrate * 1000;
76                 codec_context->sample_rate = asset->sample_rate;
77                 codec_context->channels = asset->channels;
78                 if(avcodec_open(codec_context, codec))
79                 {
80                         eprintf("failed to open codec.\n");
81                         return 1;
82                 }
84                 if(!(fd = fopen(asset->path, "w")))
85                 {
86                         eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
87                         return 1;
88                 }
89         }
90         else
91         {
92                 if(!(fd = fopen(asset->path, "r")))
93                 {
94                         eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path);
95                         return 1;
96                 }
97         }
102         return 0;
105 int FileAC3::close_file()
107         if(codec_context)
108         {
109                 avcodec_close(codec_context);
110                 free(codec_context);
111                 codec_context = 0;
112                 codec = 0;
113         }
114         if(fd)
115         {
116                 fclose(fd);
117                 fd = 0;
118         }
119         if(temp_raw)
120         {
121                 delete [] temp_raw;
122                 temp_raw = 0;
123         }
124         if(temp_compressed)
125         {
126                 delete [] temp_compressed;
127                 temp_compressed = 0;
128         }
129         reset_parameters();
130         FileBase::close_file();
133 // Channel conversion matrices because ffmpeg encodes a
134 // different channel order than liba52 decodes.
135 // Each row is an output channel.
136 // Each column is an input channel.
137 // static int channels5[] = 
138 // {
139 //      { }
140 // };
141 // 
142 // static int channels6[] = 
143 // {
144 //      { }
145 // };
148 int FileAC3::write_samples(double **buffer, int64_t len)
150 // Convert buffer to encoder format
151         if(temp_raw_size + len > temp_raw_allocated)
152         {
153                 int new_allocated = temp_raw_size + len;
154                 int16_t *new_raw = new int16_t[new_allocated * asset->channels];
155                 if(temp_raw)
156                 {
157                         memcpy(new_raw, 
158                                 temp_raw, 
159                                 sizeof(int16_t) * temp_raw_size * asset->channels);
160                         delete [] temp_raw;
161                 }
162                 temp_raw = new_raw;
163                 temp_raw_allocated = new_allocated;
164         }
166 // Allocate compressed data buffer
167         if(temp_raw_allocated * asset->channels * 2 > compressed_allocated)
168         {
169                 compressed_allocated = temp_raw_allocated * asset->channels * 2;
170                 delete [] temp_compressed;
171                 temp_compressed = new unsigned char[compressed_allocated];
172         }
174 // Append buffer to temp raw
175         int16_t *out_ptr = temp_raw + temp_raw_size * asset->channels;
176         for(int i = 0; i < len; i++)
177         {
178                 for(int j = 0; j < asset->channels; j++)
179                 {
180                         int sample = (int)(buffer[j][i] * 32767);
181                         CLAMP(sample, -32768, 32767);
182                         *out_ptr++ = sample;
183                 }
184         }
185         temp_raw_size += len;
187         int frame_size = codec_context->frame_size;
188         int output_size = 0;
189         int current_sample = 0;
190         for(current_sample = 0; 
191                 current_sample + frame_size <= temp_raw_size; 
192                 current_sample += frame_size)
193         {
194                 int compressed_size = avcodec_encode_audio(
195                         codec_context, 
196                         temp_compressed + output_size, 
197                         compressed_allocated - output_size, 
198             temp_raw + current_sample * asset->channels);
199                 output_size += compressed_size;
200         }
202 // Shift buffer back
203         memcpy(temp_raw,
204                 temp_raw + current_sample * asset->channels,
205                 (temp_raw_size - current_sample) * sizeof(int16_t) * asset->channels);
206         temp_raw_size -= current_sample;
208         int bytes_written = fwrite(temp_compressed, 1, output_size, fd);
209         if(bytes_written < output_size)
210         {
211                 eprintf("Error while writing samples. \n%m\n");
212                 return 1;
213         }
214         return 0;
223 AC3ConfigAudio::AC3ConfigAudio(BC_WindowBase *parent_window,
224         Asset *asset)
225  : BC_Window(PROGRAM_NAME ": Audio Compression",
226         parent_window->get_abs_cursor_x(1),
227         parent_window->get_abs_cursor_y(1),
228         500,
229         BC_OKButton::calculate_h() + 100,
230         500,
231         BC_OKButton::calculate_h() + 100,
232         0,
233         0,
234         1)
236         this->parent_window = parent_window;
237         this->asset = asset;
240 void AC3ConfigAudio::create_objects()
242         int x = 10, y = 10;
243         int x1 = 150;
244         add_tool(new BC_Title(x, y, "Bitrate (kbps):"));
245         AC3ConfigAudioBitrate *bitrate;
246         add_tool(bitrate = 
247                 new AC3ConfigAudioBitrate(this,
248                         x1, 
249                         y));
250         bitrate->create_objects();
252         add_subwindow(new BC_OKButton(this));
253         show_window();
254         flush();
257 int AC3ConfigAudio::close_event()
259         set_done(0);
260         return 1;
268 AC3ConfigAudioBitrate::AC3ConfigAudioBitrate(AC3ConfigAudio *gui, 
269         int x, 
270         int y)
271  : BC_PopupMenu(x,
272         y,
273         150,
274         AC3ConfigAudioBitrate::bitrate_to_string(gui->string, gui->asset->ac3_bitrate))
276         this->gui = gui;
279 char* AC3ConfigAudioBitrate::bitrate_to_string(char *string, int bitrate)
281         sprintf(string, "%d", bitrate);
282         return string;
285 void AC3ConfigAudioBitrate::create_objects()
287         add_item(new BC_MenuItem("32"));
288         add_item(new BC_MenuItem("40"));
289         add_item(new BC_MenuItem("48"));
290         add_item(new BC_MenuItem("56"));
291         add_item(new BC_MenuItem("64"));
292         add_item(new BC_MenuItem("80"));
293         add_item(new BC_MenuItem("96"));
294         add_item(new BC_MenuItem("112"));
295         add_item(new BC_MenuItem("128"));
296         add_item(new BC_MenuItem("160"));
297         add_item(new BC_MenuItem("192"));
298         add_item(new BC_MenuItem("224"));
299         add_item(new BC_MenuItem("256"));
300         add_item(new BC_MenuItem("320"));
301         add_item(new BC_MenuItem("384"));
302         add_item(new BC_MenuItem("448"));
303         add_item(new BC_MenuItem("512"));
304         add_item(new BC_MenuItem("576"));
305         add_item(new BC_MenuItem("640"));
308 int AC3ConfigAudioBitrate::handle_event()
310         gui->asset->ac3_bitrate = atol(get_text());
311         return 1;