locale expanders txt, libpulse prereq, debian shlibs deps,
authorGood Guy <[email protected]>
Fri, 28 Feb 2020 15:34:55 +0000 (08:34 -0700)
committerGood Guy <[email protected]>
Fri, 28 Feb 2020 15:34:55 +0000 (08:34 -0700)
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

73 files changed:
cinelerra-5.1/Makefile.am
cinelerra-5.1/blds/PKGBUILD
cinelerra-5.1/blds/bld_prepare.sh
cinelerra-5.1/blds/cinelerra.spec
cinelerra-5.1/blds/debian/control
cinelerra-5.1/blds/debian/rules
cinelerra-5.1/cinelerra/Makefile
cinelerra-5.1/cinelerra/asset.C
cinelerra-5.1/cinelerra/asset.h
cinelerra-5.1/cinelerra/awindowgui.C
cinelerra-5.1/cinelerra/ffmpeg.C
cinelerra-5.1/cinelerra/ffmpeg.h
cinelerra-5.1/cinelerra/file.C
cinelerra-5.1/cinelerra/file.h
cinelerra-5.1/cinelerra/file.inc
cinelerra-5.1/cinelerra/fileffmpeg.C
cinelerra-5.1/cinelerra/fileffmpeg.h
cinelerra-5.1/cinelerra/fileffmpeg.inc
cinelerra-5.1/cinelerra/filegif.C
cinelerra-5.1/cinelerra/fileogg.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/fileogg.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/filevorbis.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/filevorbis.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/filevorbis.inc [new file with mode: 0644]
cinelerra-5.1/cinelerra/formatpopup.C
cinelerra-5.1/cinelerra/formattools.C
cinelerra-5.1/cinelerra/packagedispatcher.C
cinelerra-5.1/configure.ac
cinelerra-5.1/expanders.es [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/avi.dfl [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/avi.dfl [new file with mode: 0644]
cinelerra-5.1/guicast/bcwindowbase.C
cinelerra-5.1/thirdparty/Makefile
cinelerra-5.1/thirdparty/downloads.txt
cinelerra-5.1/thirdparty/src/dav1d-0.5.0.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/dav1d-0.5.1.patch1 [moved from cinelerra-5.1/thirdparty/src/dav1d-0.5.0.patch1 with 100% similarity]
cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/ffmpeg.git.patch9
cinelerra-5.1/thirdparty/src/ffnvcodec.tar.xz
cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch1 [deleted file]
cinelerra-5.1/thirdparty/src/giflib-5.1.6.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch1 [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/giflib-5.2.1.patch2 [moved from cinelerra-5.1/thirdparty/src/giflib-5.1.6.patch2 with 100% similarity]
cinelerra-5.1/thirdparty/src/giflib-5.2.1.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/jalv-1.6.0.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/jalv-1.6.4.tar.bz2 [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/libjpeg-turbo-1.5.1.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/libjpeg-turbo-2.0.4.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/libogg-1.3.3.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/libogg-1.3.4.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/libwebp-1.1.0.tar.xz [moved from cinelerra-5.1/thirdparty/src/libwebp-1.0.2.tar.xz with 63% similarity]
cinelerra-5.1/thirdparty/src/lilv-0.24.4.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/lilv-0.24.6.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/openjpeg-2.3.0.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/openjpeg-2.3.1.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/opus-1.3.1.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/opus-1.3.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/serd-0.30.0.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/serd-0.30.2.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/sord-0.16.2.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/sord-0.16.4.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/sratom-0.6.2.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/sratom-0.6.4.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/suil-0.10.2.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/suil-0.10.6.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/tiff-4.0.10.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/tiff-4.1.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/twolame-0.3.13.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/twolame-0.4.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/x264-snapshot-20190117-2245-stable.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/x264-snapshot-20191217-2245-stable.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/x265_3.1.2.tar.xz [deleted file]
cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz [new file with mode: 0644]

index 64e1e8dff3d0162796c61b022097f41b9ab62344..bd5c0f84379e42f4424bd11efb6261d181e3c62f 100644 (file)
@@ -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/\<cin\>/$(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)" .
index 30c011b118976e0fc14527200fe32bd3be8214c8..ea6a2992fddc04879d0e6983b6fdcabe71dccd50 100644 (file)
@@ -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'
index a34f123d9c4ae3c6387296ac16d4fc3ab41922ce..3c34ff6a07d4a51ba6581c57f1fff7b7f30b27f1 100755 (executable)
@@ -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"
index 93078964205a7e3d7cebf724f7c5d8fc5761cd46..21d9f835467ca05021dfb1bcabf0bfdef682dce8 100644 (file)
@@ -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}
index a47f3f8d77c537b207a9ba4ec4c882ac673c55e7..b8d5057708634077d6354c9180c06079f4240ff7 100644 (file)
@@ -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
 
index c95b0a0300a07c49979ceed35275f8e7d6efeb0d..58dd957297897db2ad3ef56e1f7ee8c8bd114fb0 100755 (executable)
@@ -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
 
index a22a21aeccdbe3bdb36d2e8c7c77fa635a7b9b3c..d0a8f1ad919387d3e4ad84f9ff8166574c4731c0 100644 (file)
@@ -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
index 48dfca3ca66934d7379e30570f3bd115773dbd42..fd6e97e4436f738e172c4215ecf034655c52c885 100644 (file)
@@ -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_,
index 80a29eb5cc33c48b84778abf8ef01679ea71168d..096ea9882a0f58b0d0067a7adb074792cf1a527e 100644 (file)
@@ -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;
index a8e6c002832fa14cbcf06d1f3820f0f4d5d27877..1aa57e35b5ebf3eeb42ede875813adb50ec7a509 100644 (file)
@@ -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;
index 26a8ddd54c38c729fbf5cadf0dee94a2bf5fce8d..8b9cc27fe5585d70fa522c8a7cd580c47a243331 100644 (file)
@@ -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; vidx<ffvideo.size(); ++vidx ) {
+               const char *unkn = _("(unkn)");
                FFVideoStream *vid = ffvideo[vidx];
                AVStream *st = vid->st;
                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;
index 46838b4d92dca56ee8bc0625554ef5b48d0aff3a..6ad5124664940694e519527ac11e4466451a4027 100644 (file)
@@ -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);
index 1fec188eacb98570229d46acda6e27cc19322cfd..f9571c9d1dddd60bb37704dda5a18d0e740c8200 100644 (file)
@@ -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"
 #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;
index 2ca1acbe921a62482d4595f3e86519d3189b66ef..c86a1b4f72b1d9b8911798d1b297779de665ab7d 100644 (file)
@@ -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);
index 748ce065ecc9f4f5e71b92e58e6555dc75f04cb2..11a5bc9af73b1e3f2b548380c7ea35b35e940ae3 100644 (file)
@@ -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"
 
index 564306e656e82fce65b89cbe7555cde7bc72f902..0db64205be373bff1a33959de608a51b5da4438c 100644 (file)
@@ -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;
+}
+
index 5453b77ca61d0f0c692484fd4c45b11d93747170..56176a42188d848ff988bcd0559780581d11fa4c 100644 (file)
@@ -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<BC_ListBoxItem*> 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
index 4525a5a7cbfe7183394c7c1512f61391bd7636ab..b51e5d9149615ce66970f1239c27ecc56033970c 100644 (file)
@@ -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
index 6f4e3e43d800a28dd4cf57b1b45231b73d04df77..bb26762bef07094251db75deeaea1b000230bcc6 100644 (file)
 #include <fcntl.h>
 #include <string.h>
 
+//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 (file)
index 0000000..7302bcd
--- /dev/null
@@ -0,0 +1,1910 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+/* This code was aspired by ffmpeg2theora */
+/* Special thanks for help on this code goes out to [email protected] */
+
+
+#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; i<pcm_channels; ++i )
+                       delete [] pcm_history[i];
+               pcm_channels = 0;
+               delete [] pcm_history;  pcm_history = 0;
+
+               vorbis_dsp_clear(&vd);
+               vorbis_info_clear(&vi);
+               vorbis_block_clear(&vb);
+               vorbis_comment_clear(&vc);
+               ogg_stream_clear(&vo);
+               delete audiosync;  audiosync = 0;
+               audio = 0;
+       }
+       if( video ) {
+               th_info_clear(&ti);
+               th_setup_free(ts);  ts = 0;
+               th_comment_clear(&tc);
+               ogg_stream_clear(&to);
+               delete videosync;  videosync = 0;
+               video = 0;
+       }
+       if( dec ) {
+               th_decode_free(dec);
+               dec = 0;
+       }
+       if( inp ) {
+               fclose(inp);
+               inp = 0;
+       }
+}
+
+
+
+void FileOGG::get_parameters(BC_WindowBase *parent_window, Asset *asset,
+       BC_WindowBase* &format_window, int audio_options,
+       int video_options, EDL *edl)
+{
+       if(audio_options)
+       {
+               OGGConfigAudio *window = new OGGConfigAudio(parent_window, asset);
+               format_window = window;
+               window->create_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; i<asset->channels; ++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; i<asset->channels; ++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; i<asset->channels; ++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; j<len; ++j ) {
+               flush_ogg(0);
+               if( temp_frame ) {
+                       th_ycbcr_buffer ycbcr;
+                       ycbcr[0].width = frame_w;
+                       ycbcr[0].height = frame_h;
+                       ycbcr[0].stride = temp_frame->get_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 (file)
index 0000000..87c26dc
--- /dev/null
@@ -0,0 +1,340 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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 <theora/theora.h>
+#include <theora/theoraenc.h>
+#include <theora/theoradec.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisenc.h>
+
+
+/* This code was aspired by ffmpeg2theora */
+/* Special thanks for help on this code goes out to [email protected] */
+
+#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 (file)
index 0000000..f04249f
--- /dev/null
@@ -0,0 +1,490 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+//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 (file)
index 0000000..5dbf890
--- /dev/null
@@ -0,0 +1,140 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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 (file)
index 0000000..bf38c44
--- /dev/null
@@ -0,0 +1,29 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
index 6252b0c2b4d6eb07ea304ab33ca912c293ca74cf..addd4a2c7a598dbb810a3ae99260a97cc3474bdf 100644 (file)
@@ -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);
        }
index 0979dfa46f7d22a956e7ac9bc5bc0f81386dfaa6..643655e3bcac6aabd41095a9df95fd8baac10fa9 100644 (file)
@@ -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();
index aa88d5f12cdae8f437929265b813b857bcfb0e61..dccec03a2896c3f8676a0f66b44f589b285bc090 100644 (file)
@@ -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<char*> paths;
+               paths.set_array_delete();
                get_package_paths(&paths);
                result = ConfirmSave::test_files(mwindow, &paths);
                paths.remove_all_objects();
index a2d5b501a63ae120b6a3349809816660329362ed..ee75006c35636d9c94d798ea82af8239a628a27e 100644 (file)
@@ -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 (file)
index 0000000..31c8a28
--- /dev/null
@@ -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 (file)
index 0000000..81b5d79
--- /dev/null
@@ -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 (file)
index 0000000..ad4bb12
--- /dev/null
@@ -0,0 +1 @@
+asv1.avi
index a35645ad05d707ecac9c1d2b68b33d8c86530a3e..c52196f65b3e2fdba460439f129fee0ee2542b7e 100644 (file)
@@ -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)
index 25d654e48a6274bbf40e9570919306e32e4e1518..5727aadd84114a264f1534485e83c20bbc17f35b 100644 (file)
@@ -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)
index 142cc17ce356b9b5bc1f6fb226caf47c7f06055f..b56e8a77475c9a9a417ab87d620ab72787214830 100644 (file)
@@ -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 (file)
index 707430e..0000000
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.1.tar.gz b/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz
new file mode 100644 (file)
index 0000000..805f750
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/dav1d-0.5.1.tar.gz differ
index f16968a791af0c62e7b230f1a9876aff1dd3616c..ad17541c0a141cf7b2138cd71670764e374567a8 100644 (file)
@@ -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) {
                  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;
index 00bc94a5c4c654e621ec4d6135f07d9bd35ce51c..ed5cb753a652c4e40542efc7d02a70b80c47a5a3 100644 (file)
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 (file)
index 8608094..0000000
+++ /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 (file)
index 7699889..0000000
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 (file)
index 0000000..8560f04
--- /dev/null
@@ -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.2.1.tar.xz b/cinelerra-5.1/thirdparty/src/giflib-5.2.1.tar.xz
new file mode 100644 (file)
index 0000000..c633d2a
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 (file)
index 86daab2..0000000
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 (file)
index 0000000..0c6feec
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 (file)
index 2d5ddf8..0000000
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 (file)
index 0000000..5c5ba84
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 (file)
index bfd8dec..0000000
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 (file)
index 0000000..654ff9c
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/libogg-1.3.4.tar.xz differ
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 aea7ec9642ece2d491a5d2d4408a3bdf41306629..45b5e3d9854923fd886e9f19f5ea8556845bc5ab 100644 (file)
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 (file)
index 2769d4f..0000000
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 (file)
index 0000000..f32ac80
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 (file)
index 79d437f..0000000
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 (file)
index 0000000..a74212b
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 (file)
index 0000000..feeb99b
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 (file)
index 9e7e246..0000000
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 (file)
index ca9721a..0000000
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 (file)
index 0000000..25b82e8
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 (file)
index 5793b2c..0000000
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 (file)
index 0000000..ffe30e0
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 (file)
index a56b403..0000000
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 (file)
index 0000000..47e9d01
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 (file)
index 3bf2d55..0000000
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 (file)
index 0000000..21411f8
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 (file)
index dafaeb2..0000000
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 (file)
index 0000000..6a3d417
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 (file)
index b64bae3..0000000
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 (file)
index 0000000..f7fd178
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 (file)
index c77c5bb..0000000
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 (file)
index 0000000..15f9750
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 (file)
index 3bd59f8..0000000
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 (file)
index 0000000..3162128
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/x265_3.2.1.tar.gz differ