#include "asset.h"
#include "bcwindowbase.h"
+#include "bcprogressbox.h"
#include "bitspopup.h"
#include "ffmpeg.h"
#include "filebase.h"
#include "file.h"
#include "fileffmpeg.h"
#include "filesystem.h"
+#include "format.inc"
+#include "indexfile.h"
#include "mutex.h"
+#include "preferences.h"
#include "videodevice.inc"
FileFFMPEG::FileFFMPEG(Asset *asset, File *file)
return ret;
}
-void FileFFMPEG::get_info(char *path, char *text)
+void FileFFMPEG::get_info(char *path, char *text, int len)
{
char *cp = text;
FFMPEG ffmpeg(0);
- cp += sprintf(cp, "file path: %s\n", path);
+ cp += sprintf(cp, _("file path: %s\n"), path);
struct stat st;
int ret = 0;
if( stat(path, &st) < 0 ) {
- cp += sprintf(cp, " err: %s\n", strerror(errno));
+ cp += sprintf(cp, _(" err: %s\n"), strerror(errno));
ret = 1;
}
else {
- cp += sprintf(cp, " %jd bytes\n", st.st_size);
+ cp += sprintf(cp, _(" %jd bytes\n"), st.st_size);
}
if( !ret ) ret = ffmpeg.init_decoder(path);
if( !ret ) ret = ffmpeg.open_decoder();
if( !ret ) {
- cp += sprintf(cp, "info:\n");
- ffmpeg.info(cp, BCTEXTLEN-(cp-text));
+ cp += sprintf(cp, _("info:\n"));
+ ffmpeg.info(cp, len-(cp-text));
}
else
- sprintf(cp, "== open failed\n");
+ sprintf(cp, _("== open failed\n"));
}
int FileFFMPEG::get_video_info(int track, int &pid, double &framerate,
int FileFFMPEG::select_audio_stream(Asset *asset, int astream)
{
if( !ff || !asset->audio_data ) return 1;
- asset->channels = ff->ff_audio_channels(astream);
asset->sample_rate = ff->ff_sample_rate(astream);
asset->audio_length = ff->ff_audio_samples(astream);
return 0;
if( !asset->video_length ) asset->video_length = ff->ff_video_frames(0);
if( !asset->frame_rate ) asset->frame_rate = ff->ff_frame_rate(0);
}
+ IndexState *index_state = asset->index_state;
+ index_state->read_markers(file->preferences->index_directory, asset->path);
}
}
else if( wr ) {
if( !ff || len < 0 ) return -1;
int ch = file->current_channel;
int64_t pos = file->current_sample;
- ff->decode(ch, pos, buffer, len);
- return 0;
+ int ret = ff->decode(ch, pos, buffer, len);
+ if( ret > 0 ) return 0;
+ memset(buffer,0,len*sizeof(*buffer));
+ return -1;
}
int FileFFMPEG::read_frame(VFrame *frame)
if( !ff ) return -1;
int layer = file->current_layer;
int64_t pos = file->current_frame;
- ff->decode(layer, pos, frame);
- return 0;
+ int ret = ff->decode(layer, pos, frame);
+ frame->set_status(ret);
+ if( ret > 0 ) return 0;
+ frame->clear_frame();
+ return -1;
}
}
//======
-extern void get_exe_path(char *result); // from main.C
FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
- : BC_Window(PROGRAM_NAME ": Audio Preset",
+ : BC_Window(_(PROGRAM_NAME ": Audio Preset"),
parent_window->get_abs_cursor_x(1),
parent_window->get_abs_cursor_y(1),
420, 420)
FileSystem fs;
char option_path[BCTEXTLEN];
- FFMPEG::set_option_path(option_path, "/audio");
+ FFMPEG::set_option_path(option_path, "audio");
fs.update(option_path);
int total_files = fs.total_files();
for(int i = 0; i < total_files; i++) {
const char *name = fs.get_entry(i)->get_name();
if( asset->fformat[0] != 0 ) {
const char *ext = strrchr(name,'.');
- if( !ext ) ext = name;
- else if( !strcmp("opts", ++ext) ) continue;
- if( strcmp(asset->fformat, ext) ) continue;
+ if( !ext ) continue;
+ if( strcmp(asset->fformat, ++ext) ) continue;
}
presets.append(new BC_ListBoxItem(name));
}
//======
FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
- : BC_Window(PROGRAM_NAME ": Video Preset",
+ : BC_Window(_(PROGRAM_NAME ": Video Preset"),
parent_window->get_abs_cursor_x(1),
parent_window->get_abs_cursor_y(1),
420, 420)
preset_popup = 0;
bitrate = 0;
+ quality = 0;
video_options = 0;
}
const char *name = fs.get_entry(i)->get_name();
if( asset->fformat[0] != 0 ) {
const char *ext = strrchr(name,'.');
- if( !ext ) ext = name;
- else if( !strcmp("opts", ++ext) ) continue;
- if( strcmp(asset->fformat, ext) ) continue;
+ if( !ext ) continue;
+ if( strcmp(asset->fformat, ++ext) ) continue;
}
presets.append(new BC_ListBoxItem(name));
}
return 1;
}
+FFMPEGScanProgress::FFMPEGScanProgress(const char *title, int64_t length, int64_t *position, int *canceled)
+ : Thread(1, 0, 0)
+{
+ strcpy(this->progress_title, title);
+ this->length = length;
+ this->position = position;
+ this->canceled = canceled;
+ done = 0;
+ progress = 0;
+ start();
+}
+
+FFMPEGScanProgress::~FFMPEGScanProgress()
+{
+ done = 1;
+ cancel();
+ join();
+}
+
+void FFMPEGScanProgress::run()
+{
+ BC_ProgressBox *progress = new BC_ProgressBox(-1, -1, progress_title, length);
+ progress->start();
+
+ struct timeval start_time, now, then;
+ gettimeofday(&start_time, 0);
+ then = start_time;
+
+ while( !done ) {
+ if( progress->update(*position, 1) ) {
+ *canceled = done = 1;
+ break;
+ }
+ gettimeofday(&now, 0);
+ if(now.tv_sec - then.tv_sec >= 1) {
+ int64_t elapsed = now.tv_sec - start_time.tv_sec;
+ int64_t byte_rate = *position / elapsed;
+ int64_t eta = !byte_rate ? 0 : (length - *position) / byte_rate;
+ char string[BCTEXTLEN];
+ sprintf(string, "%s\nETA: " _LD "m" _LD "s",
+ progress_title, eta / 60, eta % 60);
+ progress->update_title(string, 1);
+ then = now;
+ }
+ usleep(500000);
+ }
+
+ progress->stop_progress();
+ delete progress;
+}
+
+int FileFFMPEG::get_index(char *index_path)
+{
+ if( !ff ) return -1;
+ if( !file->preferences->ffmpeg_marker_indecies ) return 1;
+
+ IndexState *index_state = asset->index_state;
+ if( index_state->index_status != INDEX_NOTTESTED ) return 0;
+ index_state->index_status = INDEX_BUILDING;
+
+ for( int aidx=0; aidx<ff->ffaudio.size(); ++aidx ) {
+ FFAudioStream *aud = ff->ffaudio[aidx];
+ index_state->add_audio_stream(aud->channels, aud->length);
+ }
+
+ char progress_title[BCTEXTLEN];
+ sprintf(progress_title, _("Creating %s\n"), index_path);
+ FileSystem fs;
+ int64_t file_bytes = fs.get_size(ff->fmt_ctx->filename);
+ int64_t scan_position = 0;
+ int canceled = 0;
+ FFMPEGScanProgress scan_progress(progress_title, file_bytes, &scan_position, &canceled);
+
+ index_state->index_bytes = file_bytes;
+ index_state->init_scan(file->preferences->index_size);
+ if( ff->scan(index_state, &scan_position, &canceled) || canceled ) {
+ index_state->reset_index();
+ index_state->reset_markers();
+ return 1;
+ }
+ index_state->marker_status = MARKERS_READY;
+ return index_state->create_index(index_path, asset);
+}