From 3564c71f425f390745eb7c75d5121689d53e14c2 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Sat, 27 Jun 2015 12:02:09 -0600 Subject: [PATCH] improve ffmpeg format selection popup menu, more ffmpeg audio fixes --- cinelerra-5.0/cinelerra/asset.C | 70 ++-- cinelerra-5.0/cinelerra/asset.h | 23 +- cinelerra-5.0/cinelerra/batchrender.C | 4 +- cinelerra-5.0/cinelerra/ffmpeg.C | 369 +++++++++--------- cinelerra-5.0/cinelerra/ffmpeg.h | 72 ++-- cinelerra-5.0/cinelerra/file.C | 7 +- cinelerra-5.0/cinelerra/fileffmpeg.C | 200 ++++++++++ cinelerra-5.0/cinelerra/fileffmpeg.h | 96 +++++ cinelerra-5.0/cinelerra/filefork.C | 2 +- cinelerra-5.0/cinelerra/filemov.C | 12 +- cinelerra-5.0/cinelerra/formatpopup.C | 48 ++- cinelerra-5.0/cinelerra/formatpopup.h | 13 + cinelerra-5.0/cinelerra/formattools.C | 52 ++- cinelerra-5.0/cinelerra/formattools.h | 32 ++ cinelerra-5.0/cinelerra/labels.C | 1 - cinelerra-5.0/cinelerra/preferencesthread.h | 2 +- cinelerra-5.0/cinelerra/recordprefs.C | 7 +- cinelerra-5.0/cinelerra/recordprefs.h | 2 +- cinelerra-5.0/cinelerra/render.C | 8 +- cinelerra-5.0/cinelerra/renderfarm.C | 6 +- cinelerra-5.0/cinelerra/undostack.C | 1 - cinelerra-5.0/ffmpeg/audio/dvd | 1 - cinelerra-5.0/ffmpeg/audio/{h265 => h265.mp4} | 1 - .../ffmpeg/audio/{qt_ima4 => ima4.qt} | 0 cinelerra-5.0/ffmpeg/audio/{qt_mp3 => mp3.qt} | 0 cinelerra-5.0/ffmpeg/audio/{qt_mp4 => mp4.qt} | 0 .../ffmpeg/audio/{qt_mulaw => mulaw.qt} | 0 .../ffmpeg/audio/{qt_s16le => s16le.qt} | 0 .../ffmpeg/audio/{qt_s32le => s32le.qt} | 0 cinelerra-5.0/ffmpeg/audio/{qt_s8 => s8.qt} | 0 .../ffmpeg/audio/{qt_vorbis => vorbis.qt} | 0 .../ffmpeg/audio/{qt_wmav1 => wmav1.qt} | 0 .../ffmpeg/audio/{qt_wmav2 => wmav2.qt} | 0 .../ffmpeg/video/{qt_div3 => div3.qt} | 0 .../ffmpeg/video/{qt_div3v2 => div3v2.qt} | 0 .../ffmpeg/video/{qt_div5 => div5.qt} | 0 .../ffmpeg/video/{qt_dnxhd => dnxhd.qt} | 0 cinelerra-5.0/ffmpeg/video/dvd | 1 - cinelerra-5.0/ffmpeg/video/{h264 => h264.mp4} | 0 cinelerra-5.0/ffmpeg/video/{h265 => h265.mp4} | 1 - cinelerra-5.0/ffmpeg/video/{qt_j2k => j2k.qt} | 0 .../ffmpeg/video/{qt_jpeg => jpeg.qt} | 0 .../ffmpeg/video/{qt_mjpa => mjpa.qt} | 0 .../ffmpeg/video/{qt_mjpg => mjpg.qt} | 0 cinelerra-5.0/ffmpeg/video/{qt_mp4 => mp4.qt} | 1 - cinelerra-5.0/ffmpeg/video/mpeg | 1 - cinelerra-5.0/ffmpeg/video/{qt_png => png.qt} | 0 .../ffmpeg/video/{qt_raw_gray => raw_gray.qt} | 0 .../video/{qt_raw_rgb24 => raw_rgb24.qt} | 0 .../ffmpeg/video/{qt_raw_rgba => raw_rgba.qt} | 0 .../video/{qt_raw_uyvy422 => raw_uyvy422.qt} | 0 .../video/{qt_raw_yuv411p => raw_yuv411p.qt} | 0 .../video/{qt_raw_yuv420p => raw_yuv420p.qt} | 0 .../video/{qt_raw_yuv422p => raw_yuv422p.qt} | 0 .../video/{qt_raw_yuv440p => raw_yuv440p.qt} | 0 .../video/{qt_raw_yuv444p => raw_yuv444p.qt} | 0 .../video/{qt_raw_yuyv422 => raw_yuyv422.qt} | 0 .../video/{qt_raw_yvyu422 => raw_yvyu422.qt} | 0 cinelerra-5.0/ffmpeg/video/{qt_rle => rle.qt} | 0 .../ffmpeg/video/{qt_rv20 => rv20.qt} | 0 .../ffmpeg/video/{qt_svq1 => svq1.qt} | 0 cinelerra-5.0/global_config | 2 +- cinelerra-5.0/guicast/Makefile | 1 - cinelerra-5.0/guicast/bchash.C | 116 ++++-- cinelerra-5.0/guicast/bchash.h | 5 +- cinelerra-5.0/guicast/bctextbox.C | 19 + cinelerra-5.0/guicast/bctextbox.h | 3 + cinelerra-5.0/guicast/bcwindowbase.h | 5 +- cinelerra-5.0/guicast/stringfile.C | 269 ------------- cinelerra-5.0/guicast/stringfile.h | 66 ---- cinelerra-5.0/guicast/stringfile.inc | 27 -- 71 files changed, 840 insertions(+), 706 deletions(-) rename cinelerra-5.0/ffmpeg/audio/{h265 => h265.mp4} (82%) rename cinelerra-5.0/ffmpeg/audio/{qt_ima4 => ima4.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_mp3 => mp3.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_mp4 => mp4.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_mulaw => mulaw.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_s16le => s16le.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_s32le => s32le.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_s8 => s8.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_vorbis => vorbis.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_wmav1 => wmav1.qt} (100%) rename cinelerra-5.0/ffmpeg/audio/{qt_wmav2 => wmav2.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_div3 => div3.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_div3v2 => div3v2.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_div5 => div5.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_dnxhd => dnxhd.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{h264 => h264.mp4} (100%) rename cinelerra-5.0/ffmpeg/video/{h265 => h265.mp4} (54%) rename cinelerra-5.0/ffmpeg/video/{qt_j2k => j2k.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_jpeg => jpeg.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_mjpa => mjpa.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_mjpg => mjpg.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_mp4 => mp4.qt} (50%) rename cinelerra-5.0/ffmpeg/video/{qt_png => png.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_gray => raw_gray.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_rgb24 => raw_rgb24.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_rgba => raw_rgba.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_uyvy422 => raw_uyvy422.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yuv411p => raw_yuv411p.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yuv420p => raw_yuv420p.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yuv422p => raw_yuv422p.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yuv440p => raw_yuv440p.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yuv444p => raw_yuv444p.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yuyv422 => raw_yuyv422.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_raw_yvyu422 => raw_yvyu422.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_rle => rle.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_rv20 => rv20.qt} (100%) rename cinelerra-5.0/ffmpeg/video/{qt_svq1 => svq1.qt} (100%) delete mode 100644 cinelerra-5.0/guicast/stringfile.C delete mode 100644 cinelerra-5.0/guicast/stringfile.h delete mode 100644 cinelerra-5.0/guicast/stringfile.inc diff --git a/cinelerra-5.0/cinelerra/asset.C b/cinelerra-5.0/cinelerra/asset.C index 50f3798e..0128f94e 100644 --- a/cinelerra-5.0/cinelerra/asset.C +++ b/cinelerra-5.0/cinelerra/asset.C @@ -72,6 +72,7 @@ int Asset::init_values() // format = FILE_MOV; // Has to be unknown for file probing to succeed format = FILE_UNKNOWN; + fformat[0] = 0; bits = 0; byte_order = 0; signed_ = 0; @@ -82,6 +83,13 @@ int Asset::init_values() strcpy(vcodec, QUICKTIME_YUV2); strcpy(acodec, QUICKTIME_TWOS); + + ff_audio_options[0] = 0; + ff_video_options[0] = 0; + ff_audio_bitrate = 0; + ff_video_bitrate = 0; + ff_video_quality = 0; + jpeg_quality = 100; aspect_ratio = -1; @@ -159,11 +167,6 @@ int Asset::init_values() id = EDL::next_id(); - pipe[0] = 0; - use_pipe = 0; - - reset_timecode(); - return 0; } @@ -206,17 +209,6 @@ void Asset::reset_index() index_state->reset(); } -int Asset::reset_timecode() -{ - strcpy(reel_name, "cin0000"); - reel_number = 0; - tcstart = 0; - tcend = 0; - tcformat = 0; - - return 0; -} - void Asset::copy_from(Asset *asset, int do_index) { copy_location(asset); @@ -235,6 +227,7 @@ void Asset::copy_format(Asset *asset, int do_index) audio_data = asset->audio_data; format = asset->format; + strcpy(fformat, asset->fformat); channels = asset->channels; sample_rate = asset->sample_rate; bits = asset->bits; @@ -259,6 +252,12 @@ void Asset::copy_format(Asset *asset, int do_index) strcpy(vcodec, asset->vcodec); strcpy(acodec, asset->acodec); + strcpy(ff_audio_options, asset->ff_audio_options); + strcpy(ff_video_options, asset->ff_video_options); + ff_audio_bitrate = asset->ff_audio_bitrate; + ff_video_bitrate = asset->ff_video_bitrate; + ff_video_quality = asset->ff_video_quality; + this->audio_length = asset->audio_length; this->video_length = asset->video_length; @@ -392,6 +391,9 @@ int Asset::equivalent(Asset &asset, int result = (!strcmp(asset.path, path) && format == asset.format); + if(result && format == FILE_FFMPEG) + result = !strcmp(fformat, asset.fformat); + if(test_audio && result) { result = (channels == asset.channels && @@ -402,6 +404,10 @@ int Asset::equivalent(Asset &asset, header == asset.header && dither == asset.dither && !strcmp(acodec, asset.acodec)); + if(result && format == FILE_FFMPEG) + result = !strcmp(ff_audio_options, asset.ff_audio_options) && + ff_audio_bitrate == asset.ff_audio_bitrate; + } @@ -413,6 +419,10 @@ int Asset::equivalent(Asset &asset, width == asset.width && height == asset.height && !strcmp(vcodec, asset.vcodec)); + if(result && format == FILE_FFMPEG) + result = !strcmp(ff_video_options, asset.ff_video_options) && + ff_video_bitrate == asset.ff_video_bitrate && + ff_video_quality == asset.ff_video_quality; } return result; @@ -503,6 +513,7 @@ int Asset::read(FileXML *file, format = File::strtoformat(string); use_header = file->tag.get_property("USE_HEADER", use_header); + file->tag.get_property("FFORMAT", fformat); } else if(file->tag.title_is("FOLDER")) @@ -548,9 +559,6 @@ int Asset::read_audio(FileXML *file) audio_length = file->tag.get_property("AUDIO_LENGTH", (int64_t)0); acodec[0] = 0; file->tag.get_property("ACODEC", acodec); - - - return 0; } @@ -633,6 +641,7 @@ int Asset::write(FileXML *file, file->tag.set_property("TYPE", File::formattostr(format)); file->tag.set_property("USE_HEADER", use_header); + file->tag.set_property("FFORMAT", fformat); file->append_tag(); file->append_newline(); @@ -772,6 +781,7 @@ void Asset::load_defaults(BC_Hash *defaults, { format = GET_DEFAULT("FORMAT", format); use_header = GET_DEFAULT("USE_HEADER", use_header); + GET_DEFAULT("FFORMAT", fformat); } if(do_data_types) @@ -820,9 +830,13 @@ void Asset::load_defaults(BC_Hash *defaults, theora_quality = GET_DEFAULT("THEORA_QUALITY", theora_quality); theora_sharpness = GET_DEFAULT("THEORA_SHARPNESS", theora_sharpness); theora_keyframe_frequency = GET_DEFAULT("THEORA_KEYFRAME_FREQUENCY", theora_keyframe_frequency); - theora_keyframe_force_frequency = GET_DEFAULT("THEORA_FORCE_KEYFRAME_FEQUENCY", theora_keyframe_force_frequency); - + theora_keyframe_force_frequency = GET_DEFAULT("THEORA_FORCE_KEYFRAME_FREQUENCY", theora_keyframe_force_frequency); + GET_DEFAULT("FF_AUDIO_OPTIONS", ff_audio_options); + ff_audio_bitrate = GET_DEFAULT("FF_AUDIO_BITRATE", ff_audio_bitrate); + GET_DEFAULT("FF_VIDEO_OPTIONS", ff_video_options); + ff_video_bitrate = GET_DEFAULT("FF_VIDEO_BITRATE", ff_video_bitrate); + ff_video_quality = GET_DEFAULT("FF_VIDEO_QUALITY", ff_video_quality); mp3_bitrate = GET_DEFAULT("MP3_BITRATE", mp3_bitrate); mp4a_bitrate = GET_DEFAULT("MP4A_BITRATE", mp4a_bitrate); @@ -899,6 +913,7 @@ void Asset::save_defaults(BC_Hash *defaults, { UPDATE_DEFAULT("FORMAT", format); UPDATE_DEFAULT("USE_HEADER", use_header); + UPDATE_DEFAULT("FFORMAT", fformat); } if(do_data_types) @@ -920,13 +935,18 @@ void Asset::save_defaults(BC_Hash *defaults, UPDATE_DEFAULT("VORBIS_BITRATE", vorbis_bitrate); UPDATE_DEFAULT("VORBIS_MAX_BITRATE", vorbis_max_bitrate); + UPDATE_DEFAULT("FF_AUDIO_OPTIONS", ff_audio_options); + UPDATE_DEFAULT("FF_AUDIO_BITRATE", ff_audio_bitrate); + UPDATE_DEFAULT("FF_VIDEO_OPTIONS", ff_video_options); + UPDATE_DEFAULT("FF_VIDEO_BITRATE", ff_video_bitrate); + UPDATE_DEFAULT("FF_VIDEO_QUALITY", ff_video_quality); UPDATE_DEFAULT("THEORA_FIX_BITRATE", theora_fix_bitrate); UPDATE_DEFAULT("THEORA_BITRATE", theora_bitrate); UPDATE_DEFAULT("THEORA_QUALITY", theora_quality); UPDATE_DEFAULT("THEORA_SHARPNESS", theora_sharpness); UPDATE_DEFAULT("THEORA_KEYFRAME_FREQUENCY", theora_keyframe_frequency); - UPDATE_DEFAULT("THEORA_FORCE_KEYFRAME_FEQUENCY", theora_keyframe_force_frequency); + UPDATE_DEFAULT("THEORA_FORCE_KEYFRAME_FREQUENCY", theora_keyframe_force_frequency); @@ -1047,6 +1067,12 @@ int Asset::dump(FILE *fp) fprintf(fp," this=%p path=%s\n", this, path); fprintf(fp," index_status %d\n", index_state->index_status); fprintf(fp," format %d\n", format); + fprintf(fp," fformat=\"%s\"\n", fformat); + fprintf(fp," ff_audio_options=\"%s\"\n", ff_audio_options); + fprintf(fp," ff_audio_bitrate=%d\n", ff_audio_bitrate); + fprintf(fp," ff_video_options=\"%s\"\n", ff_video_options); + fprintf(fp," ff_video_bitrate=%d\n", ff_video_bitrate); + fprintf(fp," ff_video_quality=%d\n", ff_video_quality); fprintf(fp," audio_data %d channels %d samplerate %d bits %d" " byte_order %d signed %d header %d dither %d acodec %c%c%c%c\n", audio_data, channels, sample_rate, bits, byte_order, signed_, diff --git a/cinelerra-5.0/cinelerra/asset.h b/cinelerra-5.0/cinelerra/asset.h index f20fbf45..8fe38692 100644 --- a/cinelerra-5.0/cinelerra/asset.h +++ b/cinelerra-5.0/cinelerra/asset.h @@ -147,13 +147,6 @@ public: int64_t audio_length; -// Timecode information. User setable, in case of errors in source - char reel_name[BCTEXTLEN]; - int reel_number; - int64_t tcstart; - int64_t tcend; - int tcformat; - // contains video data int video_data; int layers, program; @@ -220,12 +213,13 @@ public: int vmpeg_field_order; int vmpeg_pframe_distance; - - - - - - +// ffmpeg muxer file extension + char fformat[BCSTRLEN]; + char ff_audio_options[BCTEXTLEN]; + char ff_video_options[BCTEXTLEN]; + int ff_audio_bitrate; + int ff_video_bitrate; + int ff_video_quality; // Divx video compression int divx_bitrate; @@ -269,9 +263,6 @@ public: int ac3_bitrate; - char pipe[BCTEXTLEN]; - int use_pipe; - // Image file sequences. Background rendering doesn't want to write a // sequence header but instead wants to start the sequence numbering at a certain // number. This ensures deletion of all the frames which aren't being used. diff --git a/cinelerra-5.0/cinelerra/batchrender.C b/cinelerra-5.0/cinelerra/batchrender.C index 3a03f227..16d02ba1 100644 --- a/cinelerra-5.0/cinelerra/batchrender.C +++ b/cinelerra-5.0/cinelerra/batchrender.C @@ -182,7 +182,7 @@ void BatchRenderJob::save(FileXML *file) char *string; defaults.save_string(string); file->append_text(string); - delete [] string; + free(string); file->tag.set_title("/JOB"); file->append_tag(); file->append_newline(); @@ -789,7 +789,7 @@ void BatchRenderGUI::create_objects() x = x1; - y += 30; + y += 64; add_subwindow(update_selected_edl = new BatchRenderUpdateEDL(thread, x, y)); diff --git a/cinelerra-5.0/cinelerra/ffmpeg.C b/cinelerra-5.0/cinelerra/ffmpeg.C index db6ca9d6..96b09314 100644 --- a/cinelerra-5.0/cinelerra/ffmpeg.C +++ b/cinelerra-5.0/cinelerra/ffmpeg.C @@ -5,6 +5,7 @@ #include #include #include +#include #include // work arounds (centos) #include @@ -17,6 +18,7 @@ #include "fileffmpeg.h" #include "file.h" #include "ffmpeg.h" +#include "mainerror.h" #include "mwindow.h" #include "vframe.h" @@ -73,89 +75,94 @@ void FFrame::dequeue() fst->dequeue(this); } -FFAudioHistory::FFAudioHistory() +int FFAudioStream::read(float *fp, long len) { - this->nch = 1; - this->sz = 0x1000; - bsz = sz * nch; - bfr = new float[bsz]; - inp = outp = bfr; - lmt = bfr + bsz; + long n = len * nch; + float *op = outp; + while( n > 0 ) { + int k = lmt - op; + if( k > n ) k = n; + n -= k; + while( --k >= 0 ) *fp++ = *op++; + if( op >= lmt ) op = bfr; + } + return len; } -FFAudioHistory::~FFAudioHistory() +void FFAudioStream::realloc(long sz, int nch, long len) { - delete [] bfr; + long bsz = sz * nch; + float *np = new float[bsz]; + inp = np + read(np, len) * nch; + outp = np; + lmt = np + bsz; + this->nch = nch; + this->sz = sz; + delete [] bfr; bfr = np; } - -void FFAudioHistory::reserve(long sz, int nch) +void FFAudioStream::realloc(long sz, int nch) { - long isz = inp - outp; - sz += isz / nch; - if( this->sz < sz || this->nch != nch ) { - realloc(sz, nch); - return; + if( sz > this->sz || this->nch != nch ) { + long len = this->nch != nch ? 0 : curr_pos - seek_pos; + if( len > this->sz ) len = this->sz; + iseek(len); + realloc(sz, nch, len); } - if( isz > 0 ) - memmove(bfr, outp, isz*sizeof(*bfr)); - outp = bfr; - inp = bfr + isz; } -void FFAudioHistory::realloc(long sz, int nch) +void FFAudioStream::reserve(long sz, int nch) { - if( this->nch != nch ) - reset(); - else if( this->sz >= sz ) + long len = (inp - outp) / nch; + sz += len; + if( sz > this->sz || this->nch != nch ) { + if( this->nch != nch ) len = 0; + realloc(sz, nch, len); return; - this->nch = nch; - this->sz = sz; - bsz = sz * nch; - float *np = new float[bsz]; - inp = np + copy(np, used()); - outp = np; - lmt = np + bsz; - delete [] bfr; bfr = np; + } + if( (len*=nch) > 0 && bfr != outp ) + memmove(bfr, outp, len*sizeof(*bfr)); + outp = bfr; + inp = bfr + len; } -long FFAudioHistory::used() +long FFAudioStream::used() { long len = inp>=outp ? inp-outp : inp-bfr + lmt-outp; return len / nch; } -long FFAudioHistory::avail() +long FFAudioStream::avail() { float *in1 = inp+1; if( in1 >= lmt ) in1 = bfr; long len = outp >= in1 ? outp-in1 : outp-bfr + lmt-in1; return len / nch; } -void FFAudioHistory::reset() // clear bfr +void FFAudioStream::reset() // clear bfr { inp = outp = bfr; } -void FFAudioHistory::iseek(int64_t ofs) +void FFAudioStream::iseek(int64_t ofs) { outp = inp - ofs*nch; - if( outp < bfr ) outp += bsz; + if( outp < bfr ) outp += sz*nch; } -float *FFAudioHistory::get_outp(int ofs) +float *FFAudioStream::get_outp(int ofs) { float *ret = outp; outp += ofs*nch; return ret; } -int64_t FFAudioHistory::get_inp(int ofs) +int64_t FFAudioStream::put_inp(int ofs) { inp += ofs*nch; - return (inp-bfr) / nch; + return (inp-outp) / nch; } -int FFAudioHistory::write(const float *fp, long len) +int FFAudioStream::write(const float *fp, long len) { long n = len * nch; float *ip = inp; @@ -170,22 +177,7 @@ int FFAudioHistory::write(const float *fp, long len) return len; } -int FFAudioHistory::copy(float *fp, long len) -{ - long n = len * nch; - float *op = outp; - while( n > 0 ) { - int k = lmt - op; - if( k > n ) k = n; - n -= k; - while( --k >= 0 ) *fp++ = *op++; - if( op >= lmt ) op = bfr; - } - outp = op; - return len; -} - -int FFAudioHistory::zero(long len) +int FFAudioStream::zero(long len) { long n = len * nch; float *ip = inp; @@ -201,11 +193,8 @@ int FFAudioHistory::zero(long len) } // does not advance outp -int FFAudioHistory::read(double *dp, long len, int ch) +int FFAudioStream::read(double *dp, long len, int ch) { - long sz = used(); - if( !sz ) return 0; - if( len > sz ) len = sz; long n = len; float *op = outp + ch; float *lmt1 = lmt + nch-1; @@ -214,17 +203,14 @@ int FFAudioHistory::read(double *dp, long len, int ch) if( k > n ) k = n; n -= k; while( --k >= 0 ) { *dp++ = *op; op += nch; } - if( op >= lmt ) op -= bsz; + if( op >= lmt ) op -= sz*nch; } return len; } // load linear buffer, no wrapping allowed, does not advance inp -int FFAudioHistory::write(const double *dp, long len, int ch) +int FFAudioStream::write(const double *dp, long len, int ch) { - long osz = avail(); - if( !osz || !len ) return 0; - if( len > osz ) len = osz; long n = len; float *ip = inp + ch; while( --n >= 0 ) { *ip = *dp++; ip += nch; } @@ -318,10 +304,10 @@ int FFStream::decode_activate() if( ret >= 0 ) reading = 1; else - fprintf(stderr, "FFStream::decode_activate: open decoder failed\n"); + eprintf("FFStream::decode_activate: open decoder failed\n"); } else - fprintf(stderr, "FFStream::decode_activate: can't clone input file\n"); + eprintf("FFStream::decode_activate: can't clone input file\n"); av_dict_free(&copts); ff_unlock(); } @@ -384,7 +370,7 @@ int FFStream::load_filter(AVFrame *frame) frame, AV_BUFFERSRC_FLAG_KEEP_REF); if( ret < 0 ) { av_frame_unref(frame); - fprintf(stderr, "FFStream::load_filter: av_buffersrc_add_frame_flags failed\n"); + eprintf("FFStream::load_filter: av_buffersrc_add_frame_flags failed\n"); } return ret; } @@ -429,16 +415,26 @@ FFAudioStream::FFAudioStream(FFMPEG *ffmpeg, AVStream *strm, int idx) aud_bfr_sz = 0; aud_bfr = 0; + +// history buffer + nch = 2; + sz = 0x10000; + long bsz = sz * nch; + bfr = new float[bsz]; + inp = outp = bfr; + lmt = bfr + bsz; } FFAudioStream::~FFAudioStream() { if( resample_context ) swr_free(&resample_context); delete [] aud_bfr; + delete [] bfr; } -int FFAudioStream::load_history(float *&bfr, int len) +int FFAudioStream::load_history(uint8_t **data, int len) { + float *samples = *(float **)data; if( resample_context ) { if( len > aud_bfr_sz ) { delete [] aud_bfr; @@ -449,16 +445,17 @@ int FFAudioStream::load_history(float *&bfr, int len) aud_bfr = new float[aud_bfr_sz*channels]; } int ret = swr_convert(resample_context, - (uint8_t**)&aud_bfr, aud_bfr_sz, - (const uint8_t**)&bfr, len); + (uint8_t**)&aud_bfr, aud_bfr_sz, (const uint8_t**)data, len); if( ret < 0 ) { fprintf(stderr, "FFAudioStream::load_history: swr_convert failed\n"); return -1; } - bfr = aud_bfr; + samples = aud_bfr; len = ret; } - append_history(bfr, len); + // biggest user bfr since seek + frame + realloc(mbsz + len + 1, channels); + write(samples, len); return len; } @@ -488,48 +485,19 @@ int FFAudioStream::nb_samples() 10000 : ctx->frame_size; } -void FFAudioStream::alloc_history(int len) -{ - history.realloc(len+1, channels); -} - -void FFAudioStream::reserve_history(int len) -{ - history.reserve(len+1, st->codec->channels); -} - -void FFAudioStream::append_history(const float *fp, int len) -{ - // biggest user bfr since seek + length this frame - int hsz = mbsz + len; - alloc_history(hsz); - history.write(fp, len); -} - int64_t FFAudioStream::load_buffer(double ** const sp, int len) { - reserve_history(len); - int nch = st->codec->channels; + reserve(len+1, st->codec->channels); for( int ch=0; ch curr_pos ) return 0; int64_t len = curr_pos - seek_pos; - if( len > history.sz ) len = history.sz; + if( len > sz ) len = sz; if( pos < curr_pos - len ) return 0; return 1; } @@ -561,12 +529,12 @@ int FFAudioStream::load(int64_t pos, int len) for( int i=0; ret>=0 && !flushed && curr_pos 0 ) { - load_history((float *&)frame->extended_data[0], frame->nb_samples); + load_history(&frame->extended_data[0], frame->nb_samples); curr_pos += frame->nb_samples; } } if( flushed && end_pos > curr_pos ) { - zero_history(end_pos - curr_pos); + zero(end_pos - curr_pos); curr_pos = end_pos; } return curr_pos - pos; @@ -576,7 +544,7 @@ int FFAudioStream::audio_seek(int64_t pos) { if( decode_activate() < 0 ) return -1; if( in_history(pos) ) { - history.iseek(curr_pos - pos); + iseek(curr_pos - pos); return 0; } if( pos == curr_pos ) return 0; @@ -586,7 +554,7 @@ int FFAudioStream::audio_seek(int64_t pos) avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, tstmp, INT64_MAX, 0); seek_pos = curr_pos = pos; mbsz = 0; - history.reset(); + reset(); st_eof(0); return 1; } @@ -603,7 +571,7 @@ int FFAudioStream::encode(double **samples, int len) frm = new FFrame(this); if( (ret=frm->initted()) < 0 ) break; AVFrame *frame = *frm; - float *bfrp = get_history(frame_sz); + float *bfrp = get_outp(frame_sz); ret = swr_convert(resample_context, (uint8_t **)frame->extended_data, frame_sz, (const uint8_t **)&bfrp, frame_sz); @@ -993,10 +961,9 @@ void FFMPEG::get_option_path(char *path, const char *type, const char *spec) set_option_path(path, "%s/%s", type, spec); } -int FFMPEG::check_option(const char *path, char *spec) +int FFMPEG::get_format(char *format, const char *path, char *spec) { - char option_path[BCTEXTLEN], line[BCTEXTLEN]; - char format[BCSTRLEN], codec[BCSTRLEN]; + char option_path[BCTEXTLEN], line[BCTEXTLEN], codec[BCSTRLEN]; get_option_path(option_path, path, spec); FILE *fp = fopen(option_path,"r"); if( !fp ) return 1; @@ -1006,25 +973,27 @@ int FFMPEG::check_option(const char *path, char *spec) line[sizeof(line)-1] = 0; ret = scan_option_line(line, format, codec); } - if( !ret ) { - if( !file_format[0] ) strcpy(file_format, format); - else if( strcmp(file_format, format) ) ret = 1; - } fclose(fp); return ret; } -const char *FFMPEG::get_file_format() +int FFMPEG::get_file_format() { - file_format[0] = 0; int ret = 0; + char audio_format[BCSTRLEN], video_format[BCSTRLEN]; + file_format[0] = audio_format[0] = video_format[0] = 0; Asset *asset = file_base->asset; if( !ret && asset->audio_data ) - ret = check_option("audio", asset->acodec); + ret = get_format(audio_format, "audio", asset->acodec); if( !ret && asset->video_data ) - ret = check_option("video", asset->vcodec); - if( !ret && !file_format[0] ) ret = 1; - return !ret ? file_format : 0; + ret = get_format(video_format, "video", asset->vcodec); + if( !ret && !audio_format[0] && !video_format[0] ) + ret = 1; + if( !ret && audio_format[0] && video_format[0] && + strcmp(audio_format, video_format) ) ret = -1; + if( !ret ) + strcpy(file_format, audio_format[0] ? audio_format : video_format); + return ret; } int FFMPEG::scan_option_line(char *cp, char *tag, char *val) @@ -1048,42 +1017,35 @@ int FFMPEG::scan_option_line(char *cp, char *tag, char *val) return 0; } -int FFMPEG::read_options(const char *options, char *format, char *codec, - char *bsfilter, char *bsargs, AVDictionary *&opts) +int FFMPEG::get_encoder(const char *options, + char *format, char *codec, char *bsfilter, char *bsargs) { FILE *fp = fopen(options,"r"); if( !fp ) { - fprintf(stderr, "FFMPEG::read_options: options open failed %s\n",options); + eprintf("FFMPEG::get_encoder: options open failed %s\n",options); return 1; } - int ret = read_options(fp, options, format, codec, opts); - char *cp = codec; - while( *cp && *cp != '|' ) ++cp; - if( *cp == '|' && !scan_option_line(cp+1, bsfilter, bsargs) ) { - do { *cp-- = 0; } while( cp>=codec && (*cp==' ' || *cp == '\t' ) ); - } - else - bsfilter[0] = bsargs[0] = 0; + if( get_encoder(fp, format, codec, bsfilter, bsargs) ) + eprintf("FFMPEG::get_encoder:" + " err: format/codec not found %s\n", options); fclose(fp); - return ret; + return 0; } -int FFMPEG::read_options(FILE *fp, const char *options, - char *format, char *codec, AVDictionary *&opts) +int FFMPEG::get_encoder(FILE *fp, + char *format, char *codec, char *bsfilter, char *bsargs) { + format[0] = codec[0] = bsfilter[0] = bsargs[0] = 0; char line[BCTEXTLEN]; - if( !fgets(line, sizeof(line), fp) ) { - fprintf(stderr, "FFMPEG::read_options:" - " options file empty %s\n",options); - return 1; - } + if( !fgets(line, sizeof(line), fp) ) return 1; line[sizeof(line)-1] = 0; - if( scan_option_line(line, format, codec) ) { - fprintf(stderr, "FFMPEG::read_options:" - " err: format/codec not found %s\n", options); - return 1; - } - return read_options(fp, options, opts, 1); + if( scan_option_line(line, format, codec) ) return 1; + char *cp = codec; + while( *cp && *cp != '|' ) ++cp; + if( !*cp ) return 0; + if( scan_option_line(cp+1, bsfilter, bsargs) ) return 1; + do { *cp-- = 0; } while( cp>=codec && (*cp==' ' || *cp == '\t' ) ); + return 0; } int FFMPEG::read_options(const char *options, AVDictionary *&opts) @@ -1095,17 +1057,27 @@ int FFMPEG::read_options(const char *options, AVDictionary *&opts) return ret; } -int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts, int no) +int FFMPEG::scan_options(const char *options, AVDictionary *&opts) { - int ret = 0; + FILE *fp = fmemopen((void *)options,strlen(options),"r"); + if( !fp ) return 0; + int ret = read_options(fp, options, opts); + fclose(fp); + return ret; +} + +int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts) +{ + int ret = 0, no = 0; char line[BCTEXTLEN]; while( !ret && fgets(line, sizeof(line), fp) ) { line[sizeof(line)-1] = 0; ++no; if( line[0] == '#' ) continue; + if( line[0] == '\n' ) continue; char key[BCSTRLEN], val[BCTEXTLEN]; if( scan_option_line(line, key, val) ) { - fprintf(stderr, "FFMPEG::read_options:" + eprintf("FFMPEG::read_options:" " err reading %s: line %d\n", options, no); ret = 1; } @@ -1239,7 +1211,7 @@ int FFMPEG::init_decoder(const char *filename) fp = fopen(file_opts, "r"); } if( fp ) { - read_options(fp, file_opts, opts, 0); + read_options(fp, file_opts, opts); fclose(fp); } else @@ -1261,7 +1233,7 @@ int FFMPEG::open_decoder() { struct stat st; if( stat(fmt_ctx->filename, &st) < 0 ) { - fprintf(stderr,"FFMPEG::open_decoder: can't stat file: %s\n", + eprintf("FFMPEG::open_decoder: can't stat file: %s\n", fmt_ctx->filename); return 1; } @@ -1344,17 +1316,27 @@ int FFMPEG::open_decoder() int FFMPEG::init_encoder(const char *filename) { - const char *format = get_file_format(); - if( !format ) { - fprintf(stderr, "FFMPEG::init_encoder: invalid file format for %s\n", filename); + int fd = ::open(filename,O_WRONLY); + if( fd < 0 ) fd = open(filename,O_WRONLY+O_CREAT,0666); + if( fd < 0 ) { + eprintf("FFMPEG::init_encoder: bad file path: %s\n", filename); + return 1; + } + ::close(fd); + int ret = get_file_format(); + if( ret > 0 ) { + eprintf("FFMPEG::init_encoder: bad file format: %s\n", filename); + return 1; + } + if( ret < 0 ) { + eprintf("FFMPEG::init_encoder: mismatch audio/video file format: %s\n", filename); return 1; } - int ret = 0; ff_lock("FFMPEG::init_encoder"); av_register_all(); - avformat_alloc_output_context2(&fmt_ctx, 0, format, filename); + avformat_alloc_output_context2(&fmt_ctx, 0, file_format, filename); if( !fmt_ctx ) { - fprintf(stderr, "FFMPEG::init_encoder: failed: %s\n", filename); + eprintf("FFMPEG::init_encoder: failed: %s\n", filename); ret = 1; } if( !ret ) { @@ -1366,7 +1348,7 @@ int FFMPEG::init_encoder(const char *filename) return ret; } -int FFMPEG::open_encoder(const char *path, const char *spec) +int FFMPEG::open_encoder(const char *type, const char *spec) { Asset *asset = file_base->asset; @@ -1374,13 +1356,13 @@ int FFMPEG::open_encoder(const char *path, const char *spec) AVDictionary *sopts = 0; av_dict_copy(&sopts, opts, 0); char option_path[BCTEXTLEN]; - set_option_path(option_path, "%s/%s.opts", path, path); + set_option_path(option_path, "%s/%s.opts", type, type); read_options(option_path, sopts); - get_option_path(option_path, path, spec); + get_option_path(option_path, type, spec); char format_name[BCSTRLEN], codec_name[BCTEXTLEN]; char bsfilter[BCSTRLEN], bsargs[BCTEXTLEN]; - if( read_options(option_path, format_name, codec_name, bsfilter, bsargs, sopts) ) { - fprintf(stderr, "FFMPEG::open_encoder: read options failed %s:%s\n", + if( get_encoder(option_path, format_name, codec_name, bsfilter, bsargs) ) { + eprintf("FFMPEG::open_encoder: get_encoder failed %s:%s\n", option_path, filename); return 1; } @@ -1393,14 +1375,14 @@ int FFMPEG::open_encoder(const char *path, const char *spec) const AVCodecDescriptor *codec_desc = 0; AVCodec *codec = avcodec_find_encoder_by_name(codec_name); if( !codec ) { - fprintf(stderr, "FFMPEG::open_encoder: cant find codec %s:%s\n", + eprintf("FFMPEG::open_encoder: cant find codec %s:%s\n", codec_name, filename); ret = 1; } if( !ret ) { codec_desc = avcodec_descriptor_get(codec->id); if( !codec_desc ) { - fprintf(stderr, "FFMPEG::open_encoder: unknown codec %s:%s\n", + eprintf("FFMPEG::open_encoder: unknown codec %s:%s\n", codec_name, filename); ret = 1; } @@ -1408,7 +1390,7 @@ int FFMPEG::open_encoder(const char *path, const char *spec) if( !ret ) { st = avformat_new_stream(fmt_ctx, 0); if( !st ) { - fprintf(stderr, "FFMPEG::open_encoder: cant create stream %s:%s\n", + eprintf("FFMPEG::open_encoder: cant create stream %s:%s\n", codec_name, filename); ret = 1; } @@ -1418,12 +1400,23 @@ int FFMPEG::open_encoder(const char *path, const char *spec) switch( codec_desc->type ) { case AVMEDIA_TYPE_AUDIO: { if( has_audio ) { - fprintf(stderr, "FFMPEG::open_encoder: duplicate audio %s:%s\n", + eprintf("FFMPEG::open_encoder: duplicate audio %s:%s\n", codec_name, filename); ret = 1; break; } has_audio = 1; + if( scan_options(asset->ff_audio_options, sopts) ) { + eprintf("FFMPEG::open_encoder: bad audio options %s:%s\n", + codec_name, filename); + ret = 1; + break; + } + if( asset->ff_audio_bitrate > 0 ) { + char arg[BCSTRLEN]; + sprintf(arg, "%d", asset->ff_audio_bitrate); + av_dict_set(&sopts, "b", arg, 0); + } int aidx = ffaudio.size(); int idx = aidx + ffvideo.size(); FFAudioStream *aud = new FFAudioStream(this, st, idx); @@ -1435,7 +1428,7 @@ int FFMPEG::open_encoder(const char *path, const char *spec) ctx->channel_layout = av_get_default_channel_layout(ctx->channels); ctx->sample_rate = check_sample_rate(codec, asset->sample_rate); if( !ctx->sample_rate ) { - fprintf(stderr, "FFMPEG::open_audio_encode:" + eprintf("FFMPEG::open_audio_encode:" " check_sample_rate failed %s\n", filename); ret = 1; break; @@ -1452,12 +1445,36 @@ int FFMPEG::open_encoder(const char *path, const char *spec) break; } case AVMEDIA_TYPE_VIDEO: { if( has_video ) { - fprintf(stderr, "FFMPEG::open_encoder: duplicate video %s:%s\n", + eprintf("FFMPEG::open_encoder: duplicate video %s:%s\n", codec_name, filename); ret = 1; break; } has_video = 1; + if( scan_options(asset->ff_video_options, sopts) ) { + eprintf("FFMPEG::open_encoder: bad video options %s:%s\n", + codec_name, filename); + ret = 1; + break; + } + if( asset->ff_video_bitrate > 0 ) { + char arg[BCSTRLEN]; + sprintf(arg, "%d", asset->ff_video_bitrate); + av_dict_set(&sopts, "b", arg, 0); + } + else if( asset->ff_video_quality > 0 ) { + ctx->global_quality = asset->ff_video_quality * FF_QP2LAMBDA; + ctx->qmin = ctx->qmax = asset->ff_video_quality; + ctx->mb_lmin = ctx->qmin * FF_QP2LAMBDA; + ctx->mb_lmax = ctx->qmax * FF_QP2LAMBDA; + ctx->flags |= CODEC_FLAG_QSCALE; + char arg[BCSTRLEN]; + av_dict_set(&sopts, "flags", "+qscale", 0); + sprintf(arg, "%d", asset->ff_video_quality); + av_dict_set(&sopts, "qscale", arg, 0); + sprintf(arg, "%d", ctx->global_quality); + av_dict_set(&sopts, "global_quality", arg, 0); + } int vidx = ffvideo.size(); int idx = vidx + ffaudio.size(); FFVideoStream *vid = new FFVideoStream(this, st, idx); @@ -1472,7 +1489,7 @@ int FFMPEG::open_encoder(const char *path, const char *spec) ctx->pix_fmt = codec->pix_fmts ? codec->pix_fmts[0] : AV_PIX_FMT_YUV420P; AVRational frame_rate = check_frame_rate(codec, vid->frame_rate); if( !frame_rate.num || !frame_rate.den ) { - fprintf(stderr, "FFMPEG::open_audio_encode:" + eprintf("FFMPEG::open_audio_encode:" " check_frame_rate failed %s\n", filename); ret = 1; break; @@ -1482,7 +1499,7 @@ int FFMPEG::open_encoder(const char *path, const char *spec) vid->writing = -1; break; } default: - fprintf(stderr, "FFMPEG::open_encoder: not audio/video, %s:%s\n", + eprintf("FFMPEG::open_encoder: not audio/video, %s:%s\n", codec_name, filename); ret = 1; } @@ -1491,7 +1508,7 @@ int FFMPEG::open_encoder(const char *path, const char *spec) ret = avcodec_open2(st->codec, codec, &sopts); if( ret < 0 ) { ff_err(ret,"FFMPEG::open_encoder"); - fprintf(stderr, "FFMPEG::open_encoder: open failed %s:%s\n", + eprintf("FFMPEG::open_encoder: open failed %s:%s\n", codec_name, filename); ret = 1; } @@ -1659,7 +1676,7 @@ int FFMPEG::decode(int chn, int64_t pos, double *samples, int len) FFAudioStream *aud = ffaudio[aidx]; if( aud->load(pos, len) < len ) return -1; int ch = astrm_index[chn].st_ch; - return aud->history.read(samples,len,ch); + return aud->read(samples,len,ch); } int FFMPEG::decode(int layer, int64_t pos, VFrame *vframe) diff --git a/cinelerra-5.0/cinelerra/ffmpeg.h b/cinelerra-5.0/cinelerra/ffmpeg.h index 210e2171..ff924c1e 100644 --- a/cinelerra-5.0/cinelerra/ffmpeg.h +++ b/cinelerra-5.0/cinelerra/ffmpeg.h @@ -8,13 +8,17 @@ #include #include "arraylist.h" -#include "linklist.h" #include "asset.inc" #include "bccmodels.h" +#include "bcwindowbase.inc" +#include "condition.h" #include "cstrdup.h" +#include "linklist.h" #include "ffmpeg.inc" #include "filebase.inc" #include "fileffmpeg.inc" +#include "mutex.h" +#include "thread.h" #include "vframe.inc" extern "C" { @@ -61,29 +65,6 @@ public: void dequeue(); }; -class FFAudioHistory { -public: - float *inp, *outp, *bfr, *lmt; - long sz, bsz; - int nch; - - FFAudioHistory(); - ~FFAudioHistory(); - void reserve(long sz, int nch); - void realloc(long sz, int nch); - long used(); - long avail(); - void reset(); - void iseek(int64_t ofs); - float *get_outp(int len); - int64_t get_inp(int len); - int write(const float *fp, long len); - int copy(float *fp, long len); - int zero(long len); - int read(double *dp, long len, int ch); - int write(const double *dp, long len, int ch); -}; - class FFStream { public: FFStream(FFMPEG *ffmpeg, AVStream *st, int idx); @@ -155,23 +136,36 @@ public: }; class FFAudioStream : public FFStream { + float *inp, *outp, *bfr, *lmt; + long sz; + int nch; + + int read(float *fp, long len); + void realloc(long sz, int nch, long len); + void realloc(long sz, int nch); + void reserve(long sz, int nch); + long used(); + long avail(); + void reset(); + void iseek(int64_t ofs); + float *get_outp(int len); + int64_t put_inp(int len); + int write(const float *fp, long len); + int zero(long len); + int write(const double *dp, long len, int ch); public: FFAudioStream(FFMPEG *ffmpeg, AVStream *strm, int idx); virtual ~FFAudioStream(); - int load_history(float *&bfr, int len); + int load_history(uint8_t **data, int len); int decode_frame(AVFrame *frame, int &got_frame); int create_filter(const char *filter_spec, AVCodecContext *src_ctx, AVCodecContext *sink_ctx); int encode_activate(); int nb_samples(); - void alloc_history(int len); - void reserve_history(int len); - void append_history(const float *fp, int len); - void zero_history(int len); int64_t load_buffer(double ** const sp, int len); - float *get_history(int len); int in_history(int64_t pos); + int read(double *dp, long len, int ch); int init_frame(AVFrame *frame); int load(int64_t pos, int len); @@ -184,7 +178,6 @@ public: int64_t seek_pos, curr_pos; int64_t length; - FFAudioHistory history; SwrContext *resample_context; int aud_bfr_sz; float *aud_bfr; @@ -239,15 +232,16 @@ public: static void set_option_path(char *path, const char *fmt, ...); static void get_option_path(char *path, const char *type, const char *spec); - int check_option(const char *path, char *spec); - const char *get_file_format(); + int get_format(char *format, const char *path, char *spec); + int get_file_format(); int scan_option_line(char *cp,char *tag,char *val); - int read_options(const char *options, char *format, char *codec, - char *bsfilter, char *bsargs, AVDictionary *&opts); - int read_options(FILE *fp, const char *options, - char *format, char *codec, AVDictionary *&opts); + int get_encoder(const char *options, + char *format, char *codec, char *bsfilter, char *bsargs); + int get_encoder(FILE *fp, + char *format, char *codec, char *bsfilter, char *bsargs); int read_options(const char *options, AVDictionary *&opts); - int read_options(FILE *fp, const char *options, AVDictionary *&opts, int no=0); + int scan_options(const char *options, AVDictionary *&opts); + int read_options(FILE *fp, const char *options, AVDictionary *&opts); int load_options(const char *options, AVDictionary *&opts); void set_loglevel(const char *ap); static double to_secs(int64_t time, AVRational time_base); @@ -256,7 +250,7 @@ public: int init_decoder(const char *filename); int open_decoder(); int init_encoder(const char *filename); - int open_encoder(const char *path, const char *spec); + int open_encoder(const char *type, const char *spec); int close_encoder(); int total_audio_channels(); diff --git a/cinelerra-5.0/cinelerra/file.C b/cinelerra-5.0/cinelerra/file.C index 17e555aa..be231980 100644 --- a/cinelerra-5.0/cinelerra/file.C +++ b/cinelerra-5.0/cinelerra/file.C @@ -76,7 +76,6 @@ #include "pluginserver.h" #include "preferences.h" #include "samples.h" -#include "stringfile.h" #include "vframe.h" //suppress noref warning @@ -516,7 +515,7 @@ int File::open_file(Preferences *preferences, buffer, buffer_size); delete [] buffer; - delete [] string; + free(string); //printf("File::open_file %d\n", __LINE__); // Get the updated asset from the fork @@ -797,7 +796,7 @@ int File::open_file(Preferences *preferences, // Reopen file with correct parser and get header. if(file->open_file(rd, wr)) { - delete file; + delete file; file = 0; return FILE_NOT_FOUND; } @@ -2489,7 +2488,7 @@ const char* File::get_tag(int format) case FILE_VMPEG: return "m2v"; case FILE_VORBIS: return "ogg"; case FILE_WAV: return "wav"; - case FILE_FFMPEG: return "media"; + case FILE_FFMPEG: return "ffmpg"; } return 0; } diff --git a/cinelerra-5.0/cinelerra/fileffmpeg.C b/cinelerra-5.0/cinelerra/fileffmpeg.C index 2ef7d625..bfe0a107 100644 --- a/cinelerra-5.0/cinelerra/fileffmpeg.C +++ b/cinelerra-5.0/cinelerra/fileffmpeg.C @@ -32,6 +32,73 @@ FileFFMPEG::~FileFFMPEG() } +FFMpegConfigNum::FFMpegConfigNum(BC_Window *window, + int x, int y, char *title_text, int *output) + : BC_TumbleTextBox(window, (int64_t)*output, + (int64_t)-1, (int64_t)25000000, 100, y, 100) +{ + this->window = window; + this->x = x; this->y = y; + this->title_text = title_text; + this->output = output; +} + +FFMpegConfigNum::~FFMpegConfigNum() +{ +} + +void FFMpegConfigNum::create_objects() +{ + window->add_subwindow(title = new BC_Title(x, y, title_text)); + BC_TumbleTextBox::create_objects(); +} + +int FFMpegConfigNum::handle_event() +{ + *output = atol(get_text()); + return 1; +} + +FFMpegAudioNum::FFMpegAudioNum(BC_Window *window, + int x, int y, char *title_text, int *output) + : FFMpegConfigNum(window, x, y, title_text, output) +{ +} + +int FFMpegAudioBitrate::handle_event() +{ + int ret = FFMpegAudioNum::handle_event(); + return ret; +} + +FFMpegVideoNum::FFMpegVideoNum(BC_Window *window, + int x, int y, char *title_text, int *output) + : FFMpegConfigNum(window, x, y, title_text, output) +{ +} + +int FFMpegVideoBitrate::handle_event() +{ + int ret = FFMpegVideoNum::handle_event(); + Asset *asset = window()->asset; + if( asset->ff_video_bitrate ) + window()->quality->disable(); + else + window()->quality->enable(); + return ret; +} + +int FFMpegVideoQuality::handle_event() +{ + int ret = FFMpegVideoNum::handle_event(); + Asset *asset = window()->asset; + if( asset->ff_video_quality ) + window()->bitrate->disable(); + else + window()->bitrate->enable(); + return ret; +} + void FileFFMPEG::get_parameters(BC_WindowBase *parent_window, Asset *asset, BC_WindowBase *&format_window, int audio_options, int video_options) @@ -251,6 +318,17 @@ 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 @@ -264,6 +342,9 @@ FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset) this->parent_window = parent_window; this->asset = asset; preset_popup = 0; + + bitrate = 0; + audio_options = 0; } FFMPEGConfigAudio::~FFMPEGConfigAudio() @@ -286,16 +367,47 @@ void FFMPEGConfigAudio::create_objects() 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; + } presets.append(new BC_ListBoxItem(name)); } + if( asset->acodec[0] ) { + int k = presets.size(); + while( --k >= 0 && strcmp(asset->acodec, presets[k]->get_text()) ); + if( k < 0 ) asset->acodec[0] = 0; + } + + if( !asset->acodec[0] && presets.size() > 0 ) + strcpy(asset->acodec, presets[0]->get_text()); + add_tool(new BC_Title(x, y, _("Preset:"))); y += 25; preset_popup = new FFMPEGConfigAudioPopup(this, x, y); preset_popup->create_objects(); + y += 50; + bitrate = new FFMpegAudioBitrate(this, x, y, _("Bitrate:"), &asset->ff_audio_bitrate); + bitrate->create_objects(); + bitrate->set_increment(1000); + + y += bitrate->get_h() + 10; + add_subwindow(new BC_Title(x, y, _("Audio Options:"))); + 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, + sizeof(asset->ff_audio_options)); + } + add_subwindow(audio_options = new FFAudioOptions(this, x, y, get_w()-x-20, 10, + sizeof(asset->ff_audio_options)-1, asset->ff_audio_options)); add_subwindow(new BC_OKButton(this)); show_window(1); + bitrate->handle_event(); unlock_window(); } @@ -306,6 +418,20 @@ int FFMPEGConfigAudio::close_event() } +FFAudioOptions::FFAudioOptions(FFMPEGConfigAudio *audio_popup, + int x, int y, int w, int rows, int size, char *text) + : BC_TextBox(x, y, w, rows, size, text) +{ + this->audio_popup = audio_popup; +} + +int FFAudioOptions::handle_event() +{ + strcpy(audio_popup->asset->ff_audio_options, get_text()); + return 1; +} + + FFMPEGConfigAudioPopup::FFMPEGConfigAudioPopup(FFMPEGConfigAudio *popup, int x, int y) : BC_PopupTextBox(popup, &popup->presets, popup->asset->acodec, x, y, 300, 300) { @@ -315,6 +441,12 @@ FFMPEGConfigAudioPopup::FFMPEGConfigAudioPopup(FFMPEGConfigAudio *popup, int x, int FFMPEGConfigAudioPopup::handle_event() { strcpy(popup->asset->acodec, get_text()); + 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, + sizeof(asset->ff_audio_options)); + popup->audio_options->update(asset->ff_audio_options); return 1; } @@ -344,6 +476,9 @@ FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset) this->parent_window = parent_window; this->asset = asset; preset_popup = 0; + + bitrate = 0; + video_options = 0; } FFMPEGConfigVideo::~FFMPEGConfigVideo() @@ -369,14 +504,59 @@ void FFMPEGConfigVideo::create_objects() 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; + } presets.append(new BC_ListBoxItem(name)); } + if( asset->vcodec[0] ) { + int k = presets.size(); + while( --k >= 0 && strcmp(asset->vcodec, presets[k]->get_text()) ); + if( k < 0 ) asset->vcodec[0] = 0; + } + + if( !asset->vcodec[0] && presets.size() > 0 ) + strcpy(asset->vcodec, presets[0]->get_text()); + preset_popup = new FFMPEGConfigVideoPopup(this, x, y); preset_popup->create_objects(); + if( asset->ff_video_bitrate && asset->ff_video_quality ) { + asset->ff_video_bitrate = 0; + asset->ff_video_quality = 0; + } + + y += 50; + bitrate = new FFMpegVideoBitrate(this, x, y, _("Bitrate:"), &asset->ff_video_bitrate); + bitrate->create_objects(); + bitrate->set_increment(100000); + y += bitrate->get_h() + 5; + quality = new FFMpegVideoQuality(this, x, y, _("Quality:"), &asset->ff_video_quality); + quality->create_objects(); + quality->set_increment(1); + quality->set_boundaries((int64_t)0, (int64_t)31); + + y += quality->get_h() + 10; + add_subwindow(new BC_Title(x, y, _("Video Options:"))); + 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, + sizeof(asset->ff_video_options)); + } + add_subwindow(video_options = new FFVideoOptions(this, x, y, get_w()-x-20, 10, + sizeof(asset->ff_video_options)-1, asset->ff_video_options)); + add_subwindow(new BC_OKButton(this)); show_window(1); + if( asset->ff_video_bitrate ) + quality->disable(); + if( asset->ff_video_quality ) + bitrate->disable(); unlock_window(); } @@ -387,6 +567,20 @@ int FFMPEGConfigVideo::close_event() } +FFVideoOptions::FFVideoOptions(FFMPEGConfigVideo *video_popup, + int x, int y, int w, int rows, int size, char *text) + : BC_TextBox(x, y, w, rows, size, text) +{ + this->video_popup = video_popup; +} + +int FFVideoOptions::handle_event() +{ + strcpy(video_popup->asset->ff_video_options, get_text()); + return 1; +} + + FFMPEGConfigVideoPopup::FFMPEGConfigVideoPopup(FFMPEGConfigVideo *popup, int x, int y) : BC_PopupTextBox(popup, &popup->presets, popup->asset->vcodec, x, y, 300, 300) { @@ -396,6 +590,12 @@ FFMPEGConfigVideoPopup::FFMPEGConfigVideoPopup(FFMPEGConfigVideo *popup, int x, int FFMPEGConfigVideoPopup::handle_event() { strcpy(popup->asset->vcodec, get_text()); + 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, + sizeof(asset->ff_video_options)); + popup->video_options->update(asset->ff_video_options); return 1; } diff --git a/cinelerra-5.0/cinelerra/fileffmpeg.h b/cinelerra-5.0/cinelerra/fileffmpeg.h index db46e696..8e42862a 100644 --- a/cinelerra-5.0/cinelerra/fileffmpeg.h +++ b/cinelerra-5.0/cinelerra/fileffmpeg.h @@ -16,6 +16,20 @@ #include #include +class FileFFMPEG; +class FFMpegConfigNum; +class FFMpegAudioNum; +class FFMpegVideoNum; +class FFOkButton; +class FFOptions; +class FFMPEGConfigAudio; +class FFAudioOptions; +class FFMPEGConfigAudioPopup; +class FFMPEGConfigAudioToggle; +class FFMPEGConfigVideo; +class FFVideoOptions; +class FFMPEGConfigVideoPopup; +class FFMPEGConfigVideoToggle; class FileFFMPEG : public FileBase { @@ -49,6 +63,63 @@ public: int select_audio_stream(Asset *asset, int astream); }; +class FFMpegConfigNum : public BC_TumbleTextBox +{ +public: + FFMpegConfigNum(BC_Window *window, int x, int y, + char *title_text, int *output); + ~FFMpegConfigNum(); + + void create_objects(); + int handle_event(); + int *output; + BC_Window *window; + BC_Title *title; + char *title_text; + int x, y; +}; + +class FFMpegAudioNum : public FFMpegConfigNum +{ +public: + FFMpegAudioNum(BC_Window *window, int x, int y, char *title_text, int *output); + ~FFMpegAudioNum() {} + + FFMPEGConfigAudio *window() { return (FFMPEGConfigAudio *)FFMpegConfigNum::window; } +}; + +class FFMpegAudioBitrate : public FFMpegAudioNum +{ +public: + FFMpegAudioBitrate(BC_Window *window, int x, int y, char *title_text, int *output) + : FFMpegAudioNum(window, x, y, title_text, output) {} + int handle_event(); +}; + +class FFMpegVideoNum : public FFMpegConfigNum +{ +public: + FFMpegVideoNum(BC_Window *window, int x, int y, char *title_text, int *output); + ~FFMpegVideoNum() {} + + FFMPEGConfigVideo *window() { return (FFMPEGConfigVideo *)FFMpegConfigNum::window; } +}; + +class FFMpegVideoBitrate : public FFMpegVideoNum +{ +public: + FFMpegVideoBitrate(BC_Window *window, int x, int y, char *title_text, int *output) + : FFMpegVideoNum(window, x, y, title_text, output) {} + int handle_event(); +}; + +class FFMpegVideoQuality : public FFMpegVideoNum +{ +public: + FFMpegVideoQuality(BC_Window *window, int x, int y, char *title_text, int *output) + : FFMpegVideoNum(window, x, y, title_text, output) {} + int handle_event(); +}; class FFMPEGConfigAudio : public BC_Window { @@ -61,10 +132,22 @@ public: ArrayList presets; FFMPEGConfigAudioPopup *preset_popup; + FFMpegAudioBitrate *bitrate; + FFAudioOptions *audio_options; BC_WindowBase *parent_window; Asset *asset; }; +class FFAudioOptions : public BC_TextBox +{ +public: + FFAudioOptions(FFMPEGConfigAudio *audio_popup, + int x, int y, int w, int rows, int size, char *text); + int handle_event(); + + FFMPEGConfigAudio *audio_popup; +}; + class FFMPEGConfigAudioPopup : public BC_PopupTextBox { @@ -97,9 +180,22 @@ public: ArrayList presets; FFMPEGConfigVideoPopup *preset_popup; BC_WindowBase *parent_window; + FFMpegVideoBitrate *bitrate; + FFMpegVideoQuality *quality; + FFVideoOptions *video_options; Asset *asset; }; +class FFVideoOptions : public BC_TextBox +{ +public: + FFVideoOptions(FFMPEGConfigVideo *video_popup, + int x, int y, int w, int rows, int size, char *text); + int handle_event(); + + FFMPEGConfigVideo *video_popup; +}; + class FFMPEGConfigVideoPopup : public BC_PopupTextBox { public: diff --git a/cinelerra-5.0/cinelerra/filefork.C b/cinelerra-5.0/cinelerra/filefork.C index 97ddaa32..e2a17877 100644 --- a/cinelerra-5.0/cinelerra/filefork.C +++ b/cinelerra-5.0/cinelerra/filefork.C @@ -135,7 +135,7 @@ int FileFork::handle_command() table.save_string(string); int buffer_size = strlen(string) + 1; send_result(result, (unsigned char*)string, buffer_size); - delete [] string; + free(string); break; } diff --git a/cinelerra-5.0/cinelerra/filemov.C b/cinelerra-5.0/cinelerra/filemov.C index e6211f09..518d1e93 100644 --- a/cinelerra-5.0/cinelerra/filemov.C +++ b/cinelerra-5.0/cinelerra/filemov.C @@ -245,7 +245,7 @@ int FileMOV::open_file(int rd, int wr) // Set decoding parameter quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking); // Set timecode offset - quicktime_set_frame_start(fd, asset->tcstart); + quicktime_set_frame_start(fd, 0); return 0; } @@ -448,16 +448,6 @@ void FileMOV::format_to_asset() dv_parse_packs(tmp_decoder, frame->get_data()); dv_get_timestamp(tmp_decoder, tc); // printf("Timestamp %s\n", tc); - - float seconds = Units::text_to_seconds(tc, - 1, // Use 1 as sample rate, doesn't matter - TIME_HMSF, asset->frame_rate, 0); - // Set tcstart if it hasn't been set yet, this is a bit problematic - // FIXME: The problem arises if file has nonzero tcstart and user - // manualy sets it to zero - every time project will load it will - // be set to nonzero - if (asset->tcstart == 0) - asset->tcstart = int64_t(seconds * asset->frame_rate); } delete frame; dv_decoder_free(tmp_decoder); diff --git a/cinelerra-5.0/cinelerra/formatpopup.C b/cinelerra-5.0/cinelerra/formatpopup.C index 94f1ec22..55938518 100644 --- a/cinelerra-5.0/cinelerra/formatpopup.C +++ b/cinelerra-5.0/cinelerra/formatpopup.C @@ -21,6 +21,8 @@ #include "bcsignals.h" #include "file.inc" +#include "filesystem.h" +#include "ffmpeg.h" #include "formatpopup.h" #include "language.h" #include "pluginserver.h" @@ -84,10 +86,54 @@ void FormatPopup::create_objects() FormatPopup::~FormatPopup() { - for(int i = 0; i < format_items.total; i++) delete format_items.values[i]; + format_items.remove_all_objects(); } int FormatPopup::handle_event() { return 0; } + + +FFMPEGPopup::FFMPEGPopup(ArrayList *plugindb, int x, int y) + : BC_ListBox(x, y, 50, 200, LISTBOX_TEXT, 0, 0, 0, 1, 0, 1) +{ + this->plugindb = plugindb; + set_tooltip(_("Set ffmpeg file type")); +} + +void FFMPEGPopup::create_objects() +{ + static const char *dirs[] = { "/audio", "/video", }; + for( int i=0; i<(int)(sizeof(dirs)/sizeof(dirs[0])); ++i ) { + FileSystem fs; + char option_path[BCTEXTLEN]; + FFMPEG::set_option_path(option_path, dirs[i]); + fs.update(option_path); + int total_files = fs.total_files(); + for( int j=0; jget_name(); + const char *ext = strrchr(name,'.'); + if( !ext ) ext = name; + else if( !strcmp("opts", ++ext) ) continue; + int k = ffmpeg_types.size(); + while( --k >= 0 && strcmp(ffmpeg_types[k]->get_text(), ext) ); + if( k >= 0 ) continue; + ffmpeg_types.append(new BC_ListBoxItem(ext)); + } + } + + update(&ffmpeg_types, 0, 0, 1); +} + +FFMPEGPopup::~FFMPEGPopup() +{ + ffmpeg_types.remove_all_objects(); +} + +int FFMPEGPopup::handle_event() +{ + return 0; +} + + diff --git a/cinelerra-5.0/cinelerra/formatpopup.h b/cinelerra-5.0/cinelerra/formatpopup.h index d1a275ea..d0138f18 100644 --- a/cinelerra-5.0/cinelerra/formatpopup.h +++ b/cinelerra-5.0/cinelerra/formatpopup.h @@ -43,6 +43,19 @@ public: }; +class FFMPEGPopup : public BC_ListBox +{ +public: + FFMPEGPopup(ArrayList *plugindb, int x, int y); + ~FFMPEGPopup(); + + void create_objects(); + virtual int handle_event(); + ArrayList *plugindb; + ArrayList ffmpeg_types; +}; + + diff --git a/cinelerra-5.0/cinelerra/formattools.C b/cinelerra-5.0/cinelerra/formattools.C index 0cf493fa..e5f8c9ad 100644 --- a/cinelerra-5.0/cinelerra/formattools.C +++ b/cinelerra-5.0/cinelerra/formattools.C @@ -201,12 +201,17 @@ void FormatTools::create_objects(int &init_x, window->add_subwindow(format_title = new BC_Title(x, y, _("File Format:"))); x += 90; - window->add_subwindow(format_text = new BC_TextBox(x, y, 200, 1, + window->add_subwindow(format_text = new BC_TextBox(x, y, 180, 1, File::formattostr(asset->format))); x += format_text->get_w(); //printf("FormatTools::create_objects %d %p\n", __LINE__, window); window->add_subwindow(format_button = new FormatFormat(x, y, this)); format_button->create_objects(); + x += format_button->get_w() + 5; + window->add_subwindow(ffmpeg_type = new FFMpegType(x, y, 50, 1, asset->fformat)); + x += ffmpeg_type->get_w(); + window->add_subwindow(format_ffmpeg = new FormatFFMPEG(x, y, this)); + format_ffmpeg->create_objects(); x = init_x; y += format_button->get_h() + 10; @@ -374,6 +379,14 @@ void FormatTools::update_format() else video_switch->enable(); } + if( asset->format == FILE_FFMPEG ) { + ffmpeg_type->show(); + format_ffmpeg->show(); + } + else { + ffmpeg_type->hide(); + format_ffmpeg->hide(); + } } int FormatTools::handle_event() @@ -444,7 +457,8 @@ void FormatTools::update_extension() if(need_extension) { char *ptr1 = ptr; - extension_ptr = extensions.get(0); + extension_ptr = asset->format != FILE_FFMPEG ? + extensions.get(0) : asset->fformat; while(*extension_ptr != 0 && *extension_ptr != '/') *ptr1++ = *extension_ptr++; *ptr1 = 0; @@ -809,13 +823,13 @@ FormatFormat::~FormatFormat() int FormatFormat::handle_event() { - if(get_selection(0, 0) >= 0) - { + BC_ListBoxItem *selection = get_selection(0, 0); + if( selection ) { int new_format = File::strtoformat(format->plugindb, get_selection(0, 0)->get_text()); // if(new_format != format->asset->format) { format->asset->format = new_format; - format->format_text->update(get_selection(0, 0)->get_text()); + format->format_text->update(selection->get_text()); format->update_extension(); format->close_format_windows(); format->update_format(); @@ -825,6 +839,34 @@ int FormatFormat::handle_event() } +FormatFFMPEG::FormatFFMPEG(int x, int y, FormatTools *format) + : FFMPEGPopup(format->plugindb, x, y) +{ + this->format = format; +} + +FormatFFMPEG::~FormatFFMPEG() +{ +} + +int FormatFFMPEG::handle_event() +{ + BC_ListBoxItem *selection = get_selection(0, 0); + if( selection ) { + char *text = get_selection(0, 0)->get_text(); + format->ffmpeg_type->update(text); + strcpy(format->asset->fformat, text); + strcpy(format->asset->ff_audio_options, ""); + strcpy(format->asset->ff_video_options, ""); + format->update_extension(); + format->close_format_windows(); + format->update_format(); + } + return 1; +} + + + FormatChannels::FormatChannels(int x, int y, FormatTools *format) : BC_TextBox(x, y, 100, 1, format->asset->channels) diff --git a/cinelerra-5.0/cinelerra/formattools.h b/cinelerra-5.0/cinelerra/formattools.h index 3568e8c7..7c626bf1 100644 --- a/cinelerra-5.0/cinelerra/formattools.h +++ b/cinelerra-5.0/cinelerra/formattools.h @@ -39,6 +39,8 @@ class FormatChannels; class FormatPathButton; class FormatPathText; class FormatFormat; +class FormatFFMPEG; +class FFMpegType; class FormatAudio; class FormatVideo; class FormatMultiple; @@ -97,6 +99,8 @@ public: BC_Title *format_title; FormatFormat *format_button; BC_TextBox *format_text; + FormatFFMPEG *format_ffmpeg; + FFMpegType *ffmpeg_type; BC_ITumbler *channels_tumbler; BC_Title *audio_title; @@ -152,6 +156,34 @@ public: FormatTools *format; }; +class FormatFFMPEG : public FFMPEGPopup +{ +public: + FormatFFMPEG(int x, int y, FormatTools *format); + ~FormatFFMPEG(); + + int handle_event(); + FormatTools *format; +// squash show/hide window + int show_window(int flush=1) { return 0; } + int hide_window(int flush=1) { return 0; } + int show(int flush=1) { return BC_SubWindow::show_window(flush); } + int hide(int flush=1) { return BC_SubWindow::hide_window(flush); } +}; + +class FFMpegType : public BC_TextBox +{ +public: + FFMpegType(int x, int y, int w, int h, const char *text) + : BC_TextBox(x, y, w, h, text) {} + ~FFMpegType() {} +// squash show/hide window + int show_window(int flush=1) { return 0; } + int hide_window(int flush=1) { return 0; } + int show(int flush=1) { return BC_SubWindow::show_window(flush); } + int hide(int flush=1) { return BC_SubWindow::hide_window(flush); } +}; + class FormatAParams : public BC_Button { public: diff --git a/cinelerra-5.0/cinelerra/labels.C b/cinelerra-5.0/cinelerra/labels.C index 1e5d66d3..fb371678 100644 --- a/cinelerra-5.0/cinelerra/labels.C +++ b/cinelerra-5.0/cinelerra/labels.C @@ -29,7 +29,6 @@ #include "patchbay.h" #include "recordlabel.h" #include "mainsession.h" -#include "stringfile.h" #include "theme.h" #include "timebar.h" #include diff --git a/cinelerra-5.0/cinelerra/preferencesthread.h b/cinelerra-5.0/cinelerra/preferencesthread.h index c11d9c5a..3e440a8e 100644 --- a/cinelerra-5.0/cinelerra/preferencesthread.h +++ b/cinelerra-5.0/cinelerra/preferencesthread.h @@ -98,7 +98,7 @@ public: virtual int draw_framerate(int flush) { return 0; } // update rendering rates virtual void update_rates() {} - virtual void show_window(int flush) { BC_SubWindow::show_window(flush); } + virtual int show_window(int flush) { return BC_SubWindow::show_window(flush); } PreferencesWindow *pwindow; MWindow *mwindow; diff --git a/cinelerra-5.0/cinelerra/recordprefs.C b/cinelerra-5.0/cinelerra/recordprefs.C index d671b05f..9d7ae1e7 100644 --- a/cinelerra-5.0/cinelerra/recordprefs.C +++ b/cinelerra-5.0/cinelerra/recordprefs.C @@ -235,15 +235,14 @@ void RecordPrefs::create_objects() } -void RecordPrefs::show_window(int flush) +int RecordPrefs::show_window(int flush) { PreferencesDialog::show_window(flush); if( pwindow->thread->edl->session->recording_format->format == FILE_MPEG && pwindow->thread->edl->session->vconfig_in->driver == CAPTURE_DVB && pwindow->thread->edl->session->aconfig_in->driver == AUDIO_DVB ) - realtime_toc->show_window(flush); - else - realtime_toc->hide_window(flush); + return realtime_toc->show_window(flush); + return realtime_toc->hide_window(flush); } diff --git a/cinelerra-5.0/cinelerra/recordprefs.h b/cinelerra-5.0/cinelerra/recordprefs.h index 38f8c80b..42117a54 100644 --- a/cinelerra-5.0/cinelerra/recordprefs.h +++ b/cinelerra-5.0/cinelerra/recordprefs.h @@ -36,7 +36,7 @@ public: ~RecordPrefs(); void create_objects(); - void show_window(int flush); + int show_window(int flush); FormatTools *recording_format; RecordRealtimeTOC *realtime_toc; diff --git a/cinelerra-5.0/cinelerra/render.C b/cinelerra-5.0/cinelerra/render.C index b772d530..21be5580 100644 --- a/cinelerra-5.0/cinelerra/render.C +++ b/cinelerra-5.0/cinelerra/render.C @@ -374,12 +374,12 @@ void Render::handle_close_event(int result) if(debug) printf("Render::handle_close_event %d\n", __LINE__); } -PRINT_TRACE +//PRINT_TRACE save_defaults(asset); -PRINT_TRACE +//PRINT_TRACE mwindow->save_defaults(); -PRINT_TRACE +//PRINT_TRACE if(!format_error && !result) { @@ -387,7 +387,7 @@ PRINT_TRACE if(!result) start_render(); if(debug) printf("Render::handle_close_event %d\n", __LINE__); } -PRINT_TRACE +//PRINT_TRACE } diff --git a/cinelerra-5.0/cinelerra/renderfarm.C b/cinelerra-5.0/cinelerra/renderfarm.C index ce6ea84a..fa42ba0a 100644 --- a/cinelerra-5.0/cinelerra/renderfarm.C +++ b/cinelerra-5.0/cinelerra/renderfarm.C @@ -512,8 +512,7 @@ void RenderFarmServerThread::send_preferences() server->preferences->save_defaults(&defaults); defaults.save_string(string); write_string(string); - - delete [] string; + free(string); } void RenderFarmServerThread::send_asset() @@ -532,14 +531,13 @@ void RenderFarmServerThread::send_asset() 1, 1); defaults.save_string(string1); - FileXML file; server->default_asset->write(&file, 0, 0); file.terminate_string(); write_string(string1); write_string(file.string()); - delete [] string1; + free(string1); } diff --git a/cinelerra-5.0/cinelerra/undostack.C b/cinelerra-5.0/cinelerra/undostack.C index 6012bee5..99ec7377 100644 --- a/cinelerra-5.0/cinelerra/undostack.C +++ b/cinelerra-5.0/cinelerra/undostack.C @@ -23,7 +23,6 @@ #include "bctimer.h" #include "clip.h" #include "format.inc" -#include "stringfile.h" #include "undostack.h" #include diff --git a/cinelerra-5.0/ffmpeg/audio/dvd b/cinelerra-5.0/ffmpeg/audio/dvd index d1a4f483..174a56ac 100644 --- a/cinelerra-5.0/ffmpeg/audio/dvd +++ b/cinelerra-5.0/ffmpeg/audio/dvd @@ -1,5 +1,4 @@ dvd ac3 -b 448000 maxrate 9000000 minrate 0 bufsize 1835008 diff --git a/cinelerra-5.0/ffmpeg/audio/h265 b/cinelerra-5.0/ffmpeg/audio/h265.mp4 similarity index 82% rename from cinelerra-5.0/ffmpeg/audio/h265 rename to cinelerra-5.0/ffmpeg/audio/h265.mp4 index 04f68008..6d957f36 100644 --- a/cinelerra-5.0/ffmpeg/audio/h265 +++ b/cinelerra-5.0/ffmpeg/audio/h265.mp4 @@ -1,3 +1,2 @@ mp4 libfdk_aac | aac_adtstoasc -b 192000 strict -2 diff --git a/cinelerra-5.0/ffmpeg/audio/qt_ima4 b/cinelerra-5.0/ffmpeg/audio/ima4.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_ima4 rename to cinelerra-5.0/ffmpeg/audio/ima4.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_mp3 b/cinelerra-5.0/ffmpeg/audio/mp3.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_mp3 rename to cinelerra-5.0/ffmpeg/audio/mp3.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_mp4 b/cinelerra-5.0/ffmpeg/audio/mp4.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_mp4 rename to cinelerra-5.0/ffmpeg/audio/mp4.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_mulaw b/cinelerra-5.0/ffmpeg/audio/mulaw.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_mulaw rename to cinelerra-5.0/ffmpeg/audio/mulaw.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_s16le b/cinelerra-5.0/ffmpeg/audio/s16le.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_s16le rename to cinelerra-5.0/ffmpeg/audio/s16le.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_s32le b/cinelerra-5.0/ffmpeg/audio/s32le.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_s32le rename to cinelerra-5.0/ffmpeg/audio/s32le.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_s8 b/cinelerra-5.0/ffmpeg/audio/s8.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_s8 rename to cinelerra-5.0/ffmpeg/audio/s8.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_vorbis b/cinelerra-5.0/ffmpeg/audio/vorbis.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_vorbis rename to cinelerra-5.0/ffmpeg/audio/vorbis.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_wmav1 b/cinelerra-5.0/ffmpeg/audio/wmav1.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_wmav1 rename to cinelerra-5.0/ffmpeg/audio/wmav1.qt diff --git a/cinelerra-5.0/ffmpeg/audio/qt_wmav2 b/cinelerra-5.0/ffmpeg/audio/wmav2.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/audio/qt_wmav2 rename to cinelerra-5.0/ffmpeg/audio/wmav2.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_div3 b/cinelerra-5.0/ffmpeg/video/div3.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_div3 rename to cinelerra-5.0/ffmpeg/video/div3.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_div3v2 b/cinelerra-5.0/ffmpeg/video/div3v2.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_div3v2 rename to cinelerra-5.0/ffmpeg/video/div3v2.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_div5 b/cinelerra-5.0/ffmpeg/video/div5.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_div5 rename to cinelerra-5.0/ffmpeg/video/div5.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_dnxhd b/cinelerra-5.0/ffmpeg/video/dnxhd.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_dnxhd rename to cinelerra-5.0/ffmpeg/video/dnxhd.qt diff --git a/cinelerra-5.0/ffmpeg/video/dvd b/cinelerra-5.0/ffmpeg/video/dvd index a1c138c2..a5a9ceec 100644 --- a/cinelerra-5.0/ffmpeg/video/dvd +++ b/cinelerra-5.0/ffmpeg/video/dvd @@ -3,7 +3,6 @@ s 720x480 r 30000/1001 pix_fmt yuv420p g 18 -b 6000000 maxrate 9000000 minrate 0 bufsize 1835008 diff --git a/cinelerra-5.0/ffmpeg/video/h264 b/cinelerra-5.0/ffmpeg/video/h264.mp4 similarity index 100% rename from cinelerra-5.0/ffmpeg/video/h264 rename to cinelerra-5.0/ffmpeg/video/h264.mp4 diff --git a/cinelerra-5.0/ffmpeg/video/h265 b/cinelerra-5.0/ffmpeg/video/h265.mp4 similarity index 54% rename from cinelerra-5.0/ffmpeg/video/h265 rename to cinelerra-5.0/ffmpeg/video/h265.mp4 index 7e367aa0..d045e233 100644 --- a/cinelerra-5.0/ffmpeg/video/h265 +++ b/cinelerra-5.0/ffmpeg/video/h265.mp4 @@ -1,2 +1 @@ mp4 libx265 -b 2000000 diff --git a/cinelerra-5.0/ffmpeg/video/qt_j2k b/cinelerra-5.0/ffmpeg/video/j2k.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_j2k rename to cinelerra-5.0/ffmpeg/video/j2k.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_jpeg b/cinelerra-5.0/ffmpeg/video/jpeg.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_jpeg rename to cinelerra-5.0/ffmpeg/video/jpeg.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_mjpa b/cinelerra-5.0/ffmpeg/video/mjpa.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_mjpa rename to cinelerra-5.0/ffmpeg/video/mjpa.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_mjpg b/cinelerra-5.0/ffmpeg/video/mjpg.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_mjpg rename to cinelerra-5.0/ffmpeg/video/mjpg.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_mp4 b/cinelerra-5.0/ffmpeg/video/mp4.qt similarity index 50% rename from cinelerra-5.0/ffmpeg/video/qt_mp4 rename to cinelerra-5.0/ffmpeg/video/mp4.qt index cdd28ea8..c58795f7 100644 --- a/cinelerra-5.0/ffmpeg/video/qt_mp4 +++ b/cinelerra-5.0/ffmpeg/video/mp4.qt @@ -1,2 +1 @@ mov mpeg4 -b 2000000 diff --git a/cinelerra-5.0/ffmpeg/video/mpeg b/cinelerra-5.0/ffmpeg/video/mpeg index 7f689c69..c3570c40 100644 --- a/cinelerra-5.0/ffmpeg/video/mpeg +++ b/cinelerra-5.0/ffmpeg/video/mpeg @@ -1,2 +1 @@ mpeg mpeg2video -b=4000000 diff --git a/cinelerra-5.0/ffmpeg/video/qt_png b/cinelerra-5.0/ffmpeg/video/png.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_png rename to cinelerra-5.0/ffmpeg/video/png.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_gray b/cinelerra-5.0/ffmpeg/video/raw_gray.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_gray rename to cinelerra-5.0/ffmpeg/video/raw_gray.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_rgb24 b/cinelerra-5.0/ffmpeg/video/raw_rgb24.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_rgb24 rename to cinelerra-5.0/ffmpeg/video/raw_rgb24.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_rgba b/cinelerra-5.0/ffmpeg/video/raw_rgba.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_rgba rename to cinelerra-5.0/ffmpeg/video/raw_rgba.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_uyvy422 b/cinelerra-5.0/ffmpeg/video/raw_uyvy422.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_uyvy422 rename to cinelerra-5.0/ffmpeg/video/raw_uyvy422.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yuv411p b/cinelerra-5.0/ffmpeg/video/raw_yuv411p.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yuv411p rename to cinelerra-5.0/ffmpeg/video/raw_yuv411p.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yuv420p b/cinelerra-5.0/ffmpeg/video/raw_yuv420p.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yuv420p rename to cinelerra-5.0/ffmpeg/video/raw_yuv420p.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yuv422p b/cinelerra-5.0/ffmpeg/video/raw_yuv422p.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yuv422p rename to cinelerra-5.0/ffmpeg/video/raw_yuv422p.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yuv440p b/cinelerra-5.0/ffmpeg/video/raw_yuv440p.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yuv440p rename to cinelerra-5.0/ffmpeg/video/raw_yuv440p.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yuv444p b/cinelerra-5.0/ffmpeg/video/raw_yuv444p.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yuv444p rename to cinelerra-5.0/ffmpeg/video/raw_yuv444p.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yuyv422 b/cinelerra-5.0/ffmpeg/video/raw_yuyv422.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yuyv422 rename to cinelerra-5.0/ffmpeg/video/raw_yuyv422.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_raw_yvyu422 b/cinelerra-5.0/ffmpeg/video/raw_yvyu422.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_raw_yvyu422 rename to cinelerra-5.0/ffmpeg/video/raw_yvyu422.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_rle b/cinelerra-5.0/ffmpeg/video/rle.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_rle rename to cinelerra-5.0/ffmpeg/video/rle.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_rv20 b/cinelerra-5.0/ffmpeg/video/rv20.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_rv20 rename to cinelerra-5.0/ffmpeg/video/rv20.qt diff --git a/cinelerra-5.0/ffmpeg/video/qt_svq1 b/cinelerra-5.0/ffmpeg/video/svq1.qt similarity index 100% rename from cinelerra-5.0/ffmpeg/video/qt_svq1 rename to cinelerra-5.0/ffmpeg/video/svq1.qt diff --git a/cinelerra-5.0/global_config b/cinelerra-5.0/global_config index 4acf74f9..37a08dde 100644 --- a/cinelerra-5.0/global_config +++ b/cinelerra-5.0/global_config @@ -6,7 +6,7 @@ HAVE_ESOUND := y HAVE_AVIFILE := n HAVE_FIREWIRE := y HAVE_OSS := y -STATIC_LIBRARIES := y +STATIC_LIBRARIES := n OBJDIR := $(shell uname --machine) diff --git a/cinelerra-5.0/guicast/Makefile b/cinelerra-5.0/guicast/Makefile index 1dd5dfc5..f7c5ac8b 100644 --- a/cinelerra-5.0/guicast/Makefile +++ b/cinelerra-5.0/guicast/Makefile @@ -80,7 +80,6 @@ OBJS = \ $(OBJDIR)/mutex.o \ $(OBJDIR)/rotateframe.o \ $(OBJDIR)/sema.o \ - $(OBJDIR)/stringfile.o \ $(OBJDIR)/thread.o \ $(OBJDIR)/testobject.o \ $(OBJDIR)/bctimer.o \ diff --git a/cinelerra-5.0/guicast/bchash.C b/cinelerra-5.0/guicast/bchash.C index 835f3db3..573c0044 100644 --- a/cinelerra-5.0/guicast/bchash.C +++ b/cinelerra-5.0/guicast/bchash.C @@ -27,7 +27,6 @@ #include "bcsignals.h" #include "filesystem.h" #include "format.inc" -#include "stringfile.h" BC_Hash::BC_Hash() { @@ -86,60 +85,103 @@ void BC_Hash::reallocate_table(int new_total) } } -int BC_Hash::load() -{ - StringFile stringfile(filename); - load_stringfile(&stringfile); - return 0; -} - -void BC_Hash::load_stringfile(StringFile *file) +int BC_Hash::load_file(FILE *fp) { - char arg1[1024], arg2[1024]; + char line[4096]; + int done = 0, ch = -1; total = 0; - while(file->get_pointer() < file->get_length()) - { - file->readline(arg1, arg2); + + while( !done ) { + char *bp = line, *ep = bp + sizeof(line); + if( !fgets(bp, ep-bp, fp) ) break; + // skip ws (indent) + while( bp < ep && *bp == ' ' ) ++bp; + if( bp >= ep || !*bp || *bp == '\n' ) continue; + char *title = bp; + // span to ws + while( bp < ep && *bp && *bp != ' ' && *bp != '\n' ) ++bp; + if( bp >= ep || title == bp ) continue; + int title_len = bp - title; + // skip blank seperator + if( *bp++ != ' ' ) continue; reallocate_table(total + 1); - names[total] = new char[strlen(arg1) + 1]; - values[total] = new char[strlen(arg2) + 1]; - strcpy(names[total], arg1); - strcpy(values[total], arg2); + char *tp = new char[title_len + 1]; + names[total] = tp; + while( --title_len >= 0 ) *tp++ = *title++; + *tp = 0; + // accumulate value (+ continued lines) + char *value = bp; + while( bp < ep && !done ) { + while( bp < ep && *bp && *bp != '\n' ) ++bp; + if( bp >= ep || !*bp ) break; + if( (ch=fgetc(fp)) < 0 ) break; + if( ch != '+' ) { ungetc(ch, fp); break; } + *bp++ = '\n'; + done = !fgets(bp, ep-bp, fp); + } + int value_len = bp - value; + char *vp = new char[value_len + 1]; + values[total] = vp; + while( --value_len >= 0 ) *vp++ = *value++; + *vp = 0; total++; } + return 0; } -void BC_Hash::save_stringfile(StringFile *file) +int BC_Hash::load() { - for(int i = 0; i < total; i++) - { - file->writeline(names[i], values[i], 0); - } + FILE *fp = fopen(filename, "r"); + if( !fp ) return 1; + int ret = load_file(fp); + fclose(fp); + return ret; } -int BC_Hash::save() +int BC_Hash::save_file(FILE *fp) { - StringFile stringfile; - save_stringfile(&stringfile); - stringfile.write_to_file(filename); + for(int i = 0; i < total; i++) { + fputs(names[i], fp); + char *vp = values[i]; + char *bp = vp; + fputc(' ',fp); + while( (vp=strchr(vp, '\n')) ) { + while( bp < vp ) fputc(*bp++,fp); + fputc('\n',fp); fputc('+',fp); + ++bp; ++vp; + } + while( *bp ) fputc(*bp++,fp); + fputc('\n', fp); + } return 0; } -int BC_Hash::load_string(const char *string) +int BC_Hash::save() +{ + FILE *fp = fopen(filename,"w"); + if( !fp ) return 1; + int ret = save_file(fp); + fclose(fp); + return ret; +} + +int BC_Hash::load_string(const char *bfr) { - StringFile stringfile; - stringfile.read_from_string(string); - load_stringfile(&stringfile); - return 0; + FILE *fp = fmemopen((void*)bfr, strlen(bfr), "r"); + if( !fp ) return 1; + int ret = load_file(fp); + fclose(fp); + return ret; } -int BC_Hash::save_string(char* &string) +int BC_Hash::save_string(char *&bfr) { - StringFile stringfile; - save_stringfile(&stringfile); - string = new char[stringfile.get_length() + 1]; - memcpy(string, stringfile.string, stringfile.get_length() + 1); - return 0; + size_t bsz = 0; + FILE *fp = open_memstream(&bfr, &bsz); + if( !fp ) return 1; + int ret = save_file(fp); + fclose(fp); + return ret; } diff --git a/cinelerra-5.0/guicast/bchash.h b/cinelerra-5.0/guicast/bchash.h index a6ebde0f..a694f424 100644 --- a/cinelerra-5.0/guicast/bchash.h +++ b/cinelerra-5.0/guicast/bchash.h @@ -29,7 +29,6 @@ #include "bcwindowbase.inc" #include "bctextbox.inc" -#include "stringfile.inc" #include "units.h" @@ -40,12 +39,12 @@ public: BC_Hash(const char *filename); virtual ~BC_Hash(); + int load_file(FILE *fp); int load(); // load from disk file + int save_file(FILE *fp); int save(); // save to disk file int load_string(const char *string); // load from string int save_string(char* &string); // save to new string - void save_stringfile(StringFile *file); - void load_stringfile(StringFile *file); int update(const char *name, double value); // update a value if it exists int update(const char *name, float value); // update a value if it exists int update(const char *name, int32_t value); // update a value if it exists diff --git a/cinelerra-5.0/guicast/bctextbox.C b/cinelerra-5.0/guicast/bctextbox.C index d3f779bb..cab68664 100644 --- a/cinelerra-5.0/guicast/bctextbox.C +++ b/cinelerra-5.0/guicast/bctextbox.C @@ -2918,6 +2918,25 @@ int BC_TumbleTextBox::get_h() return textbox->get_h(); } +void BC_TumbleTextBox::disable() +{ + if( !get_enabled() ) return; + tumbler->hide_window(0); + return textbox->disable(); +} + +void BC_TumbleTextBox::enable() +{ + if( get_enabled() ) return; + tumbler->show_window(0); + return textbox->enable(); +} + +int BC_TumbleTextBox::get_enabled() +{ + return textbox->get_enabled(); +} + int BC_TumbleTextBox::handle_event() { return 1; diff --git a/cinelerra-5.0/guicast/bctextbox.h b/cinelerra-5.0/guicast/bctextbox.h index 847fea58..713dcf0d 100644 --- a/cinelerra-5.0/guicast/bctextbox.h +++ b/cinelerra-5.0/guicast/bctextbox.h @@ -386,6 +386,9 @@ public: int get_y(); int get_w(); int get_h(); + void disable(); + void enable(); + int get_enabled(); void reposition_window(int x, int y); void set_boundaries(int64_t min, int64_t max); void set_boundaries(float min, float max); diff --git a/cinelerra-5.0/guicast/bcwindowbase.h b/cinelerra-5.0/guicast/bcwindowbase.h index 332c32d7..c463820f 100644 --- a/cinelerra-5.0/guicast/bcwindowbase.h +++ b/cinelerra-5.0/guicast/bcwindowbase.h @@ -218,8 +218,8 @@ public: int get_color(int64_t color); // return the currently selected color int64_t get_color(); - int show_window(int flush = 1); - int hide_window(int flush = 1); + virtual int show_window(int flush = 1); + virtual int hide_window(int flush = 1); int get_hidden(); int get_video_on(); // Shouldn't deference a pointer to delete a window if a parent is @@ -278,7 +278,6 @@ public: virtual int get_h(); virtual int get_x(); virtual int get_y(); - virtual int reposition_widgets(){ printf("foo1"); return 0; } int get_root_w(int lock_display); int get_root_h(int lock_display); XineramaScreenInfo *get_xinerama_info(int screen); diff --git a/cinelerra-5.0/guicast/stringfile.C b/cinelerra-5.0/guicast/stringfile.C deleted file mode 100644 index ea553cb6..00000000 --- a/cinelerra-5.0/guicast/stringfile.C +++ /dev/null @@ -1,269 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "stringfile.h" -#include -#include -#include - -StringFile::StringFile(size_t length) -{ - pointer = 0; - if(length == 0) - { - this->length = 100000; - } - else - { - this->length = length; - } - string = new char[this->length + 1]; - available = this->length; -} - -StringFile::StringFile(const char *filename) -{ - FILE *in = fopen(filename, "rb"); - if( in ) - { - fseek(in, 0, SEEK_END); - length = ftell(in); - available = length; - fseek(in, 0, SEEK_SET); - string = new char[length + 5]; - - (void)fread(string, length, 1, in); - for(int i = 0; i < 5; i++) string[length + i] = 0; - fclose(in); - } - else - { - //printf("File not found: %s\n", filename); - length = 0; - available = 1; - string = new char[1]; - string[0] = 0; - } - - pointer = 0; -} - -StringFile::~StringFile() -{ - delete [] string; -} - -int StringFile::write_to_file(const char *filename) -{ - FILE *out = fopen(filename, "wb"); - if( out ) - { - fwrite(string, pointer, 1, out); - } - else - { -// printf("Couldn't open %s for writing.\n", filename); - return 1; - } - fclose(out); - return 0; -} - -int StringFile::read_from_string(const char *string) -{ - int i; - - delete [] this->string; - length = strlen(string); - available = length; - this->string = new char[length + 5]; - strcpy(this->string, string); - for(i = 0; i < 5; i++) this->string[length + i] = 0; - return 0; -} - -size_t StringFile::get_length() -{ - return strlen(string); -} - -size_t StringFile::get_pointer() -{ - return pointer; -} - -int StringFile::readline(char *arg2) -{ - readline(string1, arg2); - return 0; -} - -int StringFile::readline() -{ - readline(string1, string1); - return 0; -} - -int StringFile::readline(float *arg2) -{ - readline(string1, arg2); - return 0; -} - -int StringFile::readline(int *arg2) -{ - readline(string1, arg2); - return 0; -} - -int StringFile::readline(long *arg2) -{ - readline(string1, arg2); - return 0; -} - -int StringFile::readline(Freq *arg2) -{ - readline(string1, &(arg2->freq)); - return 0; -} - -int StringFile::readline(char *arg1, char *arg2) -{ - int i, len, max; - len = 0; max = 1024; - - while(string[pointer] == ' ') pointer++; // skip indent - arg1[0] = 0; arg2[0] = 0; - - for(i = 0; string[pointer] != ' ' && string[pointer] != '\n' && len < max; i++, pointer++) - { // get title - arg1[i] = string[pointer]; - len++; - } - arg1[i] = 0; - - if(string[pointer] != '\n') - { // get value - pointer++; // skip space - for(i = 0; string[pointer] != '\n' && len < max; i++, pointer++) - { - arg2[i] = string[pointer]; - len++; - } - arg2[i] = 0; - } - pointer++; // skip eoln - return 0; -} - -int StringFile::backupline() -{ - while(string[pointer] != 10 && pointer > 0) - { - pointer--; // first eoln - } - if(string[pointer] == 10) pointer--; // skip eoln - - while(string[pointer] != 10 && pointer > 0) - { - pointer--; // second eoln - } - - if(string[pointer] == 10) pointer++; // skip eoln - return 0; -} - -int StringFile::readline(char *arg1, long *arg2) -{ - readline(arg1, string1); - *arg2 = atol(string1); - return 0; -} - -int StringFile::readline(char *arg1, int *arg2) -{ - long arg; - readline(arg1, &arg); - *arg2 = (int)arg; - return 0; -} - -int StringFile::readline(char *arg1, float *arg2) -{ - readline(arg1, string1); - *arg2 = atof(string1); - return 0; -} - -int StringFile::writeline(char *arg1, int indent) -{ -// reallocate the string - int len = strlen(arg1); - if( (len + indent) > (int)(available - pointer) ) { - char *newstring = new char[available * 2]; - strcpy(newstring, string); - delete string; - available *= 2; - length *= 2; - string = newstring; - } - - for(int i = 0; i < indent; i++) string[pointer++] = ' '; - strcpy(&string[pointer], arg1); - pointer += len; - return 0; -} - -int StringFile::writeline(char *arg1, char *arg2, int indent) -{ - sprintf(string1, "%s %s\n", arg1, arg2); - writeline(string1, indent); - return 0; -} - -int StringFile::writeline(char *arg1, long arg2, int indent) -{ - sprintf(string1, "%s %ld\n", arg1, arg2); - writeline(string1, indent); - return 0; -} - -int StringFile::writeline(char *arg1, int arg2, int indent) -{ - sprintf(string1, "%s %d\n", arg1, arg2); - writeline(string1, indent); - return 0; -} - -int StringFile::writeline(char *arg1, float arg2, int indent) -{ - sprintf(string1, "%s %f\n", arg1, arg2); - writeline(string1, indent); - return 0; -} - -int StringFile::writeline(char *arg1, Freq arg2, int indent) -{ - sprintf(string1, "%s %d\n", arg1, arg2.freq); - writeline(string1, indent); - return 0; -} diff --git a/cinelerra-5.0/guicast/stringfile.h b/cinelerra-5.0/guicast/stringfile.h deleted file mode 100644 index 47320ac8..00000000 --- a/cinelerra-5.0/guicast/stringfile.h +++ /dev/null @@ -1,66 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef STRINGFILE_H -#define STRINGFILE_H - - -// Line based reading and writing from text files or arrays. -// Use for extracting databases. -#include "units.h" - -class StringFile -{ -public: - StringFile(size_t length = 0); - StringFile(const char *filename); - virtual ~StringFile(); - - int readline(); // read next line from string - int readline(char *arg2); // read next line from string - int readline(long *arg2); // read next line from string - int readline(int *arg2); // read next line from string - int readline(float *arg2); // read next line from string - int readline(Freq *arg2); // read next line from string - - int readline(char *arg1, char *arg2); // read next line from string - int readline(char *arg1, long *arg2); // read next line from string - int readline(char *arg1, int *arg2); // read next line from string - int readline(char *arg1, float *arg2); // read next line from string - int writeline(char *arg1, int indent); // write next line to string - int writeline(char *arg1, char *arg2, int indent); // write next line to string - int writeline(char *arg1, long arg2, int indent); // write next line to string - int writeline(char *arg1, int arg2, int indent); // write next line to string - int writeline(char *arg1, float arg2, int indent); // write next line to string - int writeline(char *arg1, Freq arg2, int indent); // write next line to string - int backupline(); // move back one line - - size_t get_length(); - size_t get_pointer(); - int write_to_file(const char *filename); - int read_from_string(const char *string); - - char *string; - size_t pointer, length, available; - char string1[1024]; // general purpose strings -}; - -#endif diff --git a/cinelerra-5.0/guicast/stringfile.inc b/cinelerra-5.0/guicast/stringfile.inc deleted file mode 100644 index bf567b17..00000000 --- a/cinelerra-5.0/guicast/stringfile.inc +++ /dev/null @@ -1,27 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2008 Adam Williams - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef STRINGFILE_INC -#define STRINGFILE_INC - -class StringFile; - -#endif -- 2.26.2