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

page_editor.cc File Reference

#include <iostream>
#include "page_editor.h"
#include "frame.h"
#include "commands.h"
#include "sys/time.h"
#include "pthread.h"
#include "message.h"
#include "filehandler.h"
#include "ieee1394io.h"
#include "gtkenhancedscale.h"
#include "callbacks.h"
#include "storyboard.h"
#include "support.h"

Include dependency graph for page_editor.cc:

Go to the source code of this file.

Defines

#define PLAYBACK_FRAMES   50

Functions

static int _getOneSecond (void)
static void resetThreads ()
static void * readThread (void *info)
 This function carries out the read ahead and is responsible for obtaining the each frame.
static void * audioThread (void *info)
static void * videoThread (void *info)
gboolean on_scrub_bar_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
gboolean on_scrub_bar_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
gboolean on_scrub_bar_value_changed_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)

Variables

KinoCommoncommon
navigate_control g_nav_ctl
char cmd [256] = { 0 }
char lastcmd [256] = { 0 }
static pthread_t readthread = 0
static pthread_t audiothread = 0
static pthread_t videothread = 0
static pthread_mutex_t threadlock = PTHREAD_MUTEX_INITIALIZER
static pthread_mutex_t readlock = PTHREAD_MUTEX_INITIALIZER
static int newFrame = 0
static int lastFrame = -1
static FrameframeContent [PLAYBACK_FRAMES]
IEEE1394Writerwriter1394 = NULL
static gboolean doScrub = FALSE
static int frameNumber [PLAYBACK_FRAMES]
static int pending = 0
static int head = -1
static int tail = -1
static bool playing = false
static bool showing = false


Define Documentation

#define PLAYBACK_FRAMES   50
 

Definition at line 65 of file page_editor.cc.

Referenced by audioThread(), PageTrim::clean(), PageEditor::clean(), readThread(), PageTrim::start(), and PageEditor::start().


Function Documentation

static int _getOneSecond void   )  [static]
 

Definition at line 1692 of file page_editor.cc.

References common, KinoCommon::g_currentFrame, GetFramePool(), KinoCommon::getPlayList(), and Frame::IsPAL().

Referenced by audioThread(), PageTrim::processCommand(), PageMagick::processCommand(), PageEditor::processCommand(), readThread(), PageTrim::videoShuttle(), and PageEditor::videoShuttle().

01693     {
01694         Frame & frame = *( GetFramePool() ->GetFrame( ) );
01695         common->getPlayList() ->GetFrame( common->g_currentFrame, frame );
01696         int value = ( frame.IsPAL() ? 25 : 30 );
01697         GetFramePool( ) ->DoneWithFrame( &frame );
01698         return value;
01699     }

static void * audioThread void *  info  )  [static]
 

Definition at line 1560 of file page_editor.cc.

References _getOneSecond(), navigate_control::active, Preferences::audioScrub, common, Preferences::dropFrame, Preferences::enableAudio, frameContent, KinoCommon::g_currentFrame, Preferences::getInstance(), KinoCommon::getPageEditor(), lastFrame, PLAYBACK_FRAMES, navigate_control::rate, navigate_control::step, and threadlock.

01561     {
01562 
01563         static Preferences & prefs = Preferences::getInstance();
01564         struct navigate_control *ctl = ( struct navigate_control * ) info;
01565         int lastFrame = common->g_currentFrame - 1;
01566         int time_per_frame = 1000000 / _getOneSecond( );
01567 
01568         // cerr << ">>> Starting audio thread" << endl;
01569 
01570         while ( ctl->active )
01571         {
01572             // Only do this when drop frames is active (otherwise the audio thread takes care of it)
01573             if ( prefs.dropFrame && prefs.enableAudio )
01574             {
01575                 // As long as its different to the previous one, then display it
01576                 if ( playing && pending > 0 )
01577                 {
01578                     // Play the audio
01579                     if ( prefs.enableAudio && ( frameNumber[ tail ] != lastFrame || ctl->rate > 1 || ctl->rate < -1 ) )
01580                     {
01581                         common->getPageEditor() ->getFrameDisplayer() ->PutSound( *frameContent[ tail ] );
01582                         if ( pending < 10 )
01583                         {
01584                             struct timespec t = { 0, 0 };
01585                             nanosleep( &t, NULL );
01586                         }
01587                     }
01588                     else if ( ctl->step == 0 && !prefs.audioScrub )
01589                     {
01590                         struct timespec t =
01591                             {
01592                                 0, time_per_frame * 1000
01593                             };
01594                         nanosleep( &t, NULL );
01595                     }
01596 
01597                     // Last encountered audio frame
01598                     lastFrame = frameNumber[ tail ];
01599 
01600                     // Move the tail
01601                     pthread_mutex_lock( &threadlock );
01602                     --pending;
01603                     tail = ( tail + 1 ) % PLAYBACK_FRAMES;;
01604                     pthread_mutex_unlock( &threadlock );
01605 
01606                     // Start showing frames from this point onwards
01607                     showing = true;
01608                 }
01609                 else
01610                 {
01611                     playing = false;
01612                     struct timespec t = { 0, 0 };
01613                     nanosleep( &t, NULL );
01614                 }
01615             }
01616             else
01617             {
01618                 // It is safe to cancel the audio thread here since a change to prefs necessitates a restart.
01619                 // cerr << ">>> Audio Thread not needed" << endl;
01620                 return NULL;
01621             }
01622         }
01623         // cerr << ">>> Ending audio thread" << endl;
01624 
01625         return NULL;
01626     }

gboolean on_scrub_bar_button_press_event GtkWidget *  widget,
GdkEventButton *  event,
gpointer  user_data
 

Definition at line 72 of file page_editor.cc.

References videoPause().

Referenced by PageEditor::PageEditor().

00075     {
00076         doScrub = TRUE;
00077         videoPause();
00078         return FALSE;
00079     }

gboolean on_scrub_bar_button_release_event GtkWidget *  widget,
GdkEventButton *  event,
gpointer  user_data
 

Definition at line 83 of file page_editor.cc.

Referenced by PageEditor::PageEditor().

00086     {
00087         doScrub = FALSE;
00088         return FALSE;
00089     }

gboolean on_scrub_bar_value_changed_event GtkWidget *  widget,
GdkEventButton *  event,
gpointer  user_data
 

Definition at line 92 of file page_editor.cc.

References moveToFrame().

Referenced by PageEditor::PageEditor().

00095     {
00096         if ( doScrub == TRUE )
00097             moveToFrame( ( int ) GTK_ADJUSTMENT( widget ) ->value );
00098         return FALSE;
00099     }

static void * readThread void *  info  )  [static]
 

This function carries out the read ahead and is responsible for obtaining the each frame.

audioThread monitors the queue (by checking mainly on pending) and plays the audio of each frame. videoThread picks up the last tail and displays it.

Note that only half of the queue is filled here - this provides the video thread some time to safely use a frame without worrying about it being overwritten.

Definition at line 1433 of file page_editor.cc.

References _getOneSecond(), navigate_control::active, common, countFrames(), Preferences::dropFrame, Preferences::enableAudio, frameContent, KinoCommon::g_currentFrame, Preferences::getInstance(), KinoCommon::getPageEditor(), KinoCommon::getPlayList(), lastFrame, newFrame, PLAYBACK_FRAMES, navigate_control::rate, readlock, IEEE1394Writer::SendFrame(), navigate_control::step, navigate_control::subframe, threadlock, and writer1394.

Referenced by PageTrim::startNavigator(), and PageEditor::startNavigator().

01434     {
01435         struct navigate_control * ctl = ( struct navigate_control * ) info;
01436         newFrame = 0;
01437         lastFrame = common->g_currentFrame - 1;
01438         gint totalFrames = common->getPlayList() ->GetNumFrames();
01439         gint countFrames = 0;
01440         static Preferences &prefs = Preferences::getInstance();
01441         int time_per_frame = 1000000 / _getOneSecond( );
01442 
01443         // cerr << ">>> Starting read thread " << endl;
01444 
01445         // Get start of time
01446         struct timeval start;
01447         struct timeval end;
01448         gettimeofday( &start, NULL );
01449 
01450         // Loop while active
01451         while ( ctl->active )
01452         {
01453             // Calculate time for next frame
01454             start.tv_usec += time_per_frame;
01455             if ( start.tv_usec >= 1000000 )
01456             {
01457                 start.tv_usec -= 1000000;
01458                 start.tv_sec ++;
01459             }
01460 
01461             pthread_mutex_lock( &readlock );
01462             // Determine the frame to render
01463             newFrame = lastFrame + ctl->step;
01464 
01465             // determine new frame based upon jogshuttle rate
01466             if ( ctl->step == 0 )
01467             {
01468                 ctl->subframe++;
01469                 if ( ctl->rate < 0 )
01470                 {
01471                     if ( ctl->subframe >= -ctl->rate )
01472                     {
01473                         newFrame --;
01474                         ctl->subframe = 0;
01475                     }
01476                 }
01477                 else
01478                 {
01479                     if ( ctl->subframe >= ctl->rate )
01480                     {
01481                         newFrame ++;
01482                         ctl->subframe = 0;
01483                     }
01484                 }
01485             }
01486             pthread_mutex_unlock( &readlock );
01487 
01488             // Check the bounds and adjust as necessary
01489             if ( newFrame < 0 )
01490                 newFrame = 0;
01491             else if ( newFrame >= totalFrames )
01492                 newFrame = totalFrames - 1;
01493 
01494             // Determine which locations in frameNumber and frameContent we need to use
01495             if ( pending >= PLAYBACK_FRAMES - 10 )
01496             {
01497                 // Queue is full.. do nothing
01498                 playing = true;
01499                 struct timespec t = { 0, 0 };
01500                 nanosleep( &t, NULL );
01501             }
01502             else
01503             {
01504                 frameNumber[ head ] = newFrame;
01505                 common->getPlayList() ->GetFrame( frameNumber[ head ], *frameContent[ head ] );
01506                 if ( writer1394 != NULL )
01507                     writer1394->SendFrame( *frameContent[ head ], false );
01508                 
01509                 pthread_mutex_lock( &threadlock );
01510                 ++pending;
01511                 head = ( head + 1 ) % PLAYBACK_FRAMES;
01512                 pthread_mutex_unlock( &threadlock );
01513 
01514                 // We have a frame, so start playing
01515                 playing = true;
01516 
01517                 // Render all frames if requested
01518                 if ( ( ! prefs.dropFrame || ! prefs.enableAudio ) && ctl->active )
01519                 {
01520                     if ( prefs.enableAudio && ( frameNumber[ tail ] != lastFrame || ctl->rate > 1 || ctl->rate < -1 ) )
01521                         common->getPageEditor() ->getFrameDisplayer() ->PutSound( *frameContent[ tail ] );
01522                     common->getPageEditor() ->showFrame( frameNumber[ tail ], *frameContent[ tail ] );
01523                     tail = ( tail + 1 ) % PLAYBACK_FRAMES;
01524                     --pending;
01525 
01526                     // Determine how far from the next frame we really are
01527                     gettimeofday( &end, NULL );
01528                     int difference = ( ( start.tv_sec * 1000000 + start.tv_usec ) - ( end.tv_sec * 1000000 + end.tv_usec ) );
01529 
01530                     if ( difference > 2000 && difference < time_per_frame )
01531                     {
01532                         // Sleep for half the remaining time when audio is disabled
01533                         if ( ! prefs.enableAudio )
01534                         {
01535                             struct timespec t =
01536                                 {
01537                                     0, difference * 500
01538                                 };
01539                             nanosleep( &t, NULL );
01540                         }
01541                     }
01542                     else if ( difference < 0 || difference >= time_per_frame )
01543                     {
01544                         gettimeofday( &start, NULL );
01545                     }
01546                 }
01547 
01548                 // update the lastFrame and lastPos variables
01549                 lastFrame = newFrame;
01550 
01551                 // Incrment the frame count
01552                 countFrames ++;
01553             }
01554         }
01555         // cerr << ">>> Ending read thread " << countFrames << endl;
01556 
01557         return NULL;
01558     }

static void resetThreads  )  [static]
 

Definition at line 1415 of file page_editor.cc.

Referenced by PageTrim::startNavigator(), and PageEditor::startNavigator().

01416     {
01417         playing = false;
01418         showing = false;
01419         pending = 0;
01420         head = 0;
01421         tail = 0;
01422     }

static void * videoThread void *  info  )  [static]
 

Definition at line 1628 of file page_editor.cc.

References navigate_control::active, common, count, Preferences::dropFrame, Preferences::enableAudio, frameContent, KinoCommon::g_currentFrame, Preferences::getInstance(), KinoCommon::getPageEditor(), lastFrame, navigate_control::rate, and navigate_control::step.

01629     {
01630 
01631         static Preferences & prefs = Preferences::getInstance();
01632         struct navigate_control *ctl = ( struct navigate_control * ) info;
01633         int lastFrame = common->g_currentFrame - 1;
01634 
01635 #ifdef PLAY_WITH_STATS
01636         // Statistical analysis variables
01637         int dropped = 0;
01638         int count = 0;
01639 #endif
01640 
01641         // cerr << ">>> Starting video thread" << endl;
01642         while ( ctl->active )
01643         {
01644             // Only do this when drop frames is active (otherwise the audio thread takes care of it)
01645             if ( prefs.dropFrame && prefs.enableAudio )
01646             {
01647                 if ( showing && pending > 0 && ctl->active )
01648                 {
01649                     // Store the current tail
01650                     int my_tail = tail;
01651 
01652                     // As long as its different to the previous one, then display it
01653                     if ( frameNumber[ my_tail ] != lastFrame || ctl->rate > 1 )
01654                     {
01655 #ifdef PLAY_WITH_STATS
01656                         // Statistical analysis of frame playback (useful for limited kinds of tests)
01657                         if ( ctl->step == 1 )
01658                         {
01659                             int skipped = frameNumber[ my_tail ] - lastFrame - 1;
01660                             count += skipped + 1;
01661                             if ( skipped != 0 && lastFrame != 0 && count != 0 )
01662                             {
01663                                 dropped += skipped;
01664                                 cerr << ">>>> Dropped " << dropped << " in " << count << " frames - " << ( double ) ( ( ( double ) dropped / ( double ) count ) * 100.0 ) << "%" << endl;
01665                             }
01666                             lastFrame = frameNumber[ my_tail ];
01667                         }
01668 #endif
01669                         // Show this frame
01670                         common->getPageEditor() ->showFrame( frameNumber[ my_tail ], *frameContent[ my_tail ] );
01671                     }
01672                 }
01673                 struct timespec t = { 0, 0 };
01674                 nanosleep( &t, NULL );
01675             }
01676             else
01677             {
01678                 // It is safe to cancel the video thread here since a change to prefs necessitates a restart.
01679                 // cerr << ">>> Video Thread not needed" << endl;
01680                 return NULL;
01681             }
01682         }
01683 
01684 #ifdef PLAY_WITH_STATS
01685         cerr << ">>>> Video stopped: Dropped " << dropped << " in " << count << " frames - " << ( double ) ( ( ( double ) dropped / ( double ) count ) * 100.0 ) << "%" << endl;
01686 #endif
01687         // cerr << ">>> Ending video thread" << endl;
01688 
01689         return NULL;
01690     }


Variable Documentation

pthread_t audiothread = 0 [static]
 

Definition at line 58 of file page_editor.cc.

Referenced by PageEditor::startNavigator(), and PageEditor::stopNavigator().

char cmd[256] = { 0 }
 

Definition at line 49 of file page_editor.cc.

KinoCommon* common
 

Definition at line 58 of file commands.cc.

gboolean doScrub = FALSE [static]
 

Definition at line 70 of file page_editor.cc.

Frame* frameContent[PLAYBACK_FRAMES] [static]
 

Definition at line 67 of file page_editor.cc.

Referenced by audioThread(), PageTrim::clean(), PageEditor::clean(), readThread(), PageTrim::start(), PageEditor::start(), and videoThread().

int frameNumber[PLAYBACK_FRAMES] [static]
 

Definition at line 1408 of file page_editor.cc.

struct navigate_control g_nav_ctl
 

Definition at line 33 of file callbacks.c.

int head = -1 [static]
 

Definition at line 1410 of file page_editor.cc.

char lastcmd[256] = { 0 }
 

Definition at line 50 of file page_editor.cc.

int lastFrame = -1 [static]
 

Definition at line 63 of file page_editor.cc.

Referenced by audioThread(), PageTrim::movedToFrame(), readThread(), PageEditor::ResetBar(), PageMagick::VideoThread(), and videoThread().

int newFrame = 0 [static]
 

Definition at line 62 of file page_editor.cc.

Referenced by PageTrim::movedToFrame(), and readThread().

int pending = 0 [static]
 

Definition at line 1409 of file page_editor.cc.

bool playing = false [static]
 

Definition at line 1412 of file page_editor.cc.

pthread_mutex_t readlock = PTHREAD_MUTEX_INITIALIZER [static]
 

Definition at line 61 of file page_editor.cc.

Referenced by readThread().

pthread_t readthread = 0 [static]
 

Definition at line 57 of file page_editor.cc.

Referenced by PageEditor::startNavigator(), and PageEditor::stopNavigator().

bool showing = false [static]
 

Definition at line 1413 of file page_editor.cc.

int tail = -1 [static]
 

Definition at line 1411 of file page_editor.cc.

pthread_mutex_t threadlock = PTHREAD_MUTEX_INITIALIZER [static]
 

Definition at line 60 of file page_editor.cc.

Referenced by audioThread(), and readThread().

pthread_t videothread = 0 [static]
 

Definition at line 59 of file page_editor.cc.

IEEE1394Writer* writer1394 = NULL
 

Definition at line 68 of file page_editor.cc.

Referenced by PageTrim::clean(), PageEditor::clean(), readThread(), PageTrim::showFrame(), PageEditor::showFrame(), PageTrim::start(), and PageEditor::start().


Generated on Sun Mar 11 22:12:17 2007 for Kino by  doxygen 1.4.2