00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025 #include <algorithm>
00026 #include <fstream>
00027 #include <iostream>
00028 #include <iomanip>
00029 #include <vector>
00030 #include <sstream>
00031 using std::cerr;
00032 using std::endl;
00033
00034 #include <gtk/gtk.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <sys/types.h>
00039 #include <dirent.h>
00040
00041 #include "page_export_mjpeg.h"
00042 #include "kino_av_pipe.h"
00043 #include "preferences.h"
00044 #include "kino_common.h"
00045 #include "frame.h"
00046 #include "page_editor.h"
00047 #include "message.h"
00048 #include "rwpipe.h"
00049
00050 static void
00051 on_optionmenu_export_mjpeg_format_changed( GtkOptionMenu *widget, gpointer user_data )
00052 {
00053 int i = gtk_option_menu_get_history( widget );
00054 GtkWidget* vbox = lookup_widget( GTK_WIDGET( widget ), "vbox_export_mjpeg_dvd_options" );
00055 if ( i == 6 )
00056 gtk_widget_show( vbox );
00057 else
00058 gtk_widget_hide( vbox );
00059 }
00060
00061 class DVDTool : protected RWPipe
00062 {
00063 public:
00064 string m_command;
00065 string m_description;
00066 bool m_active;
00067
00068 DVDTool( string command ) :
00069 m_command( command ),
00070 m_description( "" ),
00071 m_active( false )
00072 {
00073 load( command );
00074 }
00075
00076 void load( string command )
00077 {
00078 if ( run( command ) )
00079 {
00080 char temp[ 10240 ];
00081 while ( readLine( temp, 10240 ) > 0 )
00082 {
00083 char * ptr = strchr( temp, ':' );
00084 if ( ptr != NULL )
00085 {
00086 *ptr = '\0';
00087 ptr += 2;
00088
00089 if ( !strcmp( temp, "Title" ) )
00090 m_description = ptr;
00091 else if ( !strcmp( temp, "Status" ) )
00092 m_active = !strcmp( ptr, "Active" );
00093 else
00094 fprintf( stderr, "Unrecognised %s: %s\n", temp, ptr );
00095 }
00096 }
00097 stop( );
00098 }
00099 }
00100
00101 bool execute( const string& dvdauthorFile, const string& outputDirectory )
00102 {
00103 gchar *command;
00104 bool result;
00105
00106
00107 command = g_strdup_printf( "\"%s\" \"%s\" \"%s\"", m_command.c_str( ),
00108 dvdauthorFile.c_str( ), outputDirectory.c_str() );
00109
00110 result = system( command );
00111 g_free( command );
00112 return result;
00113 }
00114
00115 void close( )
00116 {
00117 stop( );
00118 }
00119
00120 static bool compare( const DVDTool* x, const DVDTool* y )
00121 {
00122 return ( x->m_description < y->m_description );
00123 }
00124 };
00125
00126
00133 ExportMJPEG::ExportMJPEG( PageExport *_exportPage, KinoCommon *_common ) :
00134 Export( _exportPage, _common ),
00135 prefs( Preferences::getInstance() ),
00136 hasYuvDeinterlace( false ),
00137 isAvailable( true )
00138 {
00139 cerr << "> Creating ExportMJPEG Page" << endl;
00140
00141
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
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 }
00228
00232 ExportMJPEG::~ExportMJPEG()
00233 {
00234 cerr << "> Destroying ExportMJPEG Page" << endl;
00235 }
00236
00237 void ExportMJPEG::start()
00238 {
00239
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
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
00272 isAvailable = true;
00273 gtk_widget_set_sensitive( vbox, TRUE );
00274 }
00275
00280 gulong ExportMJPEG::onActivate()
00281 {
00282 if ( isAvailable )
00283 return EXPORT_EXPORT | EXPORT_PAUSE | EXPORT_SCENE_LIST;
00284 return 0;
00285 }
00286
00289 enum export_result
00290 ExportMJPEG::doExport( PlayList * playlist, int begin, int end, int every,
00291 bool preview )
00292 {
00293 cerr << ">>> ExportMJPEG::startExport" << endl;
00294
00295
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
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
00321
00322 playlist->GetFrame( begin, *frame );
00323 frame->decoder->quality = DV_QUALITY_BEST;
00324
00325
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
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
00346
00347
00348 std::vector<std::string> nameList;
00349
00350
00351
00352
00353
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
00375 if( videoformat == 6 )
00376 {
00377
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
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:
00394 interlace = '1';
00395 break;
00396 case 1:
00397 type = PIPE_VIDEO_DEINTERLACED_MJPEG;
00398 isY4Minterlaced = false;
00399 break;
00400 case 2:
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
00476 if ( strstr( videopipeInput, " -b " ) || strstr( videopipeInput, "--video-bitrate" ) )
00477 strcpy( bitrate, "" );
00478
00479
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
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
00539
00540
00541
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
00585
00586 innerLoopUpdate( sceneBegin, begin, end, every );
00587
00588
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
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
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
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
00660 full = g_strdup_printf( multiplex, sceneString );
00661 cerr << ">>> Executing '" << full << "'" << endl;
00662 if ( 0 != mpeg->ExecuteCommand( full ) )
00663 {
00664
00665
00666 }
00667 g_free( full );
00668 }
00669
00670 if ( Usercleanup && cleanup != NULL && strcmp( cleanup, "" ) )
00671 mpeg->ExecuteCommand( cleanup );
00672
00673
00674 sceneBegin = sceneEnd + 1;
00675 }
00676
00677 if ( status == EXPORT_RESULT_SUCCESS && author )
00678 {
00679 createAuthorXml( filename, nameList, split, isPAL );
00680
00681
00682
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 }
00707
00708
00709
00710
00711
00712 void
00713 ExportMJPEG::createAuthorXml( const char *filename,
00714 std::vector<std::string>& nameList,
00715 bool split, bool isPal )
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
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
00760
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
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 }
00794
00795 void ExportMJPEG::loadTools( string directory )
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 }
00822
00823 void ExportMJPEG::activateTool( int index )
00824 {
00825
00826 GtkWidget * window = common->getWidget();
00827
00828
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
00833 if ( menu )
00834 {
00835 menu = GTK_MENU( gtk_menu_new( ) );
00836
00837 GtkWidget *item = gtk_menu_item_new_with_label( _("None") );
00838 gtk_widget_show( item );
00839 gtk_menu_append( menu, item );
00840
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
00852 gtk_option_menu_set_history( option_menu, index );
00853 }
00854
00855
00856 extern "C"
00857 {
00858 void
00859 on_button_export_mjpeg_file_clicked (GtkButton *button,
00860 gpointer user_data)
00861 {
00862 const char *filename = common->getFileToSave( _("Enter a File Name to Save As") );
00863 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "entry_export_mjpeg_file" ) );
00864 if ( strcmp( filename, "" ) )
00865 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( button ), "entry_export_mjpeg_file" ) ), filename );
00866 }
00867 }