diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h index 7ab1ea33..e00470b7 100644 --- a/include/FFmpegReader.h +++ b/include/FFmpegReader.h @@ -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(); }; } diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 8418ef0c..869ffa77 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -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() diff --git a/src/Main.cpp b/src/Main.cpp index c2f3c210..9f32c553 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -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);