From: Good Guy Date: Fri, 28 Feb 2020 15:34:55 +0000 (-0700) Subject: locale expanders txt, libpulse prereq, debian shlibs deps, X-Git-Tag: 2020-02~2 X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=commitdiff_plain;h=86c9537e0540010ff43b16feb4cd7de98409eba1 locale expanders txt, libpulse prereq, debian shlibs deps, add fileogg back, asset xml readin tweaks, add ffmpeg clrspc to probe, add view ffmpeg format, add with/out ogg configure opt, upgrade libs dav1d, giflib, lv2, libjpeg-turbo, nvcodec hdrs, libogg, libwebp, opengjpeg, opus, tiff, twolame, x264, x265, tweak get_pop_cursor, with-git-ffmpeg patch tweaks --- diff --git a/cinelerra-5.1/Makefile.am b/cinelerra-5.1/Makefile.am index 64e1e8df..bd5c0f84 100644 --- a/cinelerra-5.1/Makefile.am +++ b/cinelerra-5.1/Makefile.am @@ -32,7 +32,7 @@ export mkinstalldirs install_sh inst_sh # install to bin bin_install: install-recursive - cp -a COPYING README models Cinelerra_factory expanders.txt \ + cp -a COPYING README models Cinelerra_factory expanders.* \ shuttlerc ffmpeg msg info tips lv2_blacklist.txt bin/. sed -e 's/\/$(WANT_CIN)/g' < image/cin.desktop \ > "bin/applications/$(WANT_CIN).desktop" @@ -52,7 +52,7 @@ bin_uninstall: sys_install: $(CIN_INSTALLS) cd bin; $(inst_sh) "$(DESTDIR)$(bindir)" "$(WANT_CIN)" bdwrite cd bin; $(inst_sh) "$(DESTDIR)$(datadir)/$(WANT_CIN)" \ - COPYING README models Cinelerra_factory expanders.txt \ + COPYING README models Cinelerra_factory expanders.* \ shuttlerc ffmpeg msg info tips doc cd bin/locale; $(inst_sh) "$(DESTDIR)$(localedir)" . cd bin/plugins; $(inst_sh) "$(DESTDIR)$(WANT_PLUGIN_DIR)" . diff --git a/cinelerra-5.1/blds/PKGBUILD b/cinelerra-5.1/blds/PKGBUILD index 30c011b1..ea6a2992 100644 --- a/cinelerra-5.1/blds/PKGBUILD +++ b/cinelerra-5.1/blds/PKGBUILD @@ -15,7 +15,7 @@ DEPENDS=( 'alsa-lib' 'atk' 'bzip2' 'cairo' 'expat' 'fftw' 'flac' 'libvpx' 'libx11' 'libxau' 'libxcb' 'libxcomposite' 'libxcursor' 'libxdamage' 'libxdmcp' 'libxext' 'libxfixes' 'libxft' 'libxi' 'libxinerama' 'libxrandr' 'libxrender' 'libxv' 'numactl' 'opus' - 'pango' 'pcre' 'pixman' 'xz' 'zlib' 'xorg-server' + 'pango' 'pcre' 'pixman' 'xz' 'zlib' 'xorg-server' 'libpulse' 'xorg-fonts-misc' 'ttf-dejavu' 'inkscape' 'dvdauthor' 'udftools' ) makedepends=( 'autoconf' 'automake' 'yasm' 'nasm' 'cmake' 'libtool' diff --git a/cinelerra-5.1/blds/bld_prepare.sh b/cinelerra-5.1/blds/bld_prepare.sh index a34f123d..3c34ff6a 100755 --- a/cinelerra-5.1/blds/bld_prepare.sh +++ b/cinelerra-5.1/blds/bld_prepare.sh @@ -27,7 +27,7 @@ case "$dir" in libsndfile-devel libtheora-devel linux-firmware ivtv-firmware \ libvorbis-devel texinfo xz-devel lzma-devel cmake udftools git \ autoconf automake rpm-build jbigkit-devel libvdpau-devel libva-devel \ - alsa-lib-devel gtk2-devel + alsa-lib-devel gtk2-devel pulseaudio-libs-devel yasm=yasm-1.3.0-3.fc24.x86_64.rpm release=http://archives.fedoraproject.org/pub/fedora/linux/releases/24 url=$release/Everything/x86_64/os/Packages/y/$yasm @@ -54,7 +54,8 @@ case "$dir" in ivtv-firmware libvorbis-devel texinfo xz-devel cmake git \ ctags patch gcc-c++ perl-XML-XPath libtiff-devel python dvdauthor \ gettext-devel inkscape udftools autoconf automake numactl-devel \ - jbigkit-devel libvdpau-devel libva-devel gtk2-devel mesa-vdpau-drivers + jbigkit-devel libvdpau-devel libva-devel gtk2-devel mesa-vdpau-drivers \ + pulseaudio-libs-devel ;; "suse" | "leap" | "tumbleweed") zypper -n install nasm gcc gcc-c++ zlib-devel texinfo libpng16-devel \ @@ -66,7 +67,7 @@ case "$dir" in ilmbase-devel fftw3-devel libsndfile-devel libtheora-devel flac-devel \ libtiff-devel inkscape cmake patch libnuma-devel lzma-devel udftools git \ yasm autoconf automake rpm-build libjbig-devel libvdpau-devel libva-devel \ - gtk2-devel libusb-1_0-devel + gtk2-devel libusb-1_0-devel libpulse-devel if [ ! -f /usr/lib64/libtermcap.so ]; then ln -s libtermcap.so.2 /usr/lib64/libtermcap.so fi @@ -80,7 +81,7 @@ case "$dir" in fonts-dejavu libopenexr-dev festival libfftw3-dev gdb libusb-1.0-0-dev \ libdc1394-22-dev libflac-dev libjbig-dev libvdpau-dev libva-dev \ inkscape libsndfile1-dev libtheora-dev cmake udftools libxml2-utils git \ - autoconf automake debhelper libgtk2.0-dev + autoconf automake debhelper libgtk2.0-dev libpulse-dev ;; #"ub16-10") # apt-get -y install libx264-dev libx265-dev libvpx-dev libmjpegtools-dev @@ -92,7 +93,8 @@ case "$dir" in fonts-dejavu libopenexr-dev libavc1394-dev festival-dev fftw3-dev gdb \ libdc1394-22-dev libiec61883-dev libflac-dev libjbig-dev libusb-1.0-0-dev \ libvdpau-dev libva-dev libsndfile1-dev libtheora-dev cmake udftools \ - libxml2-utils git inkscape autoconf automake debhelper libgtk2.0-dev + libxml2-utils git inkscape autoconf automake debhelper libgtk2.0-dev \ + libpulse-dev ;; *) echo "unknown os: $dir" diff --git a/cinelerra-5.1/blds/cinelerra.spec b/cinelerra-5.1/blds/cinelerra.spec index 93078964..21d9f835 100644 --- a/cinelerra-5.1/blds/cinelerra.spec +++ b/cinelerra-5.1/blds/cinelerra.spec @@ -52,6 +52,7 @@ BuildRequires: texinfo BuildRequires: gtk2-devel BuildRequires: libva-devel BuildRequires: libvdpau-devel +BuildRequires: pulseaudio-libs-devel %{?rhat:BuildRequires: alsa-lib-devel} %{?rhat:BuildRequires: bzip2-devel} %{?rhat:BuildRequires: xorg-x11-fonts-cyrillic} diff --git a/cinelerra-5.1/blds/debian/control b/cinelerra-5.1/blds/debian/control index a47f3f8d..b8d50577 100644 --- a/cinelerra-5.1/blds/debian/control +++ b/cinelerra-5.1/blds/debian/control @@ -12,10 +12,10 @@ Build-Depends: libpng-dev, libtool, libusb-1.0-0-dev, libva-dev, libvdpau-dev, libxft-dev, libxinerama-dev, libxml2-utils, libxv-dev, libz-dev, linux-firmware, nasm, texinfo, ttf-bitstream-vera, - udftools, xfonts-100dpi, xfonts-75dpi, yasm + udftools, xfonts-100dpi, xfonts-75dpi, yasm, libpulse-dev Package: cin -Depends: ${misc:Depends} +Depends: ${misc:Depends} ${shlibs:Depends} Description: Multimedia editing and construction Architecture: any diff --git a/cinelerra-5.1/blds/debian/rules b/cinelerra-5.1/blds/debian/rules index c95b0a03..58dd9572 100755 --- a/cinelerra-5.1/blds/debian/rules +++ b/cinelerra-5.1/blds/debian/rules @@ -42,6 +42,8 @@ binary-arch: build install dh_icons -a dh_fixperms -a dh_installdeb -a + dh_makeshlibs + dh_shlibdeps dh_gencontrol dh_builddeb -p cin diff --git a/cinelerra-5.1/cinelerra/Makefile b/cinelerra-5.1/cinelerra/Makefile index a22a21ae..d0a8f1ad 100644 --- a/cinelerra-5.1/cinelerra/Makefile +++ b/cinelerra-5.1/cinelerra/Makefile @@ -145,6 +145,7 @@ OBJS := $(OVERLAYS) \ $(OBJDIR)/filejpeg.o \ $(OBJDIR)/filelist.o \ $(OBJDIR)/file.o \ + $(OBJDIR)/fileogg.o \ $(OBJDIR)/filepng.o \ $(OBJDIR)/fileppm.o \ $(OBJDIR)/fileref.o \ @@ -153,6 +154,7 @@ OBJS := $(OVERLAYS) \ $(OBJDIR)/filetga.o \ $(OBJDIR)/filethread.o \ $(OBJDIR)/filetiff.o \ + $(OBJDIR)/filevorbis.o \ $(OBJDIR)/filexml.o \ $(OBJDIR)/floatauto.o \ $(OBJDIR)/floatautos.o \ @@ -550,7 +552,8 @@ clean: rm -f shuttle_keys.h tags: - ctags -R -h default --langmap=c:+.inc . ../guicast/ ../libzmpeg3 ../plugins ../thirdparty/ffmpeg-* + ctags -R -h default --langmap=c:+.inc . ../guicast/ ../libzmpeg3 ../plugins ../thirdparty/ffmpeg-* \ + ../thirdparty/libtheora* ../thirdparty/libvorbis* ../thirdparty/libogg* $(OBJDIR)/fileexr.o: BFLAGS:= -Wno-deprecated $(OBJDIR)/sha1.o: BFLAGS:= -O3 diff --git a/cinelerra-5.1/cinelerra/asset.C b/cinelerra-5.1/cinelerra/asset.C index 48dfca3c..fd6e97e4 100644 --- a/cinelerra-5.1/cinelerra/asset.C +++ b/cinelerra-5.1/cinelerra/asset.C @@ -84,6 +84,7 @@ int Asset::init_values() strcpy(acodec, ""); strcpy(fformat,"mp4"); + ff_format_options[0] = 0; ff_audio_options[0] = 0; ff_sample_format[0] = 0; ff_audio_bitrate = 0; @@ -92,6 +93,8 @@ int Asset::init_values() ff_pixel_format[0] = 0; ff_video_bitrate = 0; ff_video_quality = -1; + ff_color_space = -1; + ff_color_range = -1; jpeg_quality = 80; aspect_ratio = -1; @@ -101,6 +104,18 @@ int Asset::init_values() ampeg_bitrate = 256; ampeg_derivative = 3; + vorbis_vbr = 0; + vorbis_min_bitrate = -1; + vorbis_bitrate = 128000; + vorbis_max_bitrate = -1; + + theora_fix_bitrate = 1; + theora_bitrate = 860000; + theora_quality = 16; + theora_sharpness = 2; + theora_keyframe_frequency = 64; + theora_keyframe_force_frequency = 64; + // mpeg parameters vmpeg_iframe_distance = 45; vmpeg_pframe_distance = 0; @@ -187,6 +202,7 @@ void Asset::copy_format(Asset *asset, int do_index) audio_data = asset->audio_data; format = asset->format; strcpy(fformat, asset->fformat); + strcpy(ff_format_options, asset->ff_format_options); channels = asset->channels; sample_rate = asset->sample_rate; bits = asset->bits; @@ -219,6 +235,8 @@ void Asset::copy_format(Asset *asset, int do_index) strcpy(ff_pixel_format, asset->ff_pixel_format); ff_video_bitrate = asset->ff_video_bitrate; ff_video_quality = asset->ff_video_quality; + ff_color_space = asset->ff_color_space; + ff_color_range = asset->ff_color_range; this->audio_length = asset->audio_length; this->video_length = asset->video_length; @@ -227,6 +245,21 @@ void Asset::copy_format(Asset *asset, int do_index) ampeg_bitrate = asset->ampeg_bitrate; ampeg_derivative = asset->ampeg_derivative; + + vorbis_vbr = asset->vorbis_vbr; + vorbis_min_bitrate = asset->vorbis_min_bitrate; + vorbis_bitrate = asset->vorbis_bitrate; + vorbis_max_bitrate = asset->vorbis_max_bitrate; + + + theora_fix_bitrate = asset->theora_fix_bitrate; + theora_bitrate = asset->theora_bitrate; + theora_quality = asset->theora_quality; + theora_sharpness = asset->theora_sharpness; + theora_keyframe_frequency = asset->theora_keyframe_frequency; + theora_keyframe_force_frequency = asset->theora_keyframe_frequency; + + jpeg_quality = asset->jpeg_quality; // mpeg parameters @@ -314,11 +347,12 @@ int Asset::equivalent(Asset &asset, int test_audio, int test_video, EDL *edl) delete [] out_path; } - if(result && format == FILE_FFMPEG && strcmp(fformat, asset.fformat) ) + if( result && format == FILE_FFMPEG && + (strcmp(fformat, asset.fformat) || + strcmp(ff_format_options, asset.ff_format_options)) ) result = 0; - if(test_audio && result) - { + if(test_audio && result) { result = (channels == asset.channels && sample_rate == asset.sample_rate && bits == asset.bits && @@ -327,7 +361,7 @@ int Asset::equivalent(Asset &asset, int test_audio, int test_video, EDL *edl) header == asset.header && dither == asset.dither && !strcmp(acodec, asset.acodec)); - if(result && format == FILE_FFMPEG) + if( result && format == FILE_FFMPEG ) result = !strcmp(ff_audio_options, asset.ff_audio_options) && !strcmp(ff_sample_format, asset.ff_sample_format) && ff_audio_bitrate == asset.ff_audio_bitrate && @@ -335,8 +369,7 @@ int Asset::equivalent(Asset &asset, int test_audio, int test_video, EDL *edl) } - if(test_video && result) - { + if(test_video && result) { result = (layers == asset.layers && program == asset.program && frame_rate == asset.frame_rate && @@ -346,11 +379,13 @@ int Asset::equivalent(Asset &asset, int test_audio, int test_video, EDL *edl) !strcmp(vcodec, asset.vcodec) && mov_sphere == asset.mov_sphere && jpeg_sphere == asset.jpeg_sphere); - if(result && format == FILE_FFMPEG) + if( result && format == FILE_FFMPEG ) result = !strcmp(ff_video_options, asset.ff_video_options) && !strcmp(ff_pixel_format, asset.ff_pixel_format) && ff_video_bitrate == asset.ff_video_bitrate && - ff_video_quality == asset.ff_video_quality; + ff_video_quality == asset.ff_video_quality && + ff_color_space == asset.ff_color_space && + ff_color_range == asset.ff_color_range; } return result; @@ -364,88 +399,38 @@ int Asset::test_path(const char *path) return 0; } -int Asset::read(FileXML *file, - int expand_relative) +int Asset::read(FileXML *file, int expand_relative) { int result = 0; - // Check for relative path. - if(expand_relative) - { + if( expand_relative ) { char new_path[BCTEXTLEN]; char asset_directory[BCTEXTLEN]; char input_directory[BCTEXTLEN]; FileSystem fs; - strcpy(new_path, path); fs.set_current_dir(""); - fs.extract_dir(asset_directory, path); - // No path in asset. // Take path of XML file. - if(!asset_directory[0]) - { + if( !asset_directory[0] ) { fs.extract_dir(input_directory, file->filename); - // Input file has a path if(input_directory[0]) - { fs.join_names(path, input_directory, new_path); - } } } - - while(!result) - { - result = file->read_tag(); - if(!result) - { - if(file->tag.title_is("/ASSET")) - { - result = 1; - } - else - if(file->tag.title_is("AUDIO")) - { - read_audio(file); - } - else - if(file->tag.title_is("AUDIO_OMIT")) - { - read_audio(file); - } - else - if(file->tag.title_is("FORMAT")) - { - const char *string = file->tag.get_property("TYPE"); - 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")) - { - folder_no = file->tag.get_property("NUMBER", AW_MEDIA_FOLDER); - } - else - if(file->tag.title_is("VIDEO")) - { - read_video(file); - } - else - if(file->tag.title_is("VIDEO_OMIT")) - { - read_video(file); - } - else - if(file->tag.title_is("INDEX")) - { - read_index(file); - } - } + while( !(result=file->read_tag()) ) { + if( file->tag.title_is("/ASSET") ) break; + if( file->tag.title_is("AUDIO") ) { read_audio(file); continue; } + if( file->tag.title_is("AUDIO_OMIT") ) { read_audio(file); continue; } + if( file->tag.title_is("FORMAT") ) { read_format(file); continue; } + if( file->tag.title_is("VIDEO") ) { read_video(file); continue; } + if( file->tag.title_is("VIDEO_OMIT") ) { read_video(file); continue; } + if( file->tag.title_is("INDEX") ) { read_index(file); continue; } + if( file->tag.title_is("FOLDER") ) + folder_no = file->tag.get_property("NUMBER", AW_MEDIA_FOLDER); } boundaries(); @@ -500,6 +485,18 @@ int Asset::read_video(FileXML *file) return 0; } +int Asset::read_format(FileXML *file) +{ + const char *string = file->tag.get_property("TYPE"); + format = File::strtoformat(string); + use_header = file->tag.get_property("USE_HEADER", use_header); + fformat[0] = 0; + file->tag.get_property("FFORMAT", fformat); + ff_format_options[0] = 0; + file->tag.get_property("FF_FORMAT_OPTIONS", ff_format_options); + return 0; +} + int Asset::read_index(FileXML *file) { index_state->read_xml(file, channels); @@ -554,6 +551,7 @@ int Asset::write(FileXML *file, File::formattostr(format)); file->tag.set_property("USE_HEADER", use_header); file->tag.set_property("FFORMAT", fformat); + file->tag.set_property("FF_FORMAT_OPTIONS", ff_format_options); file->append_tag(); file->tag.set_title("/FORMAT"); @@ -603,7 +601,14 @@ int Asset::write_audio(FileXML *file) // file->tag.set_property("AMPEG_BITRATE", ampeg_bitrate); // file->tag.set_property("AMPEG_DERIVATIVE", ampeg_derivative); +// +// file->tag.set_property("VORBIS_VBR", vorbis_vbr); +// file->tag.set_property("VORBIS_MIN_BITRATE", vorbis_min_bitrate); +// file->tag.set_property("VORBIS_BITRATE", vorbis_bitrate); +// file->tag.set_property("VORBIS_MAX_BITRATE", vorbis_max_bitrate); +// // file->tag.set_property("MP3_BITRATE", mp3_bitrate); +// @@ -703,6 +708,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); + GET_DEFAULT("FF_FORMAT_OPTIONS", ff_format_options); } if(do_data_types) @@ -742,6 +748,18 @@ void Asset::load_defaults(BC_Hash *defaults, ampeg_bitrate = GET_DEFAULT("AMPEG_BITRATE", ampeg_bitrate); ampeg_derivative = GET_DEFAULT("AMPEG_DERIVATIVE", ampeg_derivative); + vorbis_vbr = GET_DEFAULT("VORBIS_VBR", vorbis_vbr); + vorbis_min_bitrate = GET_DEFAULT("VORBIS_MIN_BITRATE", vorbis_min_bitrate); + vorbis_bitrate = GET_DEFAULT("VORBIS_BITRATE", vorbis_bitrate); + vorbis_max_bitrate = GET_DEFAULT("VORBIS_MAX_BITRATE", vorbis_max_bitrate); + + theora_fix_bitrate = GET_DEFAULT("THEORA_FIX_BITRATE", theora_fix_bitrate); + theora_bitrate = GET_DEFAULT("THEORA_BITRATE", theora_bitrate); + 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_FREQUENCY", theora_keyframe_force_frequency); + GET_DEFAULT("FF_AUDIO_OPTIONS", ff_audio_options); GET_DEFAULT("FF_SAMPLE_FORMAT", ff_sample_format); ff_audio_bitrate = GET_DEFAULT("FF_AUDIO_BITRATE", ff_audio_bitrate); @@ -750,6 +768,9 @@ void Asset::load_defaults(BC_Hash *defaults, GET_DEFAULT("FF_PIXEL_FORMAT", ff_pixel_format); ff_video_bitrate = GET_DEFAULT("FF_VIDEO_BITRATE", ff_video_bitrate); ff_video_quality = GET_DEFAULT("FF_VIDEO_QUALITY", ff_video_quality); + ff_color_space = GET_DEFAULT("FF_COLOR_SPACE", ff_color_space); + ff_color_range = GET_DEFAULT("FF_COLOR_RANGE", ff_color_range); + GET_DEFAULT("FF_FORMAT_OPTIONS", ff_format_options); mp3_bitrate = GET_DEFAULT("MP3_BITRATE", mp3_bitrate); @@ -771,6 +792,14 @@ void Asset::load_defaults(BC_Hash *defaults, vmpeg_preset = GET_DEFAULT("VMPEG_PRESET", vmpeg_preset); vmpeg_field_order = GET_DEFAULT("VMPEG_FIELD_ORDER", vmpeg_field_order); + theora_fix_bitrate = GET_DEFAULT("THEORA_FIX_BITRATE", theora_fix_bitrate); + theora_bitrate = GET_DEFAULT("THEORA_BITRATE", theora_bitrate); + 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); + + ac3_bitrate = GET_DEFAULT("AC3_BITRATE", ac3_bitrate); png_use_alpha = GET_DEFAULT("PNG_USE_ALPHA", png_use_alpha); @@ -804,6 +833,7 @@ void Asset::save_defaults(BC_Hash *defaults, UPDATE_DEFAULT("FORMAT", format); UPDATE_DEFAULT("USE_HEADER", use_header); UPDATE_DEFAULT("FFORMAT", fformat); + UPDATE_DEFAULT("FF_FORMAT_OPTIONS", ff_format_options); } if(do_data_types) @@ -820,6 +850,11 @@ void Asset::save_defaults(BC_Hash *defaults, UPDATE_DEFAULT("AMPEG_BITRATE", ampeg_bitrate); UPDATE_DEFAULT("AMPEG_DERIVATIVE", ampeg_derivative); + UPDATE_DEFAULT("VORBIS_VBR", vorbis_vbr); + UPDATE_DEFAULT("VORBIS_MIN_BITRATE", vorbis_min_bitrate); + 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_SAMPLE_FORMAT", ff_sample_format); UPDATE_DEFAULT("FF_AUDIO_BITRATE", ff_audio_bitrate); @@ -828,6 +863,17 @@ void Asset::save_defaults(BC_Hash *defaults, UPDATE_DEFAULT("FF_PIXEL_FORMAT", ff_pixel_format); UPDATE_DEFAULT("FF_VIDEO_BITRATE", ff_video_bitrate); UPDATE_DEFAULT("FF_VIDEO_QUALITY", ff_video_quality); + UPDATE_DEFAULT("FF_COLOR_SPACE", ff_color_space); + UPDATE_DEFAULT("FF_COLOR_RANGE", ff_color_range); + + 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_FREQUENCY", theora_keyframe_force_frequency); + + UPDATE_DEFAULT("MP3_BITRATE", mp3_bitrate); @@ -923,6 +969,8 @@ int Asset::dump(FILE *fp) fprintf(fp," ff_pixel_format=\"%s\"\n", ff_pixel_format); fprintf(fp," ff_video_bitrate=%d\n", ff_video_bitrate); fprintf(fp," ff_video_quality=%d\n", ff_video_quality); + fprintf(fp," ff_color_space=%d\n", ff_color_space); + fprintf(fp," ff_color_range=%d\n", ff_color_range); fprintf(fp," audio_data %d channels %d samplerate %d bits %d" " byte_order %d signed %d header %d dither %d acodec %4.4s\n", audio_data, channels, sample_rate, bits, byte_order, signed_, diff --git a/cinelerra-5.1/cinelerra/asset.h b/cinelerra-5.1/cinelerra/asset.h index 80a29eb5..096ea988 100644 --- a/cinelerra-5.1/cinelerra/asset.h +++ b/cinelerra-5.1/cinelerra/asset.h @@ -93,6 +93,7 @@ public: int expand_relative = 1); int read_audio(FileXML *xml); int read_video(FileXML *xml); + int read_format(FileXML *xml); int read_index(FileXML *xml); void reset_audio(); void reset_video(); @@ -165,6 +166,21 @@ public: // 2 - 3 int ampeg_derivative; +// Vorbis compression + int vorbis_min_bitrate; + int vorbis_bitrate; + int vorbis_max_bitrate; + int vorbis_vbr; + +// Theora compression + int theora_fix_bitrate; + int theora_bitrate; + int theora_quality; + int theora_sharpness; + int theora_keyframe_frequency; + int theora_keyframe_force_frequency; + + // Set by package render during file creation. -1 means square pixels. double aspect_ratio; @@ -191,11 +207,13 @@ public: int vmpeg_field_order; int vmpeg_pframe_distance; -// ffmpeg muxer file extension +// ffmpeg char fformat[BCSTRLEN]; + char ff_format_options[BCTEXTLEN]; char ff_video_options[BCTEXTLEN]; char ff_pixel_format[BCSTRLEN]; int ff_video_bitrate, ff_video_quality; + int ff_color_space, ff_color_range; char ff_audio_options[BCTEXTLEN]; char ff_sample_format[BCSTRLEN]; int ff_audio_bitrate, ff_audio_quality; diff --git a/cinelerra-5.1/cinelerra/awindowgui.C b/cinelerra-5.1/cinelerra/awindowgui.C index a8e6c002..1aa57e35 100644 --- a/cinelerra-5.1/cinelerra/awindowgui.C +++ b/cinelerra-5.1/cinelerra/awindowgui.C @@ -2653,12 +2653,18 @@ int AWindowFolders::load_expanders() char expanders_path[BCTEXTLEN]; mwindow->create_defaults_path(expanders_path, EXPANDERS_FILE); FILE *fp = fopen(expanders_path, "r"); + if( !fp ) { + snprintf(expanders_path, sizeof(expanders_path), "%s/%s", + File::get_cindat_path(), EXPANDERS_FILE); + char *cp = strrchr(expanders_path,'.'); + if( cp ) strcpy(cp+1, mwindow->cin_lang); + fp = fopen(expanders_path, "r"); + } if( !fp ) { snprintf(expanders_path, sizeof(expanders_path), "%s/%s", File::get_cindat_path(), EXPANDERS_FILE); fp = fopen(expanders_path, "r"); } - if( !fp ) return 1; const char tab = '\t'; char line[BCTEXTLEN]; line[0] = 0; diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 26a8ddd5..8b9cc27f 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -1043,6 +1043,8 @@ FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx) length = 0; interlaced = 0; top_field_first = 0; + color_space = -1; + color_range = -1; } FFVideoStream::~FFVideoStream() @@ -1428,13 +1430,13 @@ int FFVideoConvert::convert_picture_vframe(VFrame *frame, AVFrame *ip, AVFrame * case BC_COLORS_JPEG: color_range = 1; break; case BC_COLORS_MPEG: color_range = 0; break; } - int ff_color_space = SWS_CS_ITU601; + int color_space = SWS_CS_ITU601; switch( preferences->yuv_color_space ) { - case BC_COLORS_BT601: ff_color_space = SWS_CS_ITU601; break; - case BC_COLORS_BT709: ff_color_space = SWS_CS_ITU709; break; - case BC_COLORS_BT2020: ff_color_space = SWS_CS_BT2020; break; + case BC_COLORS_BT601: color_space = SWS_CS_ITU601; break; + case BC_COLORS_BT709: color_space = SWS_CS_ITU709; break; + case BC_COLORS_BT2020: color_space = SWS_CS_BT2020; break; } - const int *color_table = sws_getCoefficients(ff_color_space); + const int *color_table = sws_getCoefficients(color_space); int *inv_table, *table, src_range, dst_range; int brightness, contrast, saturation; @@ -1557,13 +1559,13 @@ int FFVideoConvert::convert_vframe_picture(VFrame *frame, AVFrame *op, AVFrame * case BC_COLORS_JPEG: color_range = 1; break; case BC_COLORS_MPEG: color_range = 0; break; } - int ff_color_space = SWS_CS_ITU601; + int color_space = SWS_CS_ITU601; switch( preferences->yuv_color_space ) { - case BC_COLORS_BT601: ff_color_space = SWS_CS_ITU601; break; - case BC_COLORS_BT709: ff_color_space = SWS_CS_ITU709; break; - case BC_COLORS_BT2020: ff_color_space = SWS_CS_BT2020; break; + case BC_COLORS_BT601: color_space = SWS_CS_ITU601; break; + case BC_COLORS_BT709: color_space = SWS_CS_ITU709; break; + case BC_COLORS_BT2020: color_space = SWS_CS_BT2020; break; } - const int *color_table = sws_getCoefficients(ff_color_space); + const int *color_table = sws_getCoefficients(color_space); int *inv_table, *table, src_range, dst_range; int brightness, contrast, saturation; @@ -2004,6 +2006,20 @@ void FFMPEG::load_video_options(Asset *asset, EDL *edl) scan_video_options(asset, edl); } +void FFMPEG::scan_format_options(Asset *asset, EDL *edl) +{ +} + +void FFMPEG::load_format_options(Asset *asset, EDL *edl) +{ + char options_path[BCTEXTLEN]; + set_option_path(options_path, "format/%s", asset->fformat); + if( !load_options(options_path, + asset->ff_format_options, + sizeof(asset->ff_format_options)) ) + scan_format_options(asset, edl); +} + int FFMPEG::load_defaults(const char *path, const char *type, char *codec, char *codec_options, int len) { @@ -2029,6 +2045,8 @@ void FFMPEG::set_asset_format(Asset *asset, EDL *edl, const char *text) if( asset->format != FILE_FFMPEG ) return; if( text != asset->fformat ) strcpy(asset->fformat, text); + if( !asset->ff_format_options[0] ) + load_format_options(asset, edl); if( asset->audio_data && !asset->ff_audio_options[0] ) { if( !load_defaults("audio", text, asset->acodec, asset->ff_audio_options, sizeof(asset->ff_audio_options)) ) @@ -2100,8 +2118,10 @@ int FFMPEG::scan_options(const char *options, AVDictionary *&opts, AVStream *st) if( !fp ) return 0; int ret = read_options(fp, options, opts); fclose(fp); - AVDictionaryEntry *tag = av_dict_get(opts, "id", NULL, 0); - if( tag ) st->id = strtol(tag->value,0,0); + if( !ret && st ) { + AVDictionaryEntry *tag = av_dict_get(opts, "id", NULL, 0); + if( tag ) st->id = strtol(tag->value,0,0); + } return ret; } @@ -2245,16 +2265,23 @@ int FFMPEG::info(char *text, int len) if( ffvideo.size() > 0 ) report("\n%d video stream%s\n",ffvideo.size(), ffvideo.size()!=1 ? "s" : ""); for( int vidx=0; vidxst; AVCodecID codec_id = st->codecpar->codec_id; report(_("vid%d (%d), id 0x%06x:\n"), vid->idx, vid->fidx, codec_id); const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id); - report(" video%d %s", vidx+1, desc ? desc->name : " (unkn)"); + report(" video%d %s ", vidx+1, desc ? desc->name : unkn); report(" %dx%d %5.2f", vid->width, vid->height, vid->frame_rate); AVPixelFormat pix_fmt = (AVPixelFormat)st->codecpar->format; const char *pfn = av_get_pix_fmt_name(pix_fmt); - report(" pix %s\n", pfn ? pfn : "(unkn)"); + report(" pix %s\n", pfn ? pfn : unkn); + enum AVColorSpace space = st->codecpar->color_space; + const char *nm = av_color_space_name(space); + report(" color space:%s", nm ? nm : unkn); + enum AVColorRange range = st->codecpar->color_range; + const char *rg = av_color_range_name(range); + report("/ range:%s\n", rg ? rg : unkn); double secs = to_secs(st->duration, st->time_base); int64_t length = secs * vid->frame_rate + 0.5; double ofs = to_secs((vid->nudge - st->start_time), st->time_base); @@ -2415,6 +2442,35 @@ int FFMPEG::open_decoder() vid->width = avpar->width; vid->height = avpar->height; vid->frame_rate = !framerate.den ? 0 : (double)framerate.num / framerate.den; + switch( avpar->color_range ) { + case AVCOL_RANGE_MPEG: + vid->color_range = BC_COLORS_MPEG; + break; + case AVCOL_RANGE_JPEG: + vid->color_range = BC_COLORS_JPEG; + break; + default: + vid->color_range = !file_base ? BC_COLORS_JPEG : + file_base->file->preferences->yuv_color_range; + break; + } + switch( avpar->color_space ) { + case AVCOL_SPC_BT470BG: + case AVCOL_SPC_SMPTE170M: + vid->color_space = BC_COLORS_BT601; + break; + case AVCOL_SPC_BT709: + vid->color_space = BC_COLORS_BT709; + break; + case AVCOL_SPC_BT2020_NCL: + case AVCOL_SPC_BT2020_CL: + vid->color_space = BC_COLORS_BT2020; + break; + default: + vid->color_space = !file_base ? BC_COLORS_BT601 : + file_base->file->preferences->yuv_color_space; + break; + } double secs = to_secs(st->duration, st->time_base); vid->length = secs * vid->frame_rate; vid->aspect_ratio = (double)st->sample_aspect_ratio.num / st->sample_aspect_ratio.den; @@ -2647,7 +2703,19 @@ int FFMPEG::open_encoder(const char *type, const char *spec) vid->width = asset->width; vid->height = asset->height; vid->frame_rate = asset->frame_rate; - + if( (vid->color_range = asset->ff_color_range) < 0 ) + vid->color_range = file_base->file->preferences->yuv_color_range; + switch( vid->color_range ) { + case BC_COLORS_MPEG: ctx->color_range = AVCOL_RANGE_MPEG; break; + case BC_COLORS_JPEG: ctx->color_range = AVCOL_RANGE_JPEG; break; + } + if( (vid->color_space = asset->ff_color_space) < 0 ) + vid->color_space = file_base->file->preferences->yuv_color_space; + switch( vid->color_space ) { + case BC_COLORS_BT601: ctx->colorspace = AVCOL_SPC_SMPTE170M; break; + case BC_COLORS_BT709: ctx->colorspace = AVCOL_SPC_BT709; break; + case BC_COLORS_BT2020: ctx->colorspace = AVCOL_SPC_BT2020_NCL; break; + } AVPixelFormat pix_fmt = av_get_pix_fmt(asset->ff_pixel_format); if( opt_hw_dev != 0 ) { AVHWDeviceType hw_type = vid->encode_hw_activate(opt_hw_dev); @@ -2937,7 +3005,13 @@ int FFMPEG::encode_activate() char option_path[BCTEXTLEN]; set_option_path(option_path, "format/%s", file_format); read_options(option_path, fopts, 1); - ret = avformat_write_header(fmt_ctx, &fopts); + av_dict_copy(&fopts, opts, 0); + if( scan_options(file_base->asset->ff_format_options, fopts, 0) ) { + eprintf(_("bad format options %s\n"), file_base->asset->path); + ret = -1; + } + if( ret >= 0 ) + ret = avformat_write_header(fmt_ctx, &fopts); if( ret < 0 ) { ff_err(ret, "FFMPEG::encode_activate: write header failed %s\n", fmt_ctx->url); @@ -3252,6 +3326,16 @@ const char* FFMPEG::ff_video_format(int stream) return desc ? desc->name : _("Unknown"); } +int FFMPEG::ff_color_range(int stream) +{ + return ffvideo[stream]->color_range; +} + +int FFMPEG::ff_color_space(int stream) +{ + return ffvideo[stream]->color_space; +} + double FFMPEG::ff_frame_rate(int stream) { return ffvideo[stream]->frame_rate; diff --git a/cinelerra-5.1/cinelerra/ffmpeg.h b/cinelerra-5.1/cinelerra/ffmpeg.h index 46838b4d..6ad51246 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.h +++ b/cinelerra-5.1/cinelerra/ffmpeg.h @@ -262,6 +262,7 @@ public: int interlaced; int top_field_first; + int color_space, color_range; }; class FFCodecRemap @@ -309,6 +310,8 @@ public: static void load_audio_options(Asset *asset, EDL *edl); static void scan_video_options(Asset *asset, EDL *edl); static void load_video_options(Asset *asset, EDL *edl); + static void scan_format_options(Asset *asset, EDL *edl); + static void load_format_options(Asset *asset, EDL *edl); static void set_asset_format(Asset *asset, EDL *edl, const char *text); int get_file_format(); static int get_encoder(const char *options, char *format, char *codec, char *bsfilter); @@ -409,6 +412,8 @@ public: int ff_coded_width(int stream); int ff_coded_height(int stream); float ff_aspect_ratio(int stream); + int ff_color_range(int stream); + int ff_color_space(int stream); double ff_frame_rate(int stream); const char *ff_video_format(int stream); int64_t ff_video_frames(int stream); diff --git a/cinelerra-5.1/cinelerra/file.C b/cinelerra-5.1/cinelerra/file.C index 1fec188e..f9571c9d 100644 --- a/cinelerra-5.1/cinelerra/file.C +++ b/cinelerra-5.1/cinelerra/file.C @@ -52,6 +52,7 @@ #include "filejpeg.h" #include "filempeg.h" #undef HAVE_STDLIB_H // automake conflict +#include "fileogg.h" #include "filepng.h" #include "fileppm.h" #include "fileref.h" @@ -60,6 +61,7 @@ #include "filetga.h" #include "filethread.h" #include "filetiff.h" +#include "filevorbis.h" #include "filexml.h" #include "formatwindow.h" #include "formattools.h" @@ -75,6 +77,14 @@ #include "samples.h" #include "vframe.h" +#ifdef HAVE_OGG +//suppress noref warning +void *vorbis0_ov_callbacks[] = { + &OV_CALLBACKS_DEFAULT, &OV_CALLBACKS_NOCLOSE, + &OV_CALLBACKS_STREAMONLY, &OV_CALLBACKS_STREAMONLY_NOCLOSE, +}; +#endif + File::File() { cpus = 1; @@ -94,7 +104,6 @@ File::~File() } if( temp_frame ) { -//printf("File::~File %d temp_debug=%d\n", __LINE__, --temp_debug); delete temp_frame; } @@ -229,6 +238,12 @@ int File::get_options(FormatTools *format, FileTIFF::get_parameters(parent_window, asset, format_window, audio_options, video_options, edl); break; +#ifdef HAVE_OGG + case FILE_OGG: + FileOGG::get_parameters(parent_window, asset, format_window, + audio_options, video_options, edl); + break; +#endif default: break; } @@ -350,6 +365,10 @@ const char *File::default_probes[] = { "CR2", "TGA", "TIFF", +#ifdef HAVE_OGG + "OGG", + "Vorbis", +#endif "MPEG", "EDL", "FFMPEG_Late", @@ -450,6 +469,18 @@ int File::probe() file = new FileTIFF(this->asset, this); return FILE_OK; } +#ifdef HAVE_OGG + if( !strcmp(pref->name,"OGG") ) { // OGG file + if( !FileOGG::check_sig(this->asset) ) continue; + file = new FileOGG(this->asset, this); + return FILE_OK; + } + if( !strcmp(pref->name,"Vorbis") ) { // VorbisFile file + if( !FileVorbis::check_sig(this->asset) ) continue; + file = new FileVorbis(this->asset, this); + return FILE_OK; + } +#endif #ifdef HAVE_LIBZMPEG if( !strcmp(pref->name,"MPEG") ) { // MPEG file if( !FileMPEG::check_sig(this->asset) ) continue; @@ -573,6 +604,15 @@ int File::open_file(Preferences *preferences, file = new FileMPEG(this->asset, this); break; #endif +#ifdef HAVE_OGG + case FILE_OGG: + file = new FileOGG(this->asset, this); + break; + + case FILE_VORBIS: + file = new FileVorbis(this->asset, this); + break; +#endif #ifdef HAVE_DV case FILE_RAWDV: file = new FileDV(this->asset, this); @@ -1214,6 +1254,8 @@ int File::strtoformat(const char *format) if( !strcasecmp(format, _(VMPEG_NAME)) ) return FILE_VMPEG; if( !strcasecmp(format, _(TGA_NAME)) ) return FILE_TGA; if( !strcasecmp(format, _(TGA_LIST_NAME)) ) return FILE_TGA_LIST; + if( !strcasecmp(format, _(OGG_NAME)) ) return FILE_OGG; + if( !strcasecmp(format, _(VORBIS_NAME)) ) return FILE_VORBIS; if( !strcasecmp(format, _(RAWDV_NAME)) ) return FILE_RAWDV; if( !strcasecmp(format, _(FFMPEG_NAME)) ) return FILE_FFMPEG; if( !strcasecmp(format, _(DBASE_NAME)) ) return FILE_DB; @@ -1255,6 +1297,8 @@ const char* File::formattostr(int format) case FILE_TGA_LIST: return _(TGA_LIST_NAME); case FILE_TIFF: return _(TIFF_NAME); case FILE_TIFF_LIST: return _(TIFF_LIST_NAME); + case FILE_OGG: return _(OGG_NAME); + case FILE_VORBIS: return _(VORBIS_NAME); case FILE_RAWDV: return _(RAWDV_NAME); case FILE_FFMPEG: return _(FFMPEG_NAME); case FILE_DB: return _(DBASE_NAME); @@ -1388,6 +1432,7 @@ int64_t File::get_memory_usage() int File::renders_video(int format) { switch( format ) { + case FILE_OGG: case FILE_JPEG: case FILE_JPEG_LIST: case FILE_CR2: @@ -1425,6 +1470,8 @@ int File::renders_audio(int format) case FILE_FLAC: case FILE_PCM: case FILE_WAV: + case FILE_OGG: + case FILE_VORBIS: case FILE_AMPEG: case FILE_AU: case FILE_AIFF: @@ -1471,6 +1518,7 @@ const char* File::get_tag(int format) case FILE_FLAC: return "flac"; case FILE_JPEG: return "jpg"; case FILE_JPEG_LIST: return "jpgs"; + case FILE_OGG: return "ogg"; case FILE_GIF: return "gif"; case FILE_GIF_LIST: return "gifs"; case FILE_PCM: return "pcm"; @@ -1483,6 +1531,7 @@ const char* File::get_tag(int format) case FILE_TIFF: return "tif"; case FILE_TIFF_LIST: return "tifs"; case FILE_VMPEG: return "m2v"; + case FILE_VORBIS: return "ogg"; case FILE_WAV: return "wav"; case FILE_FFMPEG: return "ffmpg"; case FILE_REF: return "ref"; @@ -1517,6 +1566,8 @@ const char* File::get_prefix(int format) case FILE_EXR: return "EXR"; case FILE_EXR_LIST: return "EXR_LIST"; case FILE_CR2: return "CR2"; + case FILE_OGG: return "OGG"; + case FILE_VORBIS: return "VORBIS"; case FILE_FLAC: return "FLAC"; case FILE_FFMPEG: return "FFMPEG"; case FILE_SCENE: return "SCENE"; @@ -1529,13 +1580,6 @@ const char* File::get_prefix(int format) } -PackagingEngine *File::new_packaging_engine(Asset *asset) -{ - PackagingEngine *result = (PackagingEngine*) new PackagingEngineDefault(); - return result; -} - - int File::record_fd() { return file ? file->record_fd() : -1; diff --git a/cinelerra-5.1/cinelerra/file.h b/cinelerra-5.1/cinelerra/file.h index 2ca1acbe..c86a1b4f 100644 --- a/cinelerra-5.1/cinelerra/file.h +++ b/cinelerra-5.1/cinelerra/file.h @@ -314,7 +314,6 @@ public: // int64_t normalized_sample_rate; Preferences *preferences; int wr, rd; - static PackagingEngine *new_packaging_engine(Asset *asset); static void init_cin_path(); static void get_exe_path(char *result, char *bnp=0); diff --git a/cinelerra-5.1/cinelerra/file.inc b/cinelerra-5.1/cinelerra/file.inc index 748ce065..11a5bc9a 100644 --- a/cinelerra-5.1/cinelerra/file.inc +++ b/cinelerra-5.1/cinelerra/file.inc @@ -81,6 +81,8 @@ #define FILE_EXR 26 #define FILE_EXR_LIST 27 #define FILE_CR2 28 +#define FILE_OGG 30 +#define FILE_VORBIS 31 #define FILE_FLAC 32 #define FILE_FFMPEG 33 #define FILE_SCENE 34 @@ -113,6 +115,8 @@ N_("Microsoft WAV") N_("MPEG Audio") // For encoding only N_("MPEG") // For decoding only N_("MPEG Video") // For encoding only +N_("OGG Theora/Vorbis") +N_("OGG Vorbis") // For decoding only N_("PNG") N_("PNG Sequence") N_("PPM") @@ -148,6 +152,7 @@ N_("Reference to EDL") #define JPEG_LIST_NAME "JPEG Sequence" #define JPEG_NAME "JPEG" #define MPEG_NAME "MPEG Stream" // For capture only +#define OGG_NAME "OGG Theora/Vorbis" #define PCM_NAME "Raw PCM" #define PNG_LIST_NAME "PNG Sequence" #define PNG_NAME "PNG" @@ -161,6 +166,7 @@ N_("Reference to EDL") #define TIFF_LIST_NAME "TIFF Sequence" #define TIFF_NAME "TIFF" #define VMPEG_NAME "MPEG Video" // For encoding only +#define VORBIS_NAME "OGG Vorbis" #define WAV_NAME "Microsoft WAV" #define REF_NAME "Reference EDL" diff --git a/cinelerra-5.1/cinelerra/fileffmpeg.C b/cinelerra-5.1/cinelerra/fileffmpeg.C index 564306e6..0db64205 100644 --- a/cinelerra-5.1/cinelerra/fileffmpeg.C +++ b/cinelerra-5.1/cinelerra/fileffmpeg.C @@ -216,8 +216,11 @@ void FileFFMPEG::get_parameters(BC_WindowBase *parent_window, { Asset *ff_asset = new Asset(); ff_asset->copy_from(asset, 0); + int wx, wy; + parent_window->get_pop_cursor(wx, wy); if( audio_options ) { - FFMPEGConfigAudio *window = new FFMPEGConfigAudio(parent_window, ff_asset, edl); + FFMPEGConfigAudio *window = new FFMPEGConfigAudio(parent_window, + wx, wy, ff_asset, edl); format_window = window; window->create_objects(); if( !window->run_window() ) { @@ -229,7 +232,8 @@ void FileFFMPEG::get_parameters(BC_WindowBase *parent_window, delete window; } else if( video_options ) { - FFMPEGConfigVideo *window = new FFMPEGConfigVideo(parent_window, ff_asset, edl); + FFMPEGConfigVideo *window = new FFMPEGConfigVideo(parent_window, + wx, wy, ff_asset, edl); format_window = window; window->create_objects(); if( !window->run_window() ) { @@ -347,6 +351,10 @@ int FileFFMPEG::open_file(int rd, int wr) (asset->video_length = ff->ff_video_frames(0)) < 2 ) asset->video_length = asset->video_length < 0 ? 0 : -1; if( !asset->frame_rate ) asset->frame_rate = ff->ff_frame_rate(0); + if( asset->ff_color_range < 0 ) + asset->ff_color_range = ff->ff_color_range(0); + if( asset->ff_color_space < 0 ) + asset->ff_color_space = ff->ff_color_space(0); strcpy(asset->vcodec, ff->ff_video_format(0)); } IndexState *index_state = asset->index_state; @@ -456,33 +464,63 @@ int FileFFMPEG::get_best_colormodel(Asset *asset, int driver) return BC_YUV420P; } -//====== -FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset, EDL *edl) - : BC_Window(_(PROGRAM_NAME ": Audio Preset"), - parent_window->get_abs_cursor_x(1), - parent_window->get_abs_cursor_y(1), - xS(420), yS(420)) +FFMPEGConfigWindow::FFMPEGConfigWindow(const char *title, + BC_WindowBase *parent_window, + int x, int y, int w, int h, + Asset *asset, EDL *edl) + : BC_Window(title, x, y, w, h) { this->parent_window = parent_window; this->asset = asset; this->edl = edl; - preset_popup = 0; + ff_options_dialog = 0; + obj = 0; + format_name = 0; + codec_name = 0; +} + +FFMPEGConfigWindow::~FFMPEGConfigWindow() +{ + delete ff_options_dialog; +} + +void FFMPEGConfigWindow::start(const void *obj) +{ + this->obj = obj; + ff_options_dialog->start(); +} + +//====== +FFMPEGConfigAudio::FFMPEGConfigAudio(BC_WindowBase *parent_window, + int x, int y, Asset *asset, EDL *edl) + : FFMPEGConfigWindow(_(PROGRAM_NAME ": Audio Preset"), parent_window, x, y, + xS(420), yS(420), asset, edl) +{ + preset_popup = 0; bitrate = 0; audio_options = 0; - ff_options_dialog = 0; + format_name = asset->fformat; + codec_name = asset->acodec; } FFMPEGConfigAudio::~FFMPEGConfigAudio() { lock_window("FFMPEGConfigAudio::~FFMPEGConfigAudio"); - delete ff_options_dialog; delete preset_popup; presets.remove_all_objects(); + delete audio_options; unlock_window(); } +char *FFMPEGConfigAudio::get_options() { + return asset->ff_audio_options; +} +int FFMPEGConfigAudio::get_options_len() { + return sizeof(asset->ff_audio_options)-1; +} + void FFMPEGConfigAudio::load_options() { FFMPEG::load_audio_options(asset, edl); @@ -550,8 +588,11 @@ void FFMPEGConfigAudio::create_objects() add_subwindow(title); ff_options_dialog = new FFOptionsAudioDialog(this); - int x1 = x + title->get_w() + 8; - add_subwindow(new FFOptionsViewAudio(this, x1, y, _("view"))); + int x1 = x + title->get_w() + xS(8); + add_subwindow(view_audio = new FFOptionsViewAudio(this, x1, y, _("view"))); + x1 += x + view_audio->get_w() + xS(20); + view_format = new FFOptionsViewFormat(this, edl, asset, x1, y, _("format")); + add_subwindow(view_format); y += yS(25); audio_options = new FFAudioOptions(this, x, y, get_w()-x-xS(20), 8, @@ -606,34 +647,17 @@ int FFMPEGConfigAudioPopup::handle_event() return 1; } - -FFMPEGConfigAudioToggle::FFMPEGConfigAudioToggle(FFMPEGConfigAudio *popup, - char *title_text, int x, int y, int *output) - : BC_CheckBox(x, y, *output, title_text) -{ - this->popup = popup; - this->output = output; -} -int FFMPEGConfigAudioToggle::handle_event() -{ - *output = get_value(); - return 1; -} - //====== -FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset, EDL *edl) - : BC_Window(_(PROGRAM_NAME ": Video Preset"), - parent_window->get_abs_cursor_x(1), - parent_window->get_abs_cursor_y(1), - xS(420), yS(420)) +FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, + int x, int y, Asset *asset, EDL *edl) + : FFMPEGConfigWindow(_(PROGRAM_NAME ": Video Preset"), parent_window, x, y, + xS(420), yS(420), asset, edl) { - this->parent_window = parent_window; - this->asset = asset; - this->edl = edl; preset_popup = 0; - ff_options_dialog = 0; pixel_format = 0; + format_name = asset->fformat; + codec_name = asset->vcodec; bitrate = 0; quality = 0; @@ -643,13 +667,20 @@ FFMPEGConfigVideo::FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset, FFMPEGConfigVideo::~FFMPEGConfigVideo() { lock_window("FFMPEGConfigVideo::~FFMPEGConfigVideo"); - delete ff_options_dialog; - delete pixel_format; delete preset_popup; + delete pixel_format; + delete video_options; presets.remove_all_objects(); unlock_window(); } +char *FFMPEGConfigVideo::get_options() { + return asset->ff_video_options; +} +int FFMPEGConfigVideo::get_options_len() { + return sizeof(asset->ff_video_options)-1; +} + void FFMPEGConfigVideo::load_options() { FFMPEG::load_video_options(asset, edl); @@ -723,7 +754,10 @@ void FFMPEGConfigVideo::create_objects() ff_options_dialog = new FFOptionsVideoDialog(this); int x1 = x + title->get_w() + 8; - add_subwindow(new FFOptionsViewVideo(this, x1, y, _("view"))); + add_subwindow(view_video = new FFOptionsViewVideo(this, x1, y, _("view"))); + x1 += x + view_video->get_w() + xS(20); + view_format = new FFOptionsViewFormat(this, edl, asset, x1, y, _("format")); + add_subwindow(view_format); y += yS(25); video_options = new FFVideoOptions(this, x, y, get_w()-x-xS(20), 8, @@ -777,20 +811,82 @@ int FFMPEGConfigVideoPopup::handle_event() return 1; } +//====== -FFMPEGConfigVideoToggle::FFMPEGConfigVideoToggle(FFMPEGConfigVideo *popup, - char *title_text, int x, int y, int *output) - : BC_CheckBox(x, y, *output, title_text) +FFMPEGConfigFormat::FFMPEGConfigFormat(FFOptionsFormatViewDialog *view_dialog, + int x, int y, Asset *asset, EDL *edl) + : FFMPEGConfigWindow(_(PROGRAM_NAME ": Format Preset"), + view_dialog->view_format, x, y, xS(420), yS(300), asset, edl) { - this->popup = popup; - this->output = output; + this->view_dialog = view_dialog; + format_options = 0; + format_name = asset->fformat; + codec_name = 0; +} + +FFMPEGConfigFormat::~FFMPEGConfigFormat() +{ + lock_window("FFMPEGConfigFormat::~FFMPEGConfigFormat"); + delete format_options; + unlock_window(); +} + +char *FFMPEGConfigFormat::get_options() { + return asset->ff_format_options; +} +int FFMPEGConfigFormat::get_options_len() { + return sizeof(asset->ff_format_options)-1; +} + +void FFMPEGConfigFormat::load_options() +{ + Asset *asset = view_dialog->view_format->asset; + EDL *edl = view_dialog->view_format->edl; + FFMPEG::load_format_options(asset, edl); } -int FFMPEGConfigVideoToggle::handle_event() + +void FFMPEGConfigFormat::create_objects() { - *output = get_value(); + int x = xS(10), y = yS(10); + lock_window("FFMPEGConfigFormat::create_objects"); + Asset *asset = view_dialog->view_format->asset; + BC_Title *title; + add_subwindow(title = new BC_Title(x, y, _("Format:"))); + int x1 = x + title->get_w() + 8; + add_subwindow(new BC_Title(x1, y, asset->fformat)); + y += yS(25); + + add_subwindow(title = new BC_Title(x, y, _("Format Options:"))); + + ff_options_dialog = new FFOptionsFormatDialog(this); + x1 = x + title->get_w() + 8; + add_subwindow(new FFOptionsFormatView(this, x1, y, _("view"))); + + y += yS(25); + format_options = new FFFormatOptions(this, x, y, get_w()-x-xS(20), 8, + sizeof(asset->ff_format_options)-1, asset->ff_format_options); + format_options->create_objects(); + add_subwindow(new BC_OKButton(this)); + add_subwindow(new BC_CancelButton(this)); + show_window(1); + unlock_window(); +} + +int FFMPEGConfigFormat::close_event() +{ + set_done(1); return 1; } +FFFormatOptions::FFFormatOptions(FFMPEGConfigFormat *format_popup, + int x, int y, int w, int rows, int size, char *text) + : BC_ScrollTextBox(format_popup, x, y, w, rows, text, size) +{ + this->format_popup = format_popup; +} + +//====== + FFMPEGScanProgress::FFMPEGScanProgress(IndexFile *index_file, MainProgressBar *progress_bar, const char *title, int64_t length, int64_t *position, int *canceled) : Thread(1, 0, 0) @@ -1012,6 +1108,7 @@ int FFOptionsKindItem::handle_event() const char *FFOptionsKind::kinds[] = { N_("codec"), // FF_KIND_CODEC + N_("format"), // FF_KIND_FORMAT N_("ffmpeg"), // FF_KIND_FFMPEG }; @@ -1029,8 +1126,8 @@ FFOptionsKind:: void FFOptionsKind::create_objects() { - for( int i=0; i<(int)(sizeof(kinds)/sizeof(kinds[0])); ++i ) - add_item(new FFOptionsKindItem(this, _(kinds[i]), i)); + add_item(new FFOptionsKindItem(this, _(kinds[FF_KIND_CODEC]), FF_KIND_CODEC)); + add_item(new FFOptionsKindItem(this, _(kinds[FF_KIND_FFMPEG]), FF_KIND_FFMPEG)); } int FFOptionsKind::handle_event() @@ -1139,19 +1236,7 @@ void FFOptions::initialize(FFOptionsWindow *win, int kind) remove_all_objects(); this->win = win; win->selected = 0; - obj = 0; - if( !avctx ) - avctx = avcodec_alloc_context3(win->dialog->codec); - - switch( kind ) { - case FF_KIND_CODEC: - obj = (const void *)avctx->priv_data; - break; - case FF_KIND_FFMPEG: - obj = (const void *)avctx; - break; - } - + obj = win->dialog->cfg_window->obj; if( obj ) { FFOptions &conf = *this; const AVOption *opt = 0; @@ -1176,10 +1261,10 @@ void FFOptions::initialize(FFOptionsWindow *win, int kind) char val[BCTEXTLEN], *vp = fopt->get(val, sizeof(val)); fopt->item_value->update(vp); } + qsort(&values[0],size(),sizeof(values[0]),cmpr); } - - qsort(&values[0],size(),sizeof(values[0]),cmpr); - win->kind->set(kind); + if( win->kind ) + win->kind->set(kind); win->panel->update(); win->panel->set_yposition(0); } @@ -1455,11 +1540,12 @@ const char *FFOptions_Opt::tip() } -FFOptionsWindow::FFOptionsWindow(FFOptionsDialog *dialog) - : BC_Window(_(PROGRAM_NAME ": Options"), xS(60), yS(30), xS(640), yS(400)) +FFOptionsWindow::FFOptionsWindow(FFOptionsDialog *dialog, int x, int y) + : BC_Window(_(PROGRAM_NAME ": Options"), x, y, xS(640), yS(400)) { this->dialog = dialog; this->selected = 0; + this->kind = 0; } FFOptionsWindow::~FFOptionsWindow() @@ -1472,16 +1558,19 @@ void FFOptionsWindow::create_objects() int ys10 = yS(10); lock_window("FFOptionsWindow::create_objects"); BC_Title *title; + const char *format_name = dialog->cfg_window->format_name; + const char *codec_name = dialog->cfg_window->codec_name; int x0 = xs10, y0 = ys10; int x = x0, y = y0; add_subwindow(title = new BC_Title(x, y, _("Format: "))); x += title->get_w(); - add_subwindow(new BC_Title(x, y, dialog->format_name)); - x = x0 + xS(150); - add_subwindow(title = new BC_Title(x, y, _("Codec: "))); - x += title->get_w(); - add_subwindow(new BC_Title(x, y, dialog->codec_name)); - + add_subwindow(new BC_Title(x, y, format_name)); + if( codec_name ) { + x = x0 + xS(150); + add_subwindow(title = new BC_Title(x, y, _("Codec: "))); + x += title->get_w(); + add_subwindow(new BC_Title(x, y, codec_name)); + } x = x0; y += title->get_h() + ys10; y0 = y; add_subwindow(title = new BC_Title(x, y, _("Type: "))); x += title->get_w() + xs8; @@ -1498,13 +1587,14 @@ void FFOptionsWindow::create_objects() add_subwindow(text = new FFOptionsText(this, x, y, x1-x - xs8)); add_subwindow(apply = new FFOptionsApply(this, x1, y)); y += units->get_h() + ys10; - add_subwindow(kind = new FFOptionsKind(this, x1, y0, apply->get_w())); - kind->create_objects(); - const char *kind_text = _("Kind:"); - x1 -= BC_Title::calculate_w(this, kind_text) + xs8; - add_subwindow(kind_title = new BC_Title(x1, y0, kind_text)); + if( codec_name ) { + add_subwindow(kind = new FFOptionsKind(this, x1, y0, apply->get_w())); + kind->create_objects(); + const char *kind_text = _("Kind:"); + x1 -= BC_Title::calculate_w(this, kind_text) + xs8; + add_subwindow(kind_title = new BC_Title(x1, y0, kind_text)); + } y0 = y; - panel_x = x0; panel_y = y0; panel_w = get_w()-xs10 - panel_x; panel_h = get_h()-ys10 - panel_y - BC_OKButton::calculate_h(); @@ -1513,7 +1603,7 @@ void FFOptionsWindow::create_objects() add_subwindow(new BC_OKButton(this)); add_subwindow(new BC_CancelButton(this)); panel->create_objects(); - options.initialize(this, FF_KIND_CODEC); + options.initialize(this, codec_name ? FF_KIND_CODEC : FF_KIND_FORMAT); draw(); show_window(1); unlock_window(); @@ -1528,12 +1618,14 @@ int FFOptionsWindow::resize_event(int w, int h) { int xs8 = xS(8), xs10 = xS(10); int ys10 = yS(10); - int x1 = w - xs8 - kind->get_w(); - int y = kind->get_y(); - kind->reposition_window(x1, y); - x1 -= kind_title->get_w() + xs8; - kind_title->reposition_window(x1,y); - x1 = get_w() - apply->get_w() - xs8; + if( kind ) { + int x0 = w - xs8 - kind->get_w(); + int y0 = kind->get_y(); + kind->reposition_window(x0, y0); + x0 -= kind_title->get_w() + xs8; + kind_title->reposition_window(x0, y0); + } + int x1 = get_w() - apply->get_w() - xs8; int y1 = units->get_y(); apply->reposition_window(x1, y1); int x0 = units->get_x() + units->get_w() + xs8; @@ -1545,20 +1637,18 @@ int FFOptionsWindow::resize_event(int w, int h) return 1; } -FFOptionsDialog::FFOptionsDialog() +FFOptionsDialog::FFOptionsDialog(FFMPEGConfigWindow *cfg_window) : BC_DialogThread() { - this->options_window = 0; - this->codec_name = 0; - this->codec = 0; - this->ff_opts = 0; - this->ff_len = 0; + this->cfg_window = cfg_window; + options_window = 0; + ff_opts = 0; } FFOptionsDialog::~FFOptionsDialog() { close_window(); - delete [] codec_name; + av_dict_free(&ff_opts); } void FFOptionsDialog::load_options(const char *bp, int len) @@ -1597,8 +1687,7 @@ void FFOptionsDialog::store_options(char *cp, int len) *cp = 0; } -void FFOptionsDialog::start(const char *format_name, const char *codec_name, - AVCodec *codec, const char *options, int len) +void FFOptionsDialog::start() { if( options_window ) { options_window->lock_window("FFOptionsDialog::start"); @@ -1606,20 +1695,16 @@ void FFOptionsDialog::start(const char *format_name, const char *codec_name, options_window->unlock_window(); return; } - - this->format_name = cstrdup(format_name); - this->codec_name = cstrdup(codec_name); - this->codec = codec; - this->ff_opts = 0; - this->ff_len = len; - load_options(options, len); - + cfg_window->get_pop_cursor(wx, wy); + char *options = cfg_window->get_options(); + int options_len = cfg_window->get_options_len(); + load_options(options, options_len); BC_DialogThread::start(); } BC_Window* FFOptionsDialog::new_gui() { - options_window = new FFOptionsWindow(this); + options_window = new FFOptionsWindow(this, wx, wy); options_window->create_objects(); return options_window; } @@ -1627,17 +1712,16 @@ BC_Window* FFOptionsDialog::new_gui() void FFOptionsDialog::handle_done_event(int result) { if( !result ) { - char options[ff_len]; - store_options(options, ff_len); + char *options = cfg_window->get_options(); + int options_len = cfg_window->get_options_len(); + store_options(options, options_len); update_options(options); } options_window = 0; - delete [] format_name; format_name = 0; - delete [] codec_name; codec_name = 0; - av_dict_free(&ff_opts); } FFOptionsAudioDialog::FFOptionsAudioDialog(FFMPEGConfigAudio *aud_config) + : FFOptionsDialog(aud_config) { this->aud_config = aud_config; } @@ -1655,6 +1739,7 @@ void FFOptionsAudioDialog::update_options(const char *options) } FFOptionsVideoDialog::FFOptionsVideoDialog(FFMPEGConfigVideo *vid_config) + : FFOptionsDialog(vid_config) { this->vid_config = vid_config; } @@ -1671,62 +1756,192 @@ void FFOptionsVideoDialog::update_options(const char *options) vid_config->unlock_window(); } +FFOptionsFormatDialog::FFOptionsFormatDialog(FFMPEGConfigFormat *fmt_config) + : FFOptionsDialog(fmt_config) +{ + this->fmt_config = fmt_config; +} + +FFOptionsFormatDialog::~FFOptionsFormatDialog() +{ + close_window(); +} + +void FFOptionsFormatDialog::update_options(const char *options) +{ + fmt_config->lock_window("FFOptionsFormatDialog::update_options"); + fmt_config->format_options->update(options); + fmt_config->unlock_window(); +} + -FFOptionsViewAudio::FFOptionsViewAudio(FFMPEGConfigAudio *aud_config, int x, int y, const char *text) +FFOptionsViewAudio::FFOptionsViewAudio(FFMPEGConfigAudio *aud_config, + int x, int y, const char *text) : BC_GenericButton(x, y, text) { this->aud_config = aud_config; + avctx = 0; } FFOptionsViewAudio::~FFOptionsViewAudio() { + avcodec_free_context(&avctx); } int FFOptionsViewAudio::handle_event() { - char audio_format[BCSTRLEN]; audio_format[0] = 0; - char audio_codec[BCSTRLEN]; audio_codec[0] = 0; - AVCodec *codec = 0; + int ret = 0; Asset *asset = aud_config->asset; const char *name = asset->acodec; - if( !FFMPEG::get_format(audio_format, "audio", name) && - !FFMPEG::get_codec(audio_codec, "audio", name) ) - codec = avcodec_find_encoder_by_name(audio_codec); - if( !codec ) { + char *audio_format = aud_config->format_name; + char *audio_codec = aud_config->codec_name; + AVCodec *codec = !ret && + !FFMPEG::get_format(audio_format, "audio", name) && + !FFMPEG::get_codec(audio_codec, "audio", name) ? + avcodec_find_encoder_by_name(audio_codec) : 0; + if( !ret && !codec ) { eprintf(_("no codec named: %s: %s"), name, audio_codec); - return 1; + ret = 1; + } + avcodec_free_context(&avctx); + if( !ret && !(avctx = avcodec_alloc_context3(codec)) ) { + eprintf(_("no codec context: %s: %s"), name, audio_codec); + ret = 1; + } + if( !ret ) { + const void *obj = avctx->priv_data; + aud_config->start(obj); } - aud_config->ff_options_dialog->start(audio_format, audio_codec, codec, - asset->ff_audio_options, sizeof(asset->ff_audio_options)); return 1; } -FFOptionsViewVideo::FFOptionsViewVideo(FFMPEGConfigVideo *vid_config, int x, int y, const char *text) +FFOptionsViewVideo::FFOptionsViewVideo(FFMPEGConfigVideo *vid_config, + int x, int y, const char *text) : BC_GenericButton(x, y, text) { this->vid_config = vid_config; + avctx = 0; } FFOptionsViewVideo::~FFOptionsViewVideo() { + avcodec_free_context(&avctx); } int FFOptionsViewVideo::handle_event() { - char video_format[BCSTRLEN]; video_format[0] = 0; - char video_codec[BCSTRLEN]; video_codec[0] = 0; - AVCodec *codec = 0; + int ret = 0; Asset *asset = vid_config->asset; const char *name = asset->vcodec; - if( !FFMPEG::get_format(video_format, "video", name) && - !FFMPEG::get_codec(video_codec, "video", name) ) - codec = avcodec_find_encoder_by_name(video_codec); - if( !codec ) { + char *video_format = vid_config->format_name; + char *video_codec = vid_config->codec_name; + AVCodec *codec = !ret && + !FFMPEG::get_format(video_format, "video", name) && + !FFMPEG::get_codec(video_codec, "video", name) ? + avcodec_find_encoder_by_name(video_codec) : 0; + if( !ret && !codec ) { eprintf(_("no codec named: %s: %s"), name, video_codec); - return 1; + ret = 1; + } + avcodec_free_context(&avctx); + if( !ret && !(avctx = avcodec_alloc_context3(codec)) ) { + eprintf(_("no codec context: %s: %s"), name, video_codec); + ret = 1; + } + + if( !ret ) { + const void *obj = (const void *)avctx->priv_data; + vid_config->start(obj); } - vid_config->ff_options_dialog->start(video_format, video_codec, codec, - asset->ff_video_options, sizeof(asset->ff_video_options)); return 1; } +FFOptionsViewFormat::FFOptionsViewFormat(BC_WindowBase *parent_window, + EDL *edl, Asset *asset, int x, int y, const char *text) + : BC_GenericButton(x, y, text) +{ + this->parent_window = parent_window; + this->edl = edl; + this->asset = asset; + format_dialog = 0; +} + +FFOptionsViewFormat::~FFOptionsViewFormat() +{ + delete format_dialog; +} + +int FFOptionsViewFormat::handle_event() +{ + delete format_dialog; + int wx, wy; + get_pop_cursor(wx, wy); + format_dialog = new FFOptionsFormatViewDialog(this, wx, wy); + format_dialog->start(); + return 1; +} + + +FFOptionsFormatView::FFOptionsFormatView(FFMPEGConfigFormat *fmt_config, + int x, int y, const char *text) + : BC_GenericButton(x, y, text) +{ + this->fmt_config = fmt_config; + fmt_ctx = 0; +} + +FFOptionsFormatView::~FFOptionsFormatView() +{ + avformat_free_context(fmt_ctx); +} + +int FFOptionsFormatView::handle_event() +{ + Asset *asset = fmt_config->asset; + char *format_name = asset->fformat; + avformat_free_context(fmt_ctx); fmt_ctx = 0; + int ret = avformat_alloc_output_context2(&fmt_ctx, 0, format_name, 0); + if( ret || !fmt_ctx ) { + eprintf(_("no format named: %s"), format_name); + ret = 1; + } + if( !ret ) { + const void *obj = fmt_ctx->priv_data; + fmt_config->start(obj); + } + return 1; +} + +FFOptionsFormatViewDialog::FFOptionsFormatViewDialog(FFOptionsViewFormat *view_format, + int wx, int wy) +{ + this->view_format = view_format; + this->wx = wx; + this->wy = wy; + cfg_window = 0; +} + +FFOptionsFormatViewDialog::~FFOptionsFormatViewDialog() +{ + close_window(); +} + +BC_Window *FFOptionsFormatViewDialog::new_gui() +{ + cfg_window = new FFMPEGConfigFormat(this, wx, wy, + view_format->asset, view_format->edl); + cfg_window->create_objects(); + return cfg_window; +} + +void FFOptionsFormatViewDialog::handle_done_event(int result) +{ + if( !result ) { + char *options = cfg_window->get_options(); + int options_len = cfg_window->get_options_len(); + cfg_window->ff_options_dialog->store_options(options, options_len); + cfg_window->ff_options_dialog->update_options(options); + } + cfg_window = 0; +} + diff --git a/cinelerra-5.1/cinelerra/fileffmpeg.h b/cinelerra-5.1/cinelerra/fileffmpeg.h index 5453b77c..56176a42 100644 --- a/cinelerra-5.1/cinelerra/fileffmpeg.h +++ b/cinelerra-5.1/cinelerra/fileffmpeg.h @@ -155,15 +155,37 @@ public: void update_formats(); }; -class FFMPEGConfigAudio : public BC_Window +class FFMPEGConfigWindow : public BC_Window { public: - FFMPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset, EDL *edl); + FFMPEGConfigWindow(const char *title, BC_WindowBase *parent_window, + int x, int y, int w, int h, Asset *asset, EDL *edl); + ~FFMPEGConfigWindow(); + virtual char *get_options() = 0; + virtual int get_options_len() = 0; + void start(const void *obj); + + BC_WindowBase *parent_window; + FFOptionsDialog *ff_options_dialog; + Asset *asset; + EDL *edl; + const void *obj; + char *format_name; + char *codec_name; +}; + +class FFMPEGConfigAudio : public FFMPEGConfigWindow +{ +public: + FFMPEGConfigAudio(BC_WindowBase *parent_window, + int x, int y, Asset *asset, EDL *edl); ~FFMPEGConfigAudio(); void create_objects(); int close_event(); void load_options(); + char *get_options(); + int get_options_len(); FFMpegSampleFormat *sample_format; ArrayList presets; @@ -172,9 +194,8 @@ public: FFMpegAudioQuality *quality; FFAudioOptions *audio_options; BC_WindowBase *parent_window; - Asset *asset; - EDL *edl; - FFOptionsDialog *ff_options_dialog; + FFOptionsViewAudio *view_audio; + FFOptionsViewFormat *view_format; }; class FFAudioOptions : public BC_ScrollTextBox @@ -195,22 +216,14 @@ public: FFMPEGConfigAudio *popup; }; - -class FFMPEGConfigAudioToggle : public BC_CheckBox +class FFMPEGConfigVideo : public FFMPEGConfigWindow { public: - FFMPEGConfigAudioToggle(FFMPEGConfigAudio *popup, - char *title_text, int x, int y, int *output); - int handle_event(); - int *output; - FFMPEGConfigAudio *popup; -}; - -class FFMPEGConfigVideo : public BC_Window -{ -public: - FFMPEGConfigVideo(BC_WindowBase *parent_window, Asset *asset, EDL *edl); + FFMPEGConfigVideo(BC_WindowBase *parent_window, + int x, int y, Asset *asset, EDL *edl); ~FFMPEGConfigVideo(); + char *get_options(); + int get_options_len(); void create_objects(); int close_event(); @@ -223,9 +236,8 @@ public: FFMpegVideoBitrate *bitrate; FFMpegVideoQuality *quality; FFVideoOptions *video_options; - Asset *asset; - EDL *edl; - FFOptionsDialog *ff_options_dialog; + FFOptionsViewVideo *view_video; + FFOptionsViewFormat *view_format; }; class FFVideoOptions : public BC_ScrollTextBox @@ -245,16 +257,33 @@ public: FFMPEGConfigVideo *popup; }; -class FFMPEGConfigVideoToggle : public BC_CheckBox +class FFMPEGConfigFormat : public FFMPEGConfigWindow { public: - FFMPEGConfigVideoToggle(FFMPEGConfigVideo *popup, - char *title_text, int x, int y, int *output); - int handle_event(); - int *output; - FFMPEGConfigVideo *popup; + FFMPEGConfigFormat(FFOptionsFormatViewDialog *view_dialog, + int x, int y, Asset *asset, EDL *edl); + ~FFMPEGConfigFormat(); + char *get_options(); + int get_options_len(); + + void create_objects(); + int close_event(); + void load_options(); + + FFOptionsFormatViewDialog *view_dialog; + FFFormatOptions *format_options; +}; + +class FFFormatOptions : public BC_ScrollTextBox +{ +public: + FFFormatOptions(FFMPEGConfigFormat *format_popup, + int x, int y, int w, int rows, int size, char *text); + + FFMPEGConfigFormat *format_popup; }; + class FFMPEGScanProgress : public Thread { public: @@ -400,7 +429,7 @@ public: class FFOptionsWindow : public BC_Window { public: - FFOptionsWindow(FFOptionsDialog *dialog); + FFOptionsWindow(FFOptionsDialog *dialog, int x, int y); ~FFOptionsWindow(); void create_objects(); @@ -425,22 +454,20 @@ public: class FFOptionsDialog : public BC_DialogThread { public: - FFOptionsDialog(); + FFOptionsDialog(FFMPEGConfigWindow *cfg_window); ~FFOptionsDialog(); virtual void update_options(const char *options) = 0; void load_options(const char *bp, int len); void store_options(char *cp, int len); - void start(const char *format_name, const char *codec_name, - AVCodec *codec, const char *options, int len); + void start(); BC_Window* new_gui(); void handle_done_event(int result); + FFMPEGConfigWindow *cfg_window; FFOptionsWindow *options_window; - const char *format_name, *codec_name; - AVCodec *codec; AVDictionary *ff_opts; - int ff_len; + int wx, wy; }; class FFOptionsAudioDialog : public FFOptionsDialog @@ -463,7 +490,17 @@ public: ~FFOptionsVideoDialog(); }; -class FFOptionsViewAudio: public BC_GenericButton +class FFOptionsFormatDialog : public FFOptionsDialog +{ +public: + FFMPEGConfigFormat *fmt_config; + void update_options(const char *options); + + FFOptionsFormatDialog(FFMPEGConfigFormat *fmt_config); + ~FFOptionsFormatDialog(); +}; + +class FFOptionsViewAudio : public BC_GenericButton { public: FFOptionsViewAudio(FFMPEGConfigAudio *aud_config, int x, int y, const char *text); @@ -471,6 +508,7 @@ public: int handle_event(); FFMPEGConfigAudio *aud_config; + AVCodecContext *avctx; }; class FFOptionsViewVideo : public BC_GenericButton @@ -481,6 +519,45 @@ public: int handle_event(); FFMPEGConfigVideo *vid_config; + AVCodecContext *avctx; +}; + +class FFOptionsViewFormat : public BC_GenericButton +{ +public: + FFOptionsViewFormat(BC_WindowBase *parent_window, + EDL *edl, Asset *asset, int x, int y, const char *text); + ~FFOptionsViewFormat(); + + int handle_event(); + BC_WindowBase *parent_window; + EDL *edl; + Asset *asset; + FFOptionsFormatViewDialog *format_dialog; +}; + +class FFOptionsFormatView : public BC_GenericButton +{ +public: + FFOptionsFormatView(FFMPEGConfigFormat *fmt_config, int x, int y, const char *text); + ~FFOptionsFormatView(); + int handle_event(); + + FFMPEGConfigFormat *fmt_config; + AVFormatContext *fmt_ctx; +}; + +class FFOptionsFormatViewDialog : public BC_DialogThread +{ +public: + FFOptionsFormatViewDialog(FFOptionsViewFormat *view_format, int wx, int wy); + ~FFOptionsFormatViewDialog(); + BC_Window* new_gui(); + void handle_done_event(int result); + + FFOptionsViewFormat *view_format; + FFMPEGConfigFormat *cfg_window; + int wx, wy; }; #endif diff --git a/cinelerra-5.1/cinelerra/fileffmpeg.inc b/cinelerra-5.1/cinelerra/fileffmpeg.inc index 4525a5a7..b51e5d91 100644 --- a/cinelerra-5.1/cinelerra/fileffmpeg.inc +++ b/cinelerra-5.1/cinelerra/fileffmpeg.inc @@ -26,17 +26,22 @@ class FileFFMPEG; class FFMpegConfigNum; class FFMpegAudioNum; class FFMpegAudioBitrate; +class FFMpegAudioQuality; class FFMpegVideoNum; class FFMpegVideoBitrate; class FFMpegVideoQuality; +class FFMpegPixFmtItems; +class FFMpegPixelFormat; +class FFMpegSampleFormat; +class FFMPEGConfigWindow; class FFMPEGConfigAudio; class FFAudioOptions; class FFMPEGConfigAudioPopup; -class FFMPEGConfigAudioToggle; class FFMPEGConfigVideo; class FFVideoOptions; class FFMPEGConfigVideoPopup; -class FFMPEGConfigVideoToggle; +class FFMPEGConfigFormat; +class FFFormatOptions; class FFMPEGScanProgress; class FFOptions_OptName; @@ -44,15 +49,24 @@ class FFOptions_OptValue; class FFOptions_Opt; class FFOptions; class FFOptions_OptPanel; +class FFOptionsKindItem; +class FFOptionsKind; class FFOptionsUnits; class FFOptionsText; class FFOptionsApply; class FFOptionsWindow; class FFOptionsDialog; -class FFOptionsKindItem; -class FFOptionsKind; +class FFOptionsAudioDialog; +class FFOptionsVideoDialog; +class FFOptionsFormatDialog; +class FFOptionsViewAudio; +class FFOptionsViewVideo; +class FFOptionsViewFormat; +class FFOptionsFormatView; +class FFOptionsFormatViewDialog; #define FF_KIND_CODEC 0 -#define FF_KIND_FFMPEG 1 +#define FF_KIND_FORMAT 1 +#define FF_KIND_FFMPEG 2 #endif diff --git a/cinelerra-5.1/cinelerra/filegif.C b/cinelerra-5.1/cinelerra/filegif.C index 6f4e3e43..bb26762b 100644 --- a/cinelerra-5.1/cinelerra/filegif.C +++ b/cinelerra-5.1/cinelerra/filegif.C @@ -32,6 +32,14 @@ #include #include +//from "getarg.h" +extern "C" +int GifQuantizeBuffer(unsigned int Width, unsigned int Height, + int *ColorMapSize, GifByteType * RedInput, + GifByteType * GreenInput, GifByteType * BlueInput, + GifByteType * OutputBuffer, + GifColorType * OutputColorMap); + FileGIF::FileGIF(Asset *asset, File *file) : FileBase(asset, file) { diff --git a/cinelerra-5.1/cinelerra/fileogg.C b/cinelerra-5.1/cinelerra/fileogg.C new file mode 100644 index 00000000..7302bcd1 --- /dev/null +++ b/cinelerra-5.1/cinelerra/fileogg.C @@ -0,0 +1,1910 @@ +/* + * 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 "asset.h" +#include "bcsignals.h" +#include "byteorder.h" +#include "clip.h" +#include "edit.h" +#include "file.h" +#include "fileogg.h" +#include "guicast.h" +#include "interlacemodes.h" +#include "language.h" +#include "mainerror.h" +#include "mutex.h" +#include "mwindow.inc" +#include "preferences.h" +#include "render.h" +#include "vframe.h" +#include "versioninfo.h" +#include "videodevice.inc" + +#include +#include +#include +#include +#include +#include + +/* This code was aspired by ffmpeg2theora */ +/* Special thanks for help on this code goes out to j@v2v.cc */ + + +#define READ_SIZE 4*66000 +#define SEEK_SIZE 2*66000 + +sync_window_t::sync_window_t(FILE *fp, Mutex *sync_lock, int64_t begin, int64_t end) +{ + ogg_sync_init(this); + this->fp = fp; + this->sync_lock = sync_lock; + this->file_begin = begin; + this->file_end = end; + filepos = -1; + bufpos = -1; + pagpos = -1; +} + +sync_window_t::~sync_window_t() +{ + ogg_sync_clear(this); +} + +int sync_window_t::ogg_read_locked(int buflen) +{ + char *buffer = ogg_sync_buffer(this, buflen); + int len = fread(buffer, 1, buflen, fp); + ogg_sync_wrote(this, len); + filepos += len; + return len; +} + +int sync_window_t::ogg_read_buffer(int buflen) +{ + sync_lock->lock("sync_window_t::ogg_read_buffer_at"); + fseeko(fp, filepos, SEEK_SET); + int len = ogg_read_locked(buflen); + sync_lock->unlock(); + return len; +} + +int sync_window_t::ogg_read_buffer_at(off_t filepos, int buflen) +{ + if( bufpos == filepos && buflen == this->filepos - bufpos ) + return buflen; + sync_lock->lock("sync_window_t::ogg_read_buffer_at"); + this->bufpos = filepos; + fseeko(fp, filepos, SEEK_SET); + this->filepos = filepos; + ogg_sync_reset(this); + int ret = ogg_read_locked(buflen); + sync_lock->unlock(); + return ret; +} + +// we never need to autoadvance when syncing, since our read chunks are larger than +// maximum page size +int sync_window_t::ogg_sync_and_take_page_out(ogg_page *og) +{ + og->header_len = 0; + og->body_len = 0; + og->header = 0; + og->body = 0; + int ret = ogg_sync_pageseek(this, og); + bufpos += abs(ret); // can be zero + return ret; +} + +int sync_window_t::ogg_sync_and_get_next_page(long serialno, ogg_page *og) +{ + int ret = 0, retries = 1000; + while( --retries >= 0 && (ret = ogg_sync_and_take_page_out(og)) < 0 ); + if( ret >= mn_pagesz && ogg_page_serialno(og) != serialno ) + ret = ogg_get_next_page(serialno, og); + if( ret ) { + pagpos = bufpos - (og->header_len + og->body_len); + return 1; + } + return 0; +} + +int sync_window_t::ogg_get_next_page(long serialno, ogg_page *og) +{ + int ret = 0, retries = 1000; + while( --retries >= 0 && (ret=ogg_take_page_out_autoadvance(og)) && + ogg_page_serialno(og) != serialno ); + if( ret ) { + pagpos = bufpos - (og->header_len + og->body_len); +} + else + printf("ogg_get_next_page missed\n"); + return ret; +} + +int sync_window_t::ogg_prev_page_search(long serialno, ogg_page *og, + off_t begin, off_t end) +{ + ogg_page page; + int retries = 100, ret = 0; + int64_t ppos = -1; + while( ppos < 0 && --retries >= 0 ) { + int64_t fpos = end; + int read_len = SEEK_SIZE; + fpos -= read_len; + if( fpos < begin ) { + read_len += fpos - begin; + if( read_len <= 0 ) break; + fpos = begin; + } + read_len = ogg_read_buffer_at(fpos, read_len); + if( read_len <= 0 ) return 0; + while( (ret=ogg_sync_and_take_page_out(&page)) < 0 ); + end = bufpos; + while( ret > 0 ) { + if( ogg_page_serialno(&page) == serialno ) { + memcpy(og, &page, sizeof(page)); + ppos = bufpos - (page.header_len + page.body_len); + } + ret = ogg_sync_pageout(this, &page); + bufpos += page.header_len + page.body_len; + } + } + if( ppos >= 0 ) { + pagpos = ppos; + return 1; + } + printf("ogg_prev_page_search missed\n"); + return 0; +} + +int sync_window_t::ogg_get_prev_page(long serialno, ogg_page *og) +{ + return ogg_prev_page_search(serialno, og, file_begin, pagpos); +} + +int sync_window_t::ogg_get_first_page(long serialno, ogg_page *og) +{ + ogg_read_buffer_at(file_begin, SEEK_SIZE); + return ogg_sync_and_get_next_page(serialno, og); +} + +int sync_window_t::ogg_get_last_page(long serialno, ogg_page *og) +{ + + ogg_page page; + off_t filepos = file_end - READ_SIZE; + if( filepos < 0 ) filepos = 0; + int ret = 0, first_page_offset = 0; + while( !ret && filepos >= 0 ) { + int readlen = ogg_read_buffer_at(filepos, READ_SIZE); + int page_offset = 0, page_length = 0; + int first_page = 1; // read all pages in the buffer + while( first_page || page_length ) { + // if negative, skip bytes + while( (page_length = ogg_sync_and_take_page_out(&page)) < 0 ) + page_offset -= page_length; + if( page_length < mn_pagesz ) continue; + if( first_page ) { + first_page = 0; + first_page_offset = page_offset; + } + if( ogg_page_serialno(&page) == serialno ) { + // return last match page + pagpos = bufpos - (page.header_len + page.body_len); + memcpy(og, &page, sizeof(page)); + ret = 1; + } + } + filepos -= readlen - first_page_offset; // move backward + } + return ret; +} + +OGG_PageBfr::OGG_PageBfr() +{ + allocated = len = 0; + valid = packets = 0; + position = 0; + page = 0; +} + +OGG_PageBfr::~OGG_PageBfr() +{ + delete [] page; +} + +void OGG_PageBfr::demand(int sz) +{ + if( allocated >= sz ) return; + uint8_t *new_page = new uint8_t[sz]; + memcpy(new_page, page, len); + delete [] page; page = new_page; + allocated = sz; +} + +int OGG_PageBfr::write_page(FILE *fp) +{ + int sz = fwrite(page, 1, len, fp); + if( sz != len ) return -1; + ogg_page op; // kludgy + op.header = page; op.header_len = len; + op.body = page+len; op.body_len = 0; + packets -= ogg_page_packets(&op); + valid = len = 0; + return packets; +} + +int64_t OGG_PageBfr::load(ogg_page *og) +{ + int sz = og->header_len + og->body_len; + demand(sz); + memcpy(page, og->header, og->header_len); + memcpy(page+og->header_len, og->body, og->body_len); + len = sz; valid = 1; + position = ogg_page_granulepos(og); + return position; +} + + + +FileOGG::FileOGG(Asset *asset, File *file) + : FileBase(asset, file) +{ + if( asset->format == FILE_UNKNOWN ) + asset->format = FILE_OGG; + asset->byte_order = 0; + init(); + file_lock = new Mutex("OGGFile::Flush lock"); +} + +FileOGG::~FileOGG() +{ + close_file(); + delete file_lock; +} + + +void FileOGG::init() +{ + inp = 0; + out = 0; + audio = 0; + video = 0; + file_length = 0; + temp_frame = 0; + file_lock = 0; + ach = 0; + ahz = 0; + asz = 0; + amn = 0; + amx = 0; + abr = 0; + avbr = 0; + aqu = 0; + afrmsz = 0; + pcm_history = 0; + pcm_channels = 0; + frame_position = 0; + sample_position = 0; + audiosync = 0; + videosync = 0; + file_begin = 0; + file_end = 0; + + memset(&to, 0, sizeof(to)); + memset(&vo, 0, sizeof(vo)); + ogg_sample_position = 0; + ogg_frame_position = 0; + next_sample_position = 0; + next_frame_position = 0; + start_sample = 0; + last_sample = 0; + start_frame = 0; + last_frame = 0; + audiotime = 0; + videotime = 0; + audio_pos = 0; audio_eos = 0; + video_pos = 0; video_eos = 0; + + keyframe_granule_shift = 0; + iframe_granule_offset = 0; + theora_cmodel = BC_YUV420P; + enc = 0; + dec = 0; + memset(&ti, 0, sizeof(ti)); + ts = 0; + memset(&tc, 0, sizeof(tc)); + memset(&vi, 0, sizeof(vi)); + memset(&vc, 0, sizeof(vc)); + memset(&vd, 0, sizeof(vd)); + memset(&vb, 0, sizeof(vb)); + force_keyframes = 0; + vp3_compatible = 0; + soft_target = 0; + + pic_x = pic_y = 0; + pic_w = pic_h = 0; + frame_w = frame_h = 0; + colorspace = OC_CS_UNSPECIFIED; + pixfmt = TH_PF_420; + bitrate = 0; quality = 0; + keyframe_period = 0; + keyframe_force = 0; + fps_num = fps_den = 0; + aratio_num = aratio_den = 0; +} + + +static int ilog(unsigned v) +{ + int ret = 0; + while( v ) { ++ret; v >>= 1; } + return ret; +} + +int FileOGG::encode_theora_init() +{ + ogg_stream_init(&to, rand()); + th_info_init(&ti); + pic_w = asset->width, pic_h = asset->height; + frame_w = (pic_w+0x0f) & ~0x0f; + frame_h = (pic_h+0x0f) & ~0x0f; + pic_x = ((frame_w-pic_w) >> 1) & ~1; + pic_y = ((frame_h-pic_h) >> 1) & ~1; + fps_num = asset->frame_rate * 1000000; + fps_den = 1000000; + if( asset->aspect_ratio > 0 ) { + // Cinelerra uses frame aspect ratio, theora uses pixel aspect ratio + float pixel_aspect = asset->aspect_ratio / asset->width * asset->height; + aratio_num = pixel_aspect * 1000000; + aratio_den = 1000000; + } + else { + aratio_num = 1000000; + aratio_den = 1000000; + } + if( EQUIV(asset->frame_rate, 25) || EQUIV(asset->frame_rate, 50) ) + colorspace = OC_CS_ITU_REC_470BG; + else if( (asset->frame_rate > 29 && asset->frame_rate < 31) || + (asset->frame_rate > 59 && asset->frame_rate < 61) ) + colorspace = OC_CS_ITU_REC_470M; + else + colorspace = OC_CS_UNSPECIFIED; + pixfmt = TH_PF_420; + if( asset->theora_fix_bitrate ) { + bitrate = asset->theora_bitrate; + quality = -1; + } + else { + bitrate = -1; + quality = asset->theora_quality; // 0-63 + } + keyframe_period = asset->theora_keyframe_frequency; + keyframe_force = asset->theora_keyframe_force_frequency; + vp3_compatible = 1; + soft_target = 0; + + ti.frame_width = frame_w; + ti.frame_height = frame_h; + ti.pic_width = pic_w; + ti.pic_height = pic_h; + ti.pic_x = pic_x; + ti.pic_y = pic_x; + ti.colorspace = (th_colorspace)colorspace; + ti.pixel_fmt = (th_pixel_fmt)pixfmt; + ti.target_bitrate = bitrate; + ti.quality = quality; + ti.fps_numerator = fps_num; + ti.fps_denominator = fps_den; + ti.aspect_numerator = aratio_num; + ti.aspect_denominator = aratio_den; + ti.keyframe_granule_shift = ilog(keyframe_period-1); + + enc = th_encode_alloc(&ti); + int ret = enc ? 0 : 1; + if( !ret && force_keyframes ) + ret = th_encode_ctl(enc,TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, + &keyframe_period, sizeof(keyframe_period)); + if( !ret && vp3_compatible ) + ret = th_encode_ctl(enc,TH_ENCCTL_SET_VP3_COMPATIBLE, + &vp3_compatible, sizeof(vp3_compatible)); + if( !ret && soft_target ) { + int arg = TH_RATECTL_CAP_UNDERFLOW; + if( th_encode_ctl(enc, TH_ENCCTL_SET_RATE_FLAGS, &arg, sizeof(arg)) < 0 ) { + eprintf(_("Could not set rate flags")); + ret = 1; + } + int kr = keyframe_period*7>>1, fr = 5*fps_num/fps_den; + arg = kr > fr ? kr : fr; + if( th_encode_ctl(enc, TH_ENCCTL_SET_RATE_BUFFER, &arg, sizeof(arg)) ) { + eprintf(_("Could not set rate buffer")); + ret = 1; + } + } + if( ret ) { + eprintf(_("theora init context failed")); + return 1; + } + + th_comment_init(&tc); + th_comment_add_tag(&tc, (char*)"ENCODER", + (char*)PROGRAM_NAME " " CINELERRA_VERSION); + ogg_page og; + ogg_packet op; + ret = th_encode_flushheader(enc, &tc, &op); + if( ret <= 0 ) return 1; + ogg_stream_packetin(&to, &op); + ret = ogg_stream_pageout(&to, &og) != 1 ? 1 : 0; + if( !ret ) { + fwrite(og.header, 1, og.header_len, out); + fwrite(og.body, 1, og.body_len, out); + } + if( ret ) { + eprintf(_("write header out failed")); + return 1; + } + while( (ret=th_encode_flushheader(enc, &tc, &op)) > 0 ) + ogg_stream_packetin(&to, &op); + if( ret ) { + eprintf(_("ogg_encoder_init video failed")); + return 1; + } + return 0; +} + +int FileOGG::encode_vorbis_init() +{ + ach = asset->channels; + ahz = asset->sample_rate; + amx = asset->vorbis_max_bitrate; + amn = asset->vorbis_min_bitrate; + abr = asset->vorbis_bitrate; + avbr = asset->vorbis_vbr; + asz = sizeof(short); + afrmsz = asz * ach; + aqu = -99; + ogg_stream_init(&vo, rand()); + vorbis_info_init(&vi); + int ret = 0; + if( avbr ) { + ret = vorbis_encode_setup_managed(&vi, ach, ahz, -1, abr, -1); + if( !ret ) + ret = vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, 0); + if( !ret ) + ret = vorbis_encode_setup_init(&vi); + } + else + ret = vorbis_encode_init(&vi, ach, ahz, amx, abr, amn); + if( ret ) { + eprintf(_("ogg_encoder_init audio init failed")); + return 1; + } + vorbis_comment_init(&vc); + vorbis_comment_add_tag(&vc, (char*)"ENCODER", + (char*)PROGRAM_NAME " " CINELERRA_VERSION); + vorbis_analysis_init(&vd, &vi); + vorbis_block_init(&vd, &vb); + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + vorbis_analysis_headerout(&vd, &vc, + &header, &header_comm, &header_code); + ogg_stream_packetin(&vo, &header); + ogg_page og; + ret = ogg_stream_pageout(&vo, &og)==1 ? 0 : -1; + if( ret >= 0 ) { + fwrite(og.header, 1, og.header_len, out); + fwrite(og.body, 1, og.body_len, out); + ogg_stream_packetin(&vo, &header_comm); + ogg_stream_packetin(&vo, &header_code); + } + if( ret < 0 ) { + eprintf(_("ogg_encoder_init audio failed")); + return 1; + } + return 0; +} + +int FileOGG::ogg_init_encode(FILE *out) +{ + this->out = out; + srand(time(0)); + video = asset->video_data; + if( video && encode_theora_init() ) + return 1; + audio = asset->audio_data; + if( audio && encode_vorbis_init() ) + return 1; + ogg_page og; + int ret = 0; + if( !ret && video ) { + while( (ret=ogg_stream_flush(&to, &og)) > 0 ) { + fwrite(og.header, 1, og.header_len, out); + fwrite(og.body, 1, og.body_len, out); + } + } + if( !ret && audio ) { + while( (ret=ogg_stream_flush(&vo, &og)) > 0 ) { + fwrite(og.header, 1, og.header_len, out); + fwrite(og.body, 1, og.body_len, out); + } + } + if( ret < 0 ) { + eprintf(_("render init failed")); + return 1; + } + return 0; +} + +int FileOGG::decode_theora_init() +{ + dec = th_decode_alloc(&ti, ts); + if( !dec ) { + eprintf(_("Error in probe data")); + return 1; + } + keyframe_granule_shift = ti.keyframe_granule_shift; + iframe_granule_offset = th_granule_frame(dec, 0); + double fps = (double)ti.fps_numerator/ti.fps_denominator; + + videosync = new sync_window_t(inp, file_lock, file_begin, file_end); + ogg_page og; + int ret = videosync->ogg_get_first_page(to.serialno, &og); + if( ret <= 0 ) { + eprintf(_("cannot read video page from file")); + return 1; + } + videosync->file_begin = videosync->pagpos; + ret = videosync->ogg_get_first_page(to.serialno, &og); + // video data starts here + // get to the page of the finish of the first packet + while( ret > 0 && !ogg_page_packets(&og) ) { + if( ogg_page_granulepos(&og) != -1 ) { + printf(_("FileOGG: Broken ogg file - broken page:" + " ogg_page_packets == 0 and granulepos != -1\n")); + return 1; + } + ret = videosync->ogg_get_next_page(to.serialno, &og); + } + // video frames start here + start_frame = ogg_frame_pos(&og); + ret = videosync->ogg_get_first_page(to.serialno, &og); + if( ret <= 0 ) { + printf(_("FileOGG: Cannot read data past header\n")); + return 1; + } +//printf("start frame = %jd, gpos %jd, begins %jd\n", +// start_frame, ogg_page_granulepos(&og), videosync->file_begin); + + ret = videosync->ogg_get_last_page(to.serialno, &og); + while( ret > 0 && !ogg_page_packets(&og) ) + ret = videosync->ogg_get_prev_page(to.serialno, &og); + if( ret > 0 ) { + last_frame = ogg_next_frame_pos(&og); + if( start_frame >= last_frame ) { + eprintf(_("no video frames in file")); + last_frame = start_frame = 0; + } + asset->video_length = last_frame - start_frame; + } + else { + printf("FileOGG: Cannot find the video length\n"); + return 1; + } + asset->layers = 1; + asset->width = ti.pic_width; + asset->height = ti.pic_height; +// Don't want a user configured frame rate to get destroyed + if( !asset->frame_rate ) + asset->frame_rate = fps; +// All theora material is noninterlaced by definition + if( !asset->interlace_mode ) + asset->interlace_mode = ILACE_MODE_NOTINTERLACED; + + set_video_position(0); // make sure seeking is done to the first sample + ogg_frame_position = -10; + asset->video_data = 1; + strncpy(asset->vcodec, "theo", 4); +// report_colorspace(&ti); +// dump_comments(&tc); + return 0; +} + +int FileOGG::decode_vorbis_init() +{ + ogg_stream_reset(&vo); + vorbis_synthesis_init(&vd, &vi); + vorbis_block_init(&vd, &vb); + audiosync = new sync_window_t(inp, file_lock, file_begin, file_end); + ogg_page og; + int ret = audiosync->ogg_get_first_page(vo.serialno, &og); + if( ret <= 0 ) { + eprintf(_("cannot read audio page from file")); + return 1; + } + // audio data starts here + audiosync->file_begin = audiosync->pagpos; + // audio samples starts here + start_sample = ogg_sample_pos(&og); +//printf("start sample = %jd, gpos %jd, begins %jd\n", +// start_sample, ogg_page_granulepos(&og), audiosync->file_begin); + ret = audiosync->ogg_get_last_page(vo.serialno, &og); + last_sample = ret > 0 ? ogg_next_sample_pos(&og) : 0; + asset->audio_length = last_sample - start_sample; + if( asset->audio_length <= 0 ) { + eprintf(_("no audio samples in file")); + asset->audio_length = 0; + last_sample = start_sample; + } + + asset->channels = vi.channels; + if( !asset->sample_rate ) + asset->sample_rate = vi.rate; + asset->audio_data = 1; + + ogg_sample_position = -10; + set_audio_position(0); // make sure seeking is done to the first sample + strncpy(asset->acodec, "vorb", 4); + return 0; +} + +int FileOGG::ogg_init_decode(FILE *inp) +{ + if( !inp ) return 1; + this->inp = inp; + struct stat file_stat; /* get file length */ + file_end = stat(asset->path, &file_stat)>=0 ? file_stat.st_size : 0; + if( file_end < mn_pagesz ) return 1; + fseek(inp, 0, SEEK_SET); + vorbis_info_init(&vi); + vorbis_comment_init(&vc); + th_comment_init(&tc); + th_info_init(&ti); + ogg_page og; + ogg_packet op; + sync_window_t sy(inp, file_lock, 0, file_end); + int ret = sy.ogg_read_buffer_at(0, READ_SIZE); + if( ret < mn_pagesz ) return 1; + if( !sy.ogg_sync_and_take_page_out(&og) ) return 1; + ogg_stream_state tst; + + while( ogg_page_bos(&og) ) { + ogg_stream_init(&tst, ogg_page_serialno(&og)); + ogg_stream_pagein(&tst, &og); + if( ogg_stream_packetout(&tst, &op) ) { + if( !video && th_decode_headerin(&ti, &tc, &ts, &op) >=0 ) { + ogg_stream_init(&to, ogg_page_serialno(&og)); + video = 1; + } + else if( !audio && vorbis_synthesis_headerin(&vi, &vc, &op) >=0 ) { + ogg_stream_init(&vo, ogg_page_serialno(&og)); + audio = 1; + } + } + ogg_stream_clear(&tst); + ret = sy.ogg_take_page_out_autoadvance(&og); + } + + if( !ret || !video && !audio ) + return 1; + + // expecting more a/v header packets + int vpkts = video ? 2 : 0; + int apkts = audio ? 2 : 0; + int retries = 100; + ret = 0; + while( --retries >= 0 && !ret && (vpkts || apkts) ) { + if( vpkts && ogg_page_serialno(&og) == to.serialno ) { + ogg_stream_init(&tst, to.serialno); + ogg_stream_pagein(&tst, &og); + while( !ret && vpkts > 0 ) { + while( (ret=ogg_stream_packetout(&tst, &op)) < 0 ); + if( !ret ) break; + --vpkts; + ret = !th_decode_headerin(&ti, &tc, &ts, &op) ? 1 : 0; + } + if( ret ) + printf("theora header error\n"); + ogg_stream_clear(&tst); + } + else if( apkts && ogg_page_serialno(&og) == vo.serialno ) { + ogg_stream_init(&tst, vo.serialno); + ogg_stream_pagein(&tst, &og); + while( !ret && apkts > 0 ) { + while( (ret=ogg_stream_packetout(&tst, &op)) < 0 ); + if( !ret ) break; + --apkts; + ret = vorbis_synthesis_headerin(&vi, &vc, &op) ? 1 : 0; + } + if( ret ) + printf("vorbis header error\n"); + ogg_stream_clear(&tst); + } + if( !ret && !sy.ogg_take_page_out_autoadvance(&og) ) + ret = 1; + if( ret ) + printf("incomplete headers\n"); + + } +// find first start packet (not continued) with data + int64_t start_pos = sy.bufpos - (og.header_len + og.body_len); + if( !ret ) { + while( --retries >= 0 && !ret && !ogg_page_packets(&og) ) { + if( !ogg_page_continued(&og) ) + start_pos = sy.bufpos - (og.header_len + og.body_len); + if( !sy.ogg_take_page_out_autoadvance(&og) ) ret = 1; + } + if( ret ) + printf("no data past headers\n"); + if( audio && apkts ) + printf("missed %d audio headers\n",apkts); + if( video && vpkts ) + printf("missed %d video headers\n",vpkts); + } + if( retries < 0 || ret || (audio && apkts) || (video && vpkts) ) { + eprintf(_("Error in headers")); + return 1; + } + // headers end here + file_begin = start_pos; + + if( video && decode_theora_init() ) + return 1; + if( audio && decode_vorbis_init() ) + return 1; + return 0; +} + +void FileOGG::close_encoder() +{ +// flush streams + if( audio ) + write_samples_vorbis(0, 0, 1); + if( video ) + write_frames_theora(0, 1, 1); + flush_ogg(1); + + if( audio ) { + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + vorbis_comment_clear(&vc); + vorbis_info_clear(&vi); + ogg_stream_clear(&vo); + audio = 0; + } + if( video ) { + th_comment_clear(&tc); + ogg_stream_clear(&to); + video = 0; + } + if( enc ) { + th_encode_free(enc); + enc = 0; + } + if( out ) { + fclose(out); + out = 0; + } +} + +void FileOGG::close_decoder() +{ + if( audio ) { + for( int i=0; icreate_objects(); + window->run_window(); + delete window; + } + else + if(video_options) + { + OGGConfigVideo *window = new OGGConfigVideo(parent_window, asset); + format_window = window; + window->create_objects(); + window->run_window(); + delete window; + } +} + + + +int sync_window_t::ogg_take_page_out_autoadvance(ogg_page *og) +{ + for(;;) { + int ret = ogg_sync_pageout(this, og); + if( ret < 0 ) { + printf("FileOGG: Lost sync reading input file\n"); + return 0; + } + if( ret > 0 ) { + bufpos += og->header_len + og->body_len; + return ret; + } + // need more data for page + if( !ogg_read_buffer(READ_SIZE) ) { + printf("FileOGG: Read past end of input file\n"); + return 0; // No more data + } + } + return 1; +} + + +int FileOGG::check_sig(Asset *asset) +{ + FILE *fp = fopen(asset->path, "rb"); + if( !fp ) return 0; +// Test for "OggS" + fseek(fp, 0, SEEK_SET); + char data[4]; + int ret = fread(data, 4, 1, fp) == 1 && + data[0] == 'O' && data[1] == 'g' && + data[2] == 'g' && data[3] == 'S' ? 1 : 0; + fclose(fp); + return ret; + +} + +int FileOGG::open_file(int rd, int wr) +{ + int ret = 1; + if( wr ) { + if( !(out = fopen(asset->path, "wb")) ) { + eprintf(_("Error while opening %s for writing. %m\n"), asset->path); + return 1; + } + if( (ret = ogg_init_encode(out)) && out ) { + fclose(out); out = 0; + } + } + else if( rd ) { + if( !(inp = fopen(asset->path, "rb")) ) { + eprintf(_("Error while opening %s for reading. %m\n"), asset->path); + return 1; + } + if( (ret = ogg_init_decode(inp)) && inp ) { + fclose(inp); inp = 0; + } + } + return ret; +} + +int FileOGG::close_file() +{ + if( file->wr ) + close_encoder(); + else if( file->rd ) + close_decoder(); + return 0; +} + + +int64_t FileOGG::ogg_sample_pos(ogg_page *og) +{ + ogg_packet op; + ogg_stream_state ss; + ogg_stream_init(&ss, vo.serialno); + ogg_stream_pagein(&ss, og); + int64_t bsz = 0; + long prev = -1; + int ret = 0; + while( (ret=ogg_stream_packetout(&ss, &op)) ) { + if( ret < 0 ) continue; // ignore holes + long sz = vorbis_packet_blocksize(&vi, &op); + if( prev != -1 ) bsz += (prev + sz) >> 2; + prev = sz; + } + ogg_stream_clear(&ss); + return ogg_next_sample_pos(og) - bsz; +} + +int64_t FileOGG::ogg_next_sample_pos(ogg_page *og) +{ + return ogg_page_granulepos(og); +} + +int64_t FileOGG::ogg_frame_pos(ogg_page *og) +{ + int64_t pos = th_granule_frame(dec, ogg_page_granulepos(og)) - ogg_page_packets(og); + if( ogg_page_continued(og) ) --pos; + return pos; +} + +int64_t FileOGG::ogg_next_frame_pos(ogg_page *og) +{ + return th_granule_frame(dec, ogg_page_granulepos(og)) + 1; +} + + +int FileOGG::ogg_get_page_of_sample(ogg_page *og, int64_t sample) +{ + if( sample >= asset->audio_length + start_sample ) { + printf(_("FileOGG: Illegal seek beyond end of samples\n")); + return 0; + } +// guess about position + int64_t file_length = audiosync->file_end - audiosync->file_begin; + off_t guess = file_length * (sample - start_sample) / + asset->audio_length - SEEK_SIZE; + if( guess < 0 ) guess = 0; + guess += audiosync->file_begin; + audiosync->ogg_read_buffer_at(guess, READ_SIZE); + if( !audiosync->ogg_sync_and_get_next_page(vo.serialno, og) ) { + printf(_("FileOGG: llegal seek no pages\n")); + return 0; + } + int ret = 1; + while( ret && (ogg_page_granulepos(og) == -1 || !ogg_page_packets(og)) ) + ret = videosync->ogg_get_next_page(to.serialno, og); + if( !ret ) return 0; + // linear seek to the sample + int missp = 0, missm = 0; + int64_t next_pos = ogg_next_sample_pos(og); + if( sample >= next_pos ) { // scan forward + while( sample >= next_pos ) { + while( !(ret=audiosync->ogg_get_next_page(vo.serialno, og)) && + (ogg_page_granulepos(og) == -1 || !ogg_page_packets(og)) ); + if( !ret ) break; + next_pos = ogg_next_sample_pos(og); + ++missp; +//printf("audio %jd next %jd %jd\n", sample, ogg_sample_pos(og), next_pos); + } + } + else { // scan backward + int64_t pos = ogg_sample_pos(og); + while( sample < pos ) { + while( (ret=audiosync->ogg_get_prev_page(vo.serialno, og)) && + (ogg_page_continued(og) && ogg_page_packets(og) == 1) ); + if( !ret ) break; + ++missm; + pos = ogg_sample_pos(og); +//printf("audio %jd prev %jd %jd\n", sample, pos, ogg_next_sample_pos(og)); + } + } +//printf("audio %d seek %jd, missp %d, missm %d from %jd to %jd\n", ret, +// sample, missp, missm, ogg_sample_pos(og), ogg_next_sample_pos(og)); + return ret; +} + +int FileOGG::ogg_seek_to_sample(int64_t ogg_sample) +{ + ogg_page og; + if( !ogg_get_page_of_sample(&og, ogg_sample) ) { + eprintf(_("Seeking to sample's page failed\n")); + return 0; + } + int ret = 1; + int64_t pos = ogg_sample_pos(&og); + int64_t next_pos = pos; + if( ogg_page_continued(&og) ) { + while( (ret=audiosync->ogg_get_prev_page(to.serialno, &og)) && + (ogg_page_packets(&og) == 0 && ogg_page_continued(&og)) ); + } + audio_eos = 0; + ogg_stream_reset(&vo); + ogg_stream_pagein(&vo, &og); + vorbis_synthesis_restart(&vd); + ogg_packet op; + while( (ret=ogg_get_audio_packet(&op)) != 0 && + op.granulepos < 0 ); + if( ret && !vorbis_synthesis(&vb, &op) ) { + vorbis_synthesis_blockin(&vd, &vb); + if( vorbis_synthesis_pcmout(&vd, 0) ) + ret = 0; + } + if( !ret ) { + eprintf(_("Something wrong while trying to seek\n")); + return 0; + } + + while( ogg_sample >= next_pos ) { + if( !(ret=ogg_get_audio_packet(&op)) ) break; + if( vorbis_synthesis(&vb, &op) ) continue; + vorbis_synthesis_blockin(&vd, &vb); + pos = next_pos; + next_pos += vorbis_synthesis_pcmout(&vd, NULL); + if( next_pos > ogg_sample ) break; + // discard decoded data before current sample + vorbis_synthesis_read(&vd, (next_pos - pos)); + } + if( ret ) { + audio_pos = next_pos; + vorbis_synthesis_read(&vd, (ogg_sample - pos)); + } + return ret; +} + + +int FileOGG::ogg_get_page_of_frame(ogg_page *og, int64_t frame) +{ + if( frame >= asset->video_length + start_frame ) { + eprintf(_("Illegal seek beyond end of frames\n")); + return 0; + } + if( frame < start_frame ) { + eprintf(_("Illegal seek before start of frames\n")); + return 0; + } + int64_t file_length = videosync->file_end - videosync->file_begin; + off_t guess = file_length * (frame - start_frame) / + asset->video_length - SEEK_SIZE; + if( guess < 0 ) guess = 0; + guess += videosync->file_begin; + videosync->ogg_read_buffer_at(guess, SEEK_SIZE); + videosync->ogg_sync_and_get_next_page(to.serialno, og); + // find the page with "real" ending + int ret = 1; + while( ret && (ogg_page_granulepos(og) == -1 || !ogg_page_packets(og)) ) + ret = videosync->ogg_get_next_page(to.serialno, og); + int64_t pos = ogg_next_frame_pos(og); + // linear search + int missp = 0, missm = 0; +// move back if continued + if( frame >= pos ) { + do { // scan forward + while( (ret=videosync->ogg_get_next_page(to.serialno, og)) && + ogg_page_packets(og) == 0 ); + if( !ret ) break; + missp++; + pos = ogg_next_frame_pos(og); +//printf("video %jd next %jd %jd\n", frame, ogg_frame_pos(og), pos); + } while( frame >= pos ); + } + else if( (pos=ogg_frame_pos(og)) > frame ) { + while( pos > start_frame && frame < pos ) { // scan backward + while( (ret=videosync->ogg_get_prev_page(to.serialno, og)) && + ogg_page_packets(og) == 0 && ogg_page_continued(og) ); + if( !ret ) break; + missm++; + pos = ogg_frame_pos(og); +//printf("video %jd next %jd %jd\n", frame, pos, ogg_next_frame_pos(og)); + } + } +//printf("video %d seek %jd, missp %d, missm %d first %jd, next %jd\n", ret, +// frame, missp, missm, ogg_frame_pos(og), ogg_next_frame_pos(og)); + return ret; +} + +int FileOGG::ogg_seek_to_keyframe(int64_t frame, int64_t *keyframe_number) +{ +//printf("ogg_seek_to_keyframe of === %jd\n", frame); + ogg_page og; + ogg_packet op; + int64_t ipagpos = -1; + int64_t istart = -1; + int64_t iframe = -1; + int ipkts = -1; + int retries = 1000, ret = 1; + while( --retries>=0 && frame>=start_frame ) { + if( !ogg_get_page_of_frame(&og, frame) ) break; + int64_t pos = ogg_frame_pos(&og); + istart = pos; + if( ogg_page_continued(&og) ) { + while( (ret=videosync->ogg_get_prev_page(to.serialno, &og)) && + (ogg_page_packets(&og) == 0 && ogg_page_continued(&og)) ); + } + int64_t pagpos = videosync->pagpos; + video_eos = 0; + ogg_stream_reset(&to); + ogg_stream_pagein(&to, &og); + int pkts = 0; + while( frame >= pos && (ret=ogg_get_video_packet(&op)) ) { + if( th_packet_iskeyframe(&op) == 1 ) { + ipagpos = pagpos; + iframe = pos; + ipkts = pkts; +//printf("keyframe %jd pkts %d\n", pos, pkts); + } +//printf("packet %jd pkts %d is a %d\n", pos, pkts, th_packet_iskeyframe(&op)); + ++pkts; ++pos; + } + if( ipagpos >= 0 ) break; + frame = istart - 1; + } + if( ipagpos < 0 ) { + printf(_("Seeking to keyframe %jd search failed\n"), frame); + return 0; + } + videosync->ogg_read_buffer_at(ipagpos, READ_SIZE); + videosync->ogg_sync_and_get_next_page(to.serialno, &og); + video_eos = 0; + ogg_stream_reset(&to); + ogg_stream_pagein(&to, &og); + video_pos = ogg_next_frame_pos(&og); +// skip prev packets +// int ipkts = iframe - ogg_frame_pos(&og); +//printf("iframe %jd, page %jd, ipkts %d\n", iframe, ogg_page_pageno(&og), ipkts); + while( --ipkts >= 0 ) + ogg_get_video_packet(&op); + *keyframe_number = iframe; + return 1; +} + + +int64_t FileOGG::get_video_position() +{ +// printf("GVP\n"); + return next_frame_position - start_frame; +} + +int64_t FileOGG::get_audio_position() +{ + return next_sample_position - start_sample; +} + +int FileOGG::set_video_position(int64_t x) +{ +// x=0; +// printf("SVP: %lli\n", x); + + next_frame_position = x + start_frame; + return 1; +} + + +int FileOGG::colormodel_supported(int colormodel) +{ +// printf("CMS\n"); + + if (colormodel == BC_YUV420P) + return BC_YUV420P; + else + return colormodel; +} +int FileOGG::get_best_colormodel(Asset *asset, int driver) +{ + + return BC_YUV420P; +} + +int FileOGG::set_audio_position(int64_t x) +{ + next_sample_position = x + start_sample; + return 0; +} + + +int FileOGG::ogg_get_video_packet(ogg_packet *op) +{ + int ret = 1; + while( (ret=ogg_stream_packetout(&to, op)) <= 0 ) { + if( video_eos ) return 0; + ogg_page og; + if( !videosync->ogg_get_next_page(to.serialno, &og) ) break; + if( ogg_page_granulepos(&og) >= 0 ) + video_pos = ogg_next_frame_pos(&og); + ogg_stream_pagein(&to, &og); + video_eos = ogg_page_eos(&og); + } + if( ret <= 0 ) { + printf("FileOGG: Cannot read video packet\n"); + return 0; + } + return 1; +} + +int FileOGG::read_frame(VFrame *frame) +{ + if( !inp || !video ) return 1; + // skip is cheaper than seek, do it... + int decode_frames = 0; + int expect_keyframe = 0; + if( ogg_frame_position >= 0 && + next_frame_position >= ogg_frame_position && + next_frame_position - ogg_frame_position < 32) { + decode_frames = next_frame_position - ogg_frame_position; + } + else if( next_frame_position != ogg_frame_position ) { + if( !ogg_seek_to_keyframe(next_frame_position, &ogg_frame_position) ) { + eprintf(_("Error while seeking to frame's keyframe" + " (frame: %jd, keyframe: %jd)\n"), + next_frame_position, ogg_frame_position); + return 1; + } + decode_frames = next_frame_position - ogg_frame_position + 1; + --ogg_frame_position; + if( decode_frames <= 0 ) { + eprintf(_("Error while seeking to keyframe," + " wrong keyframe number (frame: %jd, keyframe: %jd)\n"), + next_frame_position, ogg_frame_position); + return 1; + + } + expect_keyframe = 1; + } + int frames_remaining = asset->video_length - (video_pos - start_frame); + if( decode_frames > frames_remaining ) decode_frames = frames_remaining; + int ret = 0; + ogg_packet op; + while( decode_frames > 0 && !video_eos ) { + if( video_pos-start_frame >= asset->video_length ) + return 0; + if( !ogg_get_video_packet(&op) ) break; + if( expect_keyframe ) { + expect_keyframe = 0; + if( th_packet_iskeyframe(&op) <= 0 ) + eprintf(_("FileOGG: Expecting keyframe, but didn't get it\n")); + } + ogg_int64_t granpos = 0; + if( th_decode_packetin(dec, &op, &granpos) >= 0 ) + ret = 1; + ++ogg_frame_position; + --decode_frames; + } +//if(ret < 0 )printf("ret = %d\n", ret); + if( ret > 0 ) { + th_ycbcr_buffer ycbcr; + ret = th_decode_ycbcr_out(dec, ycbcr); + if( ret ) { + eprintf(_("th_decode_ycbcr_out failed with code %i\n"), ret); + ret = 0; // not always fatal + } + uint8_t *yp = ycbcr[0].data; + uint8_t *up = ycbcr[1].data; + uint8_t *vp = ycbcr[2].data; + int yst = ycbcr[0].stride; + int yw = ycbcr[0].width; + int yh = ycbcr[0].height; + VFrame temp_frame(yp, -1, 0, up-yp, vp-yp, yw,yh, BC_YUV420P, yst); + int px = ti.pic_x, py = ti.pic_y; + int pw = ti.pic_width, ph = ti.pic_height; + frame->transfer_from(&temp_frame, -1, px, py, pw, ph); + } + + next_frame_position++; + return ret; +} + + +int FileOGG::ogg_get_audio_packet(ogg_packet *op) +{ + int ret = 1; + while( (ret=ogg_stream_packetout(&vo, op)) <= 0 ) { + if( audio_eos ) return 0; + ogg_page og; + if( !audiosync->ogg_get_next_page(vo.serialno, &og) ) break; + if( ogg_page_granulepos(&og) >= 0 ) + audio_pos = ogg_next_sample_pos(&og); + ogg_stream_pagein(&vo, &og); + audio_eos = ogg_page_eos(&og); + } + if( ret <= 0 ) { + printf("FileOGG: Cannot read audio packet\n"); + return 0; + } + return 1; +} + +int FileOGG::ogg_decode_more_samples() +{ + ogg_packet op; + while( ogg_get_audio_packet(&op) ) { + if( !vorbis_synthesis(&vb, &op) ) { + vorbis_synthesis_blockin(&vd, &vb); + return 1; + } + } + ogg_sample_position = -11; + if( audio_eos ) return 0; + eprintf(_("Cannot find next page while trying to decode more samples\n")); + return 0; +} + +int FileOGG::move_history(int from, int to, int len) +{ + if( len > 0 ) { + for( int i=0; ichannels; ++i ) + memmove(pcm_history[i] + to, + pcm_history[i] + from, + sizeof(float) * len); + } + history_start = history_start + from - to; + if( history_start < 0 ) history_start = 0; + return 0; +} + +int FileOGG::read_samples(double *buffer, int64_t len) +{ + float **vorbis_buffer; + if( len <= 0 ) + return 0; + if( len > HISTORY_MAX ) { + eprintf(_("max samples=%d\n"), HISTORY_MAX); + return 1; + } + + if( !pcm_history ) { + pcm_history = new float*[asset->channels]; + for(int i = 0; i < asset->channels; i++) + pcm_history[i] = new float[HISTORY_MAX]; + history_start = -100000000; + history_size = 0; + } + + int64_t hole_start = -1; + int64_t hole_len = -1; + int64_t hole_absstart = -1; + int64_t hole_fill = 0; + + if( history_start < next_sample_position && + history_start + history_size > next_sample_position && + history_start + history_size < next_sample_position + len ) { + hole_fill = 1; + hole_start = history_start + history_size - next_sample_position; + hole_len = history_size - hole_start; + hole_absstart = next_sample_position + hole_start; + move_history(next_sample_position - history_start, 0, hole_start); + } + else if( next_sample_position < history_start && + history_start < next_sample_position + len ) { + hole_fill = 1; + hole_start = 0; + hole_len = history_start - next_sample_position; + hole_absstart = next_sample_position; + move_history(0, + history_start - next_sample_position, + history_size - history_start + next_sample_position); + + } + else if( next_sample_position >= history_start + history_size || + next_sample_position + len <= history_start ) { + hole_fill = 1; + hole_start = 0; + hole_len = HISTORY_MAX; + hole_absstart = next_sample_position; + history_start = hole_absstart; + history_size = hole_len; + } + + if( hole_fill ) { + if( hole_start < 0 || hole_len <= 0 || hole_absstart < 0 ) { + eprintf(_("Error in finding read file position\n")); + return 1; + } + + if( hole_absstart + hole_len > asset->audio_length + start_sample ) { + hole_len = asset->audio_length + start_sample - hole_absstart; + history_size = asset->audio_length + start_sample - history_start; + } + else { + history_size = HISTORY_MAX; + } + + int64_t samples_read = 0; + if( ogg_sample_position != hole_absstart ) { + ogg_sample_position = hole_absstart; + if( !ogg_seek_to_sample(ogg_sample_position) ) { + eprintf(_("Error while seeking to sample\n")); + return 1; + } + } + // now we have ogg_sample_positon aligned + int64_t samples_to_read = hole_len; + while( samples_read < hole_len ) { + int64_t samples_waiting = vorbis_synthesis_pcmout(&vd, &vorbis_buffer); + int64_t samples_avail = !samples_waiting && audio_eos ? + hole_len - samples_read : // silence after eos + samples_waiting ; + int64_t sample_demand = samples_to_read - samples_read; + int64_t sample_count = MIN(samples_avail, sample_demand); + if( sample_count > 0 ) { + for( int i=0; ichannels; ++i ) { + float *input = vorbis_buffer[i]; + float *output = pcm_history[i] + hole_start; + int sz = sample_count*sizeof(*output); + if( samples_waiting ) + memcpy(output, input, sz); + else + memset(output, 0, sz); + } + vorbis_synthesis_read(&vd, sample_count); + samples_read += sample_count; + ogg_sample_position += sample_count; + hole_start += sample_count; + } + + if( !ogg_decode_more_samples() ) break; + } + } + + if( next_sample_position < history_start || + next_sample_position + len > history_start + history_size ) { + printf(_("FileOGG:: History not aligned properly \n")); + printf(_("\tnext_sample_position: %jd, length: %jd\n"), next_sample_position, len); + printf(_("\thistory_start: %jd, length: %jd\n"), history_start, history_size); + return 1; + } + float *input = pcm_history[file->current_channel] + next_sample_position - history_start; + for (int i = 0; i < len; i++) + buffer[i] = input[i]; + + next_sample_position += len; + return 0; +} + + +int FileOGG::write_audio_page() +{ + int ret = apage.write_page(out); + if( ret < 0 ) + eprintf(_("error writing audio page\n")); + return ret; +} + +int FileOGG::write_video_page() +{ + int ret = vpage.write_page(out); + if( ret < 0 ) + eprintf(_("error writing video page\n")); + return ret; +} + +// flush out the ogg pages +void FileOGG::flush_ogg(int last) +{ + ogg_page og; + file_lock->lock("FileOGG::flush_ogg"); + for(;;) { +// this way seeking is much better, (per original fileogg) +// not sure if 32 packets is a good value. + int mx_pkts = 32; + if( video && !vpage.valid ) { + if( (vpage.packets > mx_pkts && ogg_stream_flush(&to, &og) > 0) || + ogg_stream_pageout(&to, &og) > 0 ) { + videotime = th_granule_time(enc, vpage.load(&og)); + } + } + if( audio && !apage.valid ) { + if( (apage.packets > mx_pkts && ogg_stream_flush(&vo, &og) > 0) || + ogg_stream_pageout(&vo, &og) > 0 ) { + audiotime = vorbis_granule_time(&vd, apage.load(&og)); + } + } + if( !audio && vpage.valid ) + write_video_page(); + else if( !video && apage.valid ) + write_audio_page(); + else if( !vpage.valid || !apage.valid ) + break; +// output earliest page + else if( videotime > audiotime ) // output earliest + write_audio_page(); + else + write_video_page(); + } + if( last ) { // at last + if( vpage.valid ) + write_video_page(); + if( apage.valid ) + write_audio_page(); + } + file_lock->unlock(); +} + + +int FileOGG::write_samples_vorbis(double **buffer, int64_t len, int last) +{ + if( !audio || !out ) return 1; + flush_ogg(0); + if( !last ) { + float **vorbis_buffer = vorbis_analysis_buffer(&vd, len); + for( int i=0; ichannels; ++i ) // double to float + for( int j=0; j < len; ++j ) + vorbis_buffer[i][j] = buffer[i][j]; + } + else + len = 0; + vorbis_analysis_wrote(&vd, len); + + while( vorbis_analysis_blockout(&vd, &vb) == 1 ) { + vorbis_analysis(&vb, 0); + vorbis_bitrate_addblock(&vb); + ogg_packet op; + while( vorbis_bitrate_flushpacket(&vd, &op) ) { + file_lock->lock("FileOGG::write_vorbis_audio"); + ogg_stream_packetin(&vo, &op); + ++apage.packets; + file_lock->unlock(); + } + } + return 0; +} + +int FileOGG::write_samples(double **buffer, int64_t len) +{ + if (len > 0) + return write_samples_vorbis(buffer, len, 0); + return 0; +} + + +int FileOGG::write_frames_theora(VFrame ***frames, int len, int last) +{ + if( !video || !out ) return 1; + for( int j=0; jget_bytes_per_line(); + ycbcr[0].data = temp_frame->get_y(); + ycbcr[1].width = frame_w/2; + ycbcr[1].height = frame_h/2; + ycbcr[1].stride = (temp_frame->get_bytes_per_line()+1)/2; + ycbcr[1].data = temp_frame->get_u(); + ycbcr[2].width = frame_w/2; + ycbcr[2].height = frame_h/2; + ycbcr[2].stride = (temp_frame->get_bytes_per_line()+1)/2; + ycbcr[2].data = temp_frame->get_v(); + if( th_encode_ycbcr_in(enc, ycbcr) ) { + eprintf(_("th_encode_ycbcr_in failed")); + return 1; + } + ogg_packet op; + while( th_encode_packetout(enc, last, &op) > 0 ) { + file_lock->lock(); + ogg_stream_packetin (&to, &op); + ++vpage.packets; + file_lock->unlock(); + } + } + if( last ) return 0; + if( !temp_frame ) + temp_frame = new VFrame (0, -1, frame_w, frame_h, theora_cmodel, -1); + VFrame *frame = frames[0][j]; + temp_frame->transfer_from(frame); + } + return 0; +} + +int FileOGG::write_frames(VFrame ***frames, int len) +{ + return write_frames_theora(frames, len, 0); +} + + + +OGGConfigAudio::OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset) + : BC_Window(PROGRAM_NAME ": Audio Compression", + parent_window->get_abs_cursor_x(1), + parent_window->get_abs_cursor_y(1), + xS(350), yS(250)) +{ + this->parent_window = parent_window; + this->asset = asset; +} + +OGGConfigAudio::~OGGConfigAudio() +{ + +} + +void OGGConfigAudio::create_objects() +{ +// add_tool(new BC_Title(10, 10, _("There are no audio options for this format"))); + + int x = xS(10), y = yS(10); + int x1 = xS(150); + char string[BCTEXTLEN]; + + lock_window("OGGConfigAudio::create_objects"); + add_tool(fixed_bitrate = new OGGVorbisFixedBitrate(x, y, this)); + add_tool(variable_bitrate = new OGGVorbisVariableBitrate(x + fixed_bitrate->get_w() + xS(5), + y, + this)); + + y += yS(30); + sprintf(string, "%d", asset->vorbis_min_bitrate); + add_tool(new BC_Title(x, y, _("Min bitrate:"))); + add_tool(new OGGVorbisMinBitrate(x1, y, this, string)); + + y += yS(30); + add_tool(new BC_Title(x, y, _("Avg bitrate:"))); + sprintf(string, "%d", asset->vorbis_bitrate); + add_tool(new OGGVorbisAvgBitrate(x1, y, this, string)); + + y += yS(30); + add_tool(new BC_Title(x, y, _("Max bitrate:"))); + sprintf(string, "%d", asset->vorbis_max_bitrate); + add_tool(new OGGVorbisMaxBitrate(x1, y, this, string)); + + + add_subwindow(new BC_OKButton(this)); + show_window(1); + unlock_window(); +} + +int OGGConfigAudio::close_event() +{ + set_done(0); + return 1; +} + +OGGVorbisFixedBitrate::OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui) + : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Average bitrate")) +{ + this->gui = gui; +} +int OGGVorbisFixedBitrate::handle_event() +{ + gui->asset->vorbis_vbr = 0; + gui->variable_bitrate->update(0); + return 1; +} + +OGGVorbisVariableBitrate::OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui) + : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate")) +{ + this->gui = gui; +} +int OGGVorbisVariableBitrate::handle_event() +{ + gui->asset->vorbis_vbr = 1; + gui->fixed_bitrate->update(0); + return 1; +} + + +OGGVorbisMinBitrate::OGGVorbisMinBitrate(int x, + int y, + OGGConfigAudio *gui, + char *text) + : BC_TextBox(x, y, xS(180), 1, text) +{ + this->gui = gui; +} +int OGGVorbisMinBitrate::handle_event() +{ + gui->asset->vorbis_min_bitrate = atol(get_text()); + return 1; +} + + + +OGGVorbisMaxBitrate::OGGVorbisMaxBitrate(int x, + int y, + OGGConfigAudio *gui, + char *text) + : BC_TextBox(x, y, xS(180), 1, text) +{ + this->gui = gui; +} +int OGGVorbisMaxBitrate::handle_event() +{ + gui->asset->vorbis_max_bitrate = atol(get_text()); + return 1; +} + + + +OGGVorbisAvgBitrate::OGGVorbisAvgBitrate(int x, int y, OGGConfigAudio *gui, char *text) + : BC_TextBox(x, y, xS(180), 1, text) +{ + this->gui = gui; +} +int OGGVorbisAvgBitrate::handle_event() +{ + gui->asset->vorbis_bitrate = atol(get_text()); + return 1; +} + + + + + +OGGConfigVideo::OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset) + : BC_Window(PROGRAM_NAME ": Video Compression", + parent_window->get_abs_cursor_x(1), + parent_window->get_abs_cursor_y(1), + xS(450), yS(220)) +{ + this->parent_window = parent_window; + this->asset = asset; +} + +OGGConfigVideo::~OGGConfigVideo() +{ + +} + +void OGGConfigVideo::create_objects() +{ +// add_tool(new BC_Title(10, 10, _("There are no video options for this format"))); + int x = xS(10), y = yS(10); + int x1 = x + xS(150); + int x2 = x + xS(300); + + lock_window("OGGConfigVideo::create_objects"); + BC_Title *title; + add_subwindow(title = new BC_Title(x, y, _("Bitrate:"))); + add_subwindow(new OGGTheoraBitrate(x + title->get_w() + xS(5), y, this)); + add_subwindow(fixed_bitrate = new OGGTheoraFixedBitrate(x2, y, this)); + y += yS(30); + + add_subwindow(new BC_Title(x, y, _("Quality:"))); + add_subwindow(new BC_ISlider(x + xS(80), y, 0, xS(200), xS(200), + 0, 63, asset->theora_quality, + 0, 0, &asset->theora_quality)); + + + add_subwindow(fixed_quality = new OGGTheoraFixedQuality(x2, y, this)); + y += yS(30); + + add_subwindow(new BC_Title(x, y, _("Keyframe frequency:"))); + OGGTheoraKeyframeFrequency *keyframe_frequency = + new OGGTheoraKeyframeFrequency(x1 + xS(60), y, this); + keyframe_frequency->create_objects(); + y += yS(30); + + add_subwindow(new BC_Title(x, y, _("Keyframe force frequency:"))); + OGGTheoraKeyframeForceFrequency *keyframe_force_frequency = + new OGGTheoraKeyframeForceFrequency(x1 + xS(60), y, this); + keyframe_force_frequency->create_objects(); + y += yS(30); + + add_subwindow(new BC_Title(x, y, _("Sharpness:"))); + OGGTheoraSharpness *sharpness = + new OGGTheoraSharpness(x1 + xS(60), y, this); + sharpness->create_objects(); + y += yS(30); + + + add_subwindow(new BC_OKButton(this)); + show_window(1); + unlock_window(); +} + + + + +int OGGConfigVideo::close_event() +{ + set_done(0); + return 1; +} + +OGGTheoraBitrate::OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui) + : BC_TextBox(x, y, xS(100), 1, gui->asset->theora_bitrate) +{ + this->gui = gui; +} + + +int OGGTheoraBitrate::handle_event() +{ + // TODO: MIN / MAX check + gui->asset->theora_bitrate = atol(get_text()); + return 1; +}; + + + + +OGGTheoraFixedBitrate::OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui) + : BC_Radial(x, y, gui->asset->theora_fix_bitrate, _("Fixed bitrate")) +{ + this->gui = gui; +} + +int OGGTheoraFixedBitrate::handle_event() +{ + update(1); + gui->asset->theora_fix_bitrate = 1; + gui->fixed_quality->update(0); + return 1; +}; + +OGGTheoraFixedQuality::OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui) + : BC_Radial(x, y, !gui->asset->theora_fix_bitrate, _("Fixed quality")) +{ + this->gui = gui; +} + +int OGGTheoraFixedQuality::handle_event() +{ + update(1); + gui->asset->theora_fix_bitrate = 0; + gui->fixed_bitrate->update(0); + return 1; +}; + +OGGTheoraKeyframeFrequency::OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui) + : BC_TumbleTextBox(gui, (int64_t)gui->asset->theora_keyframe_frequency, + (int64_t)1, (int64_t)500, x, y, xS(40)) +{ + this->gui = gui; +} + +int OGGTheoraKeyframeFrequency::handle_event() +{ + gui->asset->theora_keyframe_frequency = atol(get_text()); + return 1; +} + +OGGTheoraKeyframeForceFrequency::OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui) + : BC_TumbleTextBox(gui, (int64_t)gui->asset->theora_keyframe_frequency, + (int64_t)1, (int64_t)500, x, y, xS(40)) +{ + this->gui = gui; +} + +int OGGTheoraKeyframeForceFrequency::handle_event() +{ + gui->asset->theora_keyframe_frequency = atol(get_text()); + return 1; +} + + +OGGTheoraSharpness::OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui) + : BC_TumbleTextBox(gui, (int64_t)gui->asset->theora_sharpness, + (int64_t)0, (int64_t)2, x, y, xS(40)) +{ + this->gui = gui; +} + +int OGGTheoraSharpness::handle_event() +{ + gui->asset->theora_sharpness = atol(get_text()); + return 1; +} + + diff --git a/cinelerra-5.1/cinelerra/fileogg.h b/cinelerra-5.1/cinelerra/fileogg.h new file mode 100644 index 00000000..87c26dc1 --- /dev/null +++ b/cinelerra-5.1/cinelerra/fileogg.h @@ -0,0 +1,340 @@ + +/* + * 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 FILEOGG_H +#define FILEOGG_H +#ifdef HAVE_OGG + +#include "edl.inc" +#include "filebase.h" +#include "file.inc" +#include "mutex.inc" + +#include +#include +#include +#include +#include + + +/* This code was aspired by ffmpeg2theora */ +/* Special thanks for help on this code goes out to j@v2v.cc */ + +#define mn_pagesz 32 + +class sync_window_t : public ogg_sync_state +{ +public: + sync_window_t(FILE *fp, Mutex *sync_lock, int64_t begin=0, int64_t end=0); + ~sync_window_t(); + int ogg_read_locked(int buflen); + int ogg_read_buffer(int buflen); + int ogg_read_buffer_at(off_t filepos, int buflen); + int ogg_sync_and_take_page_out(ogg_page *og); + int ogg_take_page_out_autoadvance(ogg_page *og); + int ogg_sync_and_get_next_page(long serialno, ogg_page *og); + int ogg_prev_page_search(long serialno,ogg_page *og, + off_t begin, off_t end); + int ogg_get_prev_page(long serialno, ogg_page *og); + int ogg_get_next_page(long serialno, ogg_page *og); + int ogg_get_first_page(long serialno, ogg_page *og); + int ogg_get_last_page(long serialno, ogg_page *og); + + int64_t filepos; // current file position + int64_t bufpos; // position at start of read + int64_t pagpos; // last search target position + FILE *fp; + Mutex *sync_lock; + int64_t file_begin, file_end; +}; + +class OGG_PageBfr +{ +public: + int allocated, len; + int valid, packets; + int64_t position; + uint8_t *page; + + OGG_PageBfr(); + ~OGG_PageBfr(); + void demand(int sz); + int write_page(FILE *fp); + int64_t load(ogg_page *og); +}; + +class FileOGG : public FileBase +{ +public: + FileOGG(Asset *asset, File *file); + ~FileOGG(); + + static void get_parameters(BC_WindowBase *parent_window, + Asset *asset, BC_WindowBase *&format_window, + int audio_options,int video_options,EDL *edl); + static int check_sig(Asset *asset); + int open_file(int rd,int wr); + int close_file(); + + int64_t get_video_position(); + int64_t get_audio_position(); + int set_video_position(int64_t pos); + int colormodel_supported(int colormodel); + int get_best_colormodel(Asset *asset,int driver); + int read_frame(VFrame *frame); + int set_audio_position(int64_t pos); + int read_samples(double *buffer,int64_t len); + int write_samples(double **buffer,int64_t len); + int write_frames(VFrame ***frames,int len); + +private: + void init(); + int encode_theora_init(); + int encode_vorbis_init(); + int ogg_init_encode(FILE *out); + void close_encoder(); + int decode_theora_init(); + int decode_vorbis_init(); + int ogg_init_decode(FILE *inp); + void close_decoder(); + + int write_samples_vorbis(double **buffer, int64_t len, int e_o_s); + int write_frames_theora(VFrame ***frames, int len, int e_o_s); + void flush_ogg(int e_o_s); + int write_audio_page(); + int write_video_page(); + + FILE *inp, *out; + off_t file_length; + int audio, video; + int64_t frame_position; + int64_t sample_position; + + VFrame *temp_frame; + Mutex *file_lock; + float **pcm_history; +#ifndef HISTORY_MAX +#define HISTORY_MAX 0x100000 +#endif + int64_t history_start; + int64_t history_size; + int pcm_channels; + int ach, ahz; // audio channels, sample rate + int amn, amx; // audio min/max bitrate + int abr, avbr, aqu; // audio bitrate, variable bitrate, quality + int asz, afrmsz; // audio sample size, frame size + + off_t file_begin, file_end; + sync_window_t *audiosync; + sync_window_t *videosync; + + int64_t ogg_sample_pos(ogg_page *og); + int64_t ogg_next_sample_pos(ogg_page *og); + int64_t ogg_frame_pos(ogg_page *og); + int64_t ogg_next_frame_pos(ogg_page *og); + int ogg_read_buffer(FILE *in, sync_window_t *sy, int buflen); + int ogg_get_video_packet(ogg_packet *op); + int ogg_get_audio_packet(ogg_packet *op); + + int ogg_get_page_of_sample(ogg_page *og, int64_t sample); + int ogg_seek_to_sample(int64_t sample); + int ogg_decode_more_samples(); + + int ogg_get_page_of_frame(ogg_page *og, int64_t frame); + int ogg_seek_to_keyframe(int64_t frame, int64_t *keyframe_number); + int move_history(int from, int to, int len); + + ogg_stream_state to; // theora to ogg out + ogg_stream_state vo; // vorbis to ogg out + int64_t ogg_sample_position, ogg_frame_position; + int64_t next_sample_position, next_frame_position; + int64_t start_sample, last_sample; // first and last sample inside this file + int64_t start_frame, last_frame; // first and last frame inside this file + int64_t audio_pos, video_pos; // decoder last sample/frame in + int audio_eos, video_eos; // decoder sample/frame end of file + + th_enc_ctx *enc; // theora video encode context + th_dec_ctx *dec; // theora video decode context + th_info ti; // theora video encoder init parameters + th_setup_info *ts; // theora video setup huff/quant codes + th_comment tc; // header init parameters + vorbis_info vi; // vorbis audio encoder init parameters + vorbis_comment vc; // header init parameters + vorbis_dsp_state vd; // vorbis decode audio context + vorbis_block vb; // vorbis decode buffering + int force_keyframes; + int vp3_compatible; + int soft_target; + + int pic_x, pic_y, pic_w, pic_h; + int frame_w, frame_h; + int colorspace, pixfmt; + int bitrate, quality; + int keyframe_period, keyframe_force; + int fps_num, fps_den; + int aratio_num, aratio_den; + + OGG_PageBfr apage, vpage; + double audiotime, videotime; + int keyframe_granule_shift; + int iframe_granule_offset; + int theora_cmodel; +}; + +class OGGConfigAudio; +class OGGConfigVideo; + +class OGGVorbisFixedBitrate : public BC_Radial +{ +public: + OGGVorbisFixedBitrate(int x, int y, OGGConfigAudio *gui); + int handle_event(); + OGGConfigAudio *gui; +}; + +class OGGVorbisVariableBitrate : public BC_Radial +{ +public: + OGGVorbisVariableBitrate(int x, int y, OGGConfigAudio *gui); + int handle_event(); + OGGConfigAudio *gui; +}; + +class OGGVorbisMinBitrate : public BC_TextBox +{ +public: + OGGVorbisMinBitrate(int x, + int y, + OGGConfigAudio *gui, + char *text); + int handle_event(); + OGGConfigAudio *gui; +}; + +class OGGVorbisMaxBitrate : public BC_TextBox +{ +public: + OGGVorbisMaxBitrate(int x, + int y, + OGGConfigAudio *gui, + char *text); + int handle_event(); + OGGConfigAudio *gui; +}; + +class OGGVorbisAvgBitrate : public BC_TextBox +{ +public: + OGGVorbisAvgBitrate(int x, + int y, + OGGConfigAudio *gui, + char *text); + int handle_event(); + OGGConfigAudio *gui; +}; + + +class OGGConfigAudio: public BC_Window +{ +public: + OGGConfigAudio(BC_WindowBase *parent_window, Asset *asset); + ~OGGConfigAudio(); + + void create_objects(); + int close_event(); + + Asset *asset; + OGGVorbisFixedBitrate *fixed_bitrate; + OGGVorbisVariableBitrate *variable_bitrate; +private: + BC_WindowBase *parent_window; + char string[BCTEXTLEN]; +}; + + +class OGGTheoraBitrate : public BC_TextBox +{ +public: + OGGTheoraBitrate(int x, int y, OGGConfigVideo *gui); + int handle_event(); + OGGConfigVideo *gui; +}; + +class OGGTheoraKeyframeFrequency : public BC_TumbleTextBox +{ +public: + OGGTheoraKeyframeFrequency(int x, int y, OGGConfigVideo *gui); + int handle_event(); + OGGConfigVideo *gui; +}; + +class OGGTheoraKeyframeForceFrequency : public BC_TumbleTextBox +{ +public: + OGGTheoraKeyframeForceFrequency(int x, int y, OGGConfigVideo *gui); + int handle_event(); + OGGConfigVideo *gui; +}; + +class OGGTheoraSharpness : public BC_TumbleTextBox +{ +public: + OGGTheoraSharpness(int x, int y, OGGConfigVideo *gui); + int handle_event(); + OGGConfigVideo *gui; +}; + +class OGGTheoraFixedBitrate : public BC_Radial +{ +public: + OGGTheoraFixedBitrate(int x, int y, OGGConfigVideo *gui); + int handle_event(); + OGGConfigVideo *gui; +}; + +class OGGTheoraFixedQuality : public BC_Radial +{ +public: + OGGTheoraFixedQuality(int x, int y, OGGConfigVideo *gui); + int handle_event(); + OGGConfigVideo *gui; +}; + + + +class OGGConfigVideo: public BC_Window +{ +public: + OGGConfigVideo(BC_WindowBase *parent_window, Asset *asset); + ~OGGConfigVideo(); + + void create_objects(); + int close_event(); + + OGGTheoraFixedBitrate *fixed_bitrate; + OGGTheoraFixedQuality *fixed_quality; + Asset *asset; +private: + BC_WindowBase *parent_window; +}; + +#endif +#endif diff --git a/cinelerra-5.1/cinelerra/filevorbis.C b/cinelerra-5.1/cinelerra/filevorbis.C new file mode 100644 index 00000000..f04249f1 --- /dev/null +++ b/cinelerra-5.1/cinelerra/filevorbis.C @@ -0,0 +1,490 @@ + +/* + * 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 + * + */ +#ifdef HAVE_OGG + +#include "asset.h" +#include "bcsignals.h" +#include "byteorder.h" +#include "clip.h" +#include "file.h" +#include "filevorbis.h" +#include "guicast.h" +#include "language.h" +#include "mainerror.h" +#include "mwindow.inc" +#include "mainerror.h" + +#include +#include +#include +#include + +//suppress noref warning +void *vorbis1_ov_callbacks[] = { + &OV_CALLBACKS_DEFAULT, &OV_CALLBACKS_NOCLOSE, + &OV_CALLBACKS_STREAMONLY, &OV_CALLBACKS_STREAMONLY_NOCLOSE, +}; + +FileVorbis::FileVorbis(Asset *asset, File *file) + : FileBase(asset, file) +{ + reset_parameters(); + if(asset->format == FILE_UNKNOWN) asset->format = FILE_VORBIS; + asset->byte_order = 0; +} + +FileVorbis::~FileVorbis() +{ + close_file(); +} + +void FileVorbis::get_parameters(BC_WindowBase *parent_window, + Asset *asset, BC_WindowBase* &format_window, + int audio_options, int video_options, EDL *edl) +{ + if(audio_options) + { + VorbisConfigAudio *window = new VorbisConfigAudio(parent_window, asset); + format_window = window; + window->create_objects(); + window->run_window(); + delete window; + } +} + +int FileVorbis::check_sig(Asset *asset) +{ + FILE *fd = fopen(asset->path, "rb"); + OggVorbis_File vf; + +// Test for Quicktime since OGG misinterprets it + if(fd) + { + fseek(fd, 4, SEEK_SET); + char data[4]; + (void)fread(data, 4, 1, fd); + if(data[0] == 'm' && + data[1] == 'd' && + data[2] == 'a' && + data[3] == 't') + { + fclose(fd); + return 0; + } + + fseek(fd, 0, SEEK_SET); + + if(ov_open(fd, &vf, NULL, 0) < 0) + { + // OGG failed. Close file handle manually. + ov_clear(&vf); + if(fd) fclose(fd); + return 0; + } + else + { + ov_clear(&vf); + return 1; + } + } + + return 0; +} + +int FileVorbis::reset_parameters_derived() +{ + fd = 0; + bzero(&vf, sizeof(vf)); + return 0; +} + + +int FileVorbis::open_file(int rd, int wr) +{ + + int result = 0; + +//printf("FileVorbis::open_file 1\n"); + if(rd) + { +//printf("FileVorbis::open_file 1\n"); + if(!(fd = fopen(asset->path, "rb"))) + { + eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path); + result = 1; + } + else + { +//printf("FileVorbis::open_file 2 %p %p\n", fd, vf); + if(ov_open(fd, &vf, NULL, 0) < 0) + { + eprintf(_("FileVorbis::open_file %s: invalid bitstream.\n"), asset->path); + result = 1; + } + else + { +//printf("FileVorbis::open_file 1\n"); + vorbis_info *vi = ov_info(&vf, -1); + asset->channels = vi->channels; + if(!asset->sample_rate) + asset->sample_rate = vi->rate; +//printf("FileVorbis::open_file 1\n"); + asset->audio_length = ov_pcm_total(&vf,-1); +//printf("FileVorbis::open_file 1\n"); + asset->audio_data = 1; +// printf("FileVorbis::open_file 1 %d %d %d\n", +// asset->channels, +// asset->sample_rate, +// asset->audio_length); + } + } + } + + if(wr) + { + if(!(fd = fopen(asset->path, "wb"))) + { + eprintf(_("Error while opening \"%s\" for writing. \n%m\n"), asset->path); + result = 1; + } + else + { + vorbis_info_init(&vi); + if(!asset->vorbis_vbr) + result = vorbis_encode_init(&vi, + asset->channels, + asset->sample_rate, + asset->vorbis_max_bitrate, + asset->vorbis_bitrate, + asset->vorbis_min_bitrate); + else + { + result = vorbis_encode_setup_managed(&vi, + asset->channels, + asset->sample_rate, + asset->vorbis_max_bitrate, + asset->vorbis_bitrate, + asset->vorbis_min_bitrate); + result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL); + result |= vorbis_encode_setup_init(&vi); + } + + if(!result) + { + vorbis_analysis_init(&vd, &vi); + vorbis_block_init(&vd, &vb); + vorbis_comment_init(&vc); + srand(time(NULL)); + ogg_stream_init(&os, rand()); + + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + vorbis_analysis_headerout(&vd, + &vc, + &header, + &header_comm, + &header_code); + ogg_stream_packetin(&os, + &header); + ogg_stream_packetin(&os, + &header_comm); + ogg_stream_packetin(&os, + &header_code); + + while(1) + { + int result = ogg_stream_flush(&os, &og); + if(result == 0) break; + fwrite(og.header, 1, og.header_len, fd); + fwrite(og.body, 1, og.body_len, fd); + } + } + } + } + +//printf("FileVorbis::open_file 2\n"); + return result; +} + +#define FLUSH_VORBIS \ +while(vorbis_analysis_blockout(&vd, &vb) == 1) \ +{ \ + vorbis_analysis(&vb, NULL); \ + vorbis_bitrate_addblock(&vb); \ + while(vorbis_bitrate_flushpacket(&vd, &op)) \ + { \ + ogg_stream_packetin(&os, &op); \ + while(1) \ + { \ + int result = ogg_stream_pageout(&os, &og); \ + if(!result) break; \ + fwrite(og.header, 1, og.header_len, fd); \ + fwrite(og.body, 1, og.body_len, fd); \ + if(ogg_page_eos(&og)) break; \ + } \ + } \ +} + + +int FileVorbis::close_file_derived() +{ + if(fd) + { + if(file->wr) + { + vorbis_analysis_wrote(&vd, 0); + FLUSH_VORBIS + + ogg_stream_clear(&os); + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + vorbis_comment_clear(&vc); + vorbis_info_clear(&vi); + fclose(fd); + } + + if(file->rd) + { +// This also closes the file handle. + ov_clear(&vf); + } + fd = 0; + } + + return 0; +} + + +int FileVorbis::write_samples(double **buffer, int64_t len) +{ + if(!fd) return 0; + + float **vorbis_buffer = vorbis_analysis_buffer(&vd, len); + for(int i = 0; i < asset->channels; i++) + { + float *output = vorbis_buffer[i]; + double *input = buffer[i]; + for(int j = 0; j < len; j++) + { + output[j] = input[j]; + } + } + + vorbis_analysis_wrote(&vd, len); + FLUSH_VORBIS + + return 0; +} + +int FileVorbis::read_samples(double *buffer, int64_t len) +{ + if(!fd) return 0; + +// printf("FileVorbis::read_samples 1 %d %d %d %d\n", +// history_start, +// history_size, +// file->current_sample, +// len); + float **vorbis_output; + int bitstream; + int accumulation = 0; + + + update_pcm_history(len); + + +// Fill history buffer + if(decode_start != decode_end) + { + ov_pcm_seek(&vf, decode_start); + decode_end = decode_start; + } + + while(accumulation < decode_len) + { + int result = ov_read_float(&vf, + &vorbis_output, + decode_len - accumulation, + &bitstream); +//printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation); + if(!result) break; + + append_history(vorbis_output, result); + accumulation += result; + } + + + read_history(buffer, + file->current_sample, + file->current_channel, + len); + +// printf("FileVorbis::read_samples 2 %d %d %d %d\n", +// history_start, +// history_size, +// file->current_sample, +// len); + + return 0; +} + + + + + + + + + + +VorbisConfigAudio::VorbisConfigAudio(BC_WindowBase *parent_window, + Asset *asset) + : BC_Window(_(PROGRAM_NAME ": Audio Compression"), + parent_window->get_abs_cursor_x(1), + parent_window->get_abs_cursor_y(1), + 350, + 170, + -1, + -1, + 0, + 0, + 1) +{ + this->parent_window = parent_window; + this->asset = asset; +} + +VorbisConfigAudio::~VorbisConfigAudio() +{ +} + +void VorbisConfigAudio::create_objects() +{ + int x = 10, y = 10; + int x1 = 150; + char string[BCTEXTLEN]; + + lock_window("VorbisConfigAudio::create_objects"); + add_tool(fixed_bitrate = new VorbisFixedBitrate(x, y, this)); + add_tool(variable_bitrate = new VorbisVariableBitrate(x1, y, this)); + + y += 30; + sprintf(string, "%d", asset->vorbis_min_bitrate); + add_tool(new BC_Title(x, y, _("Min bitrate:"))); + add_tool(new VorbisMinBitrate(x1, y, this, string)); + + y += 30; + add_tool(new BC_Title(x, y, _("Avg bitrate:"))); + sprintf(string, "%d", asset->vorbis_bitrate); + add_tool(new VorbisAvgBitrate(x1, y, this, string)); + + y += 30; + add_tool(new BC_Title(x, y, _("Max bitrate:"))); + sprintf(string, "%d", asset->vorbis_max_bitrate); + add_tool(new VorbisMaxBitrate(x1, y, this, string)); + + + add_subwindow(new BC_OKButton(this)); + show_window(); + flush(); + unlock_window(); +} + +int VorbisConfigAudio::close_event() +{ + set_done(0); + return 1; +} + + + + + +VorbisFixedBitrate::VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui) + : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Fixed bitrate")) +{ + this->gui = gui; +} +int VorbisFixedBitrate::handle_event() +{ + gui->asset->vorbis_vbr = 0; + gui->variable_bitrate->update(0); + return 1; +} + +VorbisVariableBitrate::VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui) + : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate")) +{ + this->gui = gui; +} +int VorbisVariableBitrate::handle_event() +{ + gui->asset->vorbis_vbr = 1; + gui->fixed_bitrate->update(0); + return 1; +} + + +VorbisMinBitrate::VorbisMinBitrate(int x, + int y, + VorbisConfigAudio *gui, + char *text) + : BC_TextBox(x, y, 180, 1, text) +{ + this->gui = gui; +} +int VorbisMinBitrate::handle_event() +{ + gui->asset->vorbis_min_bitrate = atol(get_text()); + return 1; +} + + + +VorbisMaxBitrate::VorbisMaxBitrate(int x, + int y, + VorbisConfigAudio *gui, + char *text) + : BC_TextBox(x, y, 180, 1, text) +{ + this->gui = gui; +} +int VorbisMaxBitrate::handle_event() +{ + gui->asset->vorbis_max_bitrate = atol(get_text()); + return 1; +} + + + +VorbisAvgBitrate::VorbisAvgBitrate(int x, int y, VorbisConfigAudio *gui, char *text) + : BC_TextBox(x, y, 180, 1, text) +{ + this->gui = gui; +} +int VorbisAvgBitrate::handle_event() +{ + gui->asset->vorbis_bitrate = atol(get_text()); + return 1; +} + +#endif diff --git a/cinelerra-5.1/cinelerra/filevorbis.h b/cinelerra-5.1/cinelerra/filevorbis.h new file mode 100644 index 00000000..5dbf8900 --- /dev/null +++ b/cinelerra-5.1/cinelerra/filevorbis.h @@ -0,0 +1,140 @@ + +/* + * 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 FILEVORBIS_H +#define FILEVORBIS_H +#ifdef HAVE_OGG + +#include "edl.inc" +#include "file.inc" +#include "filebase.h" +#include "vorbis/vorbisenc.h" +#include "vorbis/vorbisfile.h" + + + + + + +class FileVorbis : public FileBase +{ +public: + FileVorbis(Asset *asset, File *file); + ~FileVorbis(); + + static void get_parameters(BC_WindowBase *parent_window, + Asset *asset, BC_WindowBase* &format_window, + int audio_options, int video_options, EDL *edl); + int reset_parameters_derived(); + + static int check_sig(Asset *asset); + int open_file(int rd, int wr); + int close_file_derived(); + int write_samples(double **buffer, + int64_t len); + + int read_samples(double *buffer, int64_t len); + +// Decoding + OggVorbis_File vf; + FILE *fd; + +// Encoding + vorbis_info vi; + vorbis_comment vc; + vorbis_dsp_state vd; + vorbis_block vb; + ogg_stream_state os; + ogg_page og; + ogg_packet op; +}; + + +class VorbisConfigAudio; + + +class VorbisFixedBitrate : public BC_Radial +{ +public: + VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui); + int handle_event(); + VorbisConfigAudio *gui; +}; + +class VorbisVariableBitrate : public BC_Radial +{ +public: + VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui); + int handle_event(); + VorbisConfigAudio *gui; +}; + +class VorbisMinBitrate : public BC_TextBox +{ +public: + VorbisMinBitrate(int x, + int y, + VorbisConfigAudio *gui, + char *text); + int handle_event(); + VorbisConfigAudio *gui; +}; + +class VorbisMaxBitrate : public BC_TextBox +{ +public: + VorbisMaxBitrate(int x, + int y, + VorbisConfigAudio *gui, + char *text); + int handle_event(); + VorbisConfigAudio *gui; +}; + +class VorbisAvgBitrate : public BC_TextBox +{ +public: + VorbisAvgBitrate(int x, + int y, + VorbisConfigAudio *gui, + char *text); + int handle_event(); + VorbisConfigAudio *gui; +}; + +class VorbisConfigAudio : public BC_Window +{ +public: + VorbisConfigAudio(BC_WindowBase *parent_window, Asset *asset); + ~VorbisConfigAudio(); + + void create_objects(); + int close_event(); + + VorbisFixedBitrate *fixed_bitrate; + VorbisVariableBitrate *variable_bitrate; + BC_WindowBase *parent_window; + char string[BCTEXTLEN]; + Asset *asset; +}; + +#endif +#endif diff --git a/cinelerra-5.1/cinelerra/filevorbis.inc b/cinelerra-5.1/cinelerra/filevorbis.inc new file mode 100644 index 00000000..bf38c445 --- /dev/null +++ b/cinelerra-5.1/cinelerra/filevorbis.inc @@ -0,0 +1,29 @@ + +/* + * 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 FILEVORBIS_INC +#define FILEVORBIS_INC + +class FileVorbis; + + + +#endif diff --git a/cinelerra-5.1/cinelerra/formatpopup.C b/cinelerra-5.1/cinelerra/formatpopup.C index 6252b0c2..addd4a2c 100644 --- a/cinelerra-5.1/cinelerra/formatpopup.C +++ b/cinelerra-5.1/cinelerra/formatpopup.C @@ -72,6 +72,10 @@ void FormatPopup::create_objects() #ifdef HAVE_LIBZMPEG post_item(FILE_AMPEG); post_item(FILE_VMPEG); +#endif +#ifdef HAVE_OGG + post_item(FILE_VORBIS); + post_item(FILE_OGG); #endif post_item(FILE_PCM); } diff --git a/cinelerra-5.1/cinelerra/formattools.C b/cinelerra-5.1/cinelerra/formattools.C index 0979dfa4..643655e3 100644 --- a/cinelerra-5.1/cinelerra/formattools.C +++ b/cinelerra-5.1/cinelerra/formattools.C @@ -748,6 +748,7 @@ int FormatFormat::handle_event() asset->video_data = File::renders_video(asset); asset->ff_audio_options[0] = 0; asset->ff_video_options[0] = 0; + asset->ff_format_options[0] = 0; format->format_text->update(selection->get_text()); if( !format->use_brender ) format->update_extension(); @@ -778,8 +779,10 @@ int FormatFFMPEG::handle_event() if( selection ) { const char *text = get_selection(0, 0)->get_text(); format->ffmpeg_type->update(text); +// forces options load defaults format->asset->ff_audio_options[0] = 0; format->asset->ff_video_options[0] = 0; + format->asset->ff_format_options[0] = 0; FFMPEG::set_asset_format(format->asset, format->mwindow->edl, text); format->update_extension(); format->close_format_windows(); diff --git a/cinelerra-5.1/cinelerra/packagedispatcher.C b/cinelerra-5.1/cinelerra/packagedispatcher.C index aa88d5f1..dccec03a 100644 --- a/cinelerra-5.1/cinelerra/packagedispatcher.C +++ b/cinelerra-5.1/cinelerra/packagedispatcher.C @@ -102,7 +102,7 @@ int PackageDispatcher::create_packages(MWindow *mwindow, EDL *edl, strcpy(packages[0]->path, default_asset->path); break; case SINGLE_PASS_FARM: - packaging_engine = File::new_packaging_engine(default_asset); + packaging_engine = (PackagingEngine*)new PackagingEngineDefault(); packaging_engine->create_packages_single_farm(edl, preferences, default_asset, total_start, total_end); break; @@ -189,6 +189,7 @@ int PackageDispatcher::create_packages(MWindow *mwindow, EDL *edl, // Only if this isn't a background render or non interactive. if( strategy != BRENDER_FARM && test_overwrite && mwindow ) { ArrayList paths; + paths.set_array_delete(); get_package_paths(&paths); result = ConfirmSave::test_files(mwindow, &paths); paths.remove_all_objects(); diff --git a/cinelerra-5.1/configure.ac b/cinelerra-5.1/configure.ac index a2d5b501..ee75006c 100644 --- a/cinelerra-5.1/configure.ac +++ b/cinelerra-5.1/configure.ac @@ -234,8 +234,9 @@ PKG_3RD([flac],[auto], [ include ]) PKG_3RD([giflib],[yes], - [giflib-5.1.6], - [ libgif.a ], + [giflib-5.2.1], + [ libgif.a \ + libutil.a ], [ . ]) PKG_3RD([ilmbase],[auto], @@ -278,24 +279,23 @@ PKG_3RD([libdv],[auto], [ . ]) PKG_3RD([libjpeg],[auto], - [libjpeg-turbo-1.5.1], - [ .libs/libjpeg.a \ - .libs/libturbojpeg.a \ - simd/.libs/libsimd.a ], - [ . ]) + [libjpeg-turbo-2.0.4], + [ build/libjpeg.a \ + build/libturbojpeg.a ], + [ opt/libjpeg-turbo/include ]) PKG_3RD([opus],[auto], - [opus-1.3], + [opus-1.3.1], [ .libs/libopus.a ], [ include ]) PKG_3RD([openjpeg],[auto], - [openjpeg-2.3.0], + [openjpeg-2.3.1], [ bin/libopenjp2.a ], [ src/lib/openjp2 ]) PKG_3RD([libogg],[auto], - [libogg-1.3.3], + [libogg-1.3.4], [ src/.libs/libogg.a ], [ include ]) @@ -353,24 +353,24 @@ PKG_3RD([openexr],[auto], # []) # PKG_3RD([tiff],[auto], - [tiff-4.0.10], + [tiff-4.1.0], [ libtiff/.libs/libtiff.a \ libtiff/.libs/libtiffxx.a \ port/.libs/libport.a ],[ . ]) PKG_3RD([twolame],[auto], - [twolame-0.3.13], + [twolame-0.4.0], [ libtwolame/.libs/libtwolame.a ], [ libtwolame ]) PKG_3RD([x264],[auto], - [x264-snapshot-20190117-2245-stable], + [x264-snapshot-20191217-2245-stable], [ libx264.a ], [ . ]) PKG_3RD([x265],[auto], - [x265_3.1.2], + [x265_3.2.1], [ libx265.a ], [ . source ]) @@ -385,27 +385,27 @@ PKG_3RD([lv2],[auto], [ usr/local/include usr/local/lib64/lv2 usr/local/lib/lv2 ]) PKG_3RD([sratom],[auto], - [sratom-0.6.2], + [sratom-0.6.4], [ usr/local/lib/libsratom-0.a ], [ usr/local/include ]) PKG_3RD([serd],[auto], - [serd-0.30.0], + [serd-0.30.2], [ usr/local/lib/libserd-0.a ], [ usr/local/include ]) PKG_3RD([sord],[auto], - [sord-0.16.2], + [sord-0.16.4], [ usr/local/lib/libsord-0.a ], [ usr/local/include ]) PKG_3RD([lilv],[auto], - [lilv-0.24.4], + [lilv-0.24.6], [ usr/local/lib/liblilv-0.a ], [ usr/local/include ]) PKG_3RD([suil],[auto], - [suil-0.10.2], + [suil-0.10.6], [ usr/local/lib/libsuil-0.a ], [ usr/local/include ]) @@ -415,12 +415,12 @@ PKG_3RD([libaom],[auto], [ usr/local/include ]) PKG_3RD([dav1d],[auto], - [dav1d-0.5.0], + [dav1d-0.5.1], [ usr/local/lib*/libdav1d*.a ], [ usr/local/include ]) PKG_3RD([libwebp],[auto], - [libwebp-1.0.2], + [libwebp-1.1.0], [ usr/local/lib*/libwebp*.a ], [ usr/local/include ]) @@ -556,20 +556,12 @@ CHECK_LIB([lame], [mp3lame], [lame_init]) CHECK_HEADERS([lame], [lame headers], [lame/lame.h]) CHECK_LIB([libjpeg], [jpeg], [jpeg_start_decompress]) CHECK_HEADERS([libjpeg], [jpeg headers], [stdio.h jpeglib.h]) -CHECK_LIB([libogg], [ogg], [ogg_stream_init]) -CHECK_HEADERS([libogg], [ogg headers], [ogg/ogg.h]) CHECK_LIB([openjpeg], [openjp2], [opj_version]) CHECK_HEADERS([openjpeg], [openjpeg headers], [openjpeg.h]) CHECK_LIB([libsndfile], [sndfile], [sf_open]) CHECK_HEADERS([libsndfile], [sndfile headers], [sndfile.h]) CHECK_LIB([ilmbase], [IlmImf], [ImfOpenInputFile]) CHECK_HEADERS([ilmbase], [IlmImf headers], [OpenEXR/ImfCRgbaFile.h]) -CHECK_LIB([libtheora], [theora], [theora_info_init], [-ltheoraenc -ltheoradec -logg]) -CHECK_HEADERS([libtheora], [threora headers], [theora/theoraenc.h]) -CHECK_LIB([libvorbis], [vorbisenc], [vorbis_encode_init], [-lvorbis -lvorbisfile -logg]) -CHECK_HEADERS([libvorbis], [vorbis encoders headers], [vorbis/vorbisenc.h]) -CHECK_LIB([libvorbis], [vorbisfile], [ov_open]) -CHECK_HEADERS([libvorbis], [vorbis file headers], [vorbis/vorbisfile.h]) CHECK_LIB([libvpx], [vpx], [vpx_codec_decode]) CHECK_HEADERS([libvpx], [vpx headers], [vpx/vpx_decoder.h]) CHECK_LIB([mjpegtools], [mjpegutils], [mjpeg_info]) @@ -658,6 +650,16 @@ CHECK_WANT([ALSA], [auto], [use libasound/alsa], [ CHECK_LIB([ALSA], [asound], [snd_pcm_open]) CHECK_HEADERS([ALSA], [asound headers], [alsa/asoundlib.h])]) +CHECK_WANT([OGG], [auto], [use ogg/theora/vorbis], [ + CHECK_LIB([libogg], [ogg], [ogg_stream_init]) + CHECK_HEADERS([libogg], [ogg headers], [ogg/ogg.h]) + CHECK_LIB([libtheora], [theora], [theora_info_init], [-ltheoraenc -ltheoradec -logg]) + CHECK_HEADERS([libtheora], [threora headers], [theora/theoraenc.h]) + CHECK_LIB([libvorbis], [vorbisenc], [vorbis_encode_init], [-lvorbis -lvorbisfile -logg]) + CHECK_HEADERS([libvorbis], [vorbis encoders headers], [vorbis/vorbisenc.h]) + CHECK_LIB([libvorbis], [vorbisfile], [ov_open]) + CHECK_HEADERS([libvorbis], [vorbis file headers], [vorbis/vorbisfile.h])]) + CHECK_WANT([FIREWIRE], [auto], [use firewire], [ CHECK_LIB([libavc1394], [avc1394], [avc1394_init_target]) CHECK_HEADERS([libavc1394], [libavc1394 headers], [libavc1394/avc1394.h]) @@ -947,7 +949,7 @@ echo "" if test "x$WANT_CIN_3RDPARTY" != "xno"; then CFG_CFLAGS+=" -DHAVE_CIN_3RDPARTY" fi -for v in GL XFT XXF86VM OSS ALSA FIREWIRE DV DVB LADSPA \ +for v in GL XFT XXF86VM OSS ALSA FIREWIRE OGG DV DVB LADSPA \ VIDEO4LINUX2 ESOUND PULSE PACTL OPENEXR LV2 \ COMMERCIAL LIBZMPEG SHUTTLE SHUTTLE_USB XV \ VAAPI VDPAU CUDA NV WINTV X10TV; do diff --git a/cinelerra-5.1/expanders.es b/cinelerra-5.1/expanders.es new file mode 100644 index 00000000..31c8a28e --- /dev/null +++ b/cinelerra-5.1/expanders.es @@ -0,0 +1,257 @@ +Video Effects + - Corrección_de_Color + Blue Banana + Brightness/Contrast + C41 + Color 3 Way + Color Balance + ColorSpace + Gamma + Gradient + HistEq + Histogram + Histogram Bezier + Hue saturation + Interpolate Bayer + Invert Video + RGBShift + RGB - 601 + Reroute + Sketcher + Swap channels + Threshold + VideoScope + YUV + YUV411 + YUVShift + - FF_Corrección_de_Color + F_chromahold + F_colorbalance + F_colorchannelmixer + F_colorkey + F_colorlevels + F_colormatrix + F_colorspace + F_curves + F_elbg + F_eq + F_fftfilt + F_floodfill + F_greyedge + F_haldclutsrc + F_histeq + F_histogram + F_limiter + F_lut + F_lut1d + F_lut3d + F_lutrgb + F_lutyuv + F_negate + F_normalize + F_pseudocolor + F_separatefields + F_setparams + F_setrange + F_shuffleplanes + F_swapuv + F_tlut2 + F_vignette + F_vibrance + - Movimiento + Motion + Motion 2 Point + Motion51 + MotionCV + MotionHV + F_dejudder + F_deshake + - Desenfoque + Blur + Edge + Linear Blur + Motion Blur + Radial Blur + Sharpen + Unsharp + Zoom Blur + F_avgblur + F_boxblur + F_deband + F_deblock + F_edgedetect + F_gblur + F_sab + F_smartblur + F_unsharp + - Eliminar Ruido + DeScratch + Denoise video + DotTV + Selective Temporal Averaging + Time Average + F_atadenoise + F_bitplanenoise + F_dctdnoiz + F_fftdnoiz + F_hqdn3d + F_nlmeans + F_noise + F_owdenoise + F_removegrain + F_vaguedenoiser + - Croma y Luma + Blue Banana + Chroma key + Chroma key (HSV) + CriKey + Difference key + F_chromakey + F_despill + F_lumakey + - Geometría + Auto Scale + Crop & Position + Flip + Lens + Perspective + Polar + Rotate + Rumbler + Scale + Scale Ratio + Sketcher + Sphere Cam + Translate + Whirl + Wave + F_cropdetect + F_crop + F_cover_rect + F_drawbox + F_drawgraph + F_drawgrid + F_fillborders + F_hflip + F_lenscorrection + F_pad + F_perspective + F_rotate + F_scale + F_super2xsai + F_swaprect + F_tile + F_vflip + - Escalado + Auto Scale + Downsample + F_hqx + F_scale + F_super2xsai + F_xbr + Scale + Scale Ratio + - Tiempo + Decimate + Delay Video + Freeze Frame + Loop video + Interpolate Video + ReframeRT + Reverse video + Time Average + TimeFront + F_amplify + F_deflicker + F_framerate + F_framestep + F_loop + F_mpdecimate + F_realtime + F_tblend + F_tinterlace + F_tmix + F_vfrdet + - Test + F_bench + F_bbox + F_ciescope + F_color + F_datascope + F_entropy + F_graphmonitor + F_mptestsrc + F_oscilloscope + F_pal100bars + F_pal75bars + F_pixscope + F_rgbtestsrc + F_showpalette + F_signalstats + F_smptebars + F_smptehdbars + F_testsrc + F_testsrc2 + F_vectorscope + F_yuvtestsrc + F_waveform +Audio Effects + - Calf + - Instrumentos / Generadores + L2_Calf Organ + L2_Calf Monosynth + L2_Calf Fluidsynth + L2_Calf Wavetable + - Modulación + L2_Calf Multi Chorus + L2_Calf Phaser + L2_Calf Flanger + L2_Calf Rotary Speaker + L2_Calf Pulsator + L2_Calf Ring Modulator + - Delay + L2_Calf Reverb + L2_Calf Vintage Delay + L2_Calf Compensation Delay Line + L2_Calf Reverse Delay + - Compresión y Dinámica + L2_Calf Compressor + L2_Calf Sidechain Compressor + L2_Calf Multiband Compressor + L2_Calf Mono Compressor + L2_Calf Deeser + L2_Calf Gate + L2_Calf Sidechain Gate + L2_Calf Multiband Gate + L2_Calf Limiter + L2_Calf Multiband Limiter + L2_Calf Sidechain Limiter + L2_Calf Transient Designer + - Filtros y Ecualizadores + L2_Calf Filter + L2_Calf Filterclavier + L2_Calf Envelope Filter + L2_Calf Emphasis + L2_Calf Vocoder + L2_Calf 5-Band Equalizer + L2_Calf 8-Band Equalizer + L2_Calf 12-Band Equalizer + L2_Calf 30-Band Equalizer + - Distorsión + L2_Calf Saturator + L2_Calf Exciter + L2_Calf Bass Enhancer + L2_Calf Tape Simulator + L2_Calf Vinyl + L2_Calf Crusher + - Herramientas + L2_Calf Mono Input + L2_Calf Pitch Tools + L2_Calf Stereo Tools + L2_Calf Haas Stereo Enhancer + L2_Calf Multi Spread + L2_Calf Multiband Enhancer + L2_Calf X-Over 2 Band + L2_Calf X-Over 3 Band + L2_Calf X-Over 4 Band + L2_Calf Analyzer diff --git a/cinelerra-5.1/ffmpeg/audio/avi.dfl b/cinelerra-5.1/ffmpeg/audio/avi.dfl new file mode 100644 index 00000000..81b5d799 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/audio/avi.dfl @@ -0,0 +1 @@ +avi_mp3.avi diff --git a/cinelerra-5.1/ffmpeg/video/avi.dfl b/cinelerra-5.1/ffmpeg/video/avi.dfl new file mode 100644 index 00000000..ad4bb125 --- /dev/null +++ b/cinelerra-5.1/ffmpeg/video/avi.dfl @@ -0,0 +1 @@ +asv1.avi diff --git a/cinelerra-5.1/guicast/bcwindowbase.C b/cinelerra-5.1/guicast/bcwindowbase.C index a35645ad..c52196f6 100644 --- a/cinelerra-5.1/guicast/bcwindowbase.C +++ b/cinelerra-5.1/guicast/bcwindowbase.C @@ -3910,9 +3910,9 @@ void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window) get_abs_cursor(px, py, lock_window); if( px < xmargin ) px = xmargin; if( py < ymargin ) py = ymargin; - int wd = get_screen_w(lock_window,-1) - xmargin; + int wd = get_screen_x(lock_window,-1) + get_screen_w(lock_window,-1) - xmargin; if( px > wd ) px = wd; - int ht = get_screen_h(lock_window,-1) - ymargin; + int ht = get_screen_y(lock_window,-1) + get_screen_h(lock_window,-1) - ymargin; if( py > ht ) py = ht; } int BC_WindowBase::get_pop_cursor_x(int lock_window) diff --git a/cinelerra-5.1/thirdparty/Makefile b/cinelerra-5.1/thirdparty/Makefile index 25d654e4..5727aadd 100644 --- a/cinelerra-5.1/thirdparty/Makefile +++ b/cinelerra-5.1/thirdparty/Makefile @@ -205,9 +205,10 @@ dav1d.cfg_vars?=echo "echo dav1d custom make" >> configure; chmod +x ./configure dav1d.mak_params?=; $(MAKE) -C dav1d* install DESTDIR="$(call bld_path,dav1d)" libwebp.cfg_vars?= mkdir build && cd build && $(call cmake_config,..) libwebp.mak_params?= -C build all install DESTDIR=$(call bld_path,libwebp) -mjpegtools.cflags?="$(call inc_path,libjpeg) $(call ld_path,libjpeg,.libs)" -mjpegtools.mak_params?=; ln -s . $(call bld_path,mjpegtools,utils)/mjpegtools -mjpegtools.cfg_params?= --enable-shared=no --without-libsdl --without-v4l +mjpegtools.cflags?="$(call inc_path,libjpeg) $(call ld_path,libjpeg,build)" +mjpegtools.cfg_vars?= ./autogen.sh; +mjpegtools.cfg_params?= --enable-shared=no --without-libsdl --without-sdlgfx --without-v4l +mjpegtools.mak_params?= all ladspa.cfg_vars?= CFLAGS+=' -Dinline="" ' ladspa.mak_params?=; $(MAKE) -C ladspa* install DESTDIR=$(call bld_path,ladspa) libavc1394.cfg_vars?=PKG_CONFIG_PATH=$(call bld_path,libraw1394) @@ -221,7 +222,9 @@ libiec61883.cflags?="$(call inc_path,libraw1394)" libiec61883.ldflags?="$(call ld_path,libraw1394,src/.libs)" libiec61883.cfg_params?= --enable-shared=no libiec61883.mak_params?=; cd $(call bld_path,libiec61883,src); ln -sf . libiec61883 -libjpeg.cfg_params?= --enable-shared=no +libjpeg.cfg_vars?= mkdir build && cd build && $(call cmake_config,..) +libjpeg.cfg_params?= -DENABLE_SHARED=no -DCMAKE_INSTALL_LIBDIR=lib +libjpeg.mak_params?= -C build all install DESTDIR=$(call bld_path,libjpeg) libogg.cfg_params?= --enable-shared=no libraw1394.cfg_params?= --enable-shared=no; ln -sf src libraw1394 libtheora.cfg_vars?=PKG_CONFIG_PATH=$(call bld_path,libogg):$(call bld_path,libvorbis) diff --git a/cinelerra-5.1/thirdparty/downloads.txt b/cinelerra-5.1/thirdparty/downloads.txt index 142cc17c..b56e8a77 100644 --- a/cinelerra-5.1/thirdparty/downloads.txt +++ b/cinelerra-5.1/thirdparty/downloads.txt @@ -1,4 +1,5 @@ -https://www.cybercom.net/~dcoffin/dcraw/dcraw.c +#https://www.cybercom.net/~dcoffin/dcraw/dcraw.c (moved to next line) +https://www.dechifro.org/dcraw/dcraw.c http://download-mirror.savannah.gnu.org/releases//openexr/ilmbase-2.2.1.tar.gz http://gnu.mirrors.pair.com/savannah/savannah//openexr/openexr-2.2.1.tar.gz https://sourceforge.net/projects/opencvlibrary/files/latest/download?source=directory = 3.2.0 @@ -9,10 +10,10 @@ https://www.kernel.org/pub/linux/libs/ieee1394/libraw1394-2.1.2.tar.xz https://www.kernel.org/pub/linux/libs/ieee1394/libiec61883-1.2.0.tar.xz https://sourceforge.net/projects/libavc1394/files/latest/download?source=directory = 0.5.4 https://sourceforge.net/projects/libdv/files/latest/download?source=directory = 0.104 -https://sourceforge.net/projects/giflib/files/latest/download = 5.1.4 +https://sourceforge.net/projects/giflib/files/latest/download = 5.2.1 https://sourceforge.net/projects/flac/files/latest/download?source=directory = 1.3.2 -https://github.com/uclouvain/openjpeg/archive/master.zip = openjpeg-2.3.0-20171004.tar.xz ?? -https://sourceforge.net/projects/libjpeg-turbo/files/1.5.1/libjpeg-turbo-1.5.1.tar.gz/download +https://github.com/uclouvain/openjpeg/ = Releases=sourcefiles openjpeg-2.3.1.tar.gz +https://sourceforge.net/projects/libjpeg-turbo/ = Code (GitHub)=sourcefiles/2.0.4/libjpeg-turbo-2.0.4.tar.gz http://www.fftw.org/fftw-3.3.8.tar.gz http://festvox.org/packed/festival/2.4/festival-2.4-release.tar.gz http://festvox.org/packed/festival/2.4/speech_tools-2.4-release.tar.gz @@ -21,28 +22,29 @@ http://festvox.org/packed/festival/2.4/voices/festvox_cmu_us_ahw_cg.tar.gz #http://downloads.sourceforge.net/faac/faad2-2.8.8.tar.gz #http://ftp.gnome.org/pub/gnome/sources/esound/0.2/esound-0.2.41.tar.bz2 http://audiofile.68k.org/audiofile-0.3.6.tar.gz -https://sourceforge.net/projects/twolame/files/latest/download?source=directory = 0.3.13 +https://sourceforge.net/projects/twolame/ = GitHub / Releases = Source Code=twolame-0.4.0.tar.gz http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.6.tar.xz -http://downloads.xiph.org/releases/ogg/libogg-1.3.3.tar.gz +http://downloads.xiph.org/releases/ogg/libogg-1.3.4.tar.gz http://downloads.xiph.org/releases/theora/libtheora-1.1.1.tar.bz2 https://sourceforge.net/projects/lame/files/latest/download?source=directory = 3.100 -https://download.osgeo.org/libtiff/tiff-4.0.10.tar.gz +https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz https://sourceforge.net/projects/libuuid/files/latest/download?source=directory - 1.0.3 -ftp://ftp.videolan.org/pub/x264/snapshots/x264-snapshot-20190131-2245-stable.tar.bz2 -https://bitbucket.org/multicoreware/x265/downloads/x265_3.1.2.tar.gz +ftp://ftp.videolan.org/pub/x264/snapshots/x264-snapshot-20191217-2245-stable.tar.bz2 +https://bitbucket.org/multicoreware/x265/downloads/x265_3.2.1.tar.gz https://ffmpeg.org/releases/ffmpeg-4.2.tar.bz2 https://github.com/webmproject/libvpx/archive/v1.8.1.tar.gz -https://code.videolan.org/videolan/dav1d/-/archive/0.4.0/dav1d-0.4.0.tar.gz +https://code.videolan.org/videolan/dav1d/-/archive/0.5.0/dav1d-0.5.0.tar.gz https://github.com/swh/ladspa/releases/tag/v0.4.17, plugin.org.uk -https://archive.mozilla.org/pub/opus/opus-1.3.tar.gz -https://github.com/webmproject/libwebp = libwebp-1.0.2 +https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz +https://github.com/webmproject/libwebp = libwebp-1.1.0 https://github.com/mozilla/aom = libaom-v1.0.0 -git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git +git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git ?? +https://github.com/FFmpeg/nv-codec-headers/releases/download/n9.1.23.1/nv-codec-headers-9.1.23.1.tar.gz https://gitlab.com/drobilla/lv2/-/archive/v1.16.0/lv2-v1.16.0.tar.gz -http://download.drobilla.net/suil-0.10.2.tar.bz2 -http://download.drobilla.net/sratom-0.6.2.tar.bz2 -http://download.drobilla.net/lilv-0.24.4.tar.bz2 -http://download.drobilla.net/sord-0.16.2.tar.bz2 -http://download.drobilla.net/serd-0.30.0.tar.bz2 -http://download.drobilla.net/jalv-1.6.0.tar.bz2 +http://download.drobilla.net/suil-0.10.6.tar.bz2 +http://download.drobilla.net/sratom-0.6.4.tar.bz2 +http://download.drobilla.net/lilv-0.24.6.tar.bz2 +http://download.drobilla.net/sord-0.16.4.tar.bz2 +http://download.drobilla.net/serd-0.30.2.tar.bz2 +http://download.drobilla.net/jalv-1.6.4.tar.bz2 diff --git a/cinelerra-5.1/thirdparty/src/dav1d-0.5.0.tar.xz b/cinelerra-5.1/thirdparty/src/dav1d-0.5.0.tar.xz deleted file mode 100644 index 707430e4..00000000 Binary files a/cinelerra-5.1/thirdparty/src/dav1d-0.5.0.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/dav1d-0.5.0.patch1 b/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.patch1 similarity index 100% rename from cinelerra-5.1/thirdparty/src/dav1d-0.5.0.patch1 rename to cinelerra-5.1/thirdparty/src/dav1d-0.5.1.patch1 diff --git a/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz b/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz new file mode 100644 index 00000000..805f750d Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz differ diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 index f16968a7..ad17541c 100644 --- a/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 +++ b/cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9 @@ -1,6 +1,8 @@ ---- a/libavutil/hwcontext_cuda.c 2019-12-03 10:04:24.521156775 -0700 -+++ b/libavutil/hwcontext_cuda.c 2019-12-03 10:59:03.924121027 -0700 -@@ -282,9 +282,11 @@ +diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c +index a87c280cf7..718def3dab 100644 +--- a/libavutil/hwcontext_cuda.c ++++ b/libavutil/hwcontext_cuda.c +@@ -296,9 +296,11 @@ static void cuda_device_uninit(AVHWDeviceContext *device_ctx) CudaFunctions *cu = hwctx->internal->cuda_dl; if (hwctx->internal->is_allocated && hwctx->cuda_ctx) { @@ -12,24 +14,23 @@ CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx)); hwctx->cuda_ctx = NULL; -@@ -351,7 +353,7 @@ - goto error; +@@ -348,7 +350,7 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { + cu = hwctx->internal->cuda_dl; hwctx->internal->flags = flags; - +#ifdef CUDA_PRIMARY_CTX if (flags & AV_CUDA_USE_PRIMARY_CONTEXT) { - ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device, &dev_flags, &dev_active)); + ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device, + &dev_flags, &dev_active)); +@@ -369,7 +371,9 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { + hwctx->internal->cuda_device)); if (ret < 0) -@@ -369,7 +371,10 @@ - ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx->cuda_ctx, hwctx->internal->cuda_device)); - if (ret < 0) - goto error; + return ret; - } else { -+ } -+ else ++ } else +#endif + { - ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags, hwctx->internal->cuda_device)); + ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags, + hwctx->internal->cuda_device)); if (ret < 0) - goto error; diff --git a/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz b/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz index 00bc94a5..ed5cb753 100644 Binary files a/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz and b/cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch1 b/cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch1 deleted file mode 100644 index 86080942..00000000 --- a/cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch1 +++ /dev/null @@ -1,23 +0,0 @@ -diff -ur a/Makefile b/Makefile ---- a/Makefile 2019-02-12 07:26:13.000000000 -0700 -+++ b/Makefile 2019-02-25 18:33:26.360039018 -0700 -@@ -7,8 +7,8 @@ - - # - CC = gcc --OFLAGS = -O0 -g --#OFLAGS = -O2 -fwhole-program -+#OFLAGS = -O0 -g -+OFLAGS = -O2 - CFLAGS = -std=gnu99 -fPIC -Wall -Wno-format-truncation $(OFLAGS) - LDFLAGS = -g - -@@ -61,7 +61,7 @@ - LDLIBS=libgif.a -lm - - all: libgif.so libgif.a $(UTILS) -- $(MAKE) -C doc -+# $(MAKE) -C doc - - $(UTILS):: libgif.a - diff --git a/cinelerra-5.1/thirdparty/src/giflib-5.1.6.tar.xz b/cinelerra-5.1/thirdparty/src/giflib-5.1.6.tar.xz deleted file mode 100644 index 7699889c..00000000 Binary files a/cinelerra-5.1/thirdparty/src/giflib-5.1.6.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch1 b/cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch1 new file mode 100644 index 00000000..8560f046 --- /dev/null +++ b/cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch1 @@ -0,0 +1,20 @@ +--- a/Makefile 2020-02-10 20:33:30.257695474 -0700 ++++ b/Makefile 2020-02-10 20:37:25.217129318 -0700 +@@ -6,7 +6,7 @@ + # of code space in the shared library. + + # +-OFLAGS = -O0 -g ++#OFLAGS = -O0 -g + OFLAGS = -O2 + CFLAGS = -std=gnu99 -fPIC -Wall -Wno-format-truncation $(OFLAGS) + +@@ -62,7 +62,7 @@ + LDLIBS=libgif.a -lm + + all: libgif.so libgif.a libutil.so libutil.a $(UTILS) +- $(MAKE) -C doc ++# $(MAKE) -C doc + + $(UTILS):: libgif.a libutil.a + diff --git a/cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch2 b/cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch2 similarity index 100% rename from cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch2 rename to cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch2 diff --git a/cinelerra-5.1/thirdparty/src/giflib-5.2.1.tar.xz b/cinelerra-5.1/thirdparty/src/giflib-5.2.1.tar.xz new file mode 100644 index 00000000..c633d2a0 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/giflib-5.2.1.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/jalv-1.6.0.tar.xz b/cinelerra-5.1/thirdparty/src/jalv-1.6.0.tar.xz deleted file mode 100644 index 86daab2a..00000000 Binary files a/cinelerra-5.1/thirdparty/src/jalv-1.6.0.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/jalv-1.6.4.tar.bz2 b/cinelerra-5.1/thirdparty/src/jalv-1.6.4.tar.bz2 new file mode 100644 index 00000000..0c6feec6 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/jalv-1.6.4.tar.bz2 differ diff --git a/cinelerra-5.1/thirdparty/src/libjpeg-turbo-1.5.1.tar.xz b/cinelerra-5.1/thirdparty/src/libjpeg-turbo-1.5.1.tar.xz deleted file mode 100644 index 2d5ddf88..00000000 Binary files a/cinelerra-5.1/thirdparty/src/libjpeg-turbo-1.5.1.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz b/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz new file mode 100644 index 00000000..5c5ba84c Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/libogg-1.3.3.tar.xz b/cinelerra-5.1/thirdparty/src/libogg-1.3.3.tar.xz deleted file mode 100644 index bfd8dec1..00000000 Binary files a/cinelerra-5.1/thirdparty/src/libogg-1.3.3.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/libogg-1.3.4.tar.xz b/cinelerra-5.1/thirdparty/src/libogg-1.3.4.tar.xz new file mode 100644 index 00000000..654ff9c2 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libogg-1.3.4.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/libwebp-1.0.2.tar.xz b/cinelerra-5.1/thirdparty/src/libwebp-1.1.0.tar.xz similarity index 63% rename from cinelerra-5.1/thirdparty/src/libwebp-1.0.2.tar.xz rename to cinelerra-5.1/thirdparty/src/libwebp-1.1.0.tar.xz index aea7ec96..45b5e3d9 100644 Binary files a/cinelerra-5.1/thirdparty/src/libwebp-1.0.2.tar.xz and b/cinelerra-5.1/thirdparty/src/libwebp-1.1.0.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/lilv-0.24.4.tar.xz b/cinelerra-5.1/thirdparty/src/lilv-0.24.4.tar.xz deleted file mode 100644 index 2769d4f4..00000000 Binary files a/cinelerra-5.1/thirdparty/src/lilv-0.24.4.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz b/cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz new file mode 100644 index 00000000..f32ac800 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/openjpeg-2.3.0.tar.xz b/cinelerra-5.1/thirdparty/src/openjpeg-2.3.0.tar.xz deleted file mode 100644 index 79d437f3..00000000 Binary files a/cinelerra-5.1/thirdparty/src/openjpeg-2.3.0.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/openjpeg-2.3.1.tar.xz b/cinelerra-5.1/thirdparty/src/openjpeg-2.3.1.tar.xz new file mode 100644 index 00000000..a74212b3 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/openjpeg-2.3.1.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/opus-1.3.1.tar.xz b/cinelerra-5.1/thirdparty/src/opus-1.3.1.tar.xz new file mode 100644 index 00000000..feeb99b2 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/opus-1.3.1.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/opus-1.3.tar.xz b/cinelerra-5.1/thirdparty/src/opus-1.3.tar.xz deleted file mode 100644 index 9e7e2469..00000000 Binary files a/cinelerra-5.1/thirdparty/src/opus-1.3.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/serd-0.30.0.tar.xz b/cinelerra-5.1/thirdparty/src/serd-0.30.0.tar.xz deleted file mode 100644 index ca9721ad..00000000 Binary files a/cinelerra-5.1/thirdparty/src/serd-0.30.0.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz b/cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz new file mode 100644 index 00000000..25b82e81 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/sord-0.16.2.tar.xz b/cinelerra-5.1/thirdparty/src/sord-0.16.2.tar.xz deleted file mode 100644 index 5793b2c8..00000000 Binary files a/cinelerra-5.1/thirdparty/src/sord-0.16.2.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/sord-0.16.4.tar.xz b/cinelerra-5.1/thirdparty/src/sord-0.16.4.tar.xz new file mode 100644 index 00000000..ffe30e04 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/sord-0.16.4.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/sratom-0.6.2.tar.xz b/cinelerra-5.1/thirdparty/src/sratom-0.6.2.tar.xz deleted file mode 100644 index a56b403c..00000000 Binary files a/cinelerra-5.1/thirdparty/src/sratom-0.6.2.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/sratom-0.6.4.tar.xz b/cinelerra-5.1/thirdparty/src/sratom-0.6.4.tar.xz new file mode 100644 index 00000000..47e9d013 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/sratom-0.6.4.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/suil-0.10.2.tar.xz b/cinelerra-5.1/thirdparty/src/suil-0.10.2.tar.xz deleted file mode 100644 index 3bf2d55a..00000000 Binary files a/cinelerra-5.1/thirdparty/src/suil-0.10.2.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/suil-0.10.6.tar.xz b/cinelerra-5.1/thirdparty/src/suil-0.10.6.tar.xz new file mode 100644 index 00000000..21411f83 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/suil-0.10.6.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/tiff-4.0.10.tar.xz b/cinelerra-5.1/thirdparty/src/tiff-4.0.10.tar.xz deleted file mode 100644 index dafaeb25..00000000 Binary files a/cinelerra-5.1/thirdparty/src/tiff-4.0.10.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/tiff-4.1.0.tar.xz b/cinelerra-5.1/thirdparty/src/tiff-4.1.0.tar.xz new file mode 100644 index 00000000..6a3d4175 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/tiff-4.1.0.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/twolame-0.3.13.tar.xz b/cinelerra-5.1/thirdparty/src/twolame-0.3.13.tar.xz deleted file mode 100644 index b64bae3a..00000000 Binary files a/cinelerra-5.1/thirdparty/src/twolame-0.3.13.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/twolame-0.4.0.tar.xz b/cinelerra-5.1/thirdparty/src/twolame-0.4.0.tar.xz new file mode 100644 index 00000000..f7fd1780 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/twolame-0.4.0.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/x264-snapshot-20190117-2245-stable.tar.xz b/cinelerra-5.1/thirdparty/src/x264-snapshot-20190117-2245-stable.tar.xz deleted file mode 100644 index c77c5bb5..00000000 Binary files a/cinelerra-5.1/thirdparty/src/x264-snapshot-20190117-2245-stable.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/x264-snapshot-20191217-2245-stable.tar.xz b/cinelerra-5.1/thirdparty/src/x264-snapshot-20191217-2245-stable.tar.xz new file mode 100644 index 00000000..15f97501 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/x264-snapshot-20191217-2245-stable.tar.xz differ diff --git a/cinelerra-5.1/thirdparty/src/x265_3.1.2.tar.xz b/cinelerra-5.1/thirdparty/src/x265_3.1.2.tar.xz deleted file mode 100644 index 3bd59f8f..00000000 Binary files a/cinelerra-5.1/thirdparty/src/x265_3.1.2.tar.xz and /dev/null differ diff --git a/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz b/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz new file mode 100644 index 00000000..31621288 Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz differ