7 // work around for __STDC_CONSTANT_MACROS
11 #include "bcwindowbase.h"
12 #include "bitspopup.h"
16 #include "fileffmpeg.h"
17 #include "filesystem.h"
19 #include "videodevice.inc"
21 FileFFMPEG::FileFFMPEG(Asset *asset, File *file)
22 : FileBase(asset, file)
25 if(asset->format == FILE_UNKNOWN)
26 asset->format = FILE_FFMPEG;
29 FileFFMPEG::~FileFFMPEG()
35 void FileFFMPEG::get_parameters(BC_WindowBase *parent_window,
36 Asset *asset, BC_WindowBase *&format_window,
37 int audio_options, int video_options)
40 FFMPEGConfigAudio *window = new FFMPEGConfigAudio(parent_window, asset);
41 format_window = window;
42 window->create_objects();
46 else if(video_options) {
47 FFMPEGConfigVideo *window = new FFMPEGConfigVideo(parent_window, asset);
48 format_window = window;
49 window->create_objects();
55 int FileFFMPEG::check_sig(Asset *asset)
57 char *ptr = strstr(asset->path, ".pcm");
59 ptr = strstr(asset->path, ".raw");
63 int ret = !ffmpeg.init_decoder(asset->path) &&
64 !ffmpeg.open_decoder() ? 1 : 0;
68 void FileFFMPEG::get_info(char *path, char *text)
72 cp += sprintf(cp, "file path: %s\n", path);
75 if( stat(path, &st) < 0 ) {
76 cp += sprintf(cp, " err: %s\n", strerror(errno));
80 cp += sprintf(cp, " %jd bytes\n", st.st_size);
82 if( !ret ) ret = ffmpeg.init_decoder(path);
83 if( !ret ) ret = ffmpeg.open_decoder();
85 cp += sprintf(cp, "info:\n");
86 ffmpeg.info(cp, BCTEXTLEN-(cp-text));
89 sprintf(cp, "== open failed\n");
92 int FileFFMPEG::get_video_info(int track, int &pid, double &framerate,
93 int &width, int &height, char *title)
96 pid = ff->ff_video_pid(track);
97 framerate = ff->ff_frame_rate(track);
98 width = ff->ff_video_width(track);
99 height = ff->ff_video_height(track);
100 if( title ) *title = 0;
104 int FileFFMPEG::get_audio_for_video(int vstream, int astream, int64_t &channel_mask)
107 return ff->ff_audio_for_video(vstream, astream, channel_mask);
110 int FileFFMPEG::select_video_stream(Asset *asset, int vstream)
112 if( !ff || !asset->video_data ) return 1;
113 asset->width = ff->ff_video_width(vstream);
114 asset->height = ff->ff_video_height(vstream);
115 asset->video_length = ff->ff_video_frames(vstream);
116 asset->frame_rate = ff->ff_frame_rate(vstream);
120 int FileFFMPEG::select_audio_stream(Asset *asset, int astream)
122 if( !ff || !asset->audio_data ) return 1;
123 asset->channels = ff->ff_audio_channels(astream);
124 asset->sample_rate = ff->ff_sample_rate(astream);
125 asset->audio_length = ff->ff_audio_samples(astream);
129 int FileFFMPEG::open_file(int rd, int wr)
133 ff = new FFMPEG(this);
136 result = ff->init_decoder(asset->path);
137 if( !result ) result = ff->open_decoder();
139 int audio_channels = ff->ff_total_audio_channels();
140 if( audio_channels > 0 ) {
141 asset->audio_data = 1;
142 asset->channels = audio_channels;
143 asset->sample_rate = ff->ff_sample_rate(0);
144 asset->audio_length = ff->ff_audio_samples(0);
146 int video_layers = ff->ff_total_video_layers();
147 if( video_layers > 0 ) {
148 asset->video_data = 1;
149 if( !asset->layers ) asset->layers = video_layers;
150 asset->actual_width = ff->ff_video_width(0);
151 asset->actual_height = ff->ff_video_height(0);
152 if( !asset->width ) asset->width = asset->actual_width;
153 if( !asset->height ) asset->height = asset->actual_height;
154 if( !asset->video_length ) asset->video_length = ff->ff_video_frames(0);
155 if( !asset->frame_rate ) asset->frame_rate = ff->ff_frame_rate(0);
160 result = ff->init_encoder(asset->path);
161 // must be in this order or dvdauthor will fail
162 if( !result && asset->video_data )
163 result = ff->open_encoder("video", asset->vcodec);
164 if( !result && asset->audio_data )
165 result = ff->open_encoder("audio", asset->acodec);
170 int FileFFMPEG::close_file()
178 int FileFFMPEG::set_video_position(int64_t pos)
180 if( !ff || pos < 0 || pos >= asset->video_length )
186 int FileFFMPEG::set_audio_position(int64_t pos)
188 if( !ff || pos < 0 || pos >= asset->audio_length )
194 int FileFFMPEG::write_samples(double **buffer, int64_t len)
196 if( !ff || len < 0 ) return -1;
198 int ret = ff->encode(stream, buffer, len);
202 int FileFFMPEG::write_frames(VFrame ***frames, int len)
205 int ret = 0, layer = 0;
206 for(int i = 0; i < 1; i++) {
207 for(int j = 0; j < len && !ret; j++) {
208 VFrame *frame = frames[i][j];
209 ret = ff->encode(layer, frame);
216 int FileFFMPEG::read_samples(double *buffer, int64_t len)
218 if( !ff || len < 0 ) return -1;
219 int ch = file->current_channel;
220 int64_t pos = file->current_sample;
221 ff->decode(ch, pos, buffer, len);
225 int FileFFMPEG::read_frame(VFrame *frame)
228 int layer = file->current_layer;
229 int64_t pos = file->current_frame;
230 ff->decode(layer, pos, frame);
235 int64_t FileFFMPEG::get_memory_usage()
240 int FileFFMPEG::colormodel_supported(int colormodel)
245 int FileFFMPEG::get_best_colormodel(Asset *asset, int driver)
248 case PLAYBACK_X11: return BC_RGB888;
249 case PLAYBACK_X11_GL: return BC_YUV888;
256 extern void get_exe_path(char *result); // from main.C
258 FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
259 : BC_Window(PROGRAM_NAME ": Audio Preset",
260 parent_window->get_abs_cursor_x(1),
261 parent_window->get_abs_cursor_y(1),
264 this->parent_window = parent_window;
269 FFMPEGConfigAudio::~FFMPEGConfigAudio()
271 lock_window("FFMPEGConfigAudio::~FFMPEGConfigAudio");
272 if(preset_popup) delete preset_popup;
273 presets.remove_all_objects();
277 void FFMPEGConfigAudio::create_objects()
280 lock_window("FFMPEGConfigAudio::create_objects");
283 char option_path[BCTEXTLEN];
284 FFMPEG::set_option_path(option_path, "/audio");
285 fs.update(option_path);
286 int total_files = fs.total_files();
287 for(int i = 0; i < total_files; i++) {
288 const char *name = fs.get_entry(i)->get_name();
289 presets.append(new BC_ListBoxItem(name));
292 add_tool(new BC_Title(x, y, _("Preset:")));
294 preset_popup = new FFMPEGConfigAudioPopup(this, x, y);
295 preset_popup->create_objects();
297 add_subwindow(new BC_OKButton(this));
302 int FFMPEGConfigAudio::close_event()
309 FFMPEGConfigAudioPopup::FFMPEGConfigAudioPopup(FFMPEGConfigAudio *popup, int x, int y)
310 : BC_PopupTextBox(popup, &popup->presets, popup->asset->acodec, x, y, 300, 300)
315 int FFMPEGConfigAudioPopup::handle_event()
317 strcpy(popup->asset->acodec, get_text());
322 FFMPEGConfigAudioToggle::FFMPEGConfigAudioToggle(FFMPEGConfigAudio *popup,
323 char *title_text, int x, int y, int *output)
324 : BC_CheckBox(x, y, *output, title_text)
327 this->output = output;
329 int FFMPEGConfigAudioToggle::handle_event()
331 *output = get_value();
338 FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
339 : BC_Window(PROGRAM_NAME ": Video Preset",
340 parent_window->get_abs_cursor_x(1),
341 parent_window->get_abs_cursor_y(1),
344 this->parent_window = parent_window;
349 FFMPEGConfigVideo::~FFMPEGConfigVideo()
351 lock_window("FFMPEGConfigVideo::~FFMPEGConfigVideo");
352 if(preset_popup) delete preset_popup;
353 presets.remove_all_objects();
357 void FFMPEGConfigVideo::create_objects()
360 lock_window("FFMPEGConfigVideo::create_objects");
362 add_subwindow(new BC_Title(x, y, _("Compression:")));
366 char option_path[BCTEXTLEN];
367 FFMPEG::set_option_path(option_path, "video");
368 fs.update(option_path);
369 int total_files = fs.total_files();
370 for(int i = 0; i < total_files; i++) {
371 const char *name = fs.get_entry(i)->get_name();
372 presets.append(new BC_ListBoxItem(name));
375 preset_popup = new FFMPEGConfigVideoPopup(this, x, y);
376 preset_popup->create_objects();
378 add_subwindow(new BC_OKButton(this));
383 int FFMPEGConfigVideo::close_event()
390 FFMPEGConfigVideoPopup::FFMPEGConfigVideoPopup(FFMPEGConfigVideo *popup, int x, int y)
391 : BC_PopupTextBox(popup, &popup->presets, popup->asset->vcodec, x, y, 300, 300)
396 int FFMPEGConfigVideoPopup::handle_event()
398 strcpy(popup->asset->vcodec, get_text());
403 FFMPEGConfigVideoToggle::FFMPEGConfigVideoToggle(FFMPEGConfigVideo *popup,
404 char *title_text, int x, int y, int *output)
405 : BC_CheckBox(x, y, *output, title_text)
408 this->output = output;
410 int FFMPEGConfigVideoToggle::handle_event()
412 *output = get_value();