add ffmpeg filters as plugins
authorGood Guy <good1.2guy@gmail.com>
Sat, 31 Oct 2015 23:33:44 +0000 (17:33 -0600)
committerGood Guy <good1.2guy@gmail.com>
Sat, 31 Oct 2015 23:33:44 +0000 (17:33 -0600)
29 files changed:
cinelerra-5.0/cinelerra/Makefile
cinelerra-5.0/cinelerra/aattachmentpoint.C
cinelerra-5.0/cinelerra/awindow.C
cinelerra-5.0/cinelerra/awindow.h
cinelerra-5.0/cinelerra/awindowgui.C
cinelerra-5.0/cinelerra/awindowgui.h
cinelerra-5.0/cinelerra/data/ff_audio.png [new file with mode: 0644]
cinelerra-5.0/cinelerra/data/ff_audio_png.h [new file with mode: 0644]
cinelerra-5.0/cinelerra/data/ff_video.png [new file with mode: 0644]
cinelerra-5.0/cinelerra/data/ff_video_png.h [new file with mode: 0644]
cinelerra-5.0/cinelerra/ffmpeg.C
cinelerra-5.0/cinelerra/ffmpeg.h
cinelerra-5.0/cinelerra/fileac3.C
cinelerra-5.0/cinelerra/mwindow.C
cinelerra-5.0/cinelerra/mwindow.h
cinelerra-5.0/cinelerra/mwindow.inc
cinelerra-5.0/cinelerra/pluginfclient.C [new file with mode: 0644]
cinelerra-5.0/cinelerra/pluginfclient.h [new file with mode: 0644]
cinelerra-5.0/cinelerra/pluginfclient.inc [new file with mode: 0644]
cinelerra-5.0/cinelerra/pluginserver.C
cinelerra-5.0/cinelerra/pluginserver.h
cinelerra-5.0/cinelerra/pluginserver.inc
cinelerra-5.0/cinelerra/vattachmentpoint.C
cinelerra-5.0/ffmpeg/plugin.opts [new file with mode: 0644]
cinelerra-5.0/guicast/bchash.C
cinelerra-5.0/guicast/bchash.h
cinelerra-5.0/guicast/vframe.C
cinelerra-5.0/mpeg2enc/Makefile
cinelerra-5.0/msg.txt

index 065346f526efa10ca1e111990a7f50c511626f3c..6b0d1bd13ce1ac630d7b51bf47b84f8f0d651e88 100644 (file)
@@ -326,6 +326,7 @@ OBJS = \
        $(OBJDIR)/vdevicempeg.o \
        $(OBJDIR)/vdevicev4l2mpeg.o \
        $(OBJDIR)/wwindow.o \
+       $(OBJDIR)/pluginfclient.o \
 
 #      $(OBJDIR)/renderfarmfsclient.o \
 #      $(OBJDIR)/renderfarmfsserver.o \
@@ -344,9 +345,6 @@ LIBRARIES := \
        $(THEME_DATA) \
 
 LIBS = $(LIBRARIES)
-LIBS += $(thirdparty_libraries)
-LIBS += $(thirdparty_libraries)
-LIBS += $(thirdparty_libraries)
 LIBS += \
        -lX11 \
        -lXext \
@@ -361,7 +359,9 @@ LIBS += \
        -llzma \
        -lfontconfig \
        -lfreetype \
-       $(EXTRA_LIBS)
+
+LIBS += -Wl,--start-group $(thirdparty_libraries) -Wl,--end-group 
+LIBS += $(EXTRA_LIBS)
 
 CUTADS = $(OBJDIR)/cutads
 CUTOBJ = $(OBJDIR)/cutads.o
index 00d8ae0de00afbe5cb2262e49f33a917040c123b..edeba467a244465e17175a26ed4506d01cfde594 100644 (file)
@@ -96,48 +96,27 @@ void AAttachmentPoint::render(Samples *output,
        if(plugin_server->multichannel)
        {
 // Test against previous parameters for reuse of previous data
-               if(is_processed &&
-                       this->start_position == start_position && 
-                       this->len == len && 
-                       this->sample_rate == sample_rate)
-               {
-                       memcpy(output->get_data(), 
-                               buffer_vector[buffer_number]->get_data(), 
-                               sizeof(double) * len);
-                       return;
-               }
-
+               if( !is_processed || this->start_position != start_position || 
+                       this->len != len || this->sample_rate != sample_rate ) {
 // Update status
-               this->start_position = start_position;
-               this->len = len;
-               this->sample_rate = sample_rate;
-               is_processed = 1;
+                       this->start_position = start_position;
+                       this->len = len;
+                       this->sample_rate = sample_rate;
+                       is_processed = 1;
 
 // Allocate buffer vector
-               new_buffer_vector(virtual_plugins.total, len);
-
-// Create temporary buffer vector with output argument substituted in
-               Samples **output_temp = new Samples*[virtual_plugins.total];
-               for(int i = 0; i < virtual_plugins.total; i++)
-               {
-                       if(i == buffer_number)
-                               output_temp[i] = output;
-                       else
-                               output_temp[i] = buffer_vector[i];
-               }
+                       new_buffer_vector(virtual_plugins.total, len);
 
 // Process plugin
-               plugin_servers.values[0]->process_buffer(output_temp,
-                       start_position,
-                       len,
-                       sample_rate,
-                       plugin->length *
-                               sample_rate /
-                               renderengine->get_edl()->session->sample_rate,
-                       renderengine->command->get_direction());
-
-// Delete temporary buffer vector
-               delete [] output_temp;
+                       plugin_servers.values[0]->process_buffer(
+                               buffer_vector, start_position, len, sample_rate,
+                               plugin->length * sample_rate /
+                                       renderengine->get_edl()->session->sample_rate,
+                               renderengine->command->get_direction());
+               }
+               memcpy(output->get_data(), 
+                       buffer_vector[buffer_number]->get_data(), 
+                       sizeof(double) * len);
        }
        else
        {
index 4dcfc4a367d76c33e36a0643a60678df3d4a49e9..f338f0e75f1f947c868a8c8b4ca3f00f44116f10 100644 (file)
@@ -62,6 +62,15 @@ void AWindow::create_objects()
        clip_edit = new ClipEdit(mwindow, this, 0);
 }
 
+int AWindow::save_defaults(BC_Hash *defaults)
+{
+       return gui->save_defaults(defaults);
+}
+int AWindow::load_defaults(BC_Hash *defaults)
+{
+       return gui->load_defaults(defaults);
+}
+
 
 void AWindow::run()
 {
index a19f8abf5a5e67c3cd98c4a3cf99cca45b0df117..65e340859ea0d9073cf8f23a785efba32e19cdc3 100644 (file)
@@ -25,6 +25,7 @@
 #include "assetedit.inc"
 #include "assetremove.inc"
 #include "awindowgui.inc"
+#include "bchash.inc"
 #include "bcwindowbase.inc"
 #include "clipedit.inc"
 #include "mwindow.inc"
@@ -38,6 +39,8 @@ public:
 
        void run();
        void create_objects();
+       int load_defaults(BC_Hash *defaults);
+       int save_defaults(BC_Hash *defaults);
 
        char current_folder[BCTEXTLEN];
 
index 70df0cce36a7813a57a33ef7a4ddd334fcbbc86b..81e8760b9794c971be7a3cbcdb52d93f52b504c6 100644 (file)
@@ -28,6 +28,7 @@
 #include "awindow.h"
 #include "awindowmenu.h"
 #include "bcsignals.h"
+#include "bchash.h"
 #include "cache.h"
 #include "bccmodels.h"
 #include "cursors.h"
@@ -54,6 +55,8 @@
 #include "vwindow.h"
 
 #include "data/lad_picon_png.h"
+#include "data/ff_audio_png.h"
+#include "data/ff_video_png.h"
 
 #include<stdio.h>
 #include<unistd.h>
@@ -257,20 +260,28 @@ void AssetPicon::create_objects()
                                icon = gui->atransition_icon;
                                icon_vframe = gui->atransition_vframe;
                        }
-                       else if( !plugin->is_ladspa() ) {
-                               icon = gui->aeffect_icon;
-                               icon_vframe = gui->aeffect_vframe;
+                       else if( plugin->is_ffmpeg() ) {
+                               icon = gui->ff_aud_icon;
+                               icon_vframe = gui->ff_aud_vframe;
                        }
-                       else {
+                       else if( plugin->is_ladspa() ) {
                                icon = gui->ladspa_icon;
                                icon_vframe = gui->ladspa_vframe;
                        }
+                       else {
+                               icon = gui->aeffect_icon;
+                               icon_vframe = gui->aeffect_vframe;
+                       }
                }
                else if( plugin->video ) {
                        if( plugin->transition ) {
                                icon = gui->vtransition_icon;
                                icon_vframe = gui->vtransition_vframe;
                        }
+                       else if( plugin->is_ffmpeg() ) {
+                               icon = gui->ff_vid_icon;
+                               icon_vframe = gui->ff_vid_vframe;
+                       }
                        else {
                                icon = gui->veffect_icon;
                                icon_vframe = gui->veffect_vframe;
@@ -321,13 +332,15 @@ AWindowGUI::AWindowGUI(MWindow *mwindow, AWindow *awindow)
        aeffect_icon = 0;      aeffect_vframe = 0;
        ladspa_icon = 0;       ladspa_vframe = 0;
        veffect_icon = 0;      veffect_vframe = 0;
+       ff_aud_icon = 0;       ff_aud_vframe = 0;
+       ff_vid_icon = 0;       ff_vid_vframe = 0;
+       plugin_visibility = ((uint64_t)1<<(8*sizeof(uint64_t)-1))-1;
        newfolder_thread = 0;
        asset_menu = 0;
        assetlist_menu = 0;
        folderlist_menu = 0;
        temp_picon = 0;
        remove_plugin = 0;
-       plugin_visibility = ~0;
 }
 
 AWindowGUI::~AWindowGUI()
@@ -339,6 +352,7 @@ AWindowGUI::~AWindowGUI()
        atransitions.remove_all_objects();
        vtransitions.remove_all_objects();
        displayed_assets[1].remove_all_objects();
+
        delete file_icon;
        delete audio_icon;
        delete video_icon;
@@ -349,6 +363,10 @@ AWindowGUI::~AWindowGUI()
        delete aeffect_icon;
        delete ladspa_icon;
        delete ladspa_vframe;
+       delete ff_aud_icon;
+       delete ff_aud_vframe;
+       delete ff_vid_icon;
+       delete ff_vid_vframe;
        delete veffect_icon;
        delete newfolder_thread;
        delete asset_menu;
@@ -361,15 +379,17 @@ AWindowGUI::~AWindowGUI()
 bool AWindowGUI::protected_pixmap(BC_Pixmap *icon)
 {
        return  icon == file_icon ||
-               icon == audio_icon ||
                icon == folder_icon ||
-               icon == clip_icon ||
+               icon == audio_icon ||
                icon == video_icon ||
-               icon == veffect_icon ||
+               icon == clip_icon ||
                icon == vtransition_icon ||
+               icon == atransition_icon ||
+               icon == veffect_icon ||
                icon == aeffect_icon ||
                icon == ladspa_icon ||
-               icon == atransition_icon; 
+               icon == ff_aud_icon ||
+               icon == ff_vid_icon;
 }
 
 void AWindowGUI::create_objects()
@@ -413,6 +433,10 @@ SET_TRACE
        aeffect_icon = new BC_Pixmap(this, aeffect_vframe, PIXMAP_ALPHA);
        ladspa_vframe = new VFrame(lad_picon_png);
        ladspa_icon = new BC_Pixmap(this, ladspa_vframe, PIXMAP_ALPHA);
+       ff_aud_vframe = new VFrame(ff_audio_png);
+       ff_aud_icon = new BC_Pixmap(this, ff_aud_vframe, PIXMAP_ALPHA);
+       ff_vid_vframe = new VFrame(ff_video_png);
+       ff_vid_icon = new BC_Pixmap(this, ff_vid_vframe, PIXMAP_ALPHA);
        veffect_vframe = mwindow->theme->get_image("veffect_icon");
        veffect_icon = new BC_Pixmap(this, veffect_vframe, PIXMAP_ALPHA);
 
@@ -438,6 +462,7 @@ SET_TRACE
 SET_TRACE
 
        mwindow->theme->get_awindow_sizes(this);
+       load_defaults(mwindow->defaults);
 
 SET_TRACE
        add_subwindow(asset_list = new AWindowAssets(mwindow,
@@ -574,6 +599,19 @@ void AWindowGUI::reposition_objects()
        flush();
 }
 
+int AWindowGUI::save_defaults(BC_Hash *defaults)
+{
+       defaults->update("PLUGIN_VISIBILTY", plugin_visibility);
+       return 0;
+}
+
+int AWindowGUI::load_defaults(BC_Hash *defaults)
+{
+       plugin_visibility = defaults->get("PLUGIN_VISIBILTY", plugin_visibility);
+       return 0;
+}
+
+
 int AWindowGUI::close_event()
 {
        hide_window();
@@ -585,6 +623,7 @@ int AWindowGUI::close_event()
        mwindow->gui->unlock_window();
 
        lock_window("AWindowGUI::close_event");
+       save_defaults(mwindow->defaults);
        mwindow->save_defaults();
        return 1;
 }
@@ -1733,7 +1772,11 @@ AddPluginsMenu::AddPluginsMenu(MWindow *mwindow, AWindowGUI *gui)
 
 void AddPluginsMenu::create_objects()
 {
-       uint32_t vis = 0;
+       uint64_t vis = 0;
+       add_item(new AddPluginItem(this, "ladspa", PLUGIN_LADSPA_ID));
+       vis |= 1 << PLUGIN_LADSPA_ID;
+       add_item(new AddPluginItem(this, "ffmpeg", PLUGIN_FFMPEG_ID));
+       vis |= 1 << PLUGIN_FFMPEG_ID;
        for( int i=0; i<MWindow::plugindb->size(); ++i ) {
                PluginServer *plugin = MWindow::plugindb->get(i);
                if( !plugin->audio && !plugin->video ) continue;
@@ -1743,16 +1786,11 @@ void AddPluginsMenu::create_objects()
                vis |= msk;
                char parent[BCTEXTLEN];
                strcpy(parent, plugin->path);
-               char *cp = strrchr(parent, '/');
-               if( !cp ) continue;
-               *cp = 0;
                char *bp = strrchr(parent, '/');
+               if( bp ) { *bp = 0;  bp = strrchr(parent, '/'); }
                if( !bp ) bp = parent; else ++bp;
-               if( !strcmp(bp, "ladspa") )
-                       gui->plugin_visibility &= ~(1 << idx);
                add_item(new AddPluginItem(this, bp, idx));
        }
-               
 }
 
 AddPluginItem::AddPluginItem(AddPluginsMenu *menu, char const *text, int idx)
@@ -1760,7 +1798,7 @@ AddPluginItem::AddPluginItem(AddPluginsMenu *menu, char const *text, int idx)
 {
        this->menu = menu;
        this->idx = idx;
-       uint32_t msk = 1 << idx, vis = menu->gui->plugin_visibility;
+       uint64_t msk = (uint64_t)1 << idx, vis = menu->gui->plugin_visibility;
        int chk = (msk & vis) ? 1 : 0;
         set_checked(chk);
 }
@@ -1769,10 +1807,11 @@ int AddPluginItem::handle_event()
 {
         int chk = get_checked() ^ 1;
         set_checked(chk);
-       uint32_t msk = 1 << idx, vis = menu->gui->plugin_visibility;
+       uint64_t msk = (uint64_t)1 << idx, vis = menu->gui->plugin_visibility;
        menu->gui->plugin_visibility = chk ? vis | msk : vis & ~msk;
        menu->gui->update_effects();
        menu->gui->update_assets();
+       menu->gui->save_defaults(menu->mwindow->defaults);
        return 1;
 }
 
index d925572a4b70f8aa38dce46c6e42a9df154dcfb7..8958fbf7dd19698fd7ad84836415f4bd5bf088d2 100644 (file)
@@ -154,6 +154,8 @@ public:
        PluginServer* selected_plugin();
        AssetPicon* selected_folder();
        bool protected_pixmap(BC_Pixmap *pixmap);
+       int save_defaults(BC_Hash *defaults);
+       int load_defaults(BC_Hash *defaults);
 
        MWindow *mwindow;
        AWindow *awindow;
@@ -161,7 +163,6 @@ public:
        AWindowAssets *asset_list;
        AWindowFolders *folder_list;
        AWindowDivider *divider;
-       uint32_t plugin_visibility;
 
 // Store data to speed up responses
 // Persistant data for listboxes
@@ -179,6 +180,7 @@ public:
 
        const char *asset_titles[ASSET_COLUMNS];
 
+       BC_Hash *defaults;
 // Persistent icons
        BC_Pixmap *folder_icon;
        BC_Pixmap *file_icon;
@@ -189,6 +191,8 @@ public:
        BC_Pixmap *vtransition_icon;  VFrame *vtransition_vframe;
        BC_Pixmap *aeffect_icon;      VFrame *aeffect_vframe;
        BC_Pixmap *ladspa_icon;       VFrame *ladspa_vframe;
+       BC_Pixmap *ff_aud_icon;       VFrame *ff_aud_vframe;
+       BC_Pixmap *ff_vid_icon;       VFrame *ff_vid_vframe;
        BC_Pixmap *veffect_icon;      VFrame *veffect_vframe;
        NewFolderThread *newfolder_thread;
 
@@ -200,6 +204,7 @@ public:
 // Temporary for reading picons from files
        VFrame *temp_picon;
 
+       int64_t plugin_visibility;
        AWindowRemovePlugin *remove_plugin;
 private:
        void update_folder_list();
diff --git a/cinelerra-5.0/cinelerra/data/ff_audio.png b/cinelerra-5.0/cinelerra/data/ff_audio.png
new file mode 100644 (file)
index 0000000..c62e407
Binary files /dev/null and b/cinelerra-5.0/cinelerra/data/ff_audio.png differ
diff --git a/cinelerra-5.0/cinelerra/data/ff_audio_png.h b/cinelerra-5.0/cinelerra/data/ff_audio_png.h
new file mode 100644 (file)
index 0000000..92b0801
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef FF_AUDIO_PNG_H
+#define FF_AUDIO_PNG_H
+
+static unsigned char ff_audio_png[] = 
+{
+       0x00, 0x00, 0x0a, 0x4a, 
+       0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 
+       0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x88, 
+       0xb1, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 
+       0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 
+       0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 
+       0x07, 0xdf, 0x0a, 0x1a, 0x00, 0x24, 0x35, 0xfd, 0xf3, 0x8e, 0x85, 0x00, 0x00, 0x00, 0x19, 0x74, 
+       0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 
+       0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0x0e, 0x17, 
+       0x00, 0x00, 0x09, 0xb2, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xd5, 0x9a, 0x41, 0x6c, 0x5c, 0x57, 
+       0x15, 0x86, 0xbf, 0x73, 0xdf, 0x9b, 0x19, 0x7b, 0x26, 0xb6, 0x43, 0x92, 0x36, 0x4d, 0xdc, 0x26, 
+       0x6d, 0x93, 0x36, 0x69, 0x9a, 0xa8, 0x4a, 0x2c, 0x55, 0x2c, 0xba, 0x29, 0x0b, 0x04, 0x1b, 0x5a, 
+       0xa9, 0x9b, 0xac, 0x41, 0x5d, 0xb2, 0x01, 0x89, 0x45, 0x61, 0xc5, 0x16, 0x44, 0x1b, 0x09, 0x90, 
+       0xc8, 0x06, 0x8a, 0x68, 0x25, 0x54, 0x55, 0x02, 0x54, 0x84, 0x8a, 0x40, 0x08, 0x28, 0x54, 0x42, 
+       0x9d, 0xa2, 0x0a, 0x62, 0x27, 0x85, 0xaa, 0x69, 0xd4, 0x3a, 0x75, 0xe2, 0x38, 0xb6, 0x13, 0xc7, 
+       0xf6, 0xcc, 0xbc, 0x7b, 0x58, 0xdc, 0x7b, 0xdf, 0xbb, 0xf3, 0xe6, 0x8d, 0x1d, 0xbb, 0x05, 0x85, 
+       0x91, 0x46, 0xf3, 0xe6, 0xdd, 0xe7, 0x79, 0xe7, 0x3f, 0xe7, 0xfc, 0xe7, 0xfc, 0xe7, 0x3e, 0xcb, 
+       0xe9, 0xd3, 0xa7, 0x75, 0x7d, 0x7d, 0x1d, 0x91, 0x04, 0x05, 0x94, 0xff, 0x83, 0x97, 0x82, 0x08, 
+       0x18, 0x51, 0xac, 0xb5, 0x34, 0x1a, 0x0d, 0xd2, 0xd5, 0xd5, 0x55, 0x3a, 0xdd, 0x0c, 0xe8, 0x50, 
+       0x4f, 0x7a, 0xa4, 0x26, 0x03, 0xd5, 0x3b, 0x1c, 0x87, 0xa1, 0x9b, 0xa5, 0x74, 0x6d, 0x82, 0x31, 
+       0x0e, 0x4c, 0x2a, 0x62, 0x68, 0xd6, 0x56, 0x79, 0xe2, 0xc8, 0x1c, 0xa7, 0x8e, 0x74, 0xd9, 0xb9, 
+       0x6b, 0x94, 0x8c, 0xf4, 0x8e, 0x05, 0x21, 0x02, 0x74, 0x56, 0x79, 0xff, 0x52, 0x8f, 0x3f, 0x9e, 
+       0x1b, 0xe7, 0xdd, 0x8f, 0xf7, 0x60, 0x24, 0x21, 0xcd, 0x2c, 0x9c, 0x3a, 0x30, 0xcf, 0x17, 0x1e, 
+       0x5f, 0xe4, 0xe8, 0xe1, 0x04, 0x46, 0x0d, 0x90, 0xdd, 0xd9, 0x49, 0x66, 0x3b, 0x3c, 0xbc, 0x6f, 
+       0x95, 0x7a, 0xda, 0x65, 0xe1, 0xc6, 0x28, 0x8b, 0xdd, 0x06, 0xa9, 0xb5, 0x70, 0xe2, 0xe0, 0x02, 
+       0xf7, 0x4f, 0xae, 0x83, 0x18, 0xb8, 0xbe, 0x76, 0x07, 0x27, 0x95, 0x80, 0x5a, 0x48, 0x0d, 0xcd, 
+       0x31, 0xcb, 0xf1, 0x07, 0x7b, 0xfc, 0xe9, 0x9f, 0x37, 0xb8, 0x36, 0xb7, 0x9b, 0xd4, 0xaa, 0xd0, 
+       0x6c, 0x75, 0xc1, 0x2e, 0xc3, 0xad, 0x55, 0xe8, 0x28, 0x48, 0x41, 0xaa, 0xf0, 0xf7, 0x31, 0xd1, 
+       0xfa, 0xce, 0x69, 0xf5, 0xfd, 0x86, 0xae, 0x6d, 0xd1, 0xee, 0xbe, 0xfb, 0x8a, 0xff, 0xec, 0x02, 
+       0x36, 0x41, 0xcc, 0x67, 0x18, 0x69, 0x58, 0x54, 0x71, 0x64, 0xb0, 0x16, 0x34, 0x5b, 0x87, 0x44, 
+       0x21, 0xd9, 0xc4, 0x68, 0x29, 0xdd, 0xe8, 0xbf, 0x09, 0xa4, 0xea, 0xb7, 0xc2, 0x77, 0x9b, 0xa1, 
+       0xd9, 0x1a, 0x56, 0xdc, 0x89, 0x34, 0x5f, 0x95, 0x21, 0x9e, 0x88, 0x0d, 0x16, 0x98, 0x9d, 0x87, 
+       0xc9, 0xa7, 0xb7, 0x67, 0xd3, 0xc7, 0xbf, 0x82, 0xbd, 0xbb, 0xb6, 0x01, 0xa4, 0xca, 0x81, 0xa6, 
+       0xff, 0x9c, 0xe9, 0x5b, 0x94, 0x0a, 0x10, 0x25, 0x70, 0xed, 0xf3, 0xdb, 0x03, 0xb1, 0x7f, 0xf7, 
+       0x36, 0x40, 0x0c, 0x73, 0xac, 0x0e, 0x66, 0x44, 0x5a, 0xa4, 0x8c, 0x01, 0xc9, 0xfa, 0xd1, 0xcb, 
+       0xa0, 0x57, 0xda, 0xef, 0x6e, 0xcf, 0x96, 0x53, 0x47, 0x36, 0x70, 0xd2, 0x56, 0x23, 0x02, 0x60, 
+       0x04, 0x24, 0x89, 0x81, 0x84, 0x36, 0x39, 0x02, 0xa2, 0x20, 0xbd, 0xea, 0xd4, 0xe2, 0x93, 0x45, 
+       0x64, 0xcb, 0x40, 0x74, 0x48, 0x86, 0xe4, 0xe7, 0x6b, 0x20, 0x23, 0x79, 0x48, 0x22, 0x8e, 0x34, 
+       0x3d, 0x88, 0x5e, 0x35, 0x59, 0x43, 0x6a, 0x5d, 0x18, 0xbc, 0x67, 0xfb, 0xc7, 0xde, 0xd0, 0x4f, 
+       0x93, 0xec, 0x52, 0x91, 0x11, 0x7d, 0x14, 0x68, 0x38, 0x9b, 0x07, 0x81, 0xd4, 0x5d, 0xa8, 0x36, 
+       0xf0, 0xda, 0xec, 0x55, 0xb8, 0x7c, 0xad, 0xff, 0x5c, 0x3d, 0x85, 0xe3, 0x87, 0x86, 0x78, 0x5b, 
+       0xf8, 0xf4, 0x5e, 0x52, 0xfa, 0x22, 0x35, 0x07, 0x66, 0x10, 0x48, 0xcd, 0x01, 0xa9, 0xca, 0xcb, 
+       0x0d, 0x88, 0x7e, 0xe2, 0x10, 0xd4, 0x6b, 0xff, 0xc3, 0xf2, 0x9b, 0xbf, 0x52, 0x67, 0x73, 0x3f, 
+       0x10, 0x9f, 0x73, 0x71, 0x13, 0xa9, 0xe8, 0x17, 0x55, 0x69, 0x35, 0xf5, 0xc8, 0xe6, 0x95, 0xee, 
+       0x13, 0x03, 0xa9, 0x2c, 0xbf, 0x09, 0x50, 0x03, 0x7a, 0x11, 0x10, 0x1b, 0x22, 0x62, 0x86, 0x7b, 
+       0x41, 0xaa, 0x23, 0x72, 0xf6, 0x17, 0xee, 0xbd, 0x91, 0x1d, 0xd7, 0x7f, 0x07, 0x13, 0x63, 0xb7, 
+       0xd1, 0x64, 0x95, 0x0d, 0xf9, 0x59, 0x9c, 0x17, 0x90, 0xd4, 0xd1, 0x21, 0x07, 0x22, 0x80, 0x8a, 
+       0x43, 0x67, 0x4c, 0x75, 0x63, 0x0c, 0x11, 0xd9, 0x46, 0xc5, 0x3a, 0x74, 0x6f, 0x04, 0x62, 0x83, 
+       0x6a, 0x38, 0x74, 0x4d, 0x2a, 0xc0, 0x0b, 0x9e, 0x06, 0x49, 0x3e, 0x72, 0xb8, 0x10, 0x58, 0xdc, 
+       0x49, 0x31, 0xa5, 0x8b, 0xc3, 0xdb, 0x30, 0x3b, 0x6f, 0x06, 0x88, 0x7e, 0x3b, 0xaf, 0xa9, 0xa3, 
+       0xc1, 0x00, 0x89, 0x8c, 0x11, 0xaf, 0xc7, 0x37, 0x58, 0x93, 0xa0, 0xd9, 0xbd, 0xc1, 0xf1, 0x35, 
+       0x12, 0xec, 0x4d, 0x73, 0x90, 0x0e, 0x48, 0xe6, 0x23, 0x12, 0x80, 0xc8, 0x60, 0x82, 0x6c, 0xb7, 
+       0x7f, 0x4c, 0x3d, 0x12, 0x0f, 0x12, 0x32, 0xc4, 0xfb, 0x32, 0x3c, 0x4a, 0x12, 0x9a, 0x5f, 0xe9, 
+       0x8f, 0x24, 0x01, 0xad, 0xb9, 0x88, 0x48, 0xce, 0x91, 0x50, 0x05, 0xcc, 0x90, 0x1b, 0x65, 0x95, 
+       0x40, 0x9e, 0x7d, 0x1a, 0xce, 0x7e, 0xb3, 0x42, 0x39, 0x86, 0x9b, 0x6a, 0x9c, 0xec, 0x5a, 0x3a, 
+       0xae, 0x92, 0xd4, 0xa5, 0xef, 0xa2, 0xc1, 0xb8, 0x8a, 0xb4, 0x33, 0x2e, 0x2a, 0x36, 0xae, 0x5a, 
+       0xd6, 0x2f, 0x94, 0x23, 0x12, 0x75, 0xd7, 0xf6, 0xcc, 0xb0, 0x8a, 0xa5, 0x43, 0xda, 0x72, 0xd9, 
+       0x21, 0x43, 0x8c, 0xdd, 0xf0, 0xd8, 0xff, 0x7e, 0x55, 0xd5, 0x92, 0x04, 0x34, 0xf5, 0xd9, 0xe4, 
+       0x81, 0xa8, 0x1a, 0x5f, 0xca, 0xcc, 0x96, 0xa4, 0xc9, 0xd4, 0xb1, 0xa2, 0x51, 0x4e, 0x7e, 0x71, 
+       0x9b, 0x8a, 0xf8, 0x75, 0xd8, 0xbb, 0xfb, 0x36, 0x4b, 0x70, 0x19, 0x08, 0x69, 0x7f, 0x1f, 0xd1, 
+       0x2c, 0xa4, 0x96, 0xef, 0xec, 0xc6, 0xf8, 0x4c, 0x70, 0xb9, 0x39, 0x7b, 0x15, 0x2e, 0xcf, 0xf7, 
+       0xfa, 0x7e, 0xbb, 0x96, 0xc2, 0x89, 0xc3, 0x29, 0x18, 0xa1, 0x7d, 0xde, 0xfa, 0xf1, 0x78, 0x8b, 
+       0x8a, 0xf8, 0x2e, 0xd8, 0xbb, 0x27, 0x8d, 0x52, 0x51, 0x8b, 0xd4, 0xec, 0x3b, 0x8e, 0x7c, 0xac, 
+       0xd6, 0x7f, 0x49, 0x41, 0xe3, 0xd4, 0x12, 0xb0, 0x19, 0xa8, 0xfa, 0x96, 0x2f, 0xa9, 0x27, 0xbe, 
+       0x78, 0xce, 0x08, 0xed, 0xf3, 0xbd, 0xbc, 0x5e, 0x87, 0xd7, 0xf1, 0x43, 0x86, 0x46, 0xa3, 0xe9, 
+       0xa2, 0x35, 0xb3, 0xb6, 0x2d, 0x20, 0xa7, 0x8e, 0xa6, 0x5e, 0xf8, 0x05, 0x6e, 0xda, 0x22, 0x97, 
+       0xc5, 0x73, 0x4a, 0xca, 0x59, 0x62, 0x3d, 0x05, 0xea, 0xbe, 0xfc, 0x46, 0x32, 0xde, 0x5a, 0xbc, 
+       0xf1, 0x23, 0xfe, 0x5d, 0xf3, 0xf3, 0xb1, 0x01, 0x11, 0xda, 0x33, 0x2b, 0x15, 0x69, 0x55, 0xf7, 
+       0x46, 0x04, 0x20, 0xdb, 0x50, 0xc4, 0x8f, 0xd4, 0xfb, 0x81, 0x54, 0x0d, 0x1a, 0x3e, 0x5a, 0xcb, 
+       0x37, 0x2d, 0x7f, 0x7e, 0xbb, 0xcb, 0x03, 0x93, 0x29, 0xc7, 0x0e, 0xd7, 0x41, 0x1a, 0xa8, 0x26, 
+       0x58, 0xab, 0x48, 0x9e, 0x5a, 0x56, 0x50, 0x42, 0xa7, 0xac, 0x47, 0x7c, 0x71, 0xde, 0x69, 0x4f, 
+       0xdf, 0xa8, 0x20, 0x7a, 0xc3, 0x5f, 0x0b, 0xed, 0x99, 0xde, 0xa0, 0x22, 0x7e, 0xf9, 0x6e, 0x67, 
+       0x28, 0xe2, 0xab, 0x89, 0x94, 0x52, 0x26, 0xae, 0x6a, 0x61, 0xad, 0x7c, 0x9d, 0x5b, 0x3b, 0xff, 
+       0x7e, 0x97, 0xef, 0xbc, 0x78, 0x8b, 0x9f, 0xbe, 0x76, 0x8b, 0xaf, 0x9e, 0x6e, 0xf1, 0xbd, 0x6f, 
+       0x8c, 0x01, 0x75, 0x54, 0x93, 0xfc, 0xe7, 0x52, 0x09, 0x33, 0x7b, 0x00, 0x22, 0x01, 0x48, 0x94, 
+       0x5a, 0x33, 0xdd, 0x0a, 0x20, 0x2d, 0x90, 0x3a, 0xb3, 0x57, 0x7a, 0x5c, 0x9e, 0xb7, 0x83, 0x8a, 
+       0xf8, 0xa1, 0x56, 0xd1, 0x3b, 0xd4, 0x46, 0x7d, 0xc4, 0x46, 0x8d, 0xcf, 0xf3, 0x62, 0x83, 0xb5, 
+       0xdf, 0xbc, 0xb1, 0xca, 0x99, 0x97, 0x96, 0x79, 0xfd, 0xcd, 0x55, 0x00, 0xae, 0x2c, 0x04, 0x5d, 
+       0x98, 0xa2, 0x6a, 0xd0, 0xc0, 0x11, 0x71, 0x73, 0xbc, 0x0f, 0x4e, 0xcd, 0x93, 0x3e, 0x75, 0x11, 
+       0x09, 0x64, 0xff, 0xfd, 0xe1, 0x52, 0x65, 0x2c, 0xf2, 0xb7, 0x3d, 0xb3, 0x3e, 0xa8, 0x88, 0x1f, 
+       0x6a, 0x50, 0xaf, 0xd7, 0xa3, 0x4c, 0xb1, 0x11, 0x0f, 0x4a, 0xe9, 0x23, 0x5a, 0xc9, 0x11, 0x55, 
+       0xcb, 0x0f, 0x7f, 0xbe, 0xc8, 0x99, 0x97, 0x17, 0xf9, 0xd7, 0xa5, 0xc8, 0x91, 0x12, 0x2a, 0x6c, 
+       0x0d, 0x2d, 0x73, 0x44, 0x33, 0x71, 0x15, 0x40, 0x6a, 0x3e, 0x2a, 0xb5, 0x48, 0x46, 0x98, 0xa2, 
+       0x72, 0x48, 0x09, 0x08, 0x86, 0xf6, 0x4c, 0xa7, 0x82, 0x3f, 0x4d, 0xcf, 0xb9, 0x7c, 0x47, 0x6d, 
+       0x08, 0x0f, 0xca, 0x6b, 0x0e, 0xc8, 0x87, 0x73, 0x3d, 0xce, 0xbc, 0xb4, 0xc0, 0x99, 0x97, 0xae, 
+       0xd1, 0xed, 0x55, 0xd4, 0x62, 0x71, 0x40, 0xac, 0x4d, 0x3c, 0xbf, 0x21, 0x45, 0x43, 0x6a, 0x19, 
+       0x5f, 0x7e, 0x93, 0x28, 0x22, 0x9e, 0x6c, 0x12, 0xe7, 0x6d, 0x94, 0xe7, 0x46, 0x68, 0x4f, 0x0f, 
+       0x46, 0xe4, 0xec, 0xab, 0xd7, 0x39, 0xfb, 0xea, 0xf5, 0x8d, 0x15, 0xf1, 0x5f, 0x4e, 0x30, 0x31, 
+       0x66, 0xf2, 0x82, 0xb2, 0x7c, 0xd3, 0x82, 0x1a, 0xc6, 0x77, 0x24, 0x7c, 0xed, 0xbb, 0x1f, 0xf1, 
+       0xca, 0x6f, 0x17, 0x87, 0xfc, 0xb5, 0x71, 0x40, 0x4c, 0x0a, 0x48, 0x04, 0x24, 0x70, 0x44, 0x83, 
+       0x34, 0xae, 0x79, 0x31, 0x66, 0xfa, 0xc5, 0x5b, 0xdf, 0xa0, 0x55, 0x78, 0xb5, 0x3d, 0xbd, 0xba, 
+       0x75, 0x45, 0x7c, 0x5f, 0x83, 0x89, 0xf1, 0x7a, 0xfe, 0x5b, 0x2f, 0xfe, 0x72, 0x81, 0x1f, 0xbd, 
+       0x72, 0x95, 0x5d, 0x13, 0x09, 0xaf, 0xfd, 0xe0, 0xf0, 0x06, 0x20, 0x22, 0x09, 0xaf, 0xa6, 0xa8, 
+       0x07, 0x05, 0x10, 0x8d, 0x34, 0x7e, 0x2d, 0xd2, 0x5d, 0x25, 0xa1, 0xa7, 0xfd, 0x12, 0x63, 0xf6, 
+       0x6a, 0x97, 0xcb, 0xf3, 0xdd, 0xad, 0x0b, 0xc9, 0x63, 0xad, 0x68, 0xa6, 0x53, 0xa6, 0xdf, 0x5b, 
+       0xe7, 0xcd, 0x77, 0x56, 0xd8, 0x31, 0x1a, 0xf2, 0x7f, 0x93, 0x5d, 0x6c, 0x9f, 0x31, 0x6a, 0xb5, 
+       0xa8, 0x5a, 0xa1, 0xa8, 0xa8, 0x4a, 0xd1, 0x31, 0x49, 0xcb, 0x3a, 0xbe, 0x34, 0xf0, 0x38, 0xc5, 
+       0xd9, 0x3e, 0x77, 0x63, 0x7b, 0x8a, 0xf8, 0xd1, 0xb1, 0x3e, 0x20, 0x1d, 0xef, 0x8b, 0x91, 0x86, 
+       0xe9, 0x1b, 0x5a, 0x87, 0xa6, 0x16, 0x0e, 0x88, 0xcb, 0x24, 0x0a, 0xf5, 0x6b, 0x6d, 0x90, 0x23, 
+       0xa6, 0x18, 0x58, 0x90, 0xbc, 0x6a, 0xf5, 0xcf, 0x0e, 0x45, 0x44, 0xaa, 0x1a, 0xe5, 0xb3, 0xcf, 
+       0xdc, 0xc3, 0xd9, 0x6f, 0x3f, 0x5c, 0x51, 0xe5, 0xaa, 0x36, 0x72, 0xdd, 0xf1, 0xcd, 0x55, 0xed, 
+       0x97, 0xe7, 0x9b, 0x09, 0x2f, 0x49, 0xf2, 0x02, 0xd1, 0x07, 0xa4, 0x88, 0x48, 0x20, 0x7a, 0x5a, 
+       0x02, 0x21, 0xfe, 0xd6, 0xda, 0x67, 0xcf, 0x5b, 0xe7, 0x2a, 0x3a, 0xfe, 0xa3, 0xe3, 0x40, 0x82, 
+       0x22, 0x88, 0x68, 0xc5, 0x88, 0xa7, 0x03, 0x6a, 0xd0, 0xdd, 0x3b, 0x36, 0x72, 0xb3, 0xd4, 0x4a, 
+       0x7c, 0x89, 0x8e, 0x38, 0xa2, 0xa1, 0x8f, 0xa8, 0x14, 0xbd, 0x44, 0xd2, 0x88, 0xe0, 0x5e, 0xda, 
+       0x07, 0x72, 0xa1, 0x88, 0xaf, 0xf7, 0xed, 0x73, 0x37, 0x07, 0x81, 0x1c, 0xdf, 0xe9, 0x79, 0x66, 
+       0x7c, 0xaf, 0xb3, 0xde, 0xd8, 0xc4, 0x03, 0xb3, 0xae, 0x42, 0xaa, 0xe4, 0x6b, 0xad, 0x66, 0x3d, 
+       0x8a, 0x55, 0x7d, 0xf3, 0xd4, 0x92, 0x3a, 0x68, 0x8a, 0x5a, 0x9b, 0x8b, 0x81, 0x14, 0x20, 0xd3, 
+       0x30, 0xd3, 0xfb, 0x99, 0x04, 0x53, 0xf4, 0x0f, 0x1f, 0x82, 0xcc, 0x0a, 0x62, 0x52, 0x12, 0xb1, 
+       0xa0, 0x3d, 0x3e, 0x9a, 0x5b, 0xe7, 0xe3, 0xf9, 0xf5, 0x92, 0x22, 0x16, 0x4e, 0x3c, 0xbc, 0x13, 
+       0xab, 0x09, 0x56, 0x13, 0x92, 0xd4, 0x80, 0xed, 0x3a, 0xb7, 0x25, 0x75, 0xb0, 0xbd, 0xc2, 0xeb, 
+       0x62, 0x40, 0xbb, 0x80, 0xd0, 0x68, 0x38, 0x82, 0xaf, 0x75, 0x2c, 0x98, 0xfa, 0xe6, 0xa9, 0x45, 
+       0xe2, 0x1d, 0xa5, 0x79, 0x92, 0x3a, 0x66, 0x85, 0x88, 0x48, 0x12, 0x6d, 0x0b, 0x49, 0xe4, 0x01, 
+       0x97, 0x7a, 0x22, 0x89, 0x07, 0xa7, 0xbc, 0x35, 0x3d, 0x18, 0x8d, 0xe3, 0x0f, 0x8d, 0xd1, 0x68, 
+       0xd4, 0xc8, 0xac, 0x41, 0x31, 0xfe, 0xfa, 0x0c, 0x10, 0x44, 0x52, 0x3f, 0x24, 0xf9, 0x63, 0x4c, 
+       0xde, 0x00, 0xef, 0xdb, 0xd7, 0xe4, 0xfe, 0xfd, 0xa3, 0xec, 0x1c, 0xaf, 0xf9, 0xb5, 0xdb, 0xe1, 
+       0x48, 0x31, 0x85, 0x8a, 0x94, 0xfb, 0x48, 0xce, 0x91, 0xc4, 0xa7, 0x5a, 0xd1, 0x10, 0x93, 0xd4, 
+       0x20, 0xa1, 0xaf, 0x90, 0xf2, 0xf6, 0xf4, 0x72, 0x05, 0x3f, 0x76, 0x82, 0xa4, 0x18, 0x63, 0x90, 
+       0x5c, 0x76, 0xa4, 0x15, 0x24, 0x0d, 0x6a, 0xc1, 0xa5, 0xf0, 0x97, 0x9f, 0x79, 0x80, 0x2f, 0x3d, 
+       0xb9, 0xd7, 0x27, 0x80, 0xf0, 0xd8, 0x91, 0x71, 0xde, 0xb9, 0xb0, 0xbc, 0x69, 0x1f, 0x41, 0x35, 
+       0x1f, 0x4f, 0x8c, 0xe0, 0x66, 0x13, 0xcd, 0x6f, 0x94, 0x46, 0x43, 0x56, 0x9a, 0xef, 0x62, 0x18, 
+       0xe3, 0x81, 0xa8, 0x2b, 0x7f, 0x6f, 0x9f, 0x5b, 0xaa, 0x00, 0xb2, 0xdb, 0x55, 0x74, 0x63, 0x30, 
+       0x26, 0x68, 0xb5, 0xc8, 0x31, 0xb1, 0x6a, 0xc0, 0xe4, 0x6b, 0xad, 0xd1, 0x1a, 0x07, 0xef, 0x1d, 
+       0xe7, 0xc0, 0xfe, 0x31, 0x50, 0xe1, 0xf9, 0xe7, 0x1e, 0xe3, 0xa9, 0xcf, 0xed, 0x1b, 0x82, 0xc3, 
+       0xe4, 0x0e, 0x51, 0x25, 0xea, 0x23, 0x61, 0xe8, 0xd2, 0x88, 0x23, 0xa1, 0xab, 0x53, 0x4c, 0x89, 
+       0x91, 0x14, 0x72, 0x32, 0xfd, 0xdc, 0x62, 0x05, 0xd1, 0x77, 0xfb, 0x9b, 0x94, 0xb7, 0xd2, 0xa3, 
+       0x72, 0x2b, 0x1a, 0x6d, 0xb2, 0x45, 0xf5, 0x33, 0xba, 0xee, 0xc9, 0xcf, 0xee, 0xe3, 0xe0, 0xe4, 
+       0x18, 0x07, 0xf6, 0xb7, 0xf8, 0xfe, 0xcf, 0xfe, 0x5d, 0x9a, 0xe2, 0x8b, 0xa7, 0x3c, 0xaa, 0x45, 
+       0x0d, 0x8c, 0x80, 0xf8, 0x2a, 0x15, 0x6f, 0x42, 0xa8, 0x0c, 0xdd, 0xc6, 0x99, 0x7d, 0xe3, 0xa9, 
+       0xa2, 0xb2, 0x55, 0x19, 0x1b, 0x5f, 0x2c, 0x25, 0x63, 0x65, 0xc8, 0x5a, 0x74, 0xfc, 0xe0, 0x7d, 
+       0xe3, 0x3c, 0xff, 0xdc, 0x49, 0x0e, 0x4e, 0xee, 0xe0, 0x85, 0x9f, 0x5c, 0xe0, 0xc3, 0xb9, 0xd5, 
+       0xfe, 0x14, 0x2d, 0x4d, 0x8e, 0xa6, 0xaf, 0x6f, 0xe5, 0xa2, 0x31, 0x89, 0x36, 0xc6, 0xcc, 0x16, 
+       0xfb, 0xb6, 0xde, 0xc6, 0xe6, 0xf5, 0xed, 0xed, 0x6e, 0x27, 0x89, 0xe1, 0xeb, 0x5f, 0x39, 0xca, 
+       0x0b, 0xdf, 0x3a, 0xc5, 0x13, 0x53, 0x7b, 0x00, 0x68, 0x8d, 0x46, 0x3c, 0x2b, 0x6b, 0x2d, 0x57, 
+       0x8f, 0x05, 0x92, 0x9d, 0xd0, 0xf0, 0x72, 0xd8, 0x66, 0xae, 0x9c, 0x69, 0x06, 0x7a, 0x2b, 0x1f, 
+       0xf2, 0x0b, 0xaf, 0x48, 0xff, 0x93, 0x56, 0x31, 0x45, 0x9a, 0x04, 0xa5, 0x1c, 0xaf, 0xe5, 0x00, 
+       0xc3, 0x6e, 0xa6, 0x0e, 0xae, 0xf5, 0x5d, 0x17, 0x52, 0x5d, 0x79, 0xe6, 0xf3, 0x07, 0xb8, 0x7f, 
+       0x72, 0x07, 0xbf, 0xfe, 0xc3, 0x2c, 0x27, 0x8f, 0x4d, 0x40, 0x3a, 0x81, 0xda, 0x16, 0xda, 0x9b, 
+       0xcb, 0x49, 0xe2, 0xb4, 0x56, 0xaf, 0xc3, 0xea, 0xc5, 0x19, 0xb8, 0xe7, 0x71, 0x98, 0x78, 0xc0, 
+       0x1b, 0x9f, 0xf9, 0x96, 0x9f, 0xb9, 0x8d, 0x87, 0xdc, 0x30, 0x8b, 0xa2, 0x88, 0xda, 0x68, 0x1c, 
+       0xd5, 0xbc, 0x59, 0x86, 0xb7, 0x0c, 0xf1, 0xba, 0xc6, 0xe7, 0x75, 0x70, 0xa3, 0x71, 0xd8, 0x76, 
+       0xd4, 0xd4, 0xc9, 0x7d, 0x4c, 0x9d, 0x3c, 0xe6, 0x25, 0xfc, 0x18, 0xbd, 0x6b, 0x1f, 0xd0, 0xf9, 
+       0xe8, 0x1f, 0x50, 0x6b, 0x04, 0x20, 0x82, 0x66, 0x19, 0x4b, 0xef, 0xfe, 0x9d, 0xf1, 0xc6, 0x12, 
+       0xcd, 0x7b, 0xef, 0xa1, 0xd6, 0xc4, 0x3d, 0xaa, 0x56, 0x5f, 0xd2, 0xac, 0xfb, 0x54, 0x75, 0x4a, 
+       0x59, 0xad, 0xc3, 0xe8, 0xca, 0xb6, 0xbb, 0xce, 0x06, 0x25, 0x6a, 0x35, 0xd7, 0x95, 0x5a, 0xb9, 
+       0x01, 0xa9, 0x39, 0xed, 0xe2, 0x51, 0x47, 0x4c, 0xf1, 0x58, 0x30, 0x7c, 0x0f, 0x02, 0x3c, 0xee, 
+       0xd1, 0xd8, 0x84, 0xde, 0x4a, 0x97, 0x95, 0x8b, 0x17, 0x59, 0x9b, 0xbf, 0x82, 0x24, 0x87, 0x8b, 
+       0xe7, 0xec, 0xa2, 0x4a, 0x77, 0x69, 0x9e, 0xb5, 0x4b, 0x8b, 0xd4, 0x6d, 0x93, 0xda, 0x2e, 0x81, 
+       0x11, 0x75, 0xbb, 0x78, 0xbd, 0x22, 0xc3, 0x6c, 0x4f, 0xc8, 0x32, 0xd7, 0xa0, 0xb3, 0x0c, 0x7f, 
+       0x2c, 0x79, 0x26, 0x66, 0x99, 0x07, 0x67, 0x8b, 0xcf, 0x58, 0x66, 0x05, 0xa3, 0x4d, 0xe2, 0xdf, 
+       0xc6, 0x7d, 0x26, 0x49, 0x71, 0x2e, 0x49, 0xa3, 0x73, 0xfe, 0x98, 0xa8, 0x2b, 0xd0, 0x05, 0xbb, 
+       0xd0, 0xa1, 0x77, 0x75, 0x05, 0xbb, 0x3e, 0x82, 0x5a, 0xe3, 0x1a, 0xa2, 0xa8, 0xb2, 0xd0, 0x19, 
+       0xe1, 0xe6, 0x5a, 0x8d, 0x6c, 0xa5, 0x0b, 0x4b, 0xcb, 0xee, 0x0f, 0x3a, 0xe4, 0x20, 0xf0, 0xdb, 
+       0x5a, 0x9a, 0x81, 0xf6, 0x1c, 0x10, 0xdb, 0x73, 0xc6, 0x07, 0x50, 0xb6, 0x07, 0x99, 0x2d, 0x8e, 
+       0x03, 0x38, 0xb5, 0x11, 0x10, 0x53, 0x18, 0x9d, 0x78, 0xa3, 0x35, 0x29, 0xfa, 0x5b, 0xd8, 0x2e, 
+       0x08, 0xbb, 0xa1, 0xa4, 0x25, 0x10, 0x89, 0xb7, 0x63, 0x19, 0x6e, 0x2d, 0xc3, 0xfc, 0x8d, 0x51, 
+       0x6e, 0x74, 0x6a, 0xc8, 0x88, 0x92, 0x62, 0x33, 0x2e, 0xac, 0xdf, 0xc5, 0xae, 0xf9, 0x9b, 0x58, 
+       0x59, 0x62, 0xcf, 0xba, 0x52, 0x9f, 0x77, 0x37, 0xc1, 0xd3, 0x40, 0x63, 0x4f, 0xab, 0x07, 0x60, 
+       0x0b, 0x0a, 0x59, 0x2d, 0xd6, 0x34, 0xf3, 0xeb, 0x5a, 0x8a, 0x8a, 0x29, 0x80, 0x88, 0xf8, 0x68, 
+       0xf8, 0xb7, 0xc4, 0x9f, 0x51, 0x6a, 0x25, 0x3e, 0x6a, 0xf9, 0x5e, 0x61, 0xe2, 0x1c, 0x7b, 0x6b, 
+       0x05, 0xde, 0xbb, 0x3c, 0xc2, 0xdf, 0xe6, 0xee, 0xe2, 0x4a, 0xd6, 0x22, 0xb5, 0x3d, 0xd2, 0x56, 
+       0x6b, 0x94, 0x25, 0xee, 0xe6, 0xaf, 0x9d, 0x51, 0xa6, 0x3f, 0x58, 0xa6, 0x71, 0xa9, 0x8b, 0x88, 
+       0xf4, 0x17, 0x5d, 0x19, 0xfe, 0x4c, 0xb2, 0xf2, 0x41, 0xac, 0x6c, 0xb2, 0x77, 0xab, 0x54, 0xff, 
+       0x93, 0x9b, 0x6e, 0x50, 0xa0, 0xa3, 0x13, 0x3d, 0x15, 0x96, 0xa5, 0xc9, 0x42, 0x3a, 0x41, 0xd2, 
+       0x18, 0xa1, 0xd5, 0x1c, 0xe1, 0x3f, 0x89, 0x98, 0x18, 0xac, 0xd2, 0xd3, 0xb2, 0x95, 0x00, 0x00, 
+       0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
+#endif
diff --git a/cinelerra-5.0/cinelerra/data/ff_video.png b/cinelerra-5.0/cinelerra/data/ff_video.png
new file mode 100644 (file)
index 0000000..73c231b
Binary files /dev/null and b/cinelerra-5.0/cinelerra/data/ff_video.png differ
diff --git a/cinelerra-5.0/cinelerra/data/ff_video_png.h b/cinelerra-5.0/cinelerra/data/ff_video_png.h
new file mode 100644 (file)
index 0000000..4b0a3df
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef FF_VIDEO_PNG_H
+#define FF_VIDEO_PNG_H
+
+static unsigned char ff_video_png[] = 
+{
+       0x00, 0x00, 0x0a, 0x9d, 
+       0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 
+       0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x32, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x88, 
+       0xb1, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 
+       0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 
+       0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 
+       0x07, 0xdf, 0x0a, 0x1a, 0x00, 0x20, 0x02, 0x21, 0x22, 0xee, 0x8e, 0x00, 0x00, 0x00, 0x19, 0x74, 
+       0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 
+       0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0x0e, 0x17, 
+       0x00, 0x00, 0x0a, 0x05, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xd5, 0x9a, 0xdf, 0x6f, 0x1c, 0x57, 
+       0x15, 0xc7, 0x3f, 0xe7, 0xce, 0xec, 0xae, 0xbd, 0x96, 0x7f, 0xc4, 0x71, 0x7e, 0x34, 0x3f, 0x4a, 
+       0x68, 0x7e, 0x35, 0xad, 0x83, 0x50, 0x42, 0x23, 0xa8, 0x8a, 0x0a, 0x34, 0xd0, 0xa6, 0xaa, 0xd4, 
+       0x14, 0xa8, 0x08, 0x0f, 0x88, 0x17, 0xfa, 0x1f, 0xf0, 0xc6, 0x03, 0x12, 0x7f, 0x44, 0x1f, 0xf2, 
+       0xc2, 0x0b, 0x02, 0x5e, 0x2a, 0x21, 0x84, 0x10, 0x48, 0x20, 0x54, 0x54, 0x40, 0x54, 0x71, 0x01, 
+       0x15, 0xc7, 0x69, 0x50, 0xd4, 0x34, 0xa5, 0xce, 0x2f, 0x37, 0x89, 0xe3, 0x38, 0xb6, 0x77, 0x77, 
+       0xee, 0xe1, 0xe1, 0xde, 0x3b, 0x73, 0x67, 0x76, 0xd6, 0x69, 0xdc, 0x82, 0xc2, 0x48, 0xa3, 0x9d, 
+       0x9d, 0x99, 0xf5, 0x9c, 0xef, 0x3d, 0xe7, 0x7b, 0xce, 0xf7, 0x9c, 0xb1, 0x9c, 0x3a, 0x75, 0x4a, 
+       0xd7, 0xd6, 0xd6, 0x10, 0x49, 0x50, 0x40, 0xf9, 0x3f, 0xd8, 0x14, 0x44, 0xc0, 0x88, 0x62, 0xad, 
+       0xa5, 0xd5, 0x6a, 0x91, 0xae, 0xac, 0xac, 0xd0, 0xe9, 0x66, 0x40, 0x87, 0x66, 0xd2, 0x23, 0x35, 
+       0x19, 0xa8, 0x3e, 0xe0, 0x38, 0x0c, 0xdd, 0x2c, 0xa5, 0x6b, 0x13, 0x8c, 0x71, 0x60, 0x52, 0x11, 
+       0x43, 0xbb, 0xb1, 0xc2, 0x53, 0x07, 0xaf, 0x72, 0xe4, 0x60, 0x97, 0x89, 0xc9, 0x61, 0x32, 0xd2, 
+       0x07, 0x16, 0x84, 0x08, 0xd0, 0x59, 0xe1, 0xdd, 0x4b, 0x3d, 0x5e, 0x9f, 0x1d, 0xe3, 0xfc, 0x95, 
+       0x29, 0x8c, 0x24, 0xa4, 0x99, 0x85, 0x23, 0x0f, 0x2f, 0xf0, 0xdc, 0xb1, 0x5b, 0x3c, 0xba, 0x2f, 
+       0x81, 0x61, 0x03, 0x64, 0x0f, 0x76, 0x90, 0xd9, 0x0e, 0x07, 0x1e, 0x5a, 0xa1, 0x99, 0x76, 0xb9, 
+       0xb1, 0x34, 0xcc, 0xad, 0x6e, 0x8b, 0xd4, 0x5a, 0x38, 0xfc, 0xa9, 0x1b, 0xec, 0xd9, 0xb9, 0x06, 
+       0x62, 0xe0, 0xe6, 0xea, 0x03, 0x1c, 0x54, 0x02, 0x6a, 0x21, 0x35, 0xb4, 0x47, 0x2d, 0xd3, 0x8f, 
+       0xf4, 0xf8, 0xe3, 0x3f, 0x97, 0xf8, 0xf0, 0xea, 0x66, 0x52, 0xab, 0x42, 0x7b, 0xa4, 0x0b, 0xf6, 
+       0x36, 0xdc, 0x5d, 0x81, 0x8e, 0x82, 0x14, 0xa4, 0x0a, 0xbf, 0x8f, 0x89, 0x56, 0x3a, 0xa7, 0xf5, 
+       0xcf, 0x1b, 0x78, 0xed, 0x3e, 0xed, 0x2e, 0x3d, 0x57, 0xfc, 0x67, 0x17, 0xb0, 0x09, 0x62, 0x36, 
+       0x31, 0xd4, 0xb2, 0xa8, 0xe2, 0xc8, 0x60, 0x2d, 0x68, 0xb6, 0x06, 0x89, 0x42, 0x72, 0x0f, 0xa3, 
+       0xa5, 0xf2, 0xa0, 0xff, 0x26, 0x90, 0xba, 0xbf, 0x15, 0xbe, 0xdb, 0x0c, 0xcd, 0x56, 0xb1, 0xe2, 
+       0x4e, 0xa4, 0xf9, 0x55, 0x19, 0xb0, 0x12, 0xb1, 0xc1, 0x02, 0xf3, 0x0b, 0xb0, 0xf3, 0xe4, 0xc6, 
+       0x6c, 0xba, 0xf2, 0x4b, 0xd8, 0x36, 0xb9, 0x01, 0x20, 0x75, 0x0b, 0x68, 0xca, 0xe7, 0x4c, 0xe9, 
+       0xa2, 0xd4, 0x80, 0xa8, 0x80, 0x9b, 0x39, 0xb7, 0x31, 0x10, 0x3b, 0x36, 0x6f, 0x00, 0xc4, 0xa0, 
+       0x85, 0xd5, 0xfe, 0x88, 0x48, 0x8b, 0x90, 0x31, 0x20, 0x59, 0x19, 0xbd, 0xf4, 0xaf, 0xca, 0xcc, 
+       0xf9, 0x8d, 0xd9, 0x72, 0xe4, 0xe0, 0x3a, 0x8b, 0x74, 0xbf, 0x1e, 0x01, 0x30, 0x02, 0x92, 0xc4, 
+       0x40, 0x42, 0x99, 0x1c, 0x02, 0x51, 0x90, 0x5e, 0x7d, 0x68, 0xf1, 0xf1, 0x3c, 0x72, 0xdf, 0x40, 
+       0x74, 0x40, 0x84, 0xe4, 0xe7, 0x1b, 0x20, 0x43, 0xb9, 0x4b, 0x22, 0x8e, 0xb4, 0x3d, 0x88, 0x5e, 
+       0x3d, 0x59, 0x43, 0x68, 0xbd, 0xd3, 0xff, 0xcc, 0x99, 0x1f, 0x7b, 0x43, 0x3f, 0x49, 0xb2, 0x4b, 
+       0x4d, 0x44, 0x94, 0x28, 0xd0, 0x72, 0x36, 0xf7, 0x03, 0x69, 0x3a, 0x57, 0xad, 0xb3, 0x6a, 0xf3, 
+       0xd7, 0xe1, 0xf2, 0x87, 0xe5, 0x73, 0xcd, 0x14, 0xa6, 0xf7, 0x0e, 0x58, 0x6d, 0xe1, 0x93, 0xdb, 
+       0xa4, 0xf2, 0x45, 0x1a, 0x0e, 0x4c, 0x3f, 0x90, 0x86, 0x03, 0x52, 0x17, 0x97, 0xeb, 0x10, 0xfd, 
+       0xf0, 0x5e, 0x68, 0x36, 0xfe, 0x87, 0xe9, 0x37, 0xdf, 0x52, 0x67, 0x73, 0x19, 0x88, 0x8f, 0xb9, 
+       0xb8, 0x88, 0xd4, 0xd4, 0x8b, 0xba, 0xb0, 0x3a, 0x7a, 0xe8, 0xde, 0x99, 0xee, 0x63, 0x03, 0xa9, 
+       0x4d, 0xbf, 0x09, 0xd0, 0x00, 0x7a, 0x11, 0x10, 0x1b, 0x3c, 0x62, 0x06, 0xaf, 0x82, 0xd4, 0x7b, 
+       0xe4, 0xf4, 0x2f, 0xdc, 0xbe, 0x9e, 0x1d, 0x37, 0x7f, 0x07, 0xe3, 0xa3, 0x1f, 0xa1, 0xc8, 0x2a, 
+       0xeb, 0xf2, 0xb3, 0x38, 0x2f, 0x20, 0xa9, 0xa3, 0x43, 0x0e, 0x44, 0x00, 0x15, 0x87, 0xce, 0x98, 
+       0xfa, 0xc2, 0x18, 0x3c, 0xb2, 0x81, 0x8c, 0xb5, 0x77, 0x57, 0x04, 0x62, 0x9d, 0x6c, 0x38, 0xf0, 
+       0x9a, 0xd4, 0x80, 0x17, 0x3c, 0x0d, 0x92, 0xbc, 0xe5, 0x70, 0x2e, 0xb0, 0xb8, 0x93, 0x62, 0x2a, 
+       0x37, 0x87, 0xdd, 0x30, 0xbf, 0x60, 0xfa, 0x88, 0xfe, 0x51, 0xb6, 0xa3, 0x8f, 0x06, 0x03, 0x24, 
+       0x32, 0x46, 0xbc, 0x1e, 0x5f, 0xe7, 0x9a, 0x04, 0xcd, 0xee, 0x0d, 0x8e, 0xef, 0x91, 0x60, 0x6f, 
+       0x9a, 0x83, 0x74, 0x40, 0x32, 0xef, 0x91, 0x00, 0x44, 0xfa, 0x03, 0x64, 0xa3, 0xf5, 0xe3, 0xe8, 
+       0xa1, 0xb8, 0x91, 0x90, 0x01, 0xab, 0x2f, 0x83, 0xbd, 0x24, 0xa1, 0xf8, 0x55, 0x7e, 0x24, 0x09, 
+       0x68, 0xc3, 0x79, 0x44, 0x72, 0x8e, 0x84, 0x2c, 0x60, 0x06, 0x3c, 0x28, 0xab, 0x05, 0xf2, 0xca, 
+       0x49, 0x38, 0xfd, 0x83, 0x1a, 0xe5, 0x18, 0x1e, 0xaa, 0x71, 0xb0, 0x6b, 0xe5, 0xb8, 0x4e, 0x52, 
+       0x57, 0xbe, 0x8b, 0x06, 0xe3, 0x6a, 0xc2, 0xce, 0x38, 0xaf, 0xd8, 0x38, 0x6b, 0x59, 0x7f, 0xa1, 
+       0xea, 0x91, 0xa8, 0xba, 0xce, 0xcc, 0x0d, 0xca, 0x58, 0x3a, 0xa0, 0x2c, 0x57, 0x17, 0x64, 0x80, 
+       0xb1, 0xeb, 0x1e, 0xfb, 0xbf, 0x5f, 0x97, 0xb5, 0x24, 0x01, 0x4d, 0x7d, 0x34, 0x79, 0x20, 0xaa, 
+       0xc6, 0xa7, 0x32, 0x73, 0x5f, 0xd2, 0xe4, 0xe8, 0x63, 0x45, 0xa1, 0xdc, 0x79, 0x62, 0x83, 0x8a, 
+       0xf8, 0xb7, 0xb0, 0x6d, 0xf3, 0x47, 0x4c, 0xc1, 0x55, 0x20, 0xa4, 0xe5, 0x3a, 0xa2, 0x59, 0x08, 
+       0x2d, 0x5f, 0xd9, 0x8d, 0xf1, 0x91, 0xe0, 0x62, 0x73, 0xfe, 0x3a, 0x5c, 0x5e, 0xe8, 0x95, 0xfe, 
+       0x76, 0x23, 0x85, 0xc3, 0xfb, 0x52, 0x30, 0xc2, 0xcc, 0x39, 0xeb, 0xdb, 0xe3, 0xfb, 0x54, 0xc4, 
+       0x5b, 0x60, 0xdb, 0x54, 0x1a, 0x85, 0xa2, 0x16, 0xa1, 0x59, 0x3a, 0x8e, 0xd6, 0x58, 0xad, 0xff, 
+       0x92, 0x82, 0xc6, 0xa1, 0x25, 0x60, 0x33, 0x50, 0xf5, 0x25, 0x5f, 0x52, 0x4f, 0x7c, 0xf1, 0x9c, 
+       0x11, 0x66, 0xce, 0xf5, 0xf2, 0x7c, 0x1d, 0xb6, 0xe9, 0xbd, 0x86, 0x56, 0xab, 0xed, 0xbc, 0x35, 
+       0xb7, 0xba, 0x21, 0x20, 0x47, 0x1e, 0x4d, 0xbd, 0xf0, 0x0b, 0xdc, 0xb4, 0x45, 0x2c, 0x8b, 0xe7, 
+       0x94, 0x54, 0xa3, 0xc4, 0x7a, 0x0a, 0x34, 0x7d, 0xfa, 0x8d, 0x64, 0xbc, 0xb5, 0x78, 0xe3, 0x87, 
+       0xfc, 0xde, 0xf0, 0xfd, 0xb1, 0x01, 0x11, 0x66, 0xe6, 0x96, 0x6b, 0xc2, 0xaa, 0xe9, 0x8d, 0x08, 
+       0x40, 0x36, 0xa0, 0x88, 0x0f, 0x35, 0xcb, 0x40, 0xea, 0x1a, 0x8d, 0x38, 0x5b, 0xa9, 0x27, 0xb4, 
+       0x18, 0x90, 0x16, 0xaa, 0x09, 0xd6, 0x2a, 0x92, 0x87, 0x96, 0x15, 0x94, 0x50, 0x29, 0x9b, 0x11, 
+       0x5f, 0xdc, 0xea, 0xcc, 0x9c, 0x5d, 0xaa, 0x21, 0x7a, 0xcb, 0xdf, 0x0b, 0x33, 0x73, 0xbd, 0x7e, 
+       0x45, 0xfc, 0xd3, 0xad, 0xce, 0x50, 0xc4, 0x67, 0x13, 0xa9, 0x84, 0x4c, 0x9c, 0xd5, 0xc2, 0xb5, 
+       0xea, 0x7d, 0x15, 0x96, 0x1b, 0x7f, 0x8f, 0x18, 0xa0, 0x89, 0x6a, 0x92, 0xff, 0xb9, 0x54, 0x42, 
+       0xcf, 0x1e, 0x80, 0x48, 0x00, 0x12, 0x85, 0xd6, 0x5c, 0xb7, 0x06, 0xc8, 0x08, 0x48, 0x93, 0xf9, 
+       0x6b, 0x3d, 0x2e, 0x2f, 0xd8, 0x7e, 0x45, 0xbc, 0x7f, 0xa4, 0xa8, 0x1d, 0x6a, 0xa3, 0x3a, 0x62, 
+       0xa3, 0xc2, 0xe7, 0x79, 0xb1, 0xde, 0xb5, 0x52, 0x1b, 0x2e, 0x2e, 0x84, 0xc5, 0x71, 0x44, 0xd5, 
+       0xa0, 0x81, 0x23, 0xe2, 0xfa, 0x78, 0xef, 0x9c, 0x86, 0x27, 0x7d, 0xea, 0x3c, 0x12, 0xc8, 0xfe, 
+       0xfb, 0x7d, 0x95, 0xcc, 0x58, 0xc4, 0xef, 0xcc, 0xdc, 0x5a, 0xbf, 0x22, 0xde, 0xdf, 0xa2, 0xd9, 
+       0x6c, 0x46, 0x91, 0x62, 0x23, 0x1e, 0x54, 0xc2, 0x47, 0xb4, 0x9e, 0x23, 0xe1, 0x5a, 0xe0, 0x48, 
+       0xfe, 0x33, 0xe3, 0xef, 0x6f, 0xa0, 0x55, 0x8e, 0x68, 0x26, 0x2e, 0x03, 0x48, 0xc3, 0x7b, 0xa5, 
+       0x11, 0xc9, 0x08, 0x53, 0x64, 0x0e, 0xa9, 0x00, 0xc1, 0x30, 0x33, 0xd7, 0xa9, 0xe1, 0x4f, 0xdb, 
+       0x73, 0x2e, 0x9f, 0xa8, 0x0d, 0xe0, 0x01, 0xf4, 0x7a, 0x19, 0xff, 0x38, 0xdf, 0xe1, 0xd6, 0x52, 
+       0xc6, 0x67, 0xf6, 0x37, 0x99, 0xda, 0x94, 0x22, 0x62, 0x4a, 0x8b, 0x55, 0x7e, 0x76, 0x08, 0xad, 
+       0x06, 0xd6, 0x26, 0x9e, 0xdf, 0x90, 0xa2, 0x21, 0xb4, 0x8c, 0x4f, 0xbf, 0x49, 0xe4, 0x11, 0x4f, 
+       0x36, 0x89, 0xe3, 0x36, 0x8a, 0x73, 0x23, 0xcc, 0x9c, 0xed, 0xf7, 0xc8, 0xe9, 0xd7, 0x6e, 0x72, 
+       0xfa, 0xb5, 0x9b, 0xeb, 0x2b, 0xe2, 0x3f, 0x1d, 0x66, 0x7c, 0xd4, 0x70, 0x71, 0xbe, 0xcb, 0x0f, 
+       0x5f, 0xbd, 0xc6, 0xdb, 0xff, 0x5a, 0xe5, 0xf8, 0xe7, 0x47, 0xf9, 0xd6, 0xb3, 0x13, 0x7c, 0xe1, 
+       0xb3, 0x23, 0x8c, 0xb6, 0x93, 0x82, 0xec, 0xa1, 0x28, 0xe6, 0x61, 0x9a, 0x80, 0x49, 0x01, 0x89, 
+       0x80, 0x04, 0x8e, 0x68, 0x90, 0xc6, 0x0d, 0x2f, 0xc6, 0x4c, 0x59, 0xbc, 0x95, 0x1a, 0xad, 0x62, 
+       0x55, 0x67, 0xce, 0xae, 0xdc, 0xbf, 0x22, 0xde, 0xdd, 0x62, 0x7c, 0xcc, 0x25, 0x8a, 0xc5, 0x65, 
+       0xe1, 0xc2, 0xbf, 0xbb, 0xbc, 0x7f, 0xa5, 0xcb, 0x4f, 0x7e, 0x75, 0x93, 0xbf, 0xfc, 0xe3, 0x2e, 
+       0x2f, 0x3c, 0x3d, 0xce, 0x37, 0xbf, 0x36, 0xc1, 0xf4, 0xfe, 0x36, 0xed, 0xe1, 0xaa, 0x47, 0x24, 
+       0xb7, 0x4f, 0x95, 0x6a, 0xfa, 0xd5, 0x48, 0xe3, 0x37, 0x22, 0xdd, 0x55, 0x11, 0x7a, 0x5a, 0x96, 
+       0x18, 0xf3, 0xd7, 0xbb, 0x5c, 0x5e, 0xe8, 0xde, 0xbf, 0x90, 0x7c, 0x6c, 0xa4, 0x18, 0xe0, 0xa8, 
+       0xc9, 0x03, 0xae, 0xd3, 0x53, 0xe6, 0xde, 0x5d, 0xe5, 0xc2, 0xfb, 0x6b, 0xbc, 0x7e, 0xe6, 0x0e, 
+       0x2f, 0x3f, 0x3b, 0xc9, 0x4b, 0xcf, 0x4c, 0xf2, 0xc8, 0xee, 0x16, 0x92, 0xdb, 0x61, 0xf3, 0x88, 
+       0x51, 0xab, 0x45, 0xd6, 0x0a, 0xde, 0x52, 0x95, 0xa2, 0x62, 0x92, 0x56, 0x75, 0x7c, 0xa5, 0xe1, 
+       0x71, 0x8a, 0x73, 0x66, 0x76, 0x69, 0x63, 0x8a, 0xf8, 0xf1, 0xd1, 0xa8, 0x39, 0x4d, 0xfb, 0x54, 
+       0x6a, 0xa7, 0xa7, 0x9c, 0x99, 0x5d, 0xe6, 0x9d, 0x8b, 0xab, 0xfc, 0xe1, 0xcd, 0x3b, 0x7c, 0xfb, 
+       0xf9, 0x29, 0xbe, 0x72, 0x6c, 0x9c, 0xed, 0x53, 0x4d, 0x8c, 0x09, 0x36, 0x1a, 0x1f, 0x49, 0x14, 
+       0xea, 0xd7, 0xda, 0x20, 0x47, 0x4c, 0xd1, 0xb0, 0x20, 0x79, 0xd6, 0x2a, 0xf7, 0x0e, 0x85, 0x47, 
+       0xea, 0x0a, 0xe5, 0x2b, 0xdf, 0xd8, 0xce, 0xe9, 0x1f, 0x1d, 0xa8, 0xc9, 0x72, 0x75, 0x83, 0x5c, 
+       0xfa, 0x2b, 0x77, 0xa0, 0xb4, 0xc2, 0xe2, 0x9d, 0x8c, 0xdf, 0xbc, 0x71, 0x93, 0xbf, 0x9f, 0x5b, 
+       0xe6, 0xcb, 0xc7, 0x26, 0x38, 0x75, 0x62, 0x0b, 0x4f, 0x3f, 0x31, 0xc6, 0xe8, 0x58, 0x92, 0x27, 
+       0x8f, 0x12, 0x90, 0xc2, 0x23, 0x81, 0xe8, 0x69, 0x05, 0x84, 0xf8, 0x47, 0x6b, 0xc9, 0x9e, 0x33, 
+       0xb3, 0x35, 0x15, 0xff, 0xf1, 0x31, 0x20, 0x41, 0x11, 0x44, 0xb4, 0xa6, 0xc5, 0xab, 0xa8, 0x3f, 
+       0x49, 0xd6, 0x6d, 0xee, 0xad, 0xc2, 0xfc, 0xf5, 0x0e, 0x3f, 0xfb, 0xf5, 0x35, 0xfe, 0xfa, 0xf6, 
+       0x12, 0x5f, 0x3f, 0x3e, 0xc5, 0x77, 0x4e, 0xee, 0x60, 0xfa, 0x80, 0x94, 0x39, 0xa2, 0xa1, 0x8e, 
+       0xa8, 0x14, 0xb5, 0x44, 0xd2, 0x88, 0xe0, 0x5e, 0xda, 0x07, 0x72, 0xa1, 0x88, 0xcf, 0xf7, 0x33, 
+       0xb3, 0x77, 0xfa, 0x81, 0x4c, 0x4f, 0x78, 0x9e, 0x19, 0x5f, 0xeb, 0x2c, 0xa0, 0xa8, 0x26, 0x1e, 
+       0x98, 0x75, 0x19, 0x52, 0xc5, 0x5d, 0x13, 0x07, 0xfa, 0x9e, 0xaf, 0x44, 0x14, 0x2e, 0x5c, 0x5a, 
+       0xe1, 0xd5, 0x9f, 0xcf, 0xd3, 0x6c, 0x35, 0x99, 0x3e, 0x90, 0xa2, 0xd6, 0xe6, 0x62, 0x20, 0x05, 
+       0xc8, 0xf2, 0xec, 0x66, 0xa2, 0x82, 0x63, 0x4a, 0x5d, 0x5d, 0x66, 0x05, 0x31, 0x29, 0x89, 0x58, 
+       0xd0, 0x1e, 0x1f, 0x5c, 0x5d, 0xe3, 0xca, 0xc2, 0x5a, 0x45, 0x11, 0x0b, 0x87, 0x0f, 0x4c, 0x60, 
+       0x35, 0xc1, 0x6a, 0x42, 0x92, 0x1a, 0xb0, 0x5d, 0xb7, 0x6c, 0x49, 0x13, 0x6c, 0xaf, 0xf0, 0x82, 
+       0x18, 0xd0, 0x6e, 0x2d, 0x47, 0x06, 0x6d, 0x69, 0x2a, 0xec, 0x7b, 0xb8, 0xcd, 0x81, 0x3d, 0xa3, 
+       0x7e, 0xa1, 0x34, 0x0f, 0x52, 0xc7, 0xb8, 0xe0, 0x11, 0x49, 0xa2, 0xb1, 0x90, 0x14, 0x73, 0x6e, 
+       0x71, 0xa1, 0x27, 0x92, 0x78, 0x70, 0xca, 0x99, 0xb3, 0xfd, 0xde, 0x98, 0xde, 0x3f, 0x4a, 0xab, 
+       0xd5, 0x20, 0xb3, 0x06, 0xc5, 0xf8, 0xfb, 0x33, 0x40, 0x10, 0x49, 0x7d, 0x3d, 0xf0, 0xc7, 0x98, 
+       0xbc, 0xb8, 0xc9, 0x3d, 0x70, 0x24, 0x89, 0xb0, 0xfb, 0xa1, 0x61, 0x4e, 0x3c, 0xb5, 0x85, 0x53, 
+       0x27, 0x1e, 0xe2, 0x89, 0x23, 0x5b, 0x4a, 0x5d, 0xa8, 0x48, 0xb5, 0x8e, 0xe4, 0x1c, 0x49, 0x7c, 
+       0xa8, 0x15, 0x05, 0x31, 0x49, 0x0d, 0x12, 0xea, 0x0a, 0x29, 0x6f, 0x9d, 0xbd, 0x5d, 0xc3, 0x8f, 
+       0x09, 0x90, 0x14, 0x63, 0x0c, 0x92, 0xcb, 0x8e, 0xb4, 0xc2, 0x87, 0xc8, 0xdb, 0x9a, 0x56, 0x16, 
+       0xad, 0x7f, 0x4e, 0x3d, 0x39, 0xde, 0xe4, 0x99, 0x27, 0xb7, 0x72, 0xea, 0xf9, 0x5d, 0x3c, 0x75, 
+       0x74, 0x13, 0x53, 0x13, 0x0d, 0x48, 0x1b, 0x60, 0x0d, 0xa8, 0xe6, 0xed, 0x89, 0xd3, 0x5a, 0x8a, 
+       0x8b, 0xd3, 0xbc, 0xeb, 0x4a, 0xca, 0xd3, 0x0d, 0x04, 0x63, 0xc2, 0x0a, 0x38, 0x43, 0xde, 0x9a, 
+       0x5d, 0xac, 0x01, 0xb2, 0xd9, 0x65, 0x74, 0x83, 0x03, 0xa2, 0xea, 0x8b, 0x97, 0x16, 0x1e, 0x2f, 
+       0x11, 0x5d, 0x4a, 0x3d, 0x45, 0x5c, 0xf9, 0x47, 0xda, 0x09, 0xc7, 0x0e, 0x4f, 0xf2, 0xf2, 0xf3, 
+       0xbb, 0x78, 0xe1, 0x4b, 0x3b, 0xd8, 0xb5, 0x7d, 0xd8, 0x2d, 0xbf, 0x6a, 0xbe, 0x20, 0xaa, 0x44, 
+       0x75, 0x24, 0x34, 0x5d, 0x1a, 0x71, 0x24, 0x54, 0x75, 0x8a, 0x2e, 0x31, 0x97, 0x4c, 0x61, 0x7c, 
+       0x3a, 0x7b, 0xab, 0x86, 0xe8, 0x9b, 0xfd, 0x43, 0xaa, 0xa3, 0xf4, 0x38, 0xdd, 0x46, 0x72, 0x43, 
+       0xf0, 0xba, 0xaa, 0xd8, 0x86, 0x5b, 0x09, 0x87, 0xf6, 0x8e, 0xf2, 0xd2, 0x57, 0x77, 0x71, 0xf2, 
+       0xf8, 0x0e, 0x0e, 0x3e, 0x32, 0x46, 0x23, 0x8d, 0xab, 0xbb, 0xe6, 0x2d, 0x86, 0x6a, 0xb1, 0x06, 
+       0x11, 0x10, 0x9f, 0xa5, 0xe2, 0x21, 0x84, 0xca, 0xc0, 0x31, 0xce, 0xfc, 0x1b, 0x2f, 0x16, 0x99, 
+       0xad, 0xce, 0xd8, 0xf8, 0x66, 0xa9, 0x8c, 0x10, 0x23, 0x52, 0xa4, 0x0d, 0x43, 0x9a, 0x1a, 0x8c, 
+       0xc0, 0xc3, 0x3b, 0xda, 0xbc, 0xf8, 0xcc, 0x2e, 0x5e, 0x7e, 0x6e, 0x37, 0x47, 0xa7, 0x27, 0x19, 
+       0x6a, 0x99, 0x9a, 0x31, 0x90, 0x16, 0xc9, 0xa2, 0x3c, 0x09, 0x8e, 0x6c, 0x09, 0xa2, 0x31, 0x9f, 
+       0x01, 0x6f, 0x64, 0x1a, 0xad, 0xf5, 0x2f, 0x66, 0x6a, 0x5f, 0x72, 0xc0, 0x9e, 0x9d, 0x23, 0x7c, 
+       0xf7, 0xa5, 0x3d, 0x5c, 0x9a, 0xbf, 0xcb, 0xf1, 0x27, 0xb7, 0xf1, 0xc5, 0xcf, 0x6d, 0x65, 0xd3, 
+       0x78, 0x73, 0x9d, 0xe7, 0x6a, 0xc1, 0xb3, 0xaa, 0xd6, 0x72, 0xf9, 0x58, 0x20, 0x99, 0x80, 0x96, 
+       0x97, 0xc3, 0x36, 0x73, 0xe9, 0x4c, 0x33, 0xd0, 0xbb, 0x79, 0x93, 0x5f, 0x8a, 0xef, 0xb8, 0xde, 
+       0x89, 0x89, 0x1a, 0x21, 0xc9, 0x07, 0x67, 0xf9, 0xb5, 0x00, 0x10, 0x53, 0x84, 0x88, 0xc2, 0xf8, 
+       0xd8, 0x30, 0xdf, 0xff, 0xde, 0x63, 0x85, 0xd2, 0x46, 0xcb, 0xbd, 0x87, 0x68, 0x11, 0xd2, 0x21, 
+       0x24, 0xd3, 0x71, 0xd4, 0x8e, 0xa0, 0xbd, 0xab, 0x39, 0x49, 0x9c, 0xd6, 0xea, 0x75, 0x58, 0xb9, 
+       0x38, 0x07, 0xdb, 0x8f, 0xc1, 0xf8, 0xa7, 0xbd, 0xf1, 0x99, 0x2f, 0xf9, 0x99, 0x1b, 0x3c, 0xe4, 
+       0x86, 0x59, 0x14, 0x45, 0xd4, 0x46, 0xed, 0xa8, 0xe6, 0xc5, 0x32, 0xec, 0x32, 0xc0, 0x8b, 0x1a, 
+       0x9f, 0xaf, 0x69, 0xcb, 0xd7, 0x9f, 0xe6, 0xab, 0x2b, 0x0f, 0x66, 0x94, 0xde, 0x87, 0xef, 0xd1, 
+       0xf9, 0xe0, 0x6d, 0x68, 0xb4, 0x02, 0x10, 0x41, 0xb3, 0x8c, 0xc5, 0xf3, 0x7f, 0x63, 0xac, 0xb5, 
+       0x48, 0x7b, 0xd7, 0x76, 0x1a, 0x6d, 0xdc, 0xab, 0x6a, 0xf5, 0x29, 0xcd, 0xba, 0x4f, 0x55, 0xa7, 
+       0x94, 0xd5, 0x3a, 0x8c, 0x2e, 0x6d, 0xbb, 0xfb, 0x6c, 0x50, 0xa2, 0x56, 0x73, 0x5d, 0xa9, 0xb5, 
+       0x03, 0x48, 0xcd, 0x69, 0x17, 0xb7, 0x3a, 0x62, 0x8a, 0xd7, 0x82, 0xe1, 0x7b, 0x10, 0xe0, 0x71, 
+       0x8d, 0xc6, 0x26, 0xf4, 0x96, 0xbb, 0x2c, 0x5f, 0xbc, 0xc8, 0xea, 0xc2, 0x35, 0x24, 0xd9, 0x57, 
+       0xbc, 0x67, 0x17, 0x55, 0xba, 0x8b, 0x0b, 0xac, 0x5e, 0xba, 0x45, 0xd3, 0xb6, 0x69, 0x4c, 0x0a, 
+       0x0c, 0xa9, 0x9b, 0xe2, 0xf5, 0x8a, 0x08, 0xb3, 0x3d, 0x21, 0xcb, 0x5c, 0x81, 0xce, 0x32, 0xfc, 
+       0xb1, 0xe4, 0x91, 0x98, 0x65, 0x1e, 0x9c, 0x2d, 0x3e, 0x63, 0x99, 0x15, 0x8c, 0x36, 0x89, 0xdf, 
+       0x8d, 0xfb, 0x4c, 0x92, 0xe2, 0x5c, 0x92, 0x46, 0xe7, 0xfc, 0x31, 0x49, 0x24, 0xca, 0xbb, 0x60, 
+       0x6f, 0x74, 0xe8, 0x5d, 0x5f, 0xc6, 0xae, 0x0d, 0xa1, 0xd6, 0x15, 0xd4, 0x54, 0x54, 0xb9, 0xd1, 
+       0x19, 0xe2, 0xce, 0x6a, 0x83, 0x6c, 0xb9, 0x0b, 0x8b, 0xb7, 0xdd, 0x0f, 0x3a, 0xe4, 0x20, 0xf0, 
+       0x63, 0x2d, 0xcd, 0x40, 0x7b, 0x0e, 0x88, 0xed, 0x39, 0xe3, 0x03, 0x28, 0xdb, 0x83, 0xcc, 0x16, 
+       0xc7, 0x01, 0x9c, 0xda, 0x08, 0x88, 0x29, 0x8c, 0x4e, 0xbc, 0xd1, 0x9a, 0x14, 0x7d, 0x5c, 0x18, 
+       0x17, 0x84, 0x69, 0x68, 0x28, 0x69, 0xc4, 0xc7, 0x3d, 0xd0, 0xdb, 0x70, 0xf7, 0x36, 0x2c, 0x2c, 
+       0x0d, 0xb3, 0xd4, 0x69, 0x20, 0x43, 0x4a, 0x8a, 0xcd, 0x78, 0x67, 0x6d, 0x0b, 0x93, 0x0b, 0x77, 
+       0xb0, 0xb2, 0xc8, 0xd4, 0x9a, 0xd2, 0x5c, 0x70, 0x0f, 0xc1, 0xd3, 0x40, 0xe3, 0x95, 0x56, 0x0f, 
+       0xc0, 0x16, 0x14, 0xb2, 0x5a, 0x5c, 0xd3, 0xcc, 0x5f, 0xd7, 0x8a, 0x57, 0x4c, 0x01, 0x44, 0xc4, 
+       0x7b, 0xc3, 0xef, 0x12, 0x7f, 0x46, 0xa1, 0x95, 0x78, 0xaf, 0xe5, 0xb3, 0xc2, 0xc4, 0x2d, 0xec, 
+       0xdd, 0x65, 0xb8, 0x70, 0x79, 0x88, 0x37, 0xaf, 0x6e, 0xe1, 0x5a, 0x36, 0x42, 0x6a, 0x7b, 0xa4, 
+       0x23, 0x23, 0xc3, 0x2c, 0xb2, 0x95, 0x3f, 0x77, 0x86, 0x39, 0xfb, 0xde, 0x6d, 0x5a, 0x97, 0xba, 
+       0x88, 0x48, 0x79, 0x0a, 0x2c, 0x83, 0xdf, 0x49, 0xd6, 0xbe, 0x88, 0x95, 0x7b, 0xcc, 0x6e, 0x95, 
+       0xfa, 0x7f, 0x72, 0xd3, 0xc1, 0x23, 0xef, 0xf8, 0x44, 0x4f, 0x85, 0xdb, 0xd2, 0xe6, 0x46, 0x3a, 
+       0x4e, 0xd2, 0x1a, 0x62, 0xa4, 0x3d, 0xc4, 0x7f, 0x00, 0x62, 0xa3, 0x30, 0x17, 0xd8, 0xe5, 0x5f, 
+       0x89, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
+#endif
index efb11be359a0bc4018000ed7784b3ad1f2bb5385..a6bbabc15d0ec5bf3019cfd518e8b576c005fd94 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "asset.h"
 #include "bccmodels.h"
+#include "bchash.h"
 #include "fileffmpeg.h"
 #include "file.h"
 #include "ffmpeg.h"
@@ -710,12 +711,10 @@ FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx)
        frame_rate = 0;
        aspect_ratio = 0;
        length = 0;
-       convert_ctx = 0;
 }
 
 FFVideoStream::~FFVideoStream()
 {
-       if( convert_ctx ) sws_freeContext(convert_ctx);
 }
 
 int FFVideoStream::decode_frame(AVPacket *pkt, AVFrame *frame, int &got_frame)
@@ -816,7 +815,7 @@ int FFVideoStream::encode_frame(AVPacket *pkt, AVFrame *frame, int &got_packet)
        return ret;
 }
 
-PixelFormat FFVideoStream::color_model_to_pix_fmt(int color_model)
+PixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model)
 {
        switch( color_model ) { 
        case BC_YUV422:         return AV_PIX_FMT_YUYV422;
@@ -837,7 +836,7 @@ PixelFormat FFVideoStream::color_model_to_pix_fmt(int color_model)
        return AV_PIX_FMT_NB;
 }
 
-int FFVideoStream::pix_fmt_to_color_model(PixelFormat pix_fmt)
+int FFVideoConvert::pix_fmt_to_color_model(PixelFormat pix_fmt)
 {
        switch (pix_fmt) { 
        case AV_PIX_FMT_YUYV422:        return BC_YUV422;
@@ -858,7 +857,7 @@ int FFVideoStream::pix_fmt_to_color_model(PixelFormat pix_fmt)
        return BC_TRANSPARENCY;
 }
 
-int FFVideoStream::convert_picture_vframe(VFrame *frame,
+int FFVideoConvert::convert_picture_vframe(VFrame *frame,
                AVPicture *ip, PixelFormat ifmt, int iw, int ih)
 {
        AVPicture opic;
@@ -885,20 +884,20 @@ int FFVideoStream::convert_picture_vframe(VFrame *frame,
        convert_ctx = sws_getCachedContext(convert_ctx, iw, ih, ifmt,
                frame->get_w(), frame->get_h(), ofmt, SWS_BICUBIC, NULL, NULL, NULL);
        if( !convert_ctx ) {
-               fprintf(stderr, "FFVideoStream::convert_picture_frame:"
+               fprintf(stderr, "FFVideoConvert::convert_picture_frame:"
                                " sws_getCachedContext() failed\n");
-               return 1;
+               return -1;
        }
        int ret = sws_scale(convert_ctx, ip->data, ip->linesize, 0, ih,
            opic.data, opic.linesize);
        if( ret < 0 ) {
-               ff_err(ret, "FFVideoStream::convert_picture_frame: sws_scale() failed\n");
-               return 1;
+               ff_err(ret, "FFVideoConvert::convert_picture_frame: sws_scale() failed\n");
+               return -1;
        }
        return 0;
 }
 
-int FFVideoStream::convert_cmodel(VFrame *frame,
+int FFVideoConvert::convert_cmodel(VFrame *frame,
                 AVPicture *ip, PixelFormat ifmt, int iw, int ih)
 {
        // try direct transfer
@@ -922,7 +921,22 @@ int FFVideoStream::convert_cmodel(VFrame *frame,
        return 1;
 }
 
-int FFVideoStream::convert_vframe_picture(VFrame *frame,
+int FFVideoConvert::transfer_cmodel(VFrame *frame,
+                AVFrame *ifp, PixelFormat ifmt, int iw, int ih)
+{
+       int ret = convert_cmodel(frame, (AVPicture *)ifp, ifmt, iw, ih);
+       if( ret > 0 ) {
+               const AVDictionary *src = av_frame_get_metadata(ifp);
+               AVDictionaryEntry *t = NULL;
+               BC_Hash *hp = frame->get_params();
+               //hp->clear();
+               while( (t=av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX)) )
+                       hp->update(t->key, t->value);
+       }
+       return ret;
+}
+
+int FFVideoConvert::convert_vframe_picture(VFrame *frame,
                AVPicture *op, PixelFormat ofmt, int ow, int oh)
 {
        AVPicture opic;
@@ -949,24 +963,24 @@ int FFVideoStream::convert_vframe_picture(VFrame *frame,
        convert_ctx = sws_getCachedContext(convert_ctx, frame->get_w(), frame->get_h(), ifmt,
                ow, oh, ofmt, SWS_BICUBIC, NULL, NULL, NULL);
        if( !convert_ctx ) {
-               fprintf(stderr, "FFVideoStream::convert_frame_picture:"
+               fprintf(stderr, "FFVideoConvert::convert_frame_picture:"
                                " sws_getCachedContext() failed\n");
-               return 1;
+               return -1;
        }
        int ret = sws_scale(convert_ctx, opic.data, opic.linesize, 0, frame->get_h(),
                        op->data, op->linesize);
        if( ret < 0 ) {
-               ff_err(ret, "FFVideoStream::convert_frame_picture: sws_scale() failed\n");
-               return 1;
+               ff_err(ret, "FFVideoConvert::convert_frame_picture: sws_scale() failed\n");
+               return -1;
        }
        return 0;
 }
 
-int FFVideoStream::convert_pixfmt(VFrame *frame,
+int FFVideoConvert::convert_pixfmt(VFrame *frame,
                 AVPicture *op, PixelFormat ofmt, int ow, int oh)
 {
        // try direct transfer
-       if( !convert_vframe_picture(frame, op, ofmt, ow, oh) ) return 0;
+       if( !convert_vframe_picture(frame, op, ofmt, ow, oh) ) return 1;
        // use indirect transfer
        int colormodel = frame->get_color_model();
        int bits = BC_CModels::calculate_pixelsize(colormodel) * 8;
@@ -976,8 +990,24 @@ int FFVideoStream::convert_pixfmt(VFrame *frame,
                (bits > 8 ? BC_RGB161616: BC_RGB888) ;
        VFrame vframe(frame->get_w(), frame->get_h(), icolor_model);
        vframe.transfer_from(frame);
-       if( convert_vframe_picture(&vframe, op, ofmt, ow, oh) ) return 1;
-       return 0;
+       if( !convert_vframe_picture(&vframe, op, ofmt, ow, oh) ) return 1;
+       return -1;
+}
+
+int FFVideoConvert::transfer_pixfmt(VFrame *frame,
+                AVFrame *ofp, PixelFormat ofmt, int ow, int oh)
+{
+       int ret = convert_pixfmt(frame, (AVPicture *)ofp, ofmt, ow, oh);
+       if( ret > 0 ) {
+               BC_Hash *hp = frame->get_params();
+               AVDictionary **dict = avpriv_frame_get_metadatap(ofp);
+               //av_dict_free(dict);
+               for( int i=0; i<hp->size(); ++i ) {
+                       char *key = hp->get_key(i), *val = hp->get_value(i);
+                       av_dict_set(dict, key, val, 0);
+               }
+       }
+       return ret;
 }
 
 void FFVideoStream::load_markers()
@@ -2214,7 +2244,7 @@ int FFVideoStream::create_filter(const char *filter_spec,
        snprintf(args, sizeof(args),
                "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
                src_ctx->width, src_ctx->height, src_ctx->pix_fmt,
-               st->time_base.num, st->time_base.den,
+               src_ctx->time_base.num, src_ctx->time_base.den,
                src_ctx->sample_aspect_ratio.num, src_ctx->sample_aspect_ratio.den);
        if( ret >= 0 )
                ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
@@ -2248,7 +2278,7 @@ int FFAudioStream::create_filter(const char *filter_spec,
        int ret = 0;  char args[BCTEXTLEN];
        snprintf(args, sizeof(args),
                "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%jx",
-               st->time_base.num, st->time_base.den, src_ctx->sample_rate,
+               src_ctx->time_base.num, src_ctx->time_base.den, src_ctx->sample_rate,
                av_get_sample_fmt_name(src_ctx->sample_fmt), src_ctx->channel_layout);
        if( ret >= 0 )
                ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
index 92fabfcdc5367a26b7ffec01c7050ea44212f69b..68649d16218c5f03763c00b282e41589b762a1bc 100644 (file)
@@ -194,7 +194,32 @@ public:
        float *aud_bfr;
 };
 
-class FFVideoStream : public FFStream {
+
+class FFVideoConvert {
+public:
+       struct SwsContext *convert_ctx;
+
+       FFVideoConvert() { convert_ctx = 0; }
+       ~FFVideoConvert() { if( convert_ctx ) sws_freeContext(convert_ctx); }
+
+       static PixelFormat color_model_to_pix_fmt(int color_model);
+       static int pix_fmt_to_color_model(PixelFormat pix_fmt);
+
+       int convert_picture_vframe(VFrame *frame,
+               AVPicture *ip, PixelFormat ifmt, int iw, int ih);
+       int convert_cmodel(VFrame *frame_out,
+               AVPicture *ip, PixelFormat ifmt, int iw, int ih);
+       int transfer_cmodel(VFrame *frame_in,  //defaults->metadata
+               AVFrame *ifp, PixelFormat ifmt, int iw, int ih);
+       int convert_vframe_picture(VFrame *frame,
+               AVPicture *op, PixelFormat ofmt, int ow, int oh);
+       int convert_pixfmt(VFrame *frame_in,
+                AVPicture *op, PixelFormat ofmt, int ow, int oh);
+       int transfer_pixfmt(VFrame *frame_in,  //metadata->defaults
+                AVFrame *ofp, PixelFormat ofmt, int ow, int oh);
+};
+
+class FFVideoStream : public FFStream, public FFVideoConvert {
 public:
        FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx);
        virtual ~FFVideoStream();
@@ -217,22 +242,9 @@ public:
        int64_t length;
        float aspect_ratio;
 
-       struct SwsContext *convert_ctx;
        uint8_t *pkt_bfr;
        int pkt_bfr_sz;
        int64_t start_pts;
-
-       static PixelFormat color_model_to_pix_fmt(int color_model);
-       static int pix_fmt_to_color_model(PixelFormat pix_fmt);
-
-       int convert_picture_vframe(VFrame *frame,
-               AVPicture *ip, PixelFormat ifmt, int iw, int ih);
-       int convert_cmodel(VFrame *frame_out,
-               AVPicture *ip, PixelFormat ifmt, int iw, int ih);
-       int convert_vframe_picture(VFrame *frame,
-               AVPicture *op, PixelFormat ofmt, int ow, int oh);
-       int convert_pixfmt(VFrame *frame_in,
-                AVPicture *op, PixelFormat ofmt, int ow, int oh);
 };
 
 class FFMPEG : public Thread {
index a072e9c0c25fef406dfaaec971bfa78cdad132d7..99ba4e5cc2c921d49eab52c8cbb71c4e6d7c53e2 100644 (file)
@@ -296,8 +296,10 @@ int FileAC3::write_samples(double **buffer, int64_t len)
                                file->get_audio_position() : AV_NOPTS_VALUE ;
                        int got_packet = 0;
                        ret = avcodec_encode_audio2(avctx, &avpkt, frame, &got_packet);
-                       if( !ret ) {
-                               fprintf(stderr, "avcodec_encode_audio2 failed. \n%m\n");
+                       if( ret < 0 ) {
+                               char errmsg[BCSTRLEN];
+                               av_strerror(ret, errmsg, sizeof(errmsg));
+                               fprintf(stderr, "avcodec_encode_audio2 failed. \n%s\n", errmsg);
                        }
                }
                av_packet_free_side_data(&avpkt);
index 4be07df6643dc975d7608f393e42f713663e93af..b1216332b4d7e862827bc7adfb8cabe783dee5c3 100644 (file)
@@ -392,23 +392,30 @@ int MWindow::load_plugin_index(MWindow *mwindow, char *path)
            index_version != PLUGIN_FILE_VERSION ) ret = 1;
 
        while( !ret && !feof(fp)) {
-               char *sp = index_line, *plugin_path = 0, *plugin_title = 0;
-               if( fgets(sp, BCTEXTLEN, fp) ) {
-                       plugin_path = PluginServer::table_quoted_field(sp);
-                       if( plugin_exists(plugin_path) ) continue;
-                       plugin_title = PluginServer::table_quoted_field(sp);
+               if( !fgets(index_line, BCTEXTLEN, fp) ) break;
+               if( index_line[0] == ';' ) continue;
+               if( index_line[0] == '#' ) continue;
+               int type = PLUGIN_TYPE_UNKNOWN;
+               char path[BCTEXTLEN], title[BCTEXTLEN];
+               if( PluginServer::scan_table(index_line, type, path, title) ) continue;
+               PluginServer *server = 0;
+               switch( type ) {
+               case PLUGIN_TYPE_BUILTIN:
+               case PLUGIN_TYPE_LADSPA:
+                       server = new PluginServer(mwindow, path, type);
+                       break;
+               case PLUGIN_TYPE_FFMPEG: // skip "ff_..."
+                       server = new_ffmpeg_server(mwindow, path+3);
+                       break;
                }
-               if( plugin_path && plugin_title ) {
+               if( !server ) continue;
 // Create plugin server from index entry
-                       PluginServer *new_plugin = new PluginServer(path, mwindow);
-                       new_plugin->set_path(plugin_path);
-                       new_plugin->set_title(plugin_title);
-                       if( new_plugin->read_table(sp) ) {
-                               delete new_plugin;
-                               ret = 1;  break;
-                       }
-                       plugindb->append(new_plugin);
+               server->set_title(title);
+               if( server->read_table(index_line) ) {
+                       delete server;
+                       ret = 1;  break;
                }
+               plugindb->append(server);
        }
 
        fclose(fp);
@@ -427,7 +434,7 @@ void MWindow::init_plugin_index(MWindow *mwindow, Preferences *preferences, FILE
        fs.set_filter( "[*.plugin][*.so]" );
        int result = fs.update(plugin_path);
        if( result || !fs.dir_list.total ) return;
-       int vis_id = ++idx;
+       int vis_id = idx++;
 
        for( int i=0; i<fs.dir_list.total; ++i ) {
                char *fs_path = fs.dir_list.values[i]->path;
@@ -441,30 +448,31 @@ void MWindow::init_plugin_index(MWindow *mwindow, Preferences *preferences, FILE
                        continue;
                }
                if( plugin_exists(plugin_path) ) continue;
-               PluginServer *new_plugin = new PluginServer(plugin_path, mwindow);
-               result = new_plugin->open_plugin(1, preferences, 0, 0);
+               PluginServer *server = new PluginServer(mwindow, plugin_path, PLUGIN_TYPE_UNKNOWN);
+               result = server->open_plugin(1, preferences, 0, 0);
                if( !result ) {
-                       new_plugin->write_table(fp,vis_id);
-                       new_plugin->close_plugin();
-                       new_plugin->delete_this();
+                       server->write_table(fp,vis_id);
+                       server->close_plugin();
+                       server->delete_this();
                        continue;
                }
                if( result != PLUGINSERVER_IS_LAD ) continue;
                int lad_index = 0;
                for(;;) {
-                       PluginServer *new_plugin = new PluginServer(plugin_path, mwindow);
-                       new_plugin->set_lad_index(lad_index++);
-                       result = new_plugin->open_plugin(1, preferences, 0, 0);
+                       PluginServer *server = new PluginServer(mwindow, plugin_path, PLUGIN_TYPE_LADSPA);
+                       server->set_lad_index(lad_index++);
+                       result = server->open_plugin(1, preferences, 0, 0);
                        if( result ) break;
-                       new_plugin->write_table(fp,vis_id);
-                       new_plugin->close_plugin();
-                       new_plugin->delete_this();
+                       server->write_table(fp, PLUGIN_LADSPA_ID);
+                       server->close_plugin();
+                       server->delete_this();
                }
        }
 }
 
 int MWindow::init_plugins(MWindow *mwindow, Preferences *preferences)
 {
+       init_ffmpeg();
        if( !plugindb ) plugindb = new ArrayList<PluginServer*>;
        char index_path[BCTEXTLEN];
        sprintf(index_path, "%s/%s", preferences->plugin_dir, PLUGIN_FILE);
@@ -477,8 +485,9 @@ int MWindow::init_plugins(MWindow *mwindow, Preferences *preferences)
        }
        fprintf(fp, "%d\n", PLUGIN_FILE_VERSION);
        char *plug_path = FileSystem::basepath(preferences->plugin_dir);
-       int dir_id = 0;
+       int dir_id = PLUGIN_IDS;
        init_plugin_index(mwindow, preferences, fp, plug_path, ".", dir_id);
+       init_ffmpeg_index(mwindow, preferences, fp);
        fclose(fp);
        delete [] plug_path;
        return load_plugin_index(mwindow, index_path);
@@ -2829,8 +2838,9 @@ void MWindow::dump_plugins(FILE *fp)
        if( !plugindb ) return;
        for(int i = 0; i < plugindb->total; i++)
        {
-               fprintf(fp, "audio=%d video=%d rt=%d multi=%d"
+               fprintf(fp, "type=%d audio=%d video=%d rt=%d multi=%d"
                        " synth=%d transition=%d theme=%d %s\n",
+                       plugindb->values[i]->plugin_type,
                        plugindb->values[i]->audio,
                        plugindb->values[i]->video,
                        plugindb->values[i]->realtime,
@@ -2908,6 +2918,7 @@ int MWindow::save_defaults()
 // Pointer comparison
                plugin_guis->values[i]->save_defaults();
        }
+       awindow->save_defaults(defaults);
 
        defaults->save();
        return 0;
index 79ef49da3f3cfec8562042adc65a09809cdc93ad..88613de83a1298c137f3ff8563d371638e2cfcd1 100644 (file)
@@ -67,6 +67,7 @@
 #include "playback3d.inc"
 #include "playbackengine.inc"
 #include "plugin.inc"
+#include "pluginfclient.inc"
 #include "pluginserver.inc"
 #include "pluginset.inc"
 #include "preferences.inc"
@@ -526,13 +527,13 @@ public:
 // Contains file descriptors for all the dlopens
        static ArrayList<PluginServer*> *plugindb;
 // Currently visible plugins
+       int64_t plugin_visibility;
        ArrayList<PluginServer*> *plugin_guis;
 // GUI Plugins to delete
        ArrayList<PluginServer*> *dead_plugins;
 // Keyframe editors
        ArrayList<KeyFrameThread*> *keyframe_threads;
 
-
 // Adjust sample position to line up with frames.
        int fix_timing(int64_t &samples_out, 
                int64_t &frames_out, 
@@ -606,7 +607,10 @@ public:
        static int init_plugins(MWindow *mwindow, Preferences *preferences);
        static void init_plugin_index(MWindow *mwindow, Preferences *preferences,
                FILE *fp, const char *plug_dir, const char *plug_path, int &dir_id);
+       static void init_ffmpeg();
+       static void init_ffmpeg_index(MWindow *mwindow, Preferences *preferences, FILE *fp);
        static int load_plugin_index(MWindow *mwindow, char *path);
+       static PluginServer* new_ffmpeg_server(MWindow *mwindow, const char *name);
        void init_preferences();
        void init_signals();
        void init_theme();
index 1dd39320ec78d22c7804fe88ab8d2da956cb7af6..b1ec4d5e1504b86227c91a9a35af33cfe9c804ff 100644 (file)
@@ -30,7 +30,7 @@
 #define PRESETS_FILE "Cinelerra_presets"
 #define PICTURE_FILE "Cinelerra_picture"
 #define PLUGIN_FILE "Cinelerra_plugins"
-#define PLUGIN_FILE_VERSION 1
+#define PLUGIN_FILE_VERSION 2
 
 // Behavior of region selections
 #define SELECTION_SAMPLES 0
diff --git a/cinelerra-5.0/cinelerra/pluginfclient.C b/cinelerra-5.0/cinelerra/pluginfclient.C
new file mode 100644 (file)
index 0000000..4efbe2d
--- /dev/null
@@ -0,0 +1,1152 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "bcwindowbase.h"
+#include "bctitle.h"
+#include "cstrdup.h"
+#include "language.h"
+#include "mwindow.h"
+#include "pluginfclient.h"
+#include "pluginserver.h"
+#include "samples.h"
+#include "vframe.h"
+#include "filexml.h"
+
+
+static void ff_err(int ret, const char *fmt, ...)
+{
+       char msg[BCTEXTLEN];
+       va_list ap;
+       va_start(ap, fmt);
+       vsnprintf(msg, sizeof(msg), fmt, ap);
+       va_end(ap);
+       char errmsg[BCSTRLEN];
+       av_strerror(ret, errmsg, sizeof(errmsg));
+       fprintf(stderr,_("%s  err: %s\n"),msg, errmsg);
+}
+
+PluginFClientConfig::PluginFClientConfig()
+{
+       ffilt = 0;
+}
+
+PluginFClientConfig::~PluginFClientConfig()
+{
+       delete ffilt;
+       remove_all_objects();
+}
+
+int PluginFClientConfig::equivalent(PluginFClientConfig &that)
+{
+       PluginFClientConfig &conf = *this;
+       for( int i=0; i<that.size(); ++i ) {
+               PluginFClient_Opt *topt = conf[i], *vopt = that[i];
+               char tval[BCTEXTLEN], *tp = topt->get(tval, sizeof(tval));
+               char vval[BCTEXTLEN], *vp = vopt->get(vval, sizeof(vval));
+               int ret = tp && vp ? strcmp(tp, vp) : tp || vp ? 1 : 0;
+               if( ret ) return 0;
+       }
+       return 1;
+}
+
+void PluginFClientConfig::copy_from(PluginFClientConfig &that)
+{
+       PluginFClientConfig &conf = *this;
+       for( int i=0; i<that.size(); ++i ) {
+               PluginFClient_Opt *vp = that[i];
+               const char *nm = vp->opt->name;
+               int k = size();
+               while( --k >= 0 && strcmp(nm, conf[k]->opt->name) );
+               if( k < 0 ) continue;
+               PluginFClient_Opt *fopt = conf[k];
+               char str[BCTEXTLEN], *sp = vp->get(str, sizeof(str));
+               if( sp ) fopt->set(sp);
+       }
+}
+
+void PluginFClientConfig::interpolate(PluginFClientConfig &prev, PluginFClientConfig &next, 
+       int64_t prev_frame, int64_t next_frame, int64_t current_frame)
+{
+       copy_from(prev);
+}
+
+void PluginFClientConfig::initialize(const char *name)
+{
+       ffilt = PluginFFilter::new_ffilter(name);
+       const AVOption *opt = 0;
+       void *obj = ffilt->filter_config();
+
+       const AVClass *filt_class = ffilt->filter_class();
+       if( filt_class && filt_class->option ) {
+               PluginFClientConfig &conf = *this;
+               while( (opt=av_opt_next(obj, opt)) != 0 ) {
+                       if( opt->type == AV_OPT_TYPE_CONST ) continue;
+                       int dupl = 0;
+                       for( int i=0; !dupl && i<size(); ++i ) {
+                               PluginFClient_Opt *fp = conf[i];
+                               const AVOption *op = fp->opt;
+                               if( op->offset != opt->offset ) continue;
+                               if( op->type != opt->type ) continue;
+                               dupl = 1;
+                               if( strlen(op->name) < strlen(opt->name) )
+                                       fp->opt = opt;
+                       }
+                       if( dupl ) continue;
+                       PluginFClient_Opt *fopt = new PluginFClient_Opt(this, opt);
+                       append(fopt);
+               }
+       }
+}
+
+int PluginFClientConfig::update()
+{
+       int ret = 0;
+       PluginFClientConfig &conf = *this;
+
+       for( int i=0; i<size(); ++i ) {
+               PluginFClient_Opt *fopt = conf[i];
+               char val[BCTEXTLEN], *vp = fopt->get(val, sizeof(val));
+               if( !vp || !strcmp(val, fopt->item_value->get_text()) ) continue;
+               fopt->item_value->update();
+               ++ret;
+       }
+       return ret;
+}
+
+void PluginFClientConfig::dump(FILE *fp)
+{
+       const AVOption *opt = 0;
+       const AVClass *obj = filter_class();
+       PluginFClientConfig &conf = *this;
+
+       while( (opt=av_opt_next(&obj, opt)) != 0 ) {
+               if( opt->type == AV_OPT_TYPE_CONST ) continue;
+               int k = size();
+               while( --k >= 0 && strcmp(opt->name, conf[k]->opt->name) );
+               if( k < 0 ) continue;
+               PluginFClient_Opt *fopt = conf[k];
+               char val[BCTEXTLEN], *vp = fopt->get(val,sizeof(val));
+               fprintf(fp, "  %s:=%s", opt->name, vp);
+               if( opt->unit ) {
+                       char unt[BCTEXTLEN], *up = unt;
+                       fopt->units(up);
+                       fprintf(fp, "%s", unt);
+               }
+               fprintf(fp, "\n");
+       }
+}
+
+PluginFClientReset::
+PluginFClientReset(PluginFClientWindow *fwin, int x, int y)
+ : BC_GenericButton(x, y, _("Reset"))
+{
+       this->fwin = fwin;
+}
+
+PluginFClientReset::
+~PluginFClientReset()
+{
+}
+
+int PluginFClientReset::handle_event()
+{
+       av_opt_set_defaults(fwin->ffmpeg->config.filter_config());
+       if( fwin->ffmpeg->config.update() > 0 )
+               fwin->draw();
+       fwin->ffmpeg->plugin->send_configure_change();
+       return 1;
+}
+
+PluginFClientText::
+PluginFClientText(PluginFClientWindow *fwin, int x, int y, int w)
+ : BC_TextBox(x, y, w, 1, (char *)"")
+{
+       this->fwin = fwin;
+}
+
+PluginFClientText::
+~PluginFClientText()
+{
+}
+
+int PluginFClientText::handle_event()
+{
+       return 0;
+}
+
+PluginFClientUnits::
+PluginFClientUnits(PluginFClientWindow *fwin, int x, int y, int w)
+ : BC_PopupMenu(x, y, w, "")
+{
+       this->fwin = fwin;
+}
+
+PluginFClientUnits::
+~PluginFClientUnits()
+{
+}
+
+int PluginFClientUnits::handle_event()
+{
+       const char *text = get_text();
+       if( text && fwin->selected ) {
+               if( text ) fwin->selected->set(text);
+               fwin->selected->item_value->update();
+               fwin->draw();
+               fwin->ffmpeg->plugin->send_configure_change();
+       }
+       return 1;
+}
+
+PluginFClientApply::
+PluginFClientApply(PluginFClientWindow *fwin, int x, int y)
+ : BC_GenericButton(x, y, _("Apply"))
+{
+       this->fwin = fwin;
+}
+
+PluginFClientApply::
+~PluginFClientApply()
+{
+}
+
+int PluginFClientApply::handle_event()
+{
+       const char *text = fwin->text->get_text();
+       if( text && fwin->selected ) {
+               fwin->selected->set(text);
+               fwin->selected->item_value->update();
+               fwin->draw();
+               fwin->ffmpeg->plugin->send_configure_change();
+       }
+       return 1;
+}
+
+
+PluginFClient_OptPanel::
+PluginFClient_OptPanel(PluginFClientWindow *fwin, int x, int y, int w, int h)
+ : BC_ListBox(x, y, w, h, LISTBOX_TEXT), opts(items[0]), vals(items[1])
+{
+       this->fwin = fwin;
+       update();  // init col/wid/columns
+}
+
+PluginFClient_OptPanel::
+~PluginFClient_OptPanel()
+{
+}
+
+void PluginFClient_OptPanel::create_objects()
+{
+       PluginFClientConfig &fconfig = fwin->ffmpeg->config;
+       for( int i=0; i<fconfig.size(); ++i ) {
+               PluginFClient_Opt *opt = fconfig[i];
+               opts.append(opt->item_name);
+               vals.append(opt->item_value);
+       }
+}
+
+int PluginFClient_OptPanel::cursor_leave_event()
+{
+       hide_tooltip();
+       return 0;
+}
+
+void PluginFClientWindow::update(PluginFClient_Opt *opt)
+{
+       if( selected != opt ) {
+               if( selected ) selected->item_name->set_selected(0);
+               selected = opt;
+               if( selected ) selected->item_name->set_selected(1);
+       }
+       clear_box(0,0, 0,panel->get_y());
+       char str[BCTEXTLEN], *sp;
+       *(sp=str) = 0;
+       if( opt ) opt->types(sp);
+       type->update(str);
+       *(sp=str) = 0;
+       if( opt ) opt->ranges(sp);
+       range->update(str);
+       while( units->total_items() ) units->remove_item(0);
+       ArrayList<const AVOption *> opts;
+       int n = !opt ? 0 : opt->units(opts);
+       for( int i=0; i<n; ++i )
+               units->add_item(new BC_MenuItem(opts[i]->name, 0));
+       char unit[BCSTRLEN];  strcpy(unit, "()");
+       if( units->total_items() && opt && opt->opt->unit )
+               strcpy(unit, opt->opt->unit);
+       units->set_text(unit);
+       char val[BCTEXTLEN];  val[0] = 0;
+       if( opt ) opt->get(val, sizeof(val));
+       text->update(val);
+
+       panel->update();
+}
+
+int PluginFClient_OptPanel::selection_changed()
+{
+       PluginFClient_Opt *opt = 0;
+       BC_ListBoxItem *item = get_selection(0, 0);
+       if( item ) {
+               PluginFClient_OptName *opt_name = (PluginFClient_OptName *)item;
+               opt = opt_name->opt;
+       }
+       fwin->update(opt);
+       fwin->panel->set_tooltip(!opt ? 0 : opt->tip());
+       fwin->panel->show_tooltip();
+       return 1;
+}
+
+void *PluginFClient_Opt::filter_config()
+{
+       return conf->filter_config();
+}
+const AVClass *PluginFClient_Opt::filter_class()
+{
+       return conf->filter_class();
+}
+
+int PluginFClient_Opt::types(char *rp)
+{
+       const char *cp;
+       switch (opt->type) {
+       case AV_OPT_TYPE_FLAGS: cp = "<flags>";  break;
+       case AV_OPT_TYPE_INT: cp = "<int>"; break;
+       case AV_OPT_TYPE_INT64: cp = "<int64>"; break;
+       case AV_OPT_TYPE_DOUBLE: cp = "<double>"; break;
+       case AV_OPT_TYPE_FLOAT: cp = "<float>"; break;
+       case AV_OPT_TYPE_STRING: cp = "<string>"; break;
+       case AV_OPT_TYPE_RATIONAL: cp = "<rational>"; break;
+       case AV_OPT_TYPE_BINARY: cp = "<binary>"; break;
+       case AV_OPT_TYPE_IMAGE_SIZE: cp = "<image_size>"; break;
+       case AV_OPT_TYPE_VIDEO_RATE: cp = "<video_rate>"; break;
+       case AV_OPT_TYPE_PIXEL_FMT: cp = "<pix_fmt>"; break;
+       case AV_OPT_TYPE_SAMPLE_FMT: cp = "<sample_fmt>"; break;
+       case AV_OPT_TYPE_DURATION: cp = "<duration>"; break;
+       case AV_OPT_TYPE_COLOR: cp = "<color>"; break;
+       case AV_OPT_TYPE_CHANNEL_LAYOUT: cp = "<channel_layout>";  break;
+       default: cp = "<undef>";  break;
+       }
+       return sprintf(rp, "%s", cp);
+}
+int PluginFClient_Opt::scalar(double d, char *rp)
+{
+       const char *cp = 0;
+            if( d == INT_MAX ) cp = "INT_MAX";
+       else if( d == INT_MIN ) cp = "INT_MIN";
+       else if( d == UINT32_MAX ) cp = "UINT32_MAX";
+       else if( d == (double)INT64_MAX ) cp = "I64_MAX";
+       else if( d == INT64_MIN ) cp = "I64_MIN";
+       else if( d == FLT_MAX ) cp = "FLT_MAX";
+       else if( d == FLT_MIN ) cp = "FLT_MIN";
+       else if( d == -FLT_MAX ) cp = "-FLT_MAX";
+       else if( d == -FLT_MIN ) cp = "-FLT_MIN";
+       else if( d == DBL_MAX ) cp = "DBL_MAX";
+       else if( d == DBL_MIN ) cp = "DBL_MIN";
+       else if( d == -DBL_MAX ) cp = "-DBL_MAX";
+       else if( d == -DBL_MIN ) cp = "-DBL_MIN";
+       else if( d == 0 ) cp = signbit(d) ? "-0" : "0";
+       else if( isnan(d) ) cp = signbit(d) ? "-NAN" : "NAN";
+       else if( isinf(d) ) cp = signbit(d) ? "-INF" : "INF";
+       else return sprintf(rp, "%g", d);
+       return sprintf(rp, "%s", cp);
+}
+
+int PluginFClient_Opt::ranges(char *rp)
+{
+       const AVClass *filt_class = filter_class();
+       if( !filt_class || !filt_class->option ) return 0;
+       switch (opt->type) {
+       case AV_OPT_TYPE_INT:
+       case AV_OPT_TYPE_INT64:
+       case AV_OPT_TYPE_DOUBLE:
+       case AV_OPT_TYPE_FLOAT: break;
+       default: return 0;;
+       }
+       AVOptionRanges *r = 0;
+       void *obj = &filt_class;
+       char *cp = rp;
+       if( av_opt_query_ranges(&r, obj, opt->name, AV_OPT_SEARCH_FAKE_OBJ) < 0 ) return 0;
+       for( int i=0; i<r->nb_ranges; ++i ) {
+               cp += sprintf(cp, " (");  cp += scalar(r->range[i]->value_min, cp);
+               cp += sprintf(cp, "..");  cp += scalar(r->range[i]->value_max, cp);
+               cp += sprintf(cp, ")");
+       }
+       av_opt_freep_ranges(&r);
+       return cp - rp;
+}
+
+int PluginFClient_Opt::units(ArrayList<const AVOption *> &opts)
+{
+       if( !this->opt->unit ) return 0;
+       const AVClass *filt_class = filter_class();
+       if( !filt_class || !filt_class->option ) return 0;
+       void *obj = &filt_class;
+       const AVOption *opt = NULL;
+       while( (opt=av_opt_next(obj, opt)) != 0 ) {
+               if( !opt->unit ) continue;
+               if( opt->type != AV_OPT_TYPE_CONST ) continue;
+               if( strcmp(this->opt->unit, opt->unit) ) continue;
+               int i = opts.size();
+               while( --i >= 0 ) {
+                       if( opts[i]->default_val.i64 != opt->default_val.i64 ) continue;
+                       if( strlen(opts[i]->name) < strlen(opt->name) ) opts[i] = opt;
+                       break;
+               }
+               if( i < 0 ) 
+                       opts.append(opt);
+       }
+       return opts.size();
+}
+
+int PluginFClient_Opt::units(char *rp)
+{
+       ArrayList<const AVOption *> opts;
+       int n = units(opts);
+       if( !n ) return 0;
+       char *cp = rp;
+       cp += sprintf(cp, " [%s:", this->opt->unit);
+       for( int i=0; i<n; ++i )
+               cp += sprintf(cp, " %s", opts[i]->name);
+       cp += sprintf(cp, "]:");
+       return cp - rp;
+}
+
+const char *PluginFClient_Opt::tip()
+{
+       return opt->help;
+}
+
+int PluginFClient_OptPanel::update()
+{
+       const char *cols[] = { "option", "value", };
+       const int col1_w = 150;
+       int wids[] = { col1_w, get_w()-col1_w };
+       BC_ListBox::update(&items[0], &cols[0], &wids[0], sizeof(items)/sizeof(items[0]));
+       return 0;
+}
+
+
+PluginFClientWindow::PluginFClientWindow(PluginFClient *ffmpeg)
+ : PluginClientWindow(ffmpeg->plugin, 600, 300, 600, 300, 1)
+{
+       this->ffmpeg = ffmpeg;
+       this->selected = 0;
+}
+
+PluginFClientWindow::~PluginFClientWindow()
+{
+}
+
+void PluginFClientWindow::create_objects()
+{
+       char string[BCTEXTLEN];
+       BC_Title *title;
+       int x = 10, y = 10;
+       const char *descr = ffmpeg->config.ffilt->description();
+       if( !descr ) descr = ffmpeg->config.ffilt->filter_name();
+       add_subwindow(title = new BC_Title(x, y, descr));
+       y += title->get_h() + 10;
+       int x0 = x;
+       sprintf(string, _("Type: "));
+       add_subwindow(title = new BC_Title(x0, y, string));
+       x0 += title->get_w() + 8;
+       add_subwindow(type = new BC_Title(x0, y, (char *)""));
+       x0 = x + 150;
+       sprintf(string, _("Range: "));
+       add_subwindow(title = new BC_Title(x0, y, string));
+       x0 += title->get_w() + 8;
+       add_subwindow(range = new BC_Title(x0, y, (char *)""));
+       int x1 = get_w() - BC_GenericButton::calculate_w(this, _("Reset")) - 8;
+       add_subwindow(reset = new PluginFClientReset(this, x1, y));
+       y += title->get_h() + 10;
+       x0 = x;
+       add_subwindow(units = new PluginFClientUnits(this, x0, y, 120));
+       x0 += units->get_w() + 8;
+       x1 = get_w() - BC_GenericButton::calculate_w(this, _("Apply")) - 8;
+       add_subwindow(apply = new PluginFClientApply(this, x1, y));
+       add_subwindow(text = new PluginFClientText(this, x0, y, x1-x0 - 8));
+       y += title->get_h() + 10;
+
+       panel_x = x;  panel_y = y;
+       panel_w = get_w()-10 - panel_x;
+       panel_h = get_h()-10 - panel_y;
+       panel = new PluginFClient_OptPanel(this, panel_x, panel_y, panel_w, panel_h);
+       add_subwindow(panel);
+       panel->create_objects();
+       ffmpeg->config.update();
+       draw();
+       show_window(1);
+}
+
+void PluginFClientWindow::draw()
+{
+       update(selected);
+}
+
+int PluginFClientWindow::resize_event(int w, int h)
+{
+       int x = get_w() - BC_GenericButton::calculate_w(this, _("Reset")) - 8;
+       int y = reset->get_y();
+       reset->reposition_window(x, y);
+       int x1 = get_w() - BC_GenericButton::calculate_w(this, _("Apply")) - 8;
+       int y1 = units->get_y();
+       apply->reposition_window(x1, y1);
+       int x0 = units->get_x() + units->get_w() + 8;
+       int y0 = units->get_y();
+       text->reposition_window(x0,y0, x1-x0-8);
+       panel_w = get_w()-10 - panel_x;
+       panel_h = get_h()-10 - panel_y;
+       panel->reposition_window(panel_x,panel_y, panel_w, panel_h);
+       return 1;
+}
+
+PluginFClient::PluginFClient(PluginClient *plugin, const char *name)
+{
+       this->plugin = plugin;
+       this->name = name;
+       ffilt = 0;
+       fsrc = fsink = 0;
+       plugin_position = -1;
+       filter_position = -1;
+       activated = 0;
+       sprintf(title, "F_%s", name);
+       config.initialize(name);
+       curr_config.initialize(name);
+}
+
+PluginFClient::~PluginFClient()
+{
+}
+
+bool PluginFClient::is_audio(AVFilter *fp)
+{
+       if( !fp->outputs ) return 0;
+       if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
+       if( !avfilter_pad_get_name(fp->outputs, 0) ) return 0;
+       if( avfilter_pad_get_type(fp->outputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
+       if( !fp->inputs ) return 1;
+       if( avfilter_pad_count(fp->inputs) > 1 ) return 0;
+       if( !avfilter_pad_get_name(fp->inputs, 0) ) return 0;
+       if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_AUDIO ) return 0;
+       return 1;
+}
+bool PluginFClient::is_video(AVFilter *fp)
+{
+       if( !fp->outputs ) return 0;
+       if( avfilter_pad_count(fp->outputs) > 1 ) return 0;
+       if( !avfilter_pad_get_name(fp->outputs, 0) ) return 0;
+       if( avfilter_pad_get_type(fp->outputs, 0) != AVMEDIA_TYPE_VIDEO ) return 0;
+       if( !fp->inputs ) return 1;
+       if( avfilter_pad_count(fp->inputs) > 1 ) return 0;
+       if( !avfilter_pad_get_name(fp->inputs, 0) ) return 0;
+       if( avfilter_pad_get_type(fp->inputs, 0) != AVMEDIA_TYPE_VIDEO ) return 0;
+       return 1;
+}
+
+NEW_WINDOW_MACRO(PluginFClient, PluginFClientWindow)
+
+int PluginFClient::load_configuration()
+{
+       int64_t src_position =  get_source_position();
+       KeyFrame *prev_keyframe = get_prev_keyframe(src_position);
+       config.copy_from(curr_config);
+       read_data(prev_keyframe);
+       int ret = !config.equivalent(curr_config) ? 1 : 0;
+       return ret;
+}
+
+
+void PluginFClient::render_gui(void *data, int size)
+{
+       PluginFClientConfig *conf = (PluginFClientConfig *)data;
+       config.copy_from(*conf);
+       KeyFrame *keyframe = plugin->server->get_keyframe();
+       save_data(keyframe);
+       update_gui();
+}
+
+void PluginFClient::update_gui()
+{
+       PluginClientThread *thread = plugin->get_thread();
+       if( !thread ) return;
+       PluginFClientWindow *window = (PluginFClientWindow*)thread->get_window();
+       window->lock_window("PluginFClient::update_gui");
+       load_configuration();
+       if( config.update() > 0 )
+               window->draw();
+       window->unlock_window();
+}
+
+const char *PluginFClient::plugin_title()
+{
+       return title;
+}
+
+char *PluginFClient::to_upper(char *cp, const char *sp)
+{
+       char *bp = cp;
+       while( *sp != 0 ) *bp++ = toupper(*sp++);
+       *bp = 0;
+       return cp;
+}
+
+void PluginFClient::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+       char string[BCTEXTLEN];
+
+// cause data to be stored directly in text
+       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+       output.tag.set_title(to_upper(string, plugin_title()));
+       const AVClass *filt_class = config.filter_class();
+       if( filt_class && filt_class->option ) {
+               void *obj = config.filter_config();
+               const AVOption *opt = NULL;
+               while( (opt=av_opt_next(obj, opt)) != 0 ) {
+                       uint8_t *buf = 0;
+                       if( av_opt_get(obj, opt->name, 0, &buf) < 0 ) continue;
+                       output.tag.set_property(opt->name, (const char *)buf);
+                       av_freep(&buf);
+               }
+       }
+
+       output.append_tag();
+       output.terminate_string();
+}
+
+void PluginFClient::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+       char string[BCTEXTLEN], value[BCTEXTLEN];
+       input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+       while( !input.read_tag() ) {
+               to_upper(string, plugin_title());
+               if( !input.tag.title_is(string) ) continue;
+               const AVClass *filt_class = config.filter_class();
+               if( filt_class && filt_class->option ) {
+                       void *obj = config.filter_config();
+                       const AVOption *opt = NULL;
+                       while( (opt=av_opt_next(obj, opt)) != 0 ) {
+                               to_upper(string, opt->name);
+                               if( !input.tag.get_property(string, value) ) continue;
+                               av_opt_set(obj, opt->name, value, 0);
+                       }
+               }
+       }
+}
+
+int PluginFClient::activate()
+{
+       if( fsrc )
+               avfilter_link(fsrc, 0, ffilt->fctx, 0);
+       avfilter_link(ffilt->fctx, 0, fsink, 0);
+       int ret = avfilter_graph_config(ffilt->graph, NULL);
+       if( ret >= 0 ) {
+               curr_config.copy_from(config);
+               activated = 1;
+       }
+       return ret;
+}
+
+void PluginFClient::reactivate()
+{
+       delete ffilt;  ffilt = 0;
+       activated = 0;
+}
+
+PluginFAClient::PluginFAClient(PluginServer *server, const char *name)
+ : PluginAClient(server), PluginFClient(this, name)
+{
+}
+
+PluginFAClient::~PluginFAClient()
+{
+}
+
+int PluginFAClient::activate()
+{
+       if( activated ) return activated;
+       ffilt = PluginFFilter::new_ffilter(name, &config);
+       if( !ffilt ) {
+               config.copy_from(curr_config);
+               send_configure_change();
+               send_render_gui(&config, sizeof(config));
+               ffilt = PluginFFilter::new_ffilter(name, &config);
+       }
+       AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP;
+       int channels = PluginClient::total_in_buffers;
+       uint64_t layout = (((uint64_t)1)<<channels) - 1;
+       AVFilterGraph *graph = !ffilt ? 0 : ffilt->graph;
+       int ret = !graph ? -1 : 0;
+       if( ret >= 0 && ffilt->filter->inputs ) {
+               char args[BCTEXTLEN];
+               snprintf(args, sizeof(args),
+                       "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%jx",
+                       1, sample_rate, sample_rate, av_get_sample_fmt_name(sample_fmt), layout);
+               ret = avfilter_graph_create_filter(&fsrc, avfilter_get_by_name("abuffer"),
+                       "in", args, NULL, graph);
+       }
+       if( ret >= 0 )
+               ret = avfilter_graph_create_filter(&fsink, avfilter_get_by_name("abuffersink"),
+                       "out", NULL, NULL, graph);
+       if( ret >= 0 )
+               ret = av_opt_set_bin(fsink, "sample_fmts",
+                       (uint8_t*)&sample_fmt, sizeof(sample_fmt), AV_OPT_SEARCH_CHILDREN);
+       if( ret >= 0 )
+               ret = av_opt_set_bin(fsink, "channel_layouts",
+                       (uint8_t*)&layout, sizeof(layout), AV_OPT_SEARCH_CHILDREN);
+       if( ret >= 0 )
+               ret = av_opt_set_bin(fsink, "sample_rates",
+                       (uint8_t*)&sample_rate, sizeof(sample_rate), AV_OPT_SEARCH_CHILDREN);
+       if( ret >= 0 )
+               ret = PluginFClient::activate();
+       if( ret < 0 && activated >= 0 ) {
+               ff_err(ret, "PluginFAClient::activate: %s failed\n", plugin_title());
+               activated = -1;
+       }
+       return activated;
+}
+
+
+static AVRational best_frame_rate(double frame_rate)
+{
+       static const int m1 = 1001*12, m2 = 1000*12;
+       static const int freqs[] = {
+               40*m1, 48*m1, 50*m1, 60*m1, 80*m1,120*m1, 240*m1,
+               24*m2, 30*m2, 60*m2, 12*m2, 15*m2, 48*m2, 0,
+       };
+       double max_err = 1.;
+       int freq, best_freq = 0;
+       for( int i=0; (freq = i<30*12 ? (i+1)*1001 : freqs[i-30*12]); ++i ) {
+               double framerate = (double)freq / m1;
+               double err = fabs(frame_rate/framerate - 1.);
+               if( err >= max_err ) continue;
+               max_err = err;
+               best_freq = freq;
+       }
+       return max_err < 0.0001 ?
+               (AVRational) { best_freq, m1 } :
+               (AVRational) { 0, 0 };
+}
+
+int PluginFVClient::activate(int width, int height, int color_model)
+{
+       if( activated ) return activated;
+       ffilt = PluginFFilter::new_ffilter(name, &config);
+       if( !ffilt ) {
+               config.copy_from(curr_config);
+               send_configure_change();
+               send_render_gui(&config, sizeof(config));
+               ffilt = PluginFFilter::new_ffilter(name, &config);
+       }
+       AVPixelFormat pix_fmt = color_model_to_pix_fmt(color_model);
+       AVFilterGraph *graph = !ffilt ? 0 : ffilt->graph;
+       int ret = !graph ? -1 : 0;
+       if( ret >= 0 && ffilt->filter->inputs ) {
+               curr_config.copy_from(config);
+               if( pix_fmt == AV_PIX_FMT_NB ) {
+                       int bpp = BC_CModels::calculate_pixelsize(color_model) * 8;
+                       int bits_per_comp = bpp / BC_CModels::components(color_model);
+                       int alpha =  BC_CModels::has_alpha(color_model);
+                       pix_fmt = bits_per_comp > 8 ?
+                               !alpha ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGBA64LE :
+                               !alpha ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_RGBA ;
+               }
+               int aspect_w = 1, aspect_h = 1; // XXX
+               AVRational best_rate = best_frame_rate(frame_rate);
+               char args[BCTEXTLEN];
+               snprintf(args, sizeof(args),
+                       "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
+                       width, height, pix_fmt, best_rate.num, best_rate.den, aspect_w, aspect_h);
+               ret = avfilter_graph_create_filter(&fsrc, avfilter_get_by_name("buffer"),
+                       "in", args, NULL, graph);
+       }
+       if( ret >= 0 )
+               ret = avfilter_graph_create_filter(&fsink, avfilter_get_by_name("buffersink"),
+                       "out", NULL, NULL, graph);
+       if( ret >= 0 )
+               ret = av_opt_set_bin(fsink, "pix_fmts",
+                       (uint8_t*)&pix_fmt, sizeof(pix_fmt), AV_OPT_SEARCH_CHILDREN);
+       if( ret >= 0 )
+               ret = PluginFClient::activate();
+       if( ret < 0 && activated >= 0 ) {
+               ff_err(ret, "PluginFVClient::activate() %s\n", plugin_title());
+               activated = -1;
+       }
+       return activated;
+}
+
+int PluginFAClient::get_inchannels()
+{
+       AVFilterContext *fctx = ffilt->fctx;
+       AVFilterLink **links = !fctx->nb_inputs ? 0 : fctx->inputs;
+       return !links ? 0 : avfilter_link_get_channels(links[0]);
+}
+
+int PluginFAClient::get_outchannels()
+{
+       AVFilterContext *fctx = ffilt->fctx;
+       AVFilterLink **links = !fctx->nb_outputs ? 0 : fctx->outputs;
+       return !links ? 0 : avfilter_link_get_channels(links[0]);
+}
+
+int PluginFAClient::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate)
+{
+       int total_in = PluginClient::total_in_buffers;
+       int total_out = PluginClient::total_out_buffers;
+       int in_channels = 0, out_channels = 0;
+
+       if( load_configuration() )
+               plugin_position = -1;
+       if( plugin_position != start_position ) {
+               filter_position = plugin_position = start_position;
+               reactivate();
+       }
+
+       AVFrame *frame = 0;
+       int ret = activate();
+       if( ret >= 0 && !(frame = av_frame_alloc()) ) {
+               fprintf(stderr, "PluginFAClient::process_buffer: av_frame_alloc failed\n");
+               ret = AVERROR(ENOMEM);
+       }
+       if( ret >= 0 ) {
+               in_channels = get_inchannels();
+               out_channels = get_outchannels();
+       }
+
+       int retry = 10;
+       while( ret >= 0 && --retry >= 0 ) {
+               ret = av_buffersink_get_frame(fsink, frame);
+               if( ret >= 0 || ret != AVERROR(EAGAIN) ) break;
+               if( !fsrc ) { ret = AVERROR(EIO);  break; }
+               for( int i=0; i<total_in; ++i )
+                       read_samples(buffer[i], i, sample_rate, filter_position, size);
+               filter_position += size;
+               frame->nb_samples = size;
+               frame->format = AV_SAMPLE_FMT_FLTP;
+               frame->channel_layout = (1<<in_channels)-1;
+               frame->sample_rate = sample_rate;
+               frame->pts = local_to_edl(filter_position);
+               ret = av_frame_get_buffer(frame, 0);
+               if( ret < 0 ) break;
+               float **in_buffers = (float **)&frame->extended_data[0];
+               for(int i = 0; i < in_channels; i++) {
+                       float *in_buffer = in_buffers[i];
+                       int k = i < total_in ? i : 0;
+                       double *in_ptr = buffer[k]->get_data();
+                       for(int j = 0; j < size; j++) in_buffer[j] = in_ptr[j];
+               }
+               ret = av_buffersrc_add_frame_flags(fsrc, frame, 0);
+       }
+       if( ret >= 0 && retry < 0 )
+               ret = AVERROR(EAGAIN);
+
+       if( ret >= 0 ) {
+               int nbfrs = total_out;
+               if( out_channels < nbfrs ) nbfrs = out_channels;
+               float **out_buffers = (float **)&frame->extended_data[0];
+               int i = 0;
+               while( i < nbfrs ) {
+                       float *out_buffer = out_buffers[i];
+                       double *out_ptr = buffer[i++]->get_data();
+                       for(int j = 0; j < size; j++) out_ptr[j] = out_buffer[j];
+               }
+               while( i < total_out ) {
+                       double *out_ptr = buffer[i++]->get_data();
+                       bzero(out_ptr, sizeof(double) * size);
+               }
+       }
+       if( ret < 0 ) {
+               int64_t position = PluginFClient::get_source_position();
+               double t0 = (double)position/sample_rate, dt = 1./sample_rate;
+               for( int i=0; i<total_out; ++i ) {
+                       double t = t0, *out = buffer[i]->get_data();
+                       for( int k=size; --k>=0; t+=dt ) {
+                               double w = int(2*t) & 1 ? 2*M_PI*440 : 2*M_PI*697;
+                               *out++ = sin(t * w);
+                       }
+               }
+               ff_err(ret, "PluginFAClient::process_buffer() %s\n", plugin_title());
+       }
+
+       av_frame_free(&frame);
+       plugin_position += size;
+       return size;
+}
+
+
+PluginFVClient::PluginFVClient(PluginServer *server, const char *name)
+ : PluginVClient(server), PluginFClient(this, name)
+{
+}
+
+PluginFVClient::~PluginFVClient()
+{
+}
+
+int PluginFVClient::process_buffer(VFrame **frames, int64_t position, double frame_rate)
+{
+       VFrame *vframe = *frames;
+       int width = vframe->get_w();
+       int height = vframe->get_h();
+
+       if( load_configuration() )
+               plugin_position = -1;
+       if( plugin_position != position ) {
+               filter_position = plugin_position = position;
+               reactivate();
+       }
+
+       int colormodel = vframe->get_color_model();
+       int ret = activate(width, height, colormodel);
+       AVPixelFormat pix_fmt = fsrc ?
+               (AVPixelFormat) fsrc->outputs[0]->format :
+               color_model_to_pix_fmt(colormodel);
+       if( pix_fmt <= AV_PIX_FMT_NONE || pix_fmt >= AV_PIX_FMT_NB )
+               pix_fmt = AV_PIX_FMT_RGBA;
+               
+       AVFrame *frame = 0;
+       if( ret >= 0 && !(frame = av_frame_alloc()) ) {
+               fprintf(stderr, "PluginFVClient::process_buffer: av_frame_alloc failed\n");
+               ret = AVERROR(ENOMEM);
+       }
+
+       int retry = 10;
+       while( ret >= 0 && --retry >= 0 ) {
+               ret = av_buffersink_get_frame(fsink, frame);
+               if( ret >= 0 || ret != AVERROR(EAGAIN) ) break;
+               if( !fsrc ) { ret = AVERROR(EIO);  break; }
+               read_frame(vframe, 0, filter_position++, frame_rate, get_use_opengl());
+               frame->format = pix_fmt;
+               frame->width  = width;
+               frame->height = height;
+               frame->pts = local_to_edl(position);
+               ret = av_frame_get_buffer(frame, 32);
+               if( ret < 0 ) break;
+               ret = transfer_pixfmt(vframe, frame, pix_fmt, width, height);
+               if( ret < 0 ) break;
+               ret = av_buffersrc_add_frame_flags(fsrc, frame, 0);
+       }
+       if( ret >= 0 && retry < 0 )
+               ret = AVERROR(EAGAIN);
+
+       if( ret >= 0 ) {
+               pix_fmt = (AVPixelFormat) frame->format;
+               ret = transfer_cmodel(vframe, frame, pix_fmt, width, height);
+       }
+       if( ret < 0 ) {
+               ff_err(ret, "PluginFVClient::process_buffer() %s\n", plugin_title());
+               if( position & 1 ) vframe->clear_frame();
+       }
+
+       ++plugin_position;
+       av_frame_free(&frame);
+       return ret >= 0 ? 0 : 1;
+}
+
+
+PluginFClient_OptName:: PluginFClient_OptName(PluginFClient_Opt *opt)
+{
+       this->opt = opt;
+       set_text(opt->opt->name);
+}
+
+PluginFClient_OptValue::PluginFClient_OptValue(PluginFClient_Opt *opt)
+{
+       this->opt = opt;
+       update();
+}
+
+void PluginFClient_OptValue::update()
+{
+       char val[BCTEXTLEN];  val[0] = 0;
+       opt->get(val, sizeof(val));
+       set_text(val);
+}
+
+
+PluginFClient_Opt::PluginFClient_Opt(PluginFClientConfig *conf, const AVOption *opt)
+{
+       this->conf = conf;
+       this->opt = opt;
+       item_name = new PluginFClient_OptName(this);
+       item_value = new PluginFClient_OptValue(this);
+}
+
+PluginFClient_Opt::~PluginFClient_Opt()
+{
+       delete item_name;
+       delete item_value;
+}
+
+char *PluginFClient_Opt::get(char *vp, int sz)
+{
+       char *ret = 0;
+       void *obj = filter_config();
+       uint8_t *bp = 0;
+       if( av_opt_get(obj, opt->name, 0, &bp) >= 0 && bp != 0 ) {
+               const char *val = (const char *)bp;
+               ret = sz >= 0 ? strncpy(vp,val,sz) : strcpy(vp, val);
+               if( sz > 0 ) vp[sz-1] = 0;
+               av_freep(&bp);
+       }
+       return ret;
+}
+void PluginFClient_Opt::set(const char *val)
+{
+       void *obj = filter_config();
+       av_opt_set(obj , opt->name, val, 0);
+}
+
+void PluginFFilter::uninit()
+{
+}
+
+static int get_defaults(const char *name, char *args)
+{
+       *args = 0;
+       char defaults_path[BCTEXTLEN];
+       FFMPEG::set_option_path(defaults_path, "plugin.opts");
+       FILE *fp = fopen(defaults_path,"r");
+       if( !fp ) return 0;
+       char ff_plugin[BCSTRLEN], ff_args[BCTEXTLEN], *ap = 0;
+       while( !ap && fgets(ff_args, sizeof(ff_args), fp) ) {
+               if( *(ap=ff_args) == ';' ) continue;
+               if( *(ap=ff_args) == '#' ) ++ap;
+               char *bp = ff_plugin, *ep = bp + sizeof(ff_plugin)-1;
+               while( bp < ep && *ap && *ap != '\n' && *ap != ' ' ) *bp++ = *ap++;
+               *bp = 0;
+               if( strcmp(ff_plugin, name) ) ap = 0;
+       }
+       fclose(fp);
+       if( !ap ) return 0;
+       if( ff_args[0] == '#' ) return -1;
+       while( *ap == ' ' ) ++ap;
+       while( *ap && *ap != '\n' ) *args++ = *ap++;
+       *args = 0;
+       return 1;
+}
+
+bool PluginFFilter::is_audio()
+{
+       return PluginFClient::is_audio(filter);
+}
+
+bool PluginFFilter::is_video()
+{
+       return PluginFClient::is_video(filter);
+}
+
+int PluginFFilter::init(const char *name, PluginFClientConfig *conf)
+{
+       char args[BCTEXTLEN];
+       int ret = get_defaults(name, args);
+       if( ret < 0 ) return 0;
+       PluginFLogLevel errs(AV_LOG_ERROR);
+       this->filter = avfilter_get_by_name(name);
+       if( !this->filter ) return AVERROR(ENOENT);
+       int flag_mask = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_DYNAMIC_OUTPUTS;
+       if( filter->flags & flag_mask ) return AVERROR(EPERM);
+       if( !this->is_audio() && !this->is_video() ) return AVERROR(EIO);
+       this->graph = avfilter_graph_alloc();
+       if( !this->graph ) return AVERROR(ENOMEM);
+       static int inst = 0;
+       char inst_name[BCSTRLEN];
+       sprintf(inst_name,"%s_%d", name, ++inst);
+       graph->thread_type = 0;
+       graph->nb_threads  = 1;
+       fctx = avfilter_graph_alloc_filter(graph, filter, inst_name);
+       if( !fctx ) return AVERROR(ENOMEM);
+       if( conf ) {
+               AVDictionary *opts = 0;
+               for( int i=0; i<conf->size(); ++i ) {
+                       PluginFClient_Opt *op = conf->get(i);
+                       const char *name = op->opt->name;
+                       char val[BCTEXTLEN], *vp = op->get(val, sizeof(val));
+                       if( vp ) av_dict_set(&opts, name, vp, 0);
+               }
+               ret = avfilter_init_dict(fctx, &opts);
+               av_dict_free(&opts);
+       }
+       else
+               ret = avfilter_init_str(fctx, args);
+       return ret < 0 ? ret : 1;
+}
+
+
+PluginFFilter::PluginFFilter()
+{
+       filter = 0;
+       graph = 0;
+       fctx = 0;
+}
+
+PluginFFilter::~PluginFFilter()
+{
+       PluginFLogLevel errs(AV_LOG_ERROR);
+       avfilter_graph_free(&graph);
+       filter = 0;  fctx = 0;
+}
+
+PluginFFilter *PluginFFilter::new_ffilter(const char *name, PluginFClientConfig *conf)
+{
+       PluginFFilter *ffilt = new PluginFFilter;
+       int ret = ffilt->init(name, conf);
+       if( ret < 0 ) ff_err(ret, "PluginFFilter::new_ffilter(%s)\n", name);
+       if( ret <= 0 ) { delete ffilt;  ffilt = 0; }
+       return ffilt;
+}
+
+PluginClient *PluginServer::new_ffmpeg_plugin()
+{
+       AVFilter *filter = avfilter_get_by_name(ff_name);
+       if( !filter ) return 0;
+       PluginFClient *ffmpeg =
+               PluginFClient::is_audio(filter) ?
+                       (PluginFClient *)new PluginFAClient(this, ff_name) :
+               PluginFClient::is_video(filter) ?
+                       (PluginFClient *)new PluginFVClient(this, ff_name) :
+               0;
+       if( !ffmpeg ) return 0;
+       return ffmpeg->plugin;
+}
+
+
+PluginServer* MWindow::new_ffmpeg_server(MWindow *mwindow, const char *name)
+{
+       PluginFFilter *ffilt = PluginFFilter::new_ffilter(name);
+       if( !ffilt ) return 0;
+       delete ffilt;
+       return new PluginServer(mwindow, (char*)name, PLUGIN_TYPE_FFMPEG);
+}
+
+void MWindow::init_ffmpeg_index(MWindow *mwindow, Preferences *preferences, FILE *fp)
+{
+       PluginFLogLevel errs(AV_LOG_ERROR);
+       const AVFilter *filter = 0;
+       while( (filter=avfilter_next(filter)) != 0 ) {
+               PluginServer *server = new_ffmpeg_server(mwindow, filter->name);
+               if( server ) {
+                       int result = server->open_plugin(1, preferences, 0, 0);
+                       if( !result ) {
+                               server->write_table(fp, PLUGIN_FFMPEG_ID);
+                               server->close_plugin();
+                       }
+                       server->delete_this();
+                       if( result ) fprintf(fp, "#%s\n", filter->name);
+               }
+       }
+}
+
+void MWindow::init_ffmpeg()
+{
+       av_register_all();
+       avfilter_register_all();
+}
+
diff --git a/cinelerra-5.0/cinelerra/pluginfclient.h b/cinelerra-5.0/cinelerra/pluginfclient.h
new file mode 100644 (file)
index 0000000..781e252
--- /dev/null
@@ -0,0 +1,285 @@
+#ifndef __PLUGINFCLIENT_H__
+#define __PLUGINFCLIENT_H__
+
+#include "arraylist.h"
+#include "bclistbox.h"
+#include "bclistboxitem.h"
+#include "bcbutton.h"
+#include "bcpopupmenu.h"
+#include "bcmenuitem.h"
+#include "bctextbox.h"
+#include "ffmpeg.h"
+#include "pluginclient.h"
+#include "pluginaclient.h"
+#include "pluginvclient.h"
+#include "pluginserver.h"
+#include "pluginfclient.inc"
+#include "preferences.inc"
+
+extern "C" {
+#include "libavfilter/buffersrc.h"
+#include "libavfilter/buffersink.h"
+#include "libavformat/avformat.h"
+#include "libavformat/avio.h"
+#include "libavcodec/avcodec.h"
+#include "libavfilter/avfilter.h"
+#include "libavutil/avutil.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "libswresample/swresample.h"
+#include "libswscale/swscale.h"
+}
+
+class PluginFClient_OptName : public BC_ListBoxItem {
+public:
+       PluginFClient_Opt *opt;
+
+       PluginFClient_OptName(PluginFClient_Opt *opt);
+};
+
+class PluginFClient_OptValue : public BC_ListBoxItem {
+public:
+       PluginFClient_Opt *opt;
+
+       void update();
+       PluginFClient_OptValue(PluginFClient_Opt *opt);
+};
+
+class PluginFClient_Opt {
+public:
+       PluginFClientConfig *conf;
+       const AVOption *opt;
+       PluginFClient_OptName *item_name;
+       PluginFClient_OptValue *item_value;
+
+       char *get(char *vp, int sz=-1);
+       void set(const char *val);
+       int types(char *rp);
+       int scalar(double d, char *rp);
+       int ranges(char *rp);
+       int units(ArrayList<const AVOption *> &opts);
+       int units(char *rp);
+       const char *tip();
+       void *filter_config();
+       const AVClass *filter_class();
+
+       PluginFClient_Opt(PluginFClientConfig *conf, const AVOption *opt);
+       ~PluginFClient_Opt();
+};
+
+class PluginFFilter {
+       PluginFFilter(PluginFFilter &that) {} //disable assign/copy
+public:
+       AVFilter *filter;
+       AVFilterGraph *graph;
+       AVFilterContext *fctx;
+
+       void *filter_config() { return fctx->priv; }
+       const AVClass *filter_class() { return filter->priv_class; }
+       const char *description() { return filter->description; }
+
+       int init(const char *name, PluginFClientConfig *conf);
+       void uninit();
+       static PluginFFilter *new_ffilter(const char *name, PluginFClientConfig *conf=0);
+
+       PluginClient* new_plugin(PluginServer*);
+       const char *filter_name() { return filter->name; }
+       bool is_audio();
+       bool is_video();
+
+       PluginFFilter();
+       ~PluginFFilter();
+};
+
+class PluginFClientConfig : public ArrayList<PluginFClient_Opt *>
+{
+public:
+       PluginFFilter *ffilt;
+       void *filter_config() { return ffilt->filter_config(); }
+       const AVClass *filter_class() { return ffilt->filter_class(); }
+
+       void copy_from(PluginFClientConfig &that);
+       int equivalent(PluginFClientConfig &that);
+       void interpolate(PluginFClientConfig &prev, PluginFClientConfig &next,
+               int64_t prev_frame, int64_t next_frame, int64_t current_frame);
+       void initialize(const char *name);
+       int update();
+       void dump(FILE *fp=stdout);
+
+       PluginFClientConfig();
+       ~PluginFClientConfig();
+};
+
+
+class PluginFClient_OptPanel : public BC_ListBox {
+public:
+       PluginFClient_OptPanel(PluginFClientWindow *fwin, int x, int y, int w, int h);
+       ~PluginFClient_OptPanel();
+       void create_objects();
+       int cursor_leave_event();
+
+       PluginFClientWindow *fwin;
+       ArrayList<BC_ListBoxItem*> items[2];
+       ArrayList<BC_ListBoxItem*> &opts;
+       ArrayList<BC_ListBoxItem*> &vals;
+
+       int selection_changed();
+       int update();
+};
+
+class PluginFClientReset : public BC_GenericButton {
+public:
+       PluginFClientWindow *fwin;
+
+       PluginFClientReset(PluginFClientWindow *fwin, int x, int y);
+       ~PluginFClientReset();
+       int handle_event();
+};
+
+class PluginFClientUnits : public BC_PopupMenu {
+public:
+       PluginFClientWindow *fwin;
+
+       PluginFClientUnits(PluginFClientWindow *fwin, int x, int y, int w);
+       ~PluginFClientUnits();
+       int handle_event();
+};
+
+class PluginFClientText : public BC_TextBox {
+public:
+       PluginFClientWindow *fwin;
+
+       PluginFClientText(PluginFClientWindow *fwin, int x, int y, int w);
+       ~PluginFClientText();
+       int handle_event();
+};
+
+class PluginFClientApply : public BC_GenericButton {
+public:
+       PluginFClientWindow *fwin;
+
+       PluginFClientApply(PluginFClientWindow *fwin, int x, int y);
+       ~PluginFClientApply();
+       int handle_event();
+};
+
+class PluginFClientWindow : public PluginClientWindow
+{
+public:
+       PluginFClientWindow(PluginFClient *ffmpeg);
+       ~PluginFClientWindow();
+
+       void create_objects();
+       void update(PluginFClient_Opt *oip);
+       void draw();
+       int resize_event(int w, int h);
+
+        PluginFClient *ffmpeg;
+       PluginFClient_OptPanel *panel;
+        int panel_x, panel_y, panel_w, panel_h;
+       BC_Title *type, *range;
+        PluginFClient_Opt *selected;
+
+       PluginFClientReset *reset;
+       PluginFClientUnits *units;
+       PluginFClientText *text;
+       PluginFClientApply *apply;
+};
+
+class PluginFLogLevel {
+       int level;
+public:
+       PluginFLogLevel(int lvl) {
+               level = av_log_get_level();
+               if( level > lvl ) av_log_set_level(lvl);
+       }
+       ~PluginFLogLevel() { av_log_set_level(level); }
+};
+
+class PluginFClient {
+public:
+       const char *name;
+       PluginClient *plugin;
+       PluginFFilter *ffilt;
+       AVFilterContext *fsrc, *fsink;
+       int64_t plugin_position, filter_position;
+       int activated;
+       char title[BCSTRLEN];
+
+       PluginFClient(PluginClient *plugin, const char *name);
+        ~PluginFClient();
+       static bool is_audio(AVFilter *fp);
+       static bool is_video(AVFilter *fp);
+
+       int64_t get_source_position() {
+               return plugin->get_source_position();
+       }
+       KeyFrame* get_prev_keyframe(int64_t position, int is_local=1) {
+               return plugin->get_prev_keyframe(position, is_local);
+       }
+       KeyFrame* get_next_keyframe(int64_t position, int is_local=1) {
+               return plugin->get_next_keyframe(position, is_local);
+       }
+       int64_t edl_to_local(int64_t position) {
+               return plugin->edl_to_local(position);
+       }
+
+        void update_gui();
+       char *to_upper(char *bp, const char *sp);
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+        void render_gui(void *data, int size);
+       int activate();
+       void reactivate();
+
+        PluginFClientConfig curr_config, av_config;
+        PLUGIN_CLASS_MEMBERS(PluginFClientConfig)
+};
+
+class PluginFAClient : public PluginAClient, public PluginFClient
+{
+public:
+       PluginFAClient(PluginServer *server, const char *name);
+        ~PluginFAClient();
+       const char *plugin_title() { return PluginFClient::plugin_title(); }
+       PluginClientWindow *new_window() { return PluginFClient::new_window(); }
+       int activate();
+
+       int load_configuration() { return PluginFClient::load_configuration(); }
+       void save_data(KeyFrame *keyframe) { PluginFClient::save_data(keyframe); }
+       void read_data(KeyFrame *keyframe) { PluginFClient::read_data(keyframe); }
+       void update_gui() { PluginFClient::update_gui(); }
+        void render_gui(void *data, int size) { PluginFClient::render_gui(data, size); }
+
+       int is_realtime() { return 1; }
+       int is_multichannel() { return 1; }
+       int uses_gui() { return 1; }
+       int is_synthesis() { return 1; }
+        int get_inchannels();
+        int get_outchannels();
+       int process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate);
+};
+
+class PluginFVClient : public PluginVClient, public PluginFClient, public FFVideoConvert
+{
+public:
+       PluginFVClient(PluginServer *server, const char *name);
+        ~PluginFVClient();
+       const char *plugin_title() { return PluginFClient::plugin_title(); }
+       PluginClientWindow *new_window() { return PluginFClient::new_window(); }
+       int activate(int width, int height, int color_model);
+
+       int load_configuration() { return PluginFClient::load_configuration(); }
+       void save_data(KeyFrame *keyframe) { PluginFClient::save_data(keyframe); }
+       void read_data(KeyFrame *keyframe) { PluginFClient::read_data(keyframe); }
+       void update_gui() { PluginFClient::update_gui(); }
+        void render_gui(void *data, int size) { PluginFClient::render_gui(data, size); }
+
+       int is_realtime() { return 1; }
+       int is_multichannel() { return 1; }
+       int uses_gui() { return 1; }
+       int is_synthesis() { return 1; }
+       int process_buffer(VFrame **frames, int64_t start_position, double frame_rate);
+};
+
+#endif
diff --git a/cinelerra-5.0/cinelerra/pluginfclient.inc b/cinelerra-5.0/cinelerra/pluginfclient.inc
new file mode 100644 (file)
index 0000000..5c3f8f0
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __PLUGINFCLIENT_INC__
+#define __PLUGINFCLIENT_INC__
+
+struct AVFilter;
+typedef struct AVFilter AVFilter;
+struct AVFilterGraph;
+typedef struct AVFilterGraph AVFilterGraph;
+
+class PluginFClient_Opt;
+class PluginFFilter;
+class PluginFClientConfig;
+class PluginFClient_OptName;
+class PluginFClient_OptValue;
+class PluginFClient_OptPanel;
+class PluginFClientUnits;
+class PluginFClientText;
+class PluginFClientApply;
+class PluginFClientWindow;
+class PluginFClient;
+class PluginFAClient;
+class PluginFVClient;
+
+#ifndef  FLT_MAX
+#define FLT_MAX 3.40282346638528859812e+38F
+#endif
+
+#ifndef  FLT_MIN
+#define FLT_MIN 1.17549435082228750797e-38F
+#endif
+    
+#ifndef  DBL_MAX
+#define DBL_MAX ((double)1.79769313486231570815e+308L)
+#endif
+
+#ifndef  DBL_MIN
+#define DBL_MIN ((double)2.22507385850720138309e-308L)
+#endif
+
+#endif
index a57da8658c25da747ab6601738fa793df1fe183f..66abd3bd87364c8ae9eb57755bcec0ce4a4dfc7c 100644 (file)
@@ -25,6 +25,7 @@
 #include "autoconf.h"
 #include "bcsignals.h"
 #include "cplayback.h"
+#include "cstrdup.h"
 #include "cwindow.h"
 #include "edl.h"
 #include "edlsession.h"
@@ -40,6 +41,7 @@
 #include "plugin.h"
 #include "pluginaclient.h"
 #include "pluginaclientlad.h"
+#include "pluginfclient.h"
 #include "pluginclient.h"
 #include "plugincommands.h"
 #include "pluginserver.h"
 #include <sys/mman.h>
 
 
-PluginServer::PluginServer()
+void PluginServer::init()
 {
        reset_parameters();
+       this->plugin_type = PLUGIN_TYPE_UNKNOWN;
        modules = new ArrayList<Module*>;
        nodes = new ArrayList<VirtualNode*>;
 }
 
-PluginServer::PluginServer(char *path, MWindow *mwindow)
+PluginServer::PluginServer()
 {
-       reset_parameters();
-       set_path(path);
-       modules = new ArrayList<Module*>;
-       nodes = new ArrayList<VirtualNode*>;
-       this->mwindow = mwindow;
+       init();
 }
 
-PluginServer::PluginServer(PluginServer &that)
+PluginServer::PluginServer(MWindow *mwindow, char *path, int type)
 {
-       reset_parameters();
-
-       if(that.title)
-       {
-               title = new char[strlen(that.title) + 1];
-               strcpy(title, that.title);
-       }
-
-       if(that.path)
-       {
-               path = new char[strlen(that.path) + 1];
-               strcpy(path, that.path);
+       char fpath[BCTEXTLEN];
+       init();
+        this->plugin_type = type;
+        this->mwindow = mwindow;
+       if( type == PLUGIN_TYPE_FFMPEG ) {
+               ff_name = cstrdup(path);
+               sprintf(fpath, "ff_%s", path);
+               path = fpath;
        }
+        set_path(path);
+}
 
+PluginServer::PluginServer(PluginServer &that)
+{
+       reset_parameters();
+       plugin_type = that.plugin_type;
+       title = !that.title ? 0 : cstrdup(that.title);
+       path = !that.path ? 0 : cstrdup(that.path);
+       ff_name = !that.ff_name ? 0 : cstrdup(that.ff_name);
        modules = new ArrayList<Module*>;
        nodes = new ArrayList<VirtualNode*>;
 
@@ -117,7 +121,6 @@ PluginServer::PluginServer(PluginServer &that)
        keyframe = that.keyframe;
        new_plugin = that.new_plugin;
 
-       is_lad = that.is_lad;
        lad_descriptor = that.lad_descriptor;
        lad_descriptor_function = that.lad_descriptor_function;
        lad_index = that.lad_index;
@@ -126,11 +129,12 @@ PluginServer::PluginServer(PluginServer &that)
 PluginServer::~PluginServer()
 {
        close_plugin();
-       if(path) delete [] path;
-       if(title) delete [] title;
-       if(modules) delete modules;
-       if(nodes) delete nodes;
-       if(picon) delete picon;
+       delete [] path;
+       delete [] ff_name;
+       delete [] title;
+       delete modules;
+       delete nodes;
+       delete picon;
 }
 
 // Done only once at creation
@@ -141,11 +145,12 @@ int PluginServer::reset_parameters()
        prompt = 0;
        cleanup_plugin();
        autos = 0;
-       plugin = 0;
        edl = 0;
+       dlobj = 0;
        preferences = 0;
        title = 0;
        path = 0;
+       ff_name = 0;
        audio = video = theme = 0;
        fileio = 0;
        uses_gui = 0;
@@ -161,14 +166,12 @@ int PluginServer::reset_parameters()
        nodes = 0;
        picon = 0;
 
-       is_lad = 0;
        lad_index = -1;
        lad_descriptor_function = 0;
        lad_descriptor = 0;
        return 0;
 }
 
-
 // Done every time the plugin is opened or closed
 int PluginServer::cleanup_plugin()
 {
@@ -217,15 +220,18 @@ int PluginServer::get_lad_index()
 
 int PluginServer::is_ladspa()
 {
-       return is_lad;
+       return plugin_type == PLUGIN_TYPE_LADSPA ? 1 : 0;
 }
 
-int PluginServer::set_path(char *path)
+int PluginServer::is_ffmpeg()
 {
-       if(this->path) delete [] this->path;
-       this->path = new char[strlen(path) + 1];
-       strcpy(this->path, path);
-       return 0;
+       return plugin_type == PLUGIN_TYPE_FFMPEG ? 1 : 0;
+}
+
+void PluginServer::set_path(const char *path)
+{
+       delete [] this->path;
+       this->path = cstrdup(path);
 }
 
 char* PluginServer::get_path()
@@ -242,8 +248,7 @@ int PluginServer::get_synthesis()
 void PluginServer::set_title(const char *string)
 {
        if(title) delete [] title;
-       title = new char[strlen(string) + 1];
-       strcpy(title, string);
+       title = cstrdup(string);
 }
 
 void PluginServer::generate_display_title(char *string)
@@ -260,11 +265,34 @@ void PluginServer::generate_display_title(char *string)
                strcpy(string, ltitle);
 }
 
+void *PluginServer::load_obj()
+{
+       if( !dlobj ) {
+               char dlpath[BCTEXTLEN], *dp = dlpath;
+               char *cp = path;
+               if( *cp != '/' ) {
+                       char *bp = preferences->plugin_dir;
+                       while( *bp ) *dp++ = *bp++;
+                       *dp++ = '/';
+               }
+               while( *cp ) *dp++ = *cp++;
+               *dp = 0;
+               dlobj = load(dlpath);
+       }
+       return dlobj;
+}
+
+void PluginServer::unload_obj()
+{
+       if( !dlobj ) return;
+       unload(dlobj);  dlobj = 0;
+}
+
 void PluginServer::delete_this()
 {
-       void *dlp = load_obj();
+       void *obj = dlobj;
        delete this;
-       unload_obj(dlp);
+       if( obj ) unload(obj);
 }
 
 // Open plugin for signal processing
@@ -278,57 +306,61 @@ int PluginServer::open_plugin(int master,
        this->preferences = preferences;
        this->plugin = plugin;
        this->edl = edl;
-       if( !load_obj() ) {
-               // add base path if not absolute path
-               char dl_path[BCTEXTLEN], *dp = dl_path;
-               char *cp = path;
-               if( *cp != '/' ) {
-                       char *bp = preferences->plugin_dir;
-                       while( *bp ) *dp++ = *bp++;
-                       *dp++ = '/';
-               }
-               while( *cp ) *dp++ = *cp++;
-               *dp = 0;
-               if( !load_obj(dl_path) ) {
+       if( plugin_type != PLUGIN_TYPE_FFMPEG && plugin_type != PLUGIN_TYPE_EXECUTABLE && !load_obj() ) {
 // If the load failed it may still be an executable tool for a specific
 // file format, in which case we just store the path.
-                       set_title(path);
-                       char string[BCTEXTLEN];
-                       strcpy(string, load_error());
-                       if(!strstr(string, "executable"))
-                               eprintf("PluginServer::open_plugin: load_obj failure = %s\n", string);
+               set_title(path);
+               char string[BCTEXTLEN];
+               strcpy(string, load_error());
+               if( !strstr(string, "executable") ) {
+                       eprintf("PluginServer::open_plugin: load_obj failure = %s\n", string);
                        return PLUGINSERVER_NOT_RECOGNIZED;
                }
+               plugin_type = PLUGIN_TYPE_EXECUTABLE;
        }
-       if( !new_plugin && !lad_descriptor ) {
+       if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_BUILTIN ) {
                new_plugin =
                        (PluginClient* (*)(PluginServer*)) load_sym("new_plugin");
-               if( !new_plugin ) {
-                       lad_descriptor_function =
-                               (LADSPA_Descriptor_Function) load_sym("ladspa_descriptor");
-                       if(!lad_descriptor_function) {
-                               fprintf(stderr, "PluginServer::open_plugin "
-                                       " %d: new_plugin undefined in %s\n", __LINE__, path);
-                               unload_obj();
-                               return PLUGINSERVER_NOT_RECOGNIZED;
-                       }
+               if( new_plugin )
+                       plugin_type = PLUGIN_TYPE_BUILTIN;
+       }
+       if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_LADSPA ) {
+               lad_descriptor_function =
+                       (LADSPA_Descriptor_Function) load_sym("ladspa_descriptor");
+               if( lad_descriptor_function ) {
                        if( lad_index < 0 ) {
                                unload_obj();
                                return PLUGINSERVER_IS_LAD;
                        }
                        lad_descriptor = lad_descriptor_function(lad_index);
-                       if(!lad_descriptor) {
-                               unload_obj();
+                       if( !lad_descriptor )
                                return PLUGINSERVER_NOT_RECOGNIZED;
-                       }
-                       is_lad = 1;
+                       plugin_type = PLUGIN_TYPE_LADSPA;
                }
        }
-
-       client = is_lad ?
-               (PluginClient *) new PluginAClientLAD(this) :
-               new_plugin(this);
-
+       if( plugin_type == PLUGIN_TYPE_UNKNOWN ) {
+               fprintf(stderr, "PluginServer::open_plugin "
+                       " %d: plugin undefined in %s\n", __LINE__, path);
+               unload_obj();
+               return PLUGINSERVER_NOT_RECOGNIZED;
+       }
+       switch( plugin_type ) {
+       case PLUGIN_TYPE_BUILTIN:
+               client = new_plugin(this);
+               break;
+       case PLUGIN_TYPE_LADSPA:
+               client = new PluginAClientLAD(this);
+               break;
+       case PLUGIN_TYPE_FFMPEG:
+               client = new_ffmpeg_plugin();
+               break;
+       default:
+               client = 0;
+               break;
+       }
+       if( !client )
+               return PLUGINSERVER_NOT_RECOGNIZED;
+       
 // Run initialization functions
        realtime = client->is_realtime();
 // Don't load defaults when probing the directory.
@@ -393,30 +425,27 @@ void PluginServer::render_stop()
 void PluginServer::write_table(FILE *fp, int idx)
 {
        if(!fp) return;
-       fprintf(fp, "\"%s\" \"%s\" %d %d %d %d %d %d %d %d %d %d %d %d\n",
-               path, title, idx, audio, video, theme, realtime, fileio,
-               uses_gui, multichannel, synthesis, transition, is_lad, lad_index);
+       fprintf(fp, "%d \"%s\" \"%s\" %d %d %d %d %d %d %d %d %d %d %d\n",
+               plugin_type, path, title, idx, audio, video, theme, realtime,
+               fileio, uses_gui, multichannel, synthesis, transition, lad_index);
 }
 
-char *PluginServer::table_quoted_field(char *&sp)
+int PluginServer::scan_table(char *text, int &type, char *path, char *title)
 {
-       char *cp = sp;
-       while( *cp && (*cp == ' ' || *cp == '\t') ) ++cp;
-       if( *cp++ != '"' ) return 0;
-       char *bp = cp;
-       while( *cp && *cp != '"' ) ++cp;
-       if( *cp != '"' ) return 0;
-       *cp++ = 0;  sp = cp;
-       return bp;
+       int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\"", &type, path, title);
+       return n < 3 ? 1 : 0;
 }
 
 int PluginServer::read_table(char *text)
 {
-       int n = sscanf(text, "%d %d %d %d %d %d %d %d %d %d %d %d",
-               &dir_idx, &audio, &video, &theme, &realtime, &fileio, &uses_gui,
-               &multichannel, &synthesis, &transition, &is_lad, &lad_index);
-
-       return n == 12 ? 0 : 1;
+       char path[BCTEXTLEN], title[BCTEXTLEN];
+       int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" %d %d %d %d %d %d %d %d %d %d %d",
+               &plugin_type, path, title, &dir_idx, &audio, &video, &theme, &realtime,
+               &fileio, &uses_gui, &multichannel, &synthesis, &transition, &lad_index);
+       if( n != 14 ) return 1;
+       this->path = cstrdup(path);
+       this->title = cstrdup(title);
+       return 0;
 }
 
 int PluginServer::init_realtime(int realtime_sched,
index 659f64ea84c75d9653ba29d4df19e5b5058c52eb..e174ebaa9ae24e464cbc009c16a72de9374421da 100644 (file)
@@ -44,6 +44,7 @@
 #include "mwindow.inc"
 #include "plugin.inc"
 #include "pluginaclientlad.inc"
+#include "pluginfclient.inc"
 #include "pluginclient.inc"
 #include "pluginserver.inc"
 #include "preferences.inc"
 
 #include <dlfcn.h>
 
-
-
-class PluginObj
+class PluginServer
 {
+       int reset_parameters();
+       void init();
+       int cleanup_plugin();
+
        void *dlobj;
-public:
-       PluginObj() { dlobj = 0; }
-       ~PluginObj() {}
-       PluginObj(PluginObj &that) { dlobj = 0; }
-// dl interface
-       void *load_obj() { return dlobj; }
-       void *load_obj(const char *path) { return dlobj = dlopen(path, RTLD_NOW); }
-       static void unload_obj(void *dlp) { if( dlp ) dlclose(dlp); }
-       void unload_obj() { unload_obj(dlobj); }
+       void *load(const char *dlp) { return dlobj = dlopen(dlp, RTLD_NOW); }
+       void unload(void *obj) { dlclose(obj); }
        void *load_sym(const char *sym) { return dlsym(dlobj, sym); }
        const char *load_error() { return dlerror(); }
-};
-
-class PluginServer : public PluginObj
-{
-       int reset_parameters();
-       int cleanup_plugin();
+       void *load_obj();
+       void unload_obj();
 
 // Base class created by client
        PluginClient *client;
@@ -87,24 +79,30 @@ class PluginServer : public PluginObj
        PluginClient* (*new_plugin)(PluginServer*);
 
 // LAD support
-       int is_lad;
        int lad_index;
        LADSPA_Descriptor_Function lad_descriptor_function;
        const LADSPA_Descriptor *lad_descriptor;
        int use_opengl;
+// FFMPEG support
+       const char *ff_name;
 // Driver for opengl calls.
        VideoDevice *vdevice;
 public:
        PluginServer();
-       PluginServer(char *path, MWindow *mwindow=0);
+       PluginServer(MWindow *mwindow, char *path, int type);
        PluginServer(PluginServer &);
        virtual ~PluginServer();
 
-
        friend class PluginAClientLAD;
        friend class PluginAClientConfig;
        friend class PluginAClientWindow;
 
+       friend class PluginFClient;
+       friend class PluginFAClient;
+       friend class PluginFVClient;
+       friend class PluginFClientConfig;
+       friend class PluginFClientWindow;
+
 // open a plugin and wait for commands
 // Get information for plugindb if master.
 #define PLUGINSERVER_IS_LAD 2
@@ -121,7 +119,7 @@ public:
        void render_stop();
 // Write entry into plugin table
        void write_table(FILE *fp, int idx);
-       static char *table_quoted_field(char *&sp);
+       static int scan_table(char *text, int &type, char *path, char *title);
        int read_table(char *text);
 // queries
        void set_title(const char *string);
@@ -151,10 +149,14 @@ public:
 // Get picon png vframe image
        VFrame *get_picon();
        VFrame *get_plugin_images();
+
 // ladspa
        void set_lad_index(int i);
        int get_lad_index();
        int is_ladspa();
+// ffmpeg
+       int is_ffmpeg();
+       PluginClient *new_ffmpeg_plugin();
 // =============================== for realtime plugins
 // save configuration of plugin
        void save_data(KeyFrame *keyframe);          
@@ -292,8 +294,8 @@ public:
        double get_framerate();     // get framerate produced by plugin
        int get_project_samplerate();            // get samplerate of project data before processing
        double get_project_framerate();         // get framerate of project data before processing
-       int set_path(char *path);    // required first
-       charget_path();
+       void set_path(const char *path);        // required first
+       char *get_path();
        int get_synthesis();
        void get_defaults_path(char *path);
        void save_defaults();
@@ -321,6 +323,8 @@ public:
        int64_t get_written_samples();   // after samples are written, get the number written
        int64_t get_written_frames();   // after frames are written, get the number written
 
+// client origin
+       int plugin_type;
 
 // buffers
        int64_t out_buffer_size;   // size of a send buffer to the plugin
index 20f3cc2fc678815d903b2ea1c27fad3f1898e2df..505af55c153d5de59626131a5e7e768f21ee4397 100644 (file)
 #ifndef PLUGINSERVER_INC
 #define PLUGINSERVER_INC
 
+class PluginObj;
 class PluginServer;
-class PluginGUIServer;
+
+#define PLUGIN_LADSPA_ID 0
+#define PLUGIN_FFMPEG_ID 1
+#define PLUGIN_IDS 2
+
+#define PLUGIN_TYPE_UNKNOWN -1
+#define PLUGIN_TYPE_EXECUTABLE 0
+#define PLUGIN_TYPE_BUILTIN 1
+#define PLUGIN_TYPE_LADSPA 2
+#define PLUGIN_TYPE_FFMPEG 3
+#define PLUGIN_TYPES 4
 
 #endif
index fd1bec75c8e38ecc5dd0af784fb40969cd668f54..062db5bb826567ff27ff2d9f1782c8253a1529f6 100644 (file)
@@ -106,64 +106,40 @@ void VAttachmentPoint::render(VFrame *output,
        if(plugin_server->multichannel)
        {
 // Test against previous parameters for reuse of previous data
-               if(is_processed &&
-                       this->start_position == start_position &&
-                       EQUIV(this->frame_rate, frame_rate))
-               {
+               if( !is_processed || this->start_position != start_position ||
+                   !EQUIV(this->frame_rate, frame_rate)) {
+                       is_processed = 1;
+                       this->start_position = start_position;
+                       this->frame_rate = frame_rate;
+
+// Allocate buffer vector for subsequent render calls
+                       new_buffer_vector(output->get_w(), output->get_h(), 
+                               output->get_color_model());
+// Process plugin
+//printf("VAttachmentPoint::render 1 %d\n", buffer_number);
+                       if(renderengine)
+                               plugin_servers.values[0]->set_use_opengl(use_opengl,
+                                       renderengine->video);
+                       plugin_servers.values[0]->process_buffer(buffer_vector,
+                               start_position, frame_rate,
+                               (int64_t)Units::round(plugin->length * frame_rate / 
+                                       renderengine->get_edl()->session->frame_rate),
+                               renderengine->command->get_direction());
+               }
+//printf("VAttachmentPoint::render 3\n");
 // Need to copy PBuffer if OpenGL, regardless of use_opengl
-                       if(buffer_vector[buffer_number]->get_opengl_state() == VFrame::RAM)
-                       {
-                               output->copy_from(buffer_vector[buffer_number]);
-                               output->set_opengl_state(VFrame::RAM);
-                       }
-                       else
-                       if(renderengine && renderengine->video)
-                       {
+               if( buffer_vector[buffer_number]->get_opengl_state() == VFrame::RAM ) {
+                       output->copy_from(buffer_vector[buffer_number]);
+                       output->set_opengl_state(VFrame::RAM);
+               }
+               else if(renderengine && renderengine->video) {
 // Need to copy PBuffer to texture
 // printf("VAttachmentPoint::render temp=%p output=%p\n", 
 // buffer_vector[buffer_number],
 // output);
-                               VDeviceX11 *x11_device = (VDeviceX11*)renderengine->video->get_output_base();
-                               x11_device->copy_frame(output, buffer_vector[buffer_number]);
-                       }
-                       return;
-               }
-
-               is_processed = 1;
-               this->start_position = start_position;
-               this->frame_rate = frame_rate;
-
-// Allocate buffer vector for subsequent render calls
-               new_buffer_vector(output->get_w(), 
-                       output->get_h(), 
-                       output->get_color_model());
-
-// Create temporary vector with output argument substituted in
-               VFrame **output_temp = new VFrame*[virtual_plugins.total];
-               for(int i = 0; i < virtual_plugins.total; i++)
-               {
-                       if(i == buffer_number)
-                               output_temp[i] = output;
-                       else
-                               output_temp[i] = buffer_vector[i];
+                       VDeviceX11 *x11_device = (VDeviceX11*)renderengine->video->get_output_base();
+                       x11_device->copy_frame(output, buffer_vector[buffer_number]);
                }
-
-// Process plugin
-//printf("VAttachmentPoint::render 1 %d\n", buffer_number);
-               if(renderengine)
-                       plugin_servers.values[0]->set_use_opengl(use_opengl,
-                               renderengine->video);
-               plugin_servers.values[0]->process_buffer(output_temp,
-                       start_position,
-                       frame_rate,
-                       (int64_t)Units::round(plugin->length * 
-                               frame_rate / 
-                               renderengine->get_edl()->session->frame_rate),
-                       renderengine->command->get_direction());
-//printf("VAttachmentPoint::render 2\n");
-
-               delete [] output_temp;
-//printf("VAttachmentPoint::render 3\n");
        }
        else
 // process single track
diff --git a/cinelerra-5.0/ffmpeg/plugin.opts b/cinelerra-5.0/ffmpeg/plugin.opts
new file mode 100644 (file)
index 0000000..e47f86f
--- /dev/null
@@ -0,0 +1,168 @@
+#abuffer
+#abuffersink
+#acrossfade
+adelay delays=1
+#adrawgraph
+aeval exprs=(sin(2*PI*t*440)+sin(2*PI*t*350))/2*mod(floor(2*t),2):channel_layout=1c
+#aevalsrc
+#afifo
+#aformat
+#ainterleave
+#allrgb
+#allyuv
+#alphaextract
+#alphamerge
+#amerge
+#amix
+#amovie
+#anull
+#anullsink
+#anullsrc
+#apad
+#aperms
+#aphasemeter
+aresample sample_rate=48000
+#areverse
+#aselect
+#asendcmd
+#asetnsamples
+#asetpts
+#asetrate
+#asettb
+#ashowinfo
+#asilencedetect
+#asilenceremove
+#asplit
+#astats
+#astreamsync
+#atadenoise
+#atempo
+#atrim
+#avectorscope
+#bbox
+#blackdetect
+#blackframe
+#blend
+#buffer
+#buffersink
+#cellauto
+#channelmap
+#channelsplit
+chorus in_gain=0.400000:out_gain=0.400000:delays=1|1:decays=1|1:speeds=1|1:depths=1|1
+#codecview
+#color
+colormatrix src=bt601:dst=smpte240m
+#concat
+#copy
+#cover_rect
+#cropdetect
+#curves
+#dctdnoiz
+#decimate
+delogo x=1:y=1:w=1:h=1:band=1:show=0
+#detelecine
+#drawgraph
+#dynaudnorm
+#ebur128
+#elbg
+equalizer frequency=1000.000000:width_type=1:width=200.000000:gain=-10.000000
+#extractplanes
+#ffabuffersink
+#ffbuffersink
+#fftfilt
+#field
+#fieldmatch
+#fieldorder
+#fifo
+#find_rect
+#fliporder
+#format
+#fps
+#framepack
+#framerate
+#framestep
+#geq
+#haldclut
+#haldclutsrc
+hflip
+#hstack
+#hue
+#idet
+#interlace
+#interleave
+#isdesctest
+#join
+#life
+#lut
+#lut3d
+#lutrgb
+#lutyuv
+#mandelbrot
+#mergeplanes
+#movie
+#mpdecimate
+#mptestsrc
+#noformat
+#null
+#nullsink
+#nullsrc
+#overlay
+#pad
+#palettegen
+#paletteuse
+#pan
+#perms
+#pixdesctest
+#psnr
+#pullup
+#qp
+#random
+#removelogo
+#repeatfields
+#replaygain
+#reverse
+#rgbtestsrc
+#scale
+#scale2ref
+#select
+#sendcmd
+#separatefields
+#setdar
+#setfield
+#setpts
+#setsar
+#settb
+#showcqt
+#showfreqs
+#showinfo
+#showpalette
+#showspectrum
+#showvolume
+#showwaves
+#showwavespic
+#shuffleplanes
+#sidechaincompress
+#signalstats
+#silencedetect
+#silenceremove
+#sine
+#smptebars
+#smptehdbars
+#split
+#ssim
+swapuv
+#tblend
+#telecine
+#testsrc
+#thumbnail
+#tile
+#tinterlace
+#trim
+#vectorscope
+vflip
+#volume
+#volumedetect
+#vstack
+#w3fdif
+#waveform
+#zoompan
index 573c0044ae260919ffae3e939b9b827700291044..180c70de7897c8c9074845fd5ec96f4886270eac 100644 (file)
@@ -48,16 +48,21 @@ BC_Hash::BC_Hash(const char *filename)
        FileSystem directory;
 
        directory.parse_tildas(this->filename);
-       total = 0;
 }
 
-BC_Hash::~BC_Hash()
+void BC_Hash::clear()
 {
        for(int i = 0; i < total; i++)
        {
                delete [] names[i];
                delete [] values[i];
        }
+       total = 0;
+}
+
+BC_Hash::~BC_Hash()
+{
+       clear();
        delete [] names;
        delete [] values;
 }
@@ -317,19 +322,8 @@ varFn(int,update,const char *)     varFn(char *,get,char *)
 void BC_Hash::copy_from(BC_Hash *src)
 {
 // Can't delete because this is used by file decoders after plugins
-// request data.
-//     for(int i = 0; i < total; i++)
-//     {
-//             delete [] names[i];
-//             delete [] values[i];
-//     }
-//     delete [] names;
-//     delete [] values;
-//
-//     allocated = 0;
-//     names = 0;
-//     values = 0;
-//     total = 0;
+// request data.  use explicit destructor to clear/clean
+//     this->~BC_Hash();
 
 SET_TRACE
        reallocate_table(src->total);
index a694f42405b9fbfa8972a56c73ea1209f6dee95d..36c4a4a3f7aaf8a6b9e1e27e4875f4f9e33dc1eb 100644 (file)
@@ -81,6 +81,7 @@ public:
        int size();
        char* get_key(int number);
        char* get_value(int number);
+       void clear();
 
 private:
 // Reallocate table so at least total entries exist
index e3f5bf0a9e668cd1ac401658d6f7e7f492bc2c7a..99746eb874b7ee3719e29a8613e5f392a94b512c 100644 (file)
@@ -1215,8 +1215,7 @@ void VFrame::clear_stacks()
 {
        next_effects.remove_all_objects();
        prev_effects.remove_all_objects();
-       delete params;
-       params = new BC_Hash;
+       params->clear();
 }
 
 void VFrame::copy_params(VFrame *src)
@@ -1241,7 +1240,7 @@ void VFrame::copy_stacks(VFrame *src)
                strcpy(ptr, src->prev_effects.values[i]);
        }
 
-       params->copy_from(src->params);
+       copy_params(src);
 }
 
 int VFrame::equal_stacks(VFrame *src)
index 1d210846c164ac3dd9b024ac2247f548fd73c63f..53578de56a3630fff240e42f2b2659917535dabe 100644 (file)
@@ -53,7 +53,6 @@ OBJ = \
 
 LIBS = \
        ../libzmpeg3/$(OBJDIR)/libzmpeg3.a \
-       $(thirdparty_libraries) $(static_libraries) \
        -lasound \
        -lpthread \
        -lpng \
@@ -64,7 +63,9 @@ LIBS = \
        -lbz2 \
        -lm \
        -ldl \
-       $(EXTRA_LIBS)
+
+LIBS += -Wl,--start-group $(thirdparty_libraries) -Wl,--end-group 
+LIBS += $(EXTRA_LIBS)
 
 HVEG2LIB = $(OBJDIR)/hveg2enc.a
 HVEG2ENC = $(OBJDIR)/hveg2enc
index 0d785e5ee71cf40d95f8a9d0119686e633ba36a7..aea639601e7b87c5628251e9881885ccea3af3d5 100644 (file)
@@ -1,3 +1,12 @@
+add ffmpeg filters as plugins
+fix nvidia gl lock problem, update active vwindow tests
+fix segv in formattools for record format ffmpeg
+add ffmpeg indexing
+upgrade to ffmpeg-2.8
+move aspect ratio fixex, better get_info, fixes for ffmpeg asset detection
+aspect ratio fixes for dvd/bd create, TZ fix
+remove old quicktime, replaced with current ffmpeg
+bunch of small fixes, add msg.txt to about prefs
 sync to last commit on google_code
 fixups for plugins interpolate, c41
 so long, Michael Niedermayer... and thanks for all the fish!!!