X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.0%2Fcinelerra%2Ffileffmpeg.C;h=b5b459ef4faaca750407bdc743cbd755a0554a6e;hb=9d843688067273fd869c55a418962c64814b12ae;hp=bfe0a107b0ab0145285bcb55337b8e9d6aeb2042;hpb=3564c71f425f390745eb7c75d5121689d53e14c2;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.0/cinelerra/fileffmpeg.C b/cinelerra-5.0/cinelerra/fileffmpeg.C index bfe0a107..b5b459ef 100644 --- a/cinelerra-5.0/cinelerra/fileffmpeg.C +++ b/cinelerra-5.0/cinelerra/fileffmpeg.C @@ -9,13 +9,17 @@ #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) @@ -132,28 +136,28 @@ int FileFFMPEG::check_sig(Asset *asset) 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, @@ -187,7 +191,6 @@ int FileFFMPEG::select_video_stream(Asset *asset, int vstream) 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; @@ -221,6 +224,8 @@ int FileFFMPEG::open_file(int rd, int wr) 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 ) { @@ -285,8 +290,10 @@ int FileFFMPEG::read_samples(double *buffer, int64_t len) 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) @@ -294,8 +301,11 @@ 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; } @@ -318,23 +328,10 @@ int FileFFMPEG::get_best_colormodel(Asset *asset, int driver) return BC_YUV420P; } -static void load_options(const char *path, char *bfr, int len) -{ - *bfr = 0; - FILE *fp = fopen(path, "r"); - if( !fp ) return; - fgets(bfr, len, fp); // skip hdr - len = fread(bfr, 1, len-1, fp); - if( len < 0 ) len = 0; - bfr[len] = 0; - fclose(fp); -} - //====== -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) @@ -362,16 +359,15 @@ void FFMPEGConfigAudio::create_objects() 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)); } @@ -400,7 +396,7 @@ void FFMPEGConfigAudio::create_objects() y += 25; if( !asset->ff_audio_options[0] && asset->acodec[0] ) { FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec); - load_options(option_path, asset->ff_audio_options, + FFMPEG::load_options(option_path, asset->ff_audio_options, sizeof(asset->ff_audio_options)); } add_subwindow(audio_options = new FFAudioOptions(this, x, y, get_w()-x-20, 10, @@ -444,7 +440,7 @@ int FFMPEGConfigAudioPopup::handle_event() Asset *asset = popup->asset; char option_path[BCTEXTLEN]; FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec); - load_options(option_path, asset->ff_audio_options, + FFMPEG::load_options(option_path, asset->ff_audio_options, sizeof(asset->ff_audio_options)); popup->audio_options->update(asset->ff_audio_options); return 1; @@ -468,7 +464,7 @@ int FFMPEGConfigAudioToggle::handle_event() //====== 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) @@ -478,6 +474,7 @@ FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset) preset_popup = 0; bitrate = 0; + quality = 0; video_options = 0; } @@ -506,9 +503,8 @@ void FFMPEGConfigVideo::create_objects() 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)); } @@ -545,7 +541,7 @@ void FFMPEGConfigVideo::create_objects() y += 25; if( !asset->ff_video_options[0] && asset->vcodec[0] ) { FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec); - load_options(option_path, asset->ff_video_options, + FFMPEG::load_options(option_path, asset->ff_video_options, sizeof(asset->ff_video_options)); } add_subwindow(video_options = new FFVideoOptions(this, x, y, get_w()-x-20, 10, @@ -593,7 +589,7 @@ int FFMPEGConfigVideoPopup::handle_event() Asset *asset = popup->asset; char option_path[BCTEXTLEN]; FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec); - load_options(option_path, asset->ff_video_options, + FFMPEG::load_options(option_path, asset->ff_video_options, sizeof(asset->ff_video_options)); popup->video_options->update(asset->ff_video_options); return 1; @@ -613,4 +609,87 @@ int FFMPEGConfigVideoToggle::handle_event() 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; aidxffaudio.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); +}