Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

ExportMJPEG Class Reference

This class represents the Export/Still Frames notebook page. More...

#include <page_export_mjpeg.h>

Inheritance diagram for ExportMJPEG:

Inheritance graph
[legend]
Collaboration diagram for ExportMJPEG:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ExportMJPEG (PageExport *, KinoCommon *)
 Constructor for page.
virtual ~ExportMJPEG ()
 Destructor for page.
void loadTools (string directory)
void activateTool (int tool)
void selectTool (int tool)

Private Member Functions

void start ()
 Empty methods - here for tracking during development.
gulong onActivate ()
 Define active widgets.
enum export_result doExport (PlayList *playlist, int begin, int end, int every, bool preview)
 start exporting MJPEG
void createAuthorXml (const char *filename, std::vector< std::string > &nameList, bool split, bool isPal)

Private Attributes

Preferencesprefs
GtkEntry * fileEntry
GtkMenu * mjpegFormat
GtkEntry * mjpegVideo
GtkEntry * mjpegAudio
GtkEntry * mjpegMultiplexer
GtkMenu * deinterlaceMenu
GtkToggleButton * splitCheck
GtkToggleButton * cleanupCheck
GtkMenu * mjpegAspect
GtkEntry * mjpegXMLScript
bool hasYuvDeinterlace
bool isAvailable
vector< DVDTool * > m_dvdTools

Detailed Description

This class represents the Export/Still Frames notebook page.

Definition at line 40 of file page_export_mjpeg.h.


Constructor & Destructor Documentation

ExportMJPEG::ExportMJPEG PageExport _exportPage,
KinoCommon _common
 

Constructor for page.

Parameters:
_exportPage page to which this page belongs
_common KinoCommon object

Definition at line 133 of file page_export_mjpeg.cc.

References activateTool(), cleanupCheck, Export::common, deinterlaceMenu, Preferences::exportMjpegAspect, Preferences::exportMjpegAudioPipe, Preferences::exportMjpegCleanup, Preferences::exportMjpegDeinterlace, Preferences::exportMjpegDvdTool, Preferences::exportMjpegFormat, Preferences::exportMjpegMultiplex, Preferences::exportMjpegSceneSplit, Preferences::exportMjpegVideoPipe, Export::exportPage, fileEntry, PageExport::getWidget(), KinoCommon::getWidget(), hasYuvDeinterlace, loadTools(), lookup_widget(), mjpegAspect, mjpegAudio, mjpegFormat, mjpegMultiplexer, mjpegVideo, on_optionmenu_export_mjpeg_format_changed(), prefs, and splitCheck.

00133                                                                        :
00134         Export( _exportPage, _common ),
00135         prefs( Preferences::getInstance() ),
00136         hasYuvDeinterlace( false ),
00137         isAvailable( true )
00138 {
00139     cerr << "> Creating ExportMJPEG Page" << endl;
00140 
00141     // Load the extensible dvdauthor tools
00142     loadTools( DATADIR "/kino/scripts/dvdauthor" );
00143     string alternate_dir = string( getenv( "HOME" ) ) + string( "/kino/dvdauthor" );
00144     loadTools( alternate_dir );
00145 
00146     char *kinoHome=getenv("KINO_HOME");
00147 
00148     if(kinoHome)
00149     {
00150         string alternate_dir = string( kinoHome ) + string( "/dvdauthor" );
00151         loadTools( alternate_dir );
00152     }
00153 
00154     activateTool( prefs.exportMjpegDvdTool );
00155 
00156     /* Get pointers to own controls */
00157     fileEntry
00158     = GTK_ENTRY( lookup_widget( common->getWidget(), "entry_export_mjpeg_file" ) );
00159 
00160     mjpegFormat
00161     = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( exportPage->getWidget(),
00162                                           "optionmenu_export_mjpeg_format" ) ) ) );
00163     deinterlaceMenu
00164     = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( common->getWidget(),
00165                                           "optionmenu_export_mjpeg_deinterlace" ) ) ) );
00166     mjpegVideo
00167     = GTK_ENTRY( lookup_widget( exportPage->getWidget(),
00168                                 "entry_mjpeg_video" ) );
00169     mjpegAudio
00170     = GTK_ENTRY( lookup_widget( exportPage->getWidget(),
00171                                 "entry_mjpeg_audio" ) );
00172     mjpegMultiplexer
00173     = GTK_ENTRY( lookup_widget( exportPage->getWidget(),
00174                                 "entry_mjpeg_multiplexer" ) );
00175     splitCheck
00176     = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(),
00177                                         "checkbutton_export_mjpeg_split" ) );
00178     cleanupCheck
00179     = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(),
00180                     "checkbutton_export_mjpeg_cleanup" ) );
00181     mjpegAspect
00182     = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( exportPage->getWidget(),
00183                                           "optionmenu_export_aspect_ratio" ) ) ) );
00184 
00185     cerr << "> Initializing MJPEG Export Page settings from Preferences" << endl;
00186     gtk_option_menu_set_history( GTK_OPTION_MENU( lookup_widget( exportPage->getWidget(),
00187                                 "optionmenu_export_mjpeg_format" ) ), prefs.exportMjpegFormat );
00188     GtkWidget* vbox = lookup_widget( GTK_WIDGET( exportPage->getWidget() ), "vbox_export_mjpeg_dvd_options" );
00189     if ( prefs.exportMjpegFormat == 6 )
00190         gtk_widget_show( vbox );
00191     else
00192         gtk_widget_hide( vbox );
00193     gtk_option_menu_set_history( GTK_OPTION_MENU( lookup_widget( exportPage->getWidget(),
00194                                 "optionmenu_export_mjpeg_deinterlace" ) ), prefs.exportMjpegDeinterlace );
00195     gtk_option_menu_set_history( GTK_OPTION_MENU( lookup_widget( exportPage->getWidget(),
00196                                 "optionmenu_export_aspect_ratio" ) ) , prefs.exportMjpegAspect );
00197     gtk_toggle_button_set_active( splitCheck, prefs.exportMjpegSceneSplit );
00198     gtk_toggle_button_set_active( cleanupCheck, prefs.exportMjpegCleanup );
00199     gtk_entry_set_text( mjpegVideo, prefs.exportMjpegVideoPipe );
00200     gtk_entry_set_text( mjpegAudio, prefs.exportMjpegAudioPipe );
00201     gtk_entry_set_text( mjpegMultiplexer, prefs.exportMjpegMultiplex );
00202 
00203     if ( system( "yuvdeinterlace -h 2> /dev/null" ) == 0 )
00204     {
00205         hasYuvDeinterlace = true;
00206         GtkWidget *widget = gtk_menu_item_new_with_label( _("YUV Deinterlace") );
00207         gtk_widget_show( widget );
00208         gtk_menu_append( deinterlaceMenu, widget );
00209         widget = gtk_menu_item_new_with_label( _("YUV Deinterlace Film-like") );
00210         gtk_widget_show( widget );
00211         gtk_menu_append( deinterlaceMenu, widget );
00212     }
00213     else if ( system( "yuvdenoise -h 2> /dev/null" ) == 0 )
00214     {
00215         GtkWidget *widget = gtk_menu_item_new_with_label( _("YUV Denoise (Fast)") );
00216         gtk_widget_show( widget );
00217         gtk_menu_append( deinterlaceMenu, widget );
00218         widget = gtk_menu_item_new_with_label( _("YUV Denoise (Slow)") );
00219         gtk_widget_show( widget );
00220         gtk_menu_append( deinterlaceMenu, widget );
00221     }
00222     gtk_option_menu_set_menu( GTK_OPTION_MENU( lookup_widget( common->getWidget(),
00223         "optionmenu_export_mjpeg_deinterlace" ) ), GTK_WIDGET( deinterlaceMenu ) );
00224     g_signal_connect ( G_OBJECT( lookup_widget( common->getWidget(),
00225         "optionmenu_export_mjpeg_format" ) ), "changed",
00226         G_CALLBACK ( on_optionmenu_export_mjpeg_format_changed ), this );
00227 }

ExportMJPEG::~ExportMJPEG  )  [virtual]
 

Destructor for page.

Definition at line 232 of file page_export_mjpeg.cc.

00233 {
00234     cerr << "> Destroying ExportMJPEG Page" << endl;
00235 }


Member Function Documentation

void ExportMJPEG::activateTool int  tool  ) 
 

Definition at line 823 of file page_export_mjpeg.cc.

References Export::common, KinoCommon::getWidget(), lookup_widget(), and m_dvdTools.

Referenced by ExportMJPEG().

00824 {
00825     // Get the main widget
00826     GtkWidget * window = common->getWidget();
00827 
00828     // Start with the option menu
00829     GtkOptionMenu *option_menu = GTK_OPTION_MENU( lookup_widget( window, "optionmenu_dvd_tools" ) );
00830     GtkMenu *menu = GTK_MENU( gtk_option_menu_get_menu( option_menu ) );
00831 
00832     // Create a menu if we don't have one
00833     if ( menu )
00834     {
00835         menu = GTK_MENU( gtk_menu_new( ) );
00836         // Create a "None" menu item
00837         GtkWidget *item = gtk_menu_item_new_with_label( _("None") );
00838         gtk_widget_show( item );
00839         gtk_menu_append( menu, item );
00840         // Creat the other menu items
00841         for ( unsigned int i = 0; i < m_dvdTools.size( ); i ++ )
00842         {
00843             GtkWidget *item = gtk_menu_item_new_with_label( m_dvdTools[ i ] ->m_description.c_str( ) );
00844             gtk_widget_show( item );
00845             gtk_menu_append( menu, item );
00846         }
00847 
00848         gtk_option_menu_set_menu( option_menu, GTK_WIDGET( menu ) );
00849     }
00850 
00851     // Set the active item
00852     gtk_option_menu_set_history( option_menu, index );
00853 }

void ExportMJPEG::createAuthorXml const char *  filename,
std::vector< std::string > &  nameList,
bool  split,
bool  isPal
[private]
 

Definition at line 713 of file page_export_mjpeg.cc.

References Export::common, KinoCommon::getPageEditor(), KinoCommon::getTime(), and SMIL::Time::TIME_FORMAT_CLOCK.

Referenced by doExport().

00716 {
00717     if( filename == NULL )
00718     {
00719       std::cerr << ">>> ExportMJPEG::createAuthorXml (file name null)" << std::endl;
00720       return;
00721     }
00722 
00723     char filenameBuffer[512];
00724 
00725     snprintf( filenameBuffer, sizeof( filenameBuffer ), "%s-dvdauthor.xml", filename );
00726 
00727     std::cerr << ">>> ExportMJPEG::createAuthorXml (filename: " << filenameBuffer << ")" << std::endl;
00728 
00729     std::stringstream xml;
00730 
00731     xml << "<?xml version=\"1.0\"?>" << std::endl;
00732     xml << "<dvdauthor>" << std::endl;
00733 
00734     xml << "\t<vmgm>" << std::endl;
00735     xml << "\t\t<menus>" << std::endl;
00736     xml << "\t\t\t<video />" << std::endl;
00737     xml << "\t\t\t<audio />" << std::endl;
00738     xml << "\t\t\t<subpicture lang=\"en\" />" << std::endl;
00739     xml << "\t\t</menus>" << std::endl;
00740     xml << "\t</vmgm>" << std::endl;
00741 
00742     xml << "\t<titleset>" << std::endl;
00743     xml << "\t\t<titles>" << std::endl;
00744     xml << "\t\t\t<pgc pause=\"0\">" << std::endl;
00745 
00746     std::vector<std::string>::iterator iter = nameList.begin();
00747 
00748     if( split == true )
00749     {
00750         /* output the list list of vobs */
00751         while( iter != nameList.end() )
00752         {
00753             xml << "\t\t\t\t<vob file=\"" << *iter << "\" chapters=\"\" pause=\"0\" />" << std::endl;
00754             iter++;
00755         }
00756     }
00757     else
00758     {
00759         /* retrieve the vector of scenes, assuming that the vector
00760          * doesn't have the 0 entry.
00761          */
00762         std::vector<int> sceneStarts = this->common->getPageEditor()->GetScene();
00763         std::vector<int>::iterator sceneIter = sceneStarts.begin();
00764         std::stringstream chapterList;
00765 
00766         chapterList << "0";
00767 
00768         for( sceneIter = sceneStarts.begin(); sceneIter != sceneStarts.end() - 1; ++sceneIter )
00769             chapterList << "," << this->common->getTime().parseFramesToString( *sceneIter, SMIL::Time::TIME_FORMAT_CLOCK );
00770 
00771         /* output the single vob, checking for chapter marks */
00772         xml << "\t\t\t\t<vob file=\"" << *iter << "\" chapters=\"" <<
00773         chapterList.str() << "\" pause=\"0\" />" << std::endl;
00774     }
00775 
00776     xml << "\t\t\t</pgc>" << std::endl;
00777     xml << "\t\t</titles>" << std::endl;
00778     xml << "\t</titleset>" <<std::endl;
00779 
00780     xml << "</dvdauthor>" << std::endl;
00781 
00782     std::cerr << xml.str() << std::endl;
00783 
00784     std::ofstream out( filenameBuffer );
00785 
00786     if( out.is_open() == true )
00787     {
00788         out << xml.str();
00789         out.flush();
00790     }
00791 
00792     out.close(); 
00793 }

enum export_result ExportMJPEG::doExport PlayList playlist,
int  begin,
int  end,
int  every,
bool  preview
[private, virtual]
 

start exporting MJPEG

Implements Export.

Definition at line 290 of file page_export_mjpeg.cc.

References AUDIO_RESAMPLE_SRC_SINC_BEST_QUALITY, Export::calculateAdjustedRate(), cleanupCheck, DVDTool::close(), KinoAVPipe::CloseAudio(), KinoAVPipe::CloseVideo(), Export::common, KinoAudioFactory::CreateAudioPipe(), createAuthorXml(), KinoVideoFactory::CreateVideoPipe(), deinterlaceMenu, DVDTool::execute(), KinoAVPipe::ExecuteCommand(), EXPORT_RESULT_ABORT, EXPORT_RESULT_FAILURE, EXPORT_RESULT_SUCCESS, Preferences::exportMjpegAspect, Preferences::exportMjpegAudioPipe, Preferences::exportMjpegCleanup, Preferences::exportMjpegDeinterlace, Preferences::exportMjpegDvdTool, Preferences::exportMjpegFormat, Preferences::exportMjpegMultiplex, Preferences::exportMjpegSceneSplit, Preferences::exportMjpegVideoPipe, Export::exportPage, fileEntry, FRAME_MAX_HEIGHT, FRAME_MAX_WIDTH, Frame::GetAudioInfo(), AsyncAudioResample< input_t, output_t >::GetError(), GetFramePool(), AsyncAudioResample< input_t, output_t >::GetOutput(), KinoCommon::getWidget(), hasYuvDeinterlace, info, Export::innerLoopUpdate(), AsyncAudioResample< input_t, output_t >::IsError(), PageExport::isExporting, Frame::IsPAL(), lookup_widget(), m_dvdTools, mjpegAspect, mjpegAudio, mjpegFormat, mjpegMultiplexer, mjpegVideo, modal_message(), KinoAVPipe::OpenAudio(), KinoAVPipe::OpenVideoPipe(), KinoAVPipe::OutputAudioFrame(), KinoAVPipe::OutputVideoFrame(), PIPE_AUDIO_WAV, PIPE_VIDEO_DEINTERLACED_MJPEG, PIPE_VIDEO_MJPEG, pixels, prefs, AsyncAudioResample< input_t, output_t >::Process(), and splitCheck.

00292 {
00293     cerr << ">>> ExportMJPEG::startExport" << endl;
00294 
00295     // Set defaults on own controls
00296     prefs.exportMjpegFormat = g_list_index ( GTK_MENU_SHELL ( mjpegFormat ) ->children, gtk_menu_get_active( mjpegFormat ) );
00297     prefs.exportMjpegDeinterlace = g_list_index ( GTK_MENU_SHELL ( deinterlaceMenu ) ->children, gtk_menu_get_active( deinterlaceMenu ) );
00298     prefs.exportMjpegAspect = g_list_index ( GTK_MENU_SHELL ( mjpegAspect ) ->children, gtk_menu_get_active( mjpegAspect ) );
00299     prefs.exportMjpegSceneSplit = gtk_toggle_button_get_active( splitCheck );
00300     prefs.exportMjpegCleanup = gtk_toggle_button_get_active( cleanupCheck );
00301     GtkWidget* widget = lookup_widget( common->getWidget(), "optionmenu_dvd_tools" );
00302     widget = gtk_option_menu_get_menu( GTK_OPTION_MENU( widget ) );
00303     prefs.exportMjpegDvdTool = g_list_index ( GTK_MENU_SHELL( widget )->children, gtk_menu_get_active( GTK_MENU( widget ) ) );
00304 
00305     // TODO: Fix this buffer stuff.
00306     gchar *filename;
00307     enum export_result status = EXPORT_RESULT_SUCCESS;
00308 
00309     filename = g_strdup( gtk_entry_get_text( fileEntry ) );
00310 
00311     if ( !( strcmp( filename, "" ) && strpbrk( filename, "\'" ) == NULL ) )
00312     {
00313         modal_message( _( "You must enter a filename which doesn't contain quotes." ) );
00314         g_free( filename );
00315         return EXPORT_RESULT_FAILURE;
00316     }
00317     unsigned char *pixels = new unsigned char[ FRAME_MAX_WIDTH * FRAME_MAX_HEIGHT * 4 ];
00318     Frame* frame = GetFramePool()->GetFrame();
00319 
00320     // Get a sample frame to obtain recording info
00321     // TODO: Sample frames are problematic...
00322     playlist->GetFrame( begin, *frame );
00323     frame->decoder->quality = DV_QUALITY_BEST;
00324 
00325     // Get all video and audio info required
00326     int width = frame->GetWidth();
00327     int height = frame->GetHeight();
00328     bool isPAL = frame->IsPAL();
00329     bool isWide = frame->IsWide();
00330     AudioInfo info;
00331     frame->GetAudioInfo( info );
00332     short channels = info.channels;
00333     int frequency = info.frequency;
00334 
00335     // vars for collecting audio and video pipe commands
00336     bool split = false;
00337     bool author = false;
00338     bool Usercleanup = true;
00339     kino_video_pipe type = PIPE_VIDEO_MJPEG;
00340     gchar *audiopipe = NULL;
00341     gchar *videopipe = NULL;
00342     gchar *multiplex = NULL;
00343     gchar *cleanup = NULL;
00344 
00345     // list to collect the names of the generated mpeg2 files
00346     // this collection only proceeds if we are authoring an
00347     // xml file for use with dvdauthor
00348     std::vector<std::string> nameList;
00349 
00350     // MPEG and DIVX translations to commands
00351     // What started off as a simple addition is getting pretty damn messy :-/ - ho hum
00352     // Essentially the important things to remember are that only the 5 variables above
00353     // are populated in the following kludge... (this should move into seprate methods)
00354     const char *videopipeInput = "";
00355     int videoformat = 0;
00356     int deinterlaceRequest = 0;
00357     const char *audioencode = "";
00358     const char *multiplexer = "";
00359     int aspectRatio = 0;
00360     bool isY4Minterlaced = true;
00361 
00362     videopipeInput = gtk_entry_get_text( mjpegVideo );
00363     strncpy( prefs.exportMjpegVideoPipe, videopipeInput, sizeof(prefs.exportMjpegVideoPipe) );
00364     GtkWidget *active_item = gtk_menu_get_active( mjpegFormat );
00365     videoformat = g_list_index ( GTK_MENU_SHELL ( mjpegFormat ) ->children, active_item );
00366     audioencode = gtk_entry_get_text( mjpegAudio );
00367     strncpy( prefs.exportMjpegAudioPipe, audioencode, sizeof(prefs.exportMjpegAudioPipe) );
00368     multiplexer = gtk_entry_get_text( mjpegMultiplexer );
00369     strncpy( prefs.exportMjpegMultiplex, multiplexer, sizeof(prefs.exportMjpegMultiplex) );
00370     active_item = gtk_menu_get_active( deinterlaceMenu );
00371     deinterlaceRequest = g_list_index ( GTK_MENU_SHELL ( deinterlaceMenu ) ->children, active_item );
00372     split = gtk_toggle_button_get_active( splitCheck );
00373     Usercleanup = gtk_toggle_button_get_active( cleanupCheck );
00374     /* only necessary to check this option if we are creating DVD video */
00375     if( videoformat == 6 )
00376     {
00377         // Tool 0 is always "None"
00378         author = prefs.exportMjpegDvdTool > 0;
00379     }
00380     active_item = gtk_menu_get_active( mjpegAspect );
00381     aspectRatio = g_list_index ( GTK_MENU_SHELL ( mjpegAspect ) ->children, active_item );
00382     
00383     /* force deinterlace on MPEG-1 formats if not specified by user */
00384     if ( videoformat < 3 && deinterlaceRequest == 0 )
00385         deinterlaceRequest = 3;
00386 
00387     char deinterlace[ 30 ] = "";
00388     char interlace = '0';
00389     char audioOptions[ 20 ] = "";
00390 
00391     switch ( deinterlaceRequest )
00392     {
00393     case 0: // None
00394         interlace = '1';
00395         break;
00396     case 1: // Internal
00397         type = PIPE_VIDEO_DEINTERLACED_MJPEG;
00398         isY4Minterlaced = false;
00399         break;
00400     case 2: // Already deinterlaced
00401         isY4Minterlaced = false;
00402         break;
00403     case 3:
00404         strcpy( deinterlace, hasYuvDeinterlace ? "yuvdeinterlace |" : "yuvdenoise -F -f |" );
00405         break;
00406     case 4:
00407         strcpy( deinterlace, hasYuvDeinterlace ? "yuvdeinterlace -f |" : "yuvdenoise -F |" );
00408         break;
00409     }
00410 
00411     if ( !strstr( videopipeInput, "yuvscaler" ) )
00412     {
00413         char scale[ 20 ] = "";
00414         char bitrate[ 20 ] = "";
00415 
00416         switch ( videoformat )
00417         {
00418         case 1:
00419             strcpy( scale, "VCD" );
00420             frequency = 44100;
00421             if ( strstr( audioencode, "ffmpeg" ) )
00422                 strcpy( audioOptions, "-ar 44100" );
00423             else if ( strstr( audioencode, "mp2enc" ) )
00424                 strcpy( audioOptions, "-r 44100" );
00425             break;
00426         case 2:
00427             strcpy( scale, "VCD" );
00428             strcpy( bitrate, "-b 1152" );
00429             frequency = 44100;
00430             if ( strstr( audioencode, "ffmpeg" ) )
00431                 strcpy( audioOptions, "-ar 44100" );
00432             else if ( strstr( audioencode, "mp2enc" ) )
00433                 strcpy( audioOptions, "-r 44100" );
00434             break;
00435         case 3:
00436             strcpy( bitrate, "-b 4000" );
00437             break;
00438         case 4:
00439             strcpy( scale, "SVCD" );
00440             frequency = 44100;
00441             if ( strstr( audioencode, "ffmpeg" ) )
00442                 strcpy( audioOptions, "-ar 44100" );
00443             else if ( strstr( audioencode, "mp2enc" ) )
00444                 strcpy( audioOptions, "-r 44100" );
00445             break;
00446         case 5:
00447             strcpy( scale, "SVCD" );
00448             strcpy( bitrate, "-b 2500" );
00449             frequency = 44100;
00450             if ( strstr( audioencode, "ffmpeg" ) )
00451                 strcpy( audioOptions, "-ar 44100" );
00452             else if ( strstr( audioencode, "mp2enc" ) )
00453                 strcpy( audioOptions, "-r 44100" );
00454             break;
00455         case 6:
00456             videoformat = 8;
00457             strcpy( scale, "" );
00458             if ( strstr( audioencode, "ffmpeg" ) )
00459             {
00460                 frequency = 48000;
00461                 if ( !strstr( audioencode, " -ab " ) )
00462                     sprintf( audioOptions, "%s -ab 192", audioOptions );
00463             }
00464             else if ( strstr( audioencode, "mp2enc" ) )
00465             {
00466                 if ( !strstr( audioencode, " -r " ) )
00467                     sprintf( audioOptions, "%s -r 48000", audioOptions );
00468                 frequency = 48000;
00469                 if ( !strstr( audioencode, " -b " ) )
00470                     sprintf( audioOptions, "%s -b 224", audioOptions );
00471             }
00472             break;
00473         }
00474 
00475         // If the bitrate is specified then remove the defaults above
00476         if ( strstr( videopipeInput, " -b " ) || strstr( videopipeInput, "--video-bitrate" ) )
00477             strcpy( bitrate, "" );
00478 
00479         // Yuck (!) - builds the video pipe depending on data collected above...
00480         if ( strcmp( scale, "" ) )
00481             videopipe = g_strdup_printf(
00482                      "%s yuvscaler -v 0 -O %s -n %c | %s -f %d -I %c -n %c -a %d %s -o \'%s\'.mpv",
00483                      deinterlace,
00484                      scale, isPAL ? 'p' : 'n', videopipeInput, videoformat, interlace,
00485                      isPAL ? 'p' : 'n', aspectRatio ? aspectRatio : (isWide ? 3 : 2), bitrate, filename );
00486         else
00487             videopipe = g_strdup_printf( "%s %s -f %d -I %c -n %c -a %d %s -o \'%s\'.mpv",
00488                      deinterlace, videopipeInput, videoformat, interlace,
00489                      isPAL ? 'p' : 'n', aspectRatio ? aspectRatio : (isWide ? 3 : 2), bitrate, filename );
00490     }
00491     else
00492     {
00493         videopipe = g_strdup_printf( "%s %s -f %d -I %c -n %c -o \'%s\'.mpv\n",
00494                  deinterlace, videopipeInput, videoformat, interlace,
00495                  isPAL ? 'p' : 'n', filename );
00496     }
00497     if ( strstr( audioencode, "ffmpeg" ) )
00498     {
00499         audiopipe = g_strdup_printf( "|%s -f wav -i pipe: %s -y \'%s\'.%s", audioencode, audioOptions,
00500             filename, videoformat == 8 ? "ac3" : "mp2" );
00501         if ( strcmp( multiplexer, "" ) )
00502         {
00503             multiplex = g_strdup_printf( "%s -f %d -o \'%s\'%%s.mpeg \'%s\'.mpv \'%s\'.%s",
00504                     multiplexer, videoformat, filename, filename, filename,
00505                     videoformat == 8 ? "ac3" : "mp2" );
00506             cleanup = g_strdup_printf( "rm -f \'%s\'.mpv \'%s\'.%s \'%s\'.wav",
00507                     filename, filename, videoformat == 8 ? "ac3" : "mp2", filename );
00508         }
00509     }
00510     else if ( strstr( audioencode, "mp2enc" ) )
00511     {
00512         audiopipe = g_strdup_printf( "|%s %s -o \'%s\'.mp2", audioencode, audioOptions, filename );
00513         if ( strcmp( multiplexer, "" ) )
00514         {
00515             multiplex = g_strdup_printf( "%s -f %d -o \'%s\'%%s.mpeg \'%s\'.mpv \'%s\'.mp2",
00516                     multiplexer, videoformat, filename, filename, filename );
00517             cleanup = g_strdup_printf( "rm -f \'%s\'.mpv \'%s\'.mp2 \'%s\'.wav",
00518                     filename, filename, filename );
00519         }
00520     }
00521 
00522     KinoAudioPipe *wav = KinoAudioFactory::CreateAudioPipe( PIPE_AUDIO_WAV );
00523     KinoVideoPipe *video = KinoVideoFactory::CreateVideoPipe( type );
00524     KinoAVPipe *mpeg = new KinoAVPipe( wav, video );
00525 
00526     // Iterate through each scene (opening and closing audio pipes as requested)
00527     int scene = 0;
00528 
00529     for ( int sceneBegin = begin; sceneBegin <= end && exportPage->isExporting;
00530             scene ++ )
00531     {
00532         gchar *full;
00533         char sceneString[ 20 ];
00534         int sceneEnd = end;
00535         bool userMplexSplit = ( multiplex != NULL && ( strstr( multiplex, "-S" ) || 
00536             strstr( multiplex, "--max-segment-size" ) ) );
00537 
00538         // Determine if we need to split by scene or not
00539         // when splitting: Output is generated as fileNNN_MMM.mpeg where NNN is the
00540         // kino scene number and MMM is the mplex split
00541         // when not splitting: Output is generated file as fileMMM.mpeg
00542         sceneString[0] = '\0';
00543         if ( split )
00544         {
00545             sprintf( sceneString, "%03d", scene );
00546             if ( userMplexSplit )
00547                 strcat( sceneString, "_%03d" );
00548             sceneEnd = playlist->FindEndOfScene( sceneBegin );
00549             if ( sceneEnd > end )
00550                 sceneEnd = end;
00551         }
00552         else if ( userMplexSplit )
00553         {
00554             strcpy( sceneString, "%03d" );
00555         }
00556 
00557         if ( author )
00558         {
00559             char tmpFilename[512];
00560 
00561             if ( split && userMplexSplit ) {
00562                 snprintf( tmpFilename, sizeof( tmpFilename ), "%s%03d_001.mpeg", filename, scene );
00563             } else if ( split ) {
00564                 snprintf( tmpFilename, sizeof( tmpFilename ), "%s%03d.mpeg", filename, scene );
00565             } else if ( userMplexSplit ) {
00566                 snprintf( tmpFilename, sizeof( tmpFilename ), "%s001.mpeg", filename );
00567             } else {
00568                 snprintf( tmpFilename, sizeof( tmpFilename ), "%s.mpeg", filename );
00569             }
00570 
00571             nameList.push_back( std::string( tmpFilename ) );
00572         }
00573 
00574         cerr << ">>> Generated video pipe '" << videopipe << "'" << endl;
00575         if ( audiopipe )
00576         {
00577             cerr << ">>> Generated audio pipe '" << audiopipe << "'" << endl;
00578             mpeg->OpenAudio( audiopipe, channels, frequency, 2 );
00579         }
00580         mpeg->OpenVideoPipe( videopipe, width, height, isY4Minterlaced );
00581 
00582         int imagesize = width * height * 3;
00583 
00584         // first call to innerLoopUpdate initializes progress tracker, which
00585         // we want to do because calculateAdjustedRate generates paused time.
00586         innerLoopUpdate( sceneBegin, begin, end, every );
00587 
00588         // Determine correct amount of audio for duration
00589         double adjustedRate = 0;
00590         AsyncAudioResample<int16_ne_t,int16_le_t>* resampler = 0;
00591         if ( audiopipe )
00592         {
00593             adjustedRate = calculateAdjustedRate( playlist, frequency, sceneBegin, sceneEnd, every );
00594             if ( !adjustedRate )
00595                 status = EXPORT_RESULT_ABORT;
00596 
00597             // Setup a resampler
00598             resampler = new AsyncAudioResample<int16_ne_t,int16_le_t>(
00599                 AUDIO_RESAMPLE_SRC_SINC_BEST_QUALITY, playlist, frequency, sceneBegin, sceneEnd, every );
00600             if ( resampler->IsError() )
00601             {
00602                 std::cerr << ">>> Resampler error: " << resampler->GetError() << std::endl;
00603                 exportPage->isExporting = false;
00604                 status = EXPORT_RESULT_FAILURE;
00605                 break;
00606             }
00607         }
00608 
00609         /* Iterate over frames in scene */
00610         for ( int i = sceneBegin, j = 0; i <= sceneEnd && exportPage->isExporting;
00611             i += every, j++ )
00612         {
00613             innerLoopUpdate( i, begin, end, every );
00614             playlist->GetFrame( i, *frame );
00615 
00616             if ( audiopipe && resampler )
00617             {
00618                 int requestedSamples = frame->CalculateNumberSamples( frequency, j );
00619                 int nsamples = resampler->Process( adjustedRate, requestedSamples );
00620                 if ( nsamples > 0 && !mpeg->OutputAudioFrame( reinterpret_cast<int16_t *>(resampler->GetOutput()), 
00621                     nsamples * channels * sizeof(int16_t) ) )
00622                 {
00623                     modal_message( _( "Error writing to KINO/MJPEG audio filter - aborting." ) );
00624                     status = EXPORT_RESULT_FAILURE;
00625                     break;
00626                 }
00627             }
00628 
00629             if ( exportPage->isExporting )
00630             {
00631                 if ( type == PIPE_VIDEO_MJPEG )
00632                     frame->ExtractYUV( pixels );
00633                 else
00634                     frame->ExtractRGB( pixels );
00635                 if ( !mpeg->OutputVideoFrame( pixels, imagesize ) )
00636                 {
00637                     modal_message( _( "Error writing to KINO/MJPEG video filter - aborting." ) );
00638                     status = EXPORT_RESULT_FAILURE;
00639                     break;
00640                 }
00641             }
00642         }
00643 
00644         if ( status == EXPORT_RESULT_SUCCESS && !exportPage->isExporting )
00645             status = EXPORT_RESULT_ABORT;
00646 
00647         if ( !split )
00648             exportPage->isExporting = false;
00649 
00650         // Try to finish the stream to create a valid mpeg if possible
00651         if ( audiopipe )
00652             mpeg->CloseAudio();
00653         mpeg->CloseVideo();
00654         delete resampler;
00655         resampler = 0;
00656 
00657         if ( status == EXPORT_RESULT_SUCCESS && multiplex != NULL && strcmp( multiplex, "" ) )
00658         {
00659             // expand the template to accomodate the scene splits
00660             full = g_strdup_printf( multiplex, sceneString );
00661             cerr << ">>> Executing '" << full << "'" << endl;
00662             if ( 0 != mpeg->ExecuteCommand( full ) )
00663             {
00664                 // If mplex error, use user setting
00665                 //do_cleanup = Usercleanup;
00666             }
00667             g_free( full );
00668         }
00669 
00670         if ( Usercleanup && cleanup != NULL && strcmp( cleanup, "" ) )
00671             mpeg->ExecuteCommand( cleanup );
00672         
00673         // Move to start of next scene
00674         sceneBegin = sceneEnd + 1;
00675     }
00676 
00677     if ( status == EXPORT_RESULT_SUCCESS && author )
00678     {
00679         createAuthorXml( filename, nameList, split, isPAL );
00680 
00681         // Run the selected tool
00682         // -1 to account for first "None" item
00683         DVDTool *tool = m_dvdTools[ prefs.exportMjpegDvdTool - 1 ];
00684         if ( tool )
00685         {
00686             string dvdauthorFile( string( filename ) + "-dvdauthor.xml" );
00687             if ( tool->execute( dvdauthorFile, string( filename ) ) )
00688                 modal_message( _("The dvdauthor script failed, but the MPEG export succeeded.") );
00689             tool->close();
00690         }
00691     }
00692 
00693     g_free( filename );
00694     g_free( audiopipe );
00695     g_free( videopipe );
00696     g_free( multiplex );
00697     g_free( cleanup );
00698     delete mpeg;
00699     delete video;
00700     delete wav;
00701     delete[] pixels;
00702 
00703     GetFramePool()->DoneWithFrame( frame );
00704     
00705     return status;
00706 }

void ExportMJPEG::loadTools string  directory  ) 
 

Definition at line 795 of file page_export_mjpeg.cc.

References DVDTool::compare(), DVDTool::m_active, and m_dvdTools.

Referenced by ExportMJPEG().

00796 {
00797     char * filename;
00798     struct dirent *entry;
00799 
00800     DIR *dir = opendir( directory.c_str( ) );
00801 
00802     if ( dir )
00803     {
00804         while ( ( entry = readdir( dir ) ) != NULL )
00805         {
00806             filename = g_strdup_printf( "%s/%s", directory.c_str( ), entry->d_name );
00807             if ( entry->d_name[ 0 ] != '.' )
00808             {
00809                 fprintf( stderr, "%s\n", filename );
00810                 DVDTool *tool = new DVDTool( filename );
00811                 if ( tool->m_active )
00812                     m_dvdTools.push_back( tool );
00813                 else
00814                     delete tool;
00815             }
00816             g_free( filename );
00817         }
00818         closedir( dir );
00819     }
00820     std::sort( m_dvdTools.begin(), m_dvdTools.end(), DVDTool::compare );
00821 }

gulong ExportMJPEG::onActivate  )  [private, virtual]
 

Define active widgets.

If mjpegtools are not installed, do not support any common functions.

Reimplemented from Export.

Definition at line 280 of file page_export_mjpeg.cc.

References EXPORT_EXPORT, EXPORT_PAUSE, EXPORT_SCENE_LIST, and isAvailable.

00281 {
00282     if ( isAvailable )
00283         return EXPORT_EXPORT | EXPORT_PAUSE | EXPORT_SCENE_LIST;
00284     return 0;
00285 }

void ExportMJPEG::selectTool int  tool  ) 
 

void ExportMJPEG::start  )  [private, virtual]
 

Empty methods - here for tracking during development.

Reimplemented from Export.

Definition at line 237 of file page_export_mjpeg.cc.

References Export::common, Preferences::exportMjpegFormat, KinoCommon::getWidget(), isAvailable, lookup_widget(), prefs, and KinoCommon::setStatusBar().

00238 {
00239     // Show DVD options if applicable
00240     GtkWidget* vbox = lookup_widget(  common->getWidget(), "vbox_export_mjpeg_dvd_options" );
00241     if ( prefs.exportMjpegFormat == 6 )
00242         gtk_widget_show( vbox );
00243     else
00244         gtk_widget_hide( vbox );
00245     
00246     // Disable UI if mjpegtools not installed.
00247     vbox = lookup_widget(  common->getWidget(), "vbox_export_mjpeg" );
00248     const char* errorMessage = _( "Failed to execute %s. MPEG export requires a complete installation of mjpegtools." );
00249     if ( system( "which mpeg2enc > /dev/null 2> /dev/null" ) )
00250     {
00251         gtk_widget_set_sensitive( vbox, FALSE );
00252         common->setStatusBar( errorMessage, "mpeg2enc" );
00253         isAvailable = false;
00254         return;
00255     }
00256     if ( system( "which mp2enc > /dev/null 2> /dev/null" ) )
00257     {
00258         gtk_widget_set_sensitive( vbox, FALSE );
00259         common->setStatusBar( errorMessage, "mp2enc" );
00260         isAvailable = false;
00261         return;
00262     }
00263     if ( system( "which mplex > /dev/null 2> /dev/null" ) )
00264     {
00265         gtk_widget_set_sensitive( vbox, FALSE );
00266         common->setStatusBar( errorMessage, "mplex" );
00267         isAvailable = false;
00268         return;
00269     }
00270     
00271     // Otherwise, enable UI
00272     isAvailable = true;
00273     gtk_widget_set_sensitive( vbox, TRUE );
00274 }


Member Data Documentation

GtkToggleButton* ExportMJPEG::cleanupCheck [private]
 

Definition at line 53 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkMenu* ExportMJPEG::deinterlaceMenu [private]
 

Definition at line 51 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkEntry* ExportMJPEG::fileEntry [private]
 

Definition at line 44 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

bool ExportMJPEG::hasYuvDeinterlace [private]
 

Definition at line 56 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

bool ExportMJPEG::isAvailable [private]
 

Definition at line 57 of file page_export_mjpeg.h.

Referenced by onActivate(), and start().

vector< DVDTool * > ExportMJPEG::m_dvdTools [private]
 

Definition at line 58 of file page_export_mjpeg.h.

Referenced by activateTool(), doExport(), and loadTools().

GtkMenu* ExportMJPEG::mjpegAspect [private]
 

Definition at line 54 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkEntry* ExportMJPEG::mjpegAudio [private]
 

Definition at line 49 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkMenu* ExportMJPEG::mjpegFormat [private]
 

Definition at line 47 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkEntry* ExportMJPEG::mjpegMultiplexer [private]
 

Definition at line 50 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkEntry* ExportMJPEG::mjpegVideo [private]
 

Definition at line 48 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().

GtkEntry* ExportMJPEG::mjpegXMLScript [private]
 

Definition at line 55 of file page_export_mjpeg.h.

Preferences& ExportMJPEG::prefs [private]
 

Definition at line 43 of file page_export_mjpeg.h.

Referenced by doExport(), ExportMJPEG(), and start().

GtkToggleButton* ExportMJPEG::splitCheck [private]
 

Definition at line 52 of file page_export_mjpeg.h.

Referenced by doExport(), and ExportMJPEG().


The documentation for this class was generated from the following files:
Generated on Sun Mar 11 22:12:52 2007 for Kino by  doxygen 1.4.2