Protected the Open() and Close() methods better, so the FFmpegReader will not crash. Also, made the Open() method public, so the Timeline and Clip classes can control the reader better.

This commit is contained in:
Jonathan Thomas
2012-10-08 15:02:52 -05:00
parent 6d790d2670
commit 8518071890
3 changed files with 161 additions and 147 deletions

View File

@@ -63,6 +63,7 @@ namespace openshot
AVStream *pStream, *aStream;
AVPacket *packet;
AVFrame *pFrame;
bool is_open;
bool check_interlace;
bool check_fps;
@@ -135,9 +136,6 @@ namespace openshot
/// Init a collection of software rescalers (thread safe)
void InitScalers();
/// Open File - which is called by the constructor automatically
void Open();
/// Process a video packet
void ProcessVideoPacket(int requested_frame);
@@ -186,6 +184,9 @@ namespace openshot
/// @returns The requested frame of video
/// @param[requested_frame] number The frame number that is requested.
Frame* GetFrame(int requested_frame);
/// Open File - which is called by the constructor automatically
void Open();
};
}

View File

@@ -6,7 +6,7 @@ FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, Inval
: last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0),
audio_pts_offset(99999), video_pts_offset(99999), working_cache(12), final_cache(24), path(path),
is_video_seek(true), check_interlace(false), check_fps(false), enable_seek(true),
rescaler_position(0), num_of_rescalers(32) {
rescaler_position(0), num_of_rescalers(32), is_open(false) {
// Init FileInfo struct (clear all values)
InitFileInfo();
@@ -17,10 +17,6 @@ FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, Inval
// Open the file (if possible)
Open();
// Init rescalers (if video stream detected)
if (info.has_video)
InitScalers();
// Get 1st frame
GetFrame(1);
}
@@ -52,113 +48,128 @@ void FFmpegReader::RemoveScalers()
void FFmpegReader::Open()
{
// Initialize format context
pFormatCtx = NULL;
// Open video file
if (avformat_open_input(&pFormatCtx, path.c_str(), NULL, NULL) != 0)
throw InvalidFile("File could not be opened.", path);
// Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
throw NoStreamsFound("No streams found in file.", path);
videoStream = -1;
audioStream = -1;
// Loop through each stream, and identify the video and audio stream index
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
// Open reader if not already open
if (!is_open)
{
// Is this a video stream?
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
videoStream = i;
// Initialize format context
pFormatCtx = NULL;
// Open video file
if (avformat_open_input(&pFormatCtx, path.c_str(), NULL, NULL) != 0)
throw InvalidFile("File could not be opened.", path);
// Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
throw NoStreamsFound("No streams found in file.", path);
videoStream = -1;
audioStream = -1;
// Loop through each stream, and identify the video and audio stream index
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
{
// Is this a video stream?
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
videoStream = i;
}
// Is this an audio stream?
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audioStream < 0) {
audioStream = i;
}
}
// Is this an audio stream?
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audioStream < 0) {
audioStream = i;
if (videoStream == -1 && audioStream == -1)
throw NoStreamsFound("No video or audio streams found in this file.", path);
// Is there a video stream?
if (videoStream != -1)
{
// Set the stream index
info.video_stream_index = videoStream;
// Set the codec and codec context pointers
pStream = pFormatCtx->streams[videoStream];
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
// Set number of threads equal to number of processors + 1
pCodecCtx->thread_count = omp_get_num_procs();
// Find the decoder for the video stream
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
throw InvalidCodec("A valid video codec could not be found for this file.", path);
}
// Open video codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
throw InvalidCodec("A video codec was found, but could not be opened.", path);
// Update the File Info struct with video details (if a video stream is found)
UpdateVideoInfo();
// Init rescalers (if video stream detected)
InitScalers();
}
// Is there an audio stream?
if (audioStream != -1)
{
// Set the stream index
info.audio_stream_index = audioStream;
// Get a pointer to the codec context for the audio stream
aStream = pFormatCtx->streams[audioStream];
aCodecCtx = pFormatCtx->streams[audioStream]->codec;
// Set number of threads equal to number of processors + 1
aCodecCtx->thread_count = omp_get_num_procs();
// Find the decoder for the audio stream
AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
if (aCodec == NULL) {
throw InvalidCodec("A valid audio codec could not be found for this file.", path);
}
// Open audio codec
if (avcodec_open2(aCodecCtx, aCodec, NULL) < 0)
throw InvalidCodec("An audio codec was found, but could not be opened.", path);
// Update the File Info struct with audio details (if an audio stream is found)
UpdateAudioInfo();
}
// Mark as "open"
is_open = true;
}
if (videoStream == -1 && audioStream == -1)
throw NoStreamsFound("No video or audio streams found in this file.", path);
// Is there a video stream?
if (videoStream != -1)
{
// Set the stream index
info.video_stream_index = videoStream;
// Set the codec and codec context pointers
pStream = pFormatCtx->streams[videoStream];
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
// Set number of threads equal to number of processors + 1
pCodecCtx->thread_count = omp_get_num_procs();
// Find the decoder for the video stream
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
throw InvalidCodec("A valid video codec could not be found for this file.", path);
}
// Open video codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
throw InvalidCodec("A video codec was found, but could not be opened.", path);
// Update the File Info struct with video details (if a video stream is found)
UpdateVideoInfo();
}
// Is there an audio stream?
if (audioStream != -1)
{
// Set the stream index
info.audio_stream_index = audioStream;
// Get a pointer to the codec context for the audio stream
aStream = pFormatCtx->streams[audioStream];
aCodecCtx = pFormatCtx->streams[audioStream]->codec;
// Set number of threads equal to number of processors + 1
aCodecCtx->thread_count = omp_get_num_procs();
// Find the decoder for the audio stream
AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
if (aCodec == NULL) {
throw InvalidCodec("A valid audio codec could not be found for this file.", path);
}
// Open audio codec
if (avcodec_open2(aCodecCtx, aCodec, NULL) < 0)
throw InvalidCodec("An audio codec was found, but could not be opened.", path);
// Update the File Info struct with audio details (if an audio stream is found)
UpdateAudioInfo();
}
}
void FFmpegReader::Close()
{
// Close the codec
if (info.has_video)
// Close all objects, if reader is 'open'
if (is_open)
{
avcodec_flush_buffers(pCodecCtx);
avcodec_close(pCodecCtx);
// Close the codec
if (info.has_video)
{
// Clear image scalers
RemoveScalers();
avcodec_flush_buffers(pCodecCtx);
avcodec_close(pCodecCtx);
}
if (info.has_audio)
{
avcodec_flush_buffers(aCodecCtx);
avcodec_close(aCodecCtx);
}
// Clear cache
working_cache.Clear();
final_cache.Clear();
// Close the video file
avformat_close_input(&pFormatCtx);
av_freep(&pFormatCtx);
// Mark as "closed"
is_open = false;
}
if (info.has_audio)
{
avcodec_flush_buffers(aCodecCtx);
avcodec_close(aCodecCtx);
}
// Clear image scalers
if (info.has_video)
RemoveScalers();
// Clear cache
working_cache.Clear();
final_cache.Clear();
// Close the video file
avformat_close_input(&pFormatCtx);
av_freep(&pFormatCtx);
}
void FFmpegReader::UpdateAudioInfo()

View File

@@ -14,50 +14,52 @@ void FrameReady(int number)
int main()
{
// Create timeline
Framerate fps(30000,1000);
Timeline t(640, 480, fps);
// // Create timeline
// Framerate fps(30000,1000);
// Timeline t(640, 480, fps);
//
// // Add some clips
// Clip c1;
// c1.Position(10.0);
//
// Clip c2;
// c2.Position(0.0);
//
// Clip c3;
// c3.Position(2.5);
//
// Clip c4;
// c4.Position(40.4);
//
// Clip c5;
// c5.Position(0.1);
//
// t.AddClip(&c4);
// t.AddClip(&c2);
// t.AddClip(&c3);
// t.AddClip(&c1);
// t.AddClip(&c5);
//
// t.GetFrame(1);
//
// c1.Position(50.0);
// c2.Position(42.0);
// c3.Position(33.0);
// c4.Position(63.0);
// c5.Position(13.0);
//
// t.SortClips();
// t.GetFrame(1);
//
// // Create a clip
// Clip c("/home/jonathan/Videos/sintel_trailer-720p.mp4");
// cout << "Position: " << c.Position() << endl;
// cout << "Start: " << c.Start() << endl;
// cout << "End: " << c.End() << endl;
//
// return 0;
// Add some clips
Clip c1;
c1.Position(10.0);
Clip c2;
c2.Position(0.0);
Clip c3;
c3.Position(2.5);
Clip c4;
c4.Position(40.4);
Clip c5;
c5.Position(0.1);
t.AddClip(&c4);
t.AddClip(&c2);
t.AddClip(&c3);
t.AddClip(&c1);
t.AddClip(&c5);
t.GetFrame(1);
c1.Position(50.0);
c2.Position(42.0);
c3.Position(33.0);
c4.Position(63.0);
c5.Position(13.0);
t.SortClips();
t.GetFrame(1);
// Create a clip
Clip c("/home/jonathan/Videos/sintel_trailer-720p.mp4");
cout << "Position: " << c.Position() << endl;
cout << "Start: " << c.Start() << endl;
cout << "End: " << c.End() << endl;
return 0;
//openshot::ImageReader i("/home/jonathan/Apps/videcho_site/media/logos/watermark3.png");
//openshot::Frame* overlay = i.GetFrame(1);