#include <VideoFile.h>
Classes | |
class | PacketQueue |
Public Types | |
enum | PlaySpeed { SPEED_QUARTER = 0, SPEED_THIRD, SPEED_HALF, SPEED_NORMAL, SPEED_DOUBLE, SPEED_TRIPLE } |
Public Slots | |
bool | open (QString file, int64_t markIn=0, int64_t markOut=0) |
void | start () |
void | stop () |
void | play (bool startorstop) |
void | pause (bool pause) |
void | resetMarkIn () |
void | resetMarkOut () |
void | setMarkIn () |
void | setMarkOut () |
void | setLoop (bool loop) |
void | setPlaySpeed (int playspeed) |
void | seekBackward () |
void | seekForward () |
void | seekBegin () |
void | setOptionAllowDirtySeek (bool dirty) |
void | setOptionRestartToMarkIn (bool on) |
void | setOptionRevertToBlackWhenStop (bool black) |
Signals | |
void | frameReady (int id) |
void | running (bool run) |
void | paused (bool p) |
void | markingChanged () |
void | info (QString msg) |
void | error (QString msg) |
Public Member Functions | |
VideoFile (QObject *parent=0, bool generatePowerOfTwo=false, int swsConversionQuality=SWS_POINT, enum PixelFormat avFormat=PIX_FMT_RGB24, int destinationWidth=0, int destinationHeight=0) | |
~VideoFile () | |
const VideoPicture * | getPictureAtIndex (int index) const |
bool | isOpen () const |
bool | isRunning () const |
bool | isPaused () const |
bool | isLoop () const |
const char * | getFileName () const |
QString | getCodecName () const |
int | getFrameWidth () const |
int | getFrameHeight () const |
int | getStreamFrameWidth () const |
int | getStreamFrameHeight () const |
float | getStreamAspectRatio () const |
float | getFrameRate () const |
double | getDuration () const |
int64_t | getBegin () const |
int64_t | getEnd () const |
int64_t | getCurrentFrameTime () const |
int64_t | getMarkIn () const |
void | setMarkIn (int64_t t) |
int64_t | getMarkOut () const |
void | setMarkOut (int64_t t) |
void | seekToPosition (int64_t t) |
void | seekBySeconds (double ss) |
void | seekByFrames (int64_t ss) |
QString | getTimeFromFrame (int64_t t) const |
int64_t | getFrameFromTime (QString t) const |
Static Public Member Functions | |
static void | displayFormatsCodecsInformation () |
Protected Slots | |
void | video_refresh_timer () |
void | thread_terminated () |
Protected Member Functions | |
double | get_clock () |
void | reset () |
void | parse_decode_update (int64_t t) |
void | fill_first_frame (bool) |
int | stream_component_open (AVFormatContext *) |
double | synchronize_video (AVFrame *src_frame, double pts) |
void | queue_picture (AVFrame *pFrame, double pts) |
Static Protected Member Functions | |
static int | roundPowerOfTwo (int v) |
Protected Attributes | |
QString | filename |
QString | codecname |
QString | logmessage |
AVFormatContext * | pFormatCtx |
AVStream * | video_st |
SwsContext * | img_convert_ctx |
int | videoStream |
PacketQueue | videoq |
bool | seek_req |
bool | seek_backward |
bool | seek_any |
int64_t | seek_pos |
int64_t | mark_in |
int64_t | mark_out |
int64_t | mark_stop |
double | frame_timer |
double | frame_last_pts |
double | frame_last_delay |
double | video_clock |
double | video_current_pts |
int64_t | video_current_pts_time |
QTimer * | ptimer |
int64_t | last_time |
int64_t | last_virtual_time |
double | play_speed |
VideoPicture | pictq [VIDEO_PICTURE_QUEUE_SIZE] |
int | pictq_size |
int | pictq_rindex |
int | pictq_windex |
QMutex * | pictq_mutex |
QWaitCondition * | pictq_cond |
int | conversionAlgorithm |
int | targetWidth |
int | targetHeight |
enum PixelFormat | targetFormat |
bool | powerOfTwo |
VideoPicture | firstPicture |
VideoPicture | blackPicture |
VideoPicture * | resetPicture |
ParsingThread * | parse_tid |
DecodingThread * | decod_tid |
bool | quit |
bool | loop_video |
bool | pause_video |
bool | pause_video_last |
bool | restart_where_stopped |
Static Protected Attributes | |
static bool | ffmpegregistered |
Friends | |
class | ParsingThread |
class | DecodingThread |
Once instanciated, a VideoFile is suppoesed to read a movie by calling open(). The file can be a video (e.g. avi, mov) or a picture (e.g. jpg, png). All ffmpeg formats and Codecs are accepted (call displayFormatsCodecsInformation() to get a list).
If a picture file was opened, a frameReady() QT event is sent with the argument (-1) to inform that the picture was loaded; the -1 index is a special case for the pre-loaded frame of a video (before reading the full movie), and is also used for pictures files (jpg, png, tif, etc.). So, to display the loaded picture, call getPictureAtIndex(-1) and display the given VideoPicture.
If a movie file was opened, a frameReady() QT event is sent with the argument (-1) to inform that a preview frame was pre-loaded and the VideoFile is ready to start (call start() or play( true )). When started, a VideoFile will create two internal threads, one for decoding the movie and one for converting the frames into VideoPicture. The internal parrallel process of decoding & conversion will emit a frameReady() QT event each time a VideoPicture is produced. To display those pictures, connect this signal to a slot taking the integer index as argument for getPictureAtIndex(int). The picture index are in the range [0..VIDEO_PICTURE_QUEUE_SIZE]. See VideoPicture class for more details.
When playing, the VideoFile can seek for another time in the movie (no effect if movie is stopped). You can jump to a given position in frame (seekToPosition()), or jump relatively to the current play position (seekBySeconds(), seekByFrames(), seekForward(), etc.). However, be careful because calling one of those methods will only *request* a jump for *next* frame; all is fine if the video is playing, but this means that if the VideoFile was paused nothing will happen immediately; you have to unpause the video to actually jump and see the frame. This seems annoying but it is easy to program with qt events (just connect to the frameReady() event and pause again when recieving the event) and it guarantees the continuity of the decoding process after seeking.
To interrupt the video, you can either pause it (call pause()) or stop it (call stop() or play( false )). When paused, the processes are still running, waiting to restart exactly at the frame it was interrupted. When stopped, all activity is ended and the VideoFile will have to be started again. Note that by default, the behavior is to restart where the movie was stopped but that this is NOT equivalent to pause (see setOptionRestartToMarkIn(bool) ).
In addition, a VideoFile can use two marks, IN and OUT, defining the beginning and the end of the exerpt to play. Marks can be given when opening the file, but they can be defined and modified at any time (see setMarkIn(), setMarkOut()). This is particularly useful to repetitively show an excerpt of a movie when combined with the loop mode (setLoop()).
This code was inpired by the C/SDL tutorial by Martin Bohme (http://www.dranger.com/ffmpeg/) and by the C/SDL code of ffplay provided with ffmpeg (http://ffmpeg.org/)
Definition at line 196 of file VideoFile.h.
enum VideoFile::PlaySpeed |
Set of video playback speeds available. See setPlaySpeed(int) for details.
Definition at line 208 of file VideoFile.h.
VideoFile::VideoFile | ( | QObject * | parent = 0 , |
|
bool | generatePowerOfTwo = false , |
|||
int | swsConversionQuality = SWS_POINT , |
|||
enum PixelFormat | avFormat = PIX_FMT_RGB24 , |
|||
int | destinationWidth = 0 , |
|||
int | destinationHeight = 0 | |||
) |
Constructor of a VideoFile.
By default, a VideoFile should be instanciated with only its QObject parent.
Set the generatePowerOfTwo parameter to true in order to approximate the original dimensions of the movie to the closest power of two values. (this could be needed for old graphic cards which do not support the GL_EXT_texture_non_power_of_two extension).
The swsConversionQuality parameter is to decide for the scaling algorithm. In order of speed (inverse order of quality), swsConversionQuality can be : SWS_POINT, SWS_FAST_BILINEAR, SWS_BILINEAR, SWS_BICUBLIN, SWS_BICUBIC, SWS_SPLINE or SWS_SINC If no scaling is needed (generatePowerOfTwo false and no custom dimensions), use SWS_POINT for best performance. See libswscale/swscale.h for details.
The avFormat parameter specifies the internal pixel format of the decoded frames. To use frames as OpenGL textures, this is usually PIX_FMT_RGB24 (for GL_RGB) or PIX_FMT_RGBA (for GL_RGBA). See libswscale/swscale.h and libavutil/pixfmt.h for details.
The width and height parameters should be used only if your application requires frames of special dimensions. (If the generatePowerOfTwo parameter is true, these dimensions will be approximated to the closest power of two values).
PERFORMANCE REMARK; as the size conversion is done by ffmpeg in software (lib swscale) and is rather slow, use the generatePowerOfTwo or the custom dimensions only if needed.
parent | QObject parent class. | |
generatePowerOfTwo | True to request a resize of the frames to the closest power of two dimensions. | |
swsConversionQuality | SWS_POINT, SWS_FAST_BILINEAR, SWS_BILINEAR, SWS_BICUBLIN, SWS_BICUBIC, SWS_SPLINE or SWS_SINC | |
avFormat | Usually PIX_FMT_RGB24 or PIX_FMT_RGBA | |
destinationWidth | Width of the VideoPicture to produce; leave at 0 for auto detection from the file resolution. | |
destinationHeight | Height of the VideoPicture to produce; leave at 0 for auto detection from the file resolution. |
VideoFile::~VideoFile | ( | ) |
Destructor.
Automatically calls stop() and waits for the threads to end before clearing memory.
static void VideoFile::displayFormatsCodecsInformation | ( | ) | [static] |
Displays a dialog window (QDialog) listing the formats and video codecs supported for reading.
void VideoFile::error | ( | QString | msg | ) | [signal] |
Signal emmited when an error occurs; The VideoFile should gently stop, but may stay in a non-usable state; better stop it, or delete it.
msg | Error message |
void VideoFile::frameReady | ( | int | id | ) | [signal] |
Signal emmited when a new VideoPicture is ready;
id | the argument is the id of the VideoPicture to read. |
int64_t VideoFile::getBegin | ( | ) | const |
Get the time of the first picture in VideoFile.
QString VideoFile::getCodecName | ( | ) | const [inline] |
Get the name of the codec of the file opened.
Definition at line 321 of file VideoFile.h.
int64_t VideoFile::getCurrentFrameTime | ( | ) | const |
Get the time of the current frame.
double VideoFile::getDuration | ( | ) | const |
int64_t VideoFile::getEnd | ( | ) | const |
Get the time of the last picture in VideoFile.
const char* VideoFile::getFileName | ( | ) | const [inline] |
Get the name of the file opened in this VideoFile.
Definition at line 313 of file VideoFile.h.
int64_t VideoFile::getFrameFromTime | ( | QString | t | ) | const |
Gives a value in stream time-base (frames) from a given string in a human readable time format (hh:mm:ss.ms).
t | a string in 'hh:mm:ss.ms' format |
int VideoFile::getFrameHeight | ( | ) | const [inline] |
Get the height of the produced frames.
Dimensions of frames were either specified when creating the VideoFile, either read from the file when opened.
Definition at line 341 of file VideoFile.h.
float VideoFile::getFrameRate | ( | ) | const [inline] |
Get the frame rate of the movie file opened.
NB: the frame rate is computed from avcodec information, which is not always correct as some codecs have non-constant frame rates.
Definition at line 380 of file VideoFile.h.
int VideoFile::getFrameWidth | ( | ) | const [inline] |
Get the width of the produced frames.
Dimensions of frames were either specified when creating the VideoFile, either read from the file when opened.
Definition at line 331 of file VideoFile.h.
int64_t VideoFile::getMarkIn | ( | ) | const [inline] |
Get the time when the IN mark was set
Definition at line 416 of file VideoFile.h.
int64_t VideoFile::getMarkOut | ( | ) | const [inline] |
Get the time when the OUT mark was set
Definition at line 430 of file VideoFile.h.
const VideoPicture* VideoFile::getPictureAtIndex | ( | int | index | ) | const |
Get a VideoPicture from the internal queue of pictures.
Calling getPictureAtIndex with a valid index (typically given by a frameReady(int) event) returns the current picture of the movie to display. The index of the pictures which can be obtained with this function are in the range [0 .. VIDEO_PICTURE_QUEUE_SIZE ].
Calling getPictureAtIndex with an invalid index (e.g. -1) returns the special VideoPicture previously pre-loaded. This special VideoPicture can be:
It returns a const pointer to make sure you don't mess with it! You can only use the public methods of VideoPicture to read the picture.
index | Index of the picture to read; this should be used when recieving a frameReady(int) event and using the given index. |
float VideoFile::getStreamAspectRatio | ( | ) | const |
Get the aspect ratio of the video stream.
int VideoFile::getStreamFrameHeight | ( | ) | const [inline] |
Get the height of the frames contained in the stream.
Definition at line 360 of file VideoFile.h.
int VideoFile::getStreamFrameWidth | ( | ) | const [inline] |
Get the width of the frames contained in the stream.
Definition at line 349 of file VideoFile.h.
QString VideoFile::getTimeFromFrame | ( | int64_t | t | ) | const |
Gives a string for human readable display of time (hh:mm:ss.ms) from a stream time-base value (frames).
t | a time in stream time base (usually frame number) |
void VideoFile::info | ( | QString | msg | ) | [signal] |
Signal emmited when a special event occurs during decoding; The VideoFile is still working fine; nothing to do but display the messages if wanted.
msg | Information message |
bool VideoFile::isLoop | ( | ) | const [inline] |
Test if in loop mode.
When loop mode is active, the playback will restart at MarkIn when arriving at MarkOut.
Definition at line 305 of file VideoFile.h.
bool VideoFile::isOpen | ( | ) | const [inline] |
Test if a file was open for this VideoFile.
Definition at line 279 of file VideoFile.h.
bool VideoFile::isPaused | ( | ) | const [inline] |
bool VideoFile::isRunning | ( | ) | const [inline] |
Test if running (playing).
Definition at line 287 of file VideoFile.h.
void VideoFile::markingChanged | ( | ) | [signal] |
Signal emited when a mark (IN or OUT) has been moved.
bool VideoFile::open | ( | QString | file, | |
int64_t | markIn = 0 , |
|||
int64_t | markOut = 0 | |||
) | [slot] |
Opens the file and reads first frame.
Emits a frameReady signal to display this first frame (this is useful for 1 frame files like jpg or png).
file | Full path of the file to open | |
markIn | Position of the mark IN where to start. | |
markOut | Position of the mark OUT where to stop. |
void VideoFile::pause | ( | bool | pause | ) | [slot] |
Pauses / resumes the reading of the video. Does nothing if the process is not running (started) or already paused.
When paused, the processes are still running but just not going to the next frame. (NB: Call stop() if you want to interrupt the playback more permanently).
Emits a pause(bool) signal.
pause | If argument is true, pauses the reading of the video, if it is false, resumes play. |
void VideoFile::paused | ( | bool | p | ) | [signal] |
Signal emmited when video is paused;
p | the argument is true for paused, and false for playing. |
void VideoFile::play | ( | bool | startorstop | ) | [slot] |
void VideoFile::resetMarkIn | ( | ) | [inline, slot] |
Set the IN mark to the movie first frame.
Definition at line 583 of file VideoFile.h.
void VideoFile::resetMarkOut | ( | ) | [inline, slot] |
Set the OUT mark to the movie last frame.
Definition at line 589 of file VideoFile.h.
void VideoFile::running | ( | bool | run | ) | [signal] |
Signal emmited when started or stopped;
run | the argument is true for running, and false for not running. |
void VideoFile::seekBackward | ( | ) | [inline, slot] |
Seek backward of SEEK_STEP percent of the movie duration. Does nothing if the process is not running (started).
Definition at line 636 of file VideoFile.h.
void VideoFile::seekBegin | ( | ) | [inline, slot] |
Seek backward to the movie first frame. Does nothing if the process is not running (started).
Definition at line 650 of file VideoFile.h.
void VideoFile::seekByFrames | ( | int64_t | ss | ) |
Requests a seek (jump) into the video by a given amount of frames.
Does nothing if the process is not running (started) or already seeking.
ss | Amount of frames to jump; if ss > 0 it seeks forward. if ss < 0, it seeks backward. |
void VideoFile::seekBySeconds | ( | double | ss | ) |
Requests a seek (jump) into the video by a given amount of seconds.
Does nothing if the process is not running (started) or already seeking.
ss | Amount of time to jump; if ss > 0 it seeks forward. if ss < 0, it seeks backward. |
void VideoFile::seekForward | ( | ) | [inline, slot] |
Seek forward of SEEK_STEP percent of the movie duration. Does nothing if the process is not running (started).
Definition at line 643 of file VideoFile.h.
void VideoFile::seekToPosition | ( | int64_t | t | ) |
Requests a seek (jump) into the video to the time t.
Does nothing if the process is not running (started) or already seeking.
t | Time where to jump to, in stream time base (usually frame number). t shall be > 0 and < getEnd(). |
void VideoFile::setLoop | ( | bool | loop | ) | [inline, slot] |
Sets the reading to loop at the end or not. When loop mode is active, the playback will restart at MarkIn when arriving at MarkOut. Else, playing will pause after the last frame.
loop | activate the loop mode if true, |
Definition at line 611 of file VideoFile.h.
void VideoFile::setMarkIn | ( | ) | [inline, slot] |
Set the IN mark to the current frame.
Definition at line 595 of file VideoFile.h.
void VideoFile::setMarkIn | ( | int64_t | t | ) |
Set the IN mark time ; this is the time in the video where the playback will restart or loop.
t | Mark IN time, in stream time base (usually frame number). |
void VideoFile::setMarkOut | ( | ) | [inline, slot] |
Set the OUT mark to the current frame.
Definition at line 601 of file VideoFile.h.
void VideoFile::setMarkOut | ( | int64_t | t | ) |
Set the OUT mark time ; this is the time in the video at which the playback will end (pause) or loop.
t | Mark OUT time, in stream time base (usually frame number). |
void VideoFile::setOptionAllowDirtySeek | ( | bool | dirty | ) | [slot] |
Sets the "allow dirty seek" option.
This option is a parameter of ffmpeg seek; when dirty seek is allowed, seek to position will allow any frame to be accepted (AVSEEK_FLAG_ANY) and displayed. However, with files using frame difference for compressed encoding, this means that only a partial information is available, and that the frame is incomplete, aka dirty.
This option tries to compensate for some cases where seeking into a file causes jumps to 'real' key frames at times which are quite far from the target seekToPosition time (the default behavior is to find the closest full frame to display). Use it carefully!
dirty | true to activate the option. |
void VideoFile::setOptionRestartToMarkIn | ( | bool | on | ) | [inline, slot] |
Sets the "restart to Mark IN" option.
When this option is active, stopping a VideoFile will jump back to the IN mark, ready to restart from there.
on | true to activate the optin. |
Definition at line 675 of file VideoFile.h.
void VideoFile::setOptionRevertToBlackWhenStop | ( | bool | black | ) | [slot] |
Sets the "revert to black" option.
When this option AND the "restart to Mark IN" option are active, stopping a VideoFile will show a black frame instead of the begining frame.
black | true to activate the option. |
void VideoFile::setPlaySpeed | ( | int | playspeed | ) | [slot] |
Sets the playing speed factor from the list of available playback speeds available in the PlaySpeed type. NB: the argument is an integer for Qt compatibility with signals/slots, but it is used as a type PlaySpeed.
This option alters the time stamp of the next frame decoded; this is not exactly the next frame to display as there is a small buffer queue between the decoding and display threads, but the effect is almost instantaneous (few frames later).
If speed is set to less than 1 (SPEED_QUARTER, SPEED_THIRD, SPEED_HALF), the presentation time stamp of the frame is delayed and the frames will be displayed later than normal. If speed is set to more than 1 (SPEED_DOUBLE, SPEED_TRIPLE) the time stamp is reduced and the frame will be displayed earlier than normal.
However, this implementation of the playing speed is still not fully correct :(... The problem is that the delay or acceleration seems to accumulate after a long period out of normal play speed. Although the playback speed always end up to be the one requested, it sometimes takes time to reach it :(...
playspeed | SPEED_QUARTER = 0, SPEED_THIRD = 1, SPEED_HALF = 2, SPEED_NORMAL = 3, SPEED_DOUBLE = 4, SPEED_TRIPLE = 5 |
void VideoFile::start | ( | ) | [slot] |
Starts the decoding-conversion process. Does nothing if the process was already started.
Before starting, the processes are reseted to play the movie from the beginning (a paused(false) signal may be emited).
Emits a frameReady signal at every frame.
Emits an error message if no file was openned.
Emits running(true) on success.
void VideoFile::stop | ( | ) | [slot] |
Stops the decoding-conversion process. Does nothing if the process was not started.
Once stopped, the process is reseted in order to restart from beginning next time. (NB: call pause(true) if you want to temporarily interrupt the playback).
Emits a frameReady signal to display the first frame.
Emits an error message if no file was openned.
Emits running(false) on success.
void VideoFile::thread_terminated | ( | ) | [protected, slot] |
Slot called when a thread ends prematurely (error handling).
void VideoFile::video_refresh_timer | ( | ) | [protected, slot] |
Slot called from an internal timer synchronized on the video time code.