diff --git a/include/Clip.h b/include/Clip.h index b28faec2..cfe754b9 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -94,9 +94,12 @@ namespace openshot { /// Default Constructor Clip(); - /// Constructor with filepath + /// Constructor with filepath (reader is automatically created... by guessing file extensions) Clip(string path); + /// Constructor with reader + Clip(FileReaderBase* reader); + /// Close the internal reader void Close(); @@ -104,14 +107,19 @@ namespace openshot { /// /// @returns The requested frame (containing the image) /// @param[requested_frame] number The frame number that is requested. - Frame* GetFrame(int requested_frame); + Frame* GetFrame(int requested_frame) throw(ReaderClosed); /// Map frame rate of this clip to a different frame rate void MapFrames(Framerate fps, Pulldown_Method pulldown); /// Open the internal reader - void Open(); + void Open() throw(InvalidFile); + /// Set the current reader + void Reader(FileReaderBase* reader); + + /// Get the current reader + FileReaderBase* Reader(); /// Get basic properties float Position() { return position; } ///info.duration); +} + +/// Set the current reader +void Clip::Reader(FileReaderBase* reader) +{ + // set reader pointer + file_reader = reader; +} + +/// Get the current reader +FileReaderBase* Clip::Reader() +{ + return file_reader; } // Open the internal reader -void Clip::Open() +void Clip::Open() throw(InvalidFile) { if (file_reader) + { + // Open the reader file_reader->Open(); + + // Set some clip properties from the file reader + End(file_reader->info.duration); + } } // Close the internal reader @@ -125,7 +150,7 @@ void Clip::Close() } // Get an openshot::Frame object for a specific frame number of this reader. -Frame* Clip::GetFrame(int requested_frame) +Frame* Clip::GetFrame(int requested_frame) throw(ReaderClosed) { // Adjust out of bounds frame number if (requested_frame < 1) diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 869ffa77..3c714ca7 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -2,7 +2,7 @@ using namespace openshot; -FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, InvalidCodec) +FFmpegReader::FFmpegReader(string path) : 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), @@ -13,12 +13,6 @@ FFmpegReader::FFmpegReader(string path) throw(InvalidFile, NoStreamsFound, Inval // Initialize FFMpeg, and register all formats and codecs av_register_all(); - - // Open the file (if possible) - Open(); - - // Get 1st frame - GetFrame(1); } // Init a collection of software rescalers (thread safe) @@ -46,7 +40,7 @@ void FFmpegReader::RemoveScalers() image_rescalers.clear(); } -void FFmpegReader::Open() +void FFmpegReader::Open() throw(InvalidFile, NoStreamsFound, InvalidCodec) { // Open reader if not already open if (!is_open) @@ -136,6 +130,9 @@ void FFmpegReader::Open() // Mark as "open" is_open = true; + + // Get 1st frame + GetFrame(1); } } @@ -279,8 +276,12 @@ void FFmpegReader::UpdateVideoInfo() } -Frame* FFmpegReader::GetFrame(int requested_frame) +Frame* FFmpegReader::GetFrame(int requested_frame) throw(ReaderClosed) { + // Check for open reader (or throw exception) + if (!is_open) + throw ReaderClosed("The FFmpegReader is closed. Call Open() before calling this method.", path); + // Check the cache for this frame if (final_cache.Exists(requested_frame)) // Return the cached frame diff --git a/src/ImageReader.cpp b/src/ImageReader.cpp index cb9a042e..c10f0d52 100644 --- a/src/ImageReader.cpp +++ b/src/ImageReader.cpp @@ -2,77 +2,91 @@ using namespace openshot; -ImageReader::ImageReader(string path) throw(InvalidFile) : path(path) +ImageReader::ImageReader(string path) : path(path), is_open(false) { // Init FileInfo struct (clear all values) InitFileInfo(); - - // Open the file (if possible) - Open(); - - // Get 1st frame - GetFrame(1); } // Open image file -void ImageReader::Open() +void ImageReader::Open() throw(InvalidFile) { - // Attempt to open file - Magick::Image* source = NULL; - try + // Open reader if not already open + if (!is_open) { - // load image - source = new Magick::Image(path); + // Attempt to open file + Magick::Image* source = NULL; + try + { + // load image + source = new Magick::Image(path); + } + catch (Magick::Exception e) { + // raise exception + throw InvalidFile("File could not be opened.", path); + } + + // Create or get frame object + image_frame = new Frame(1, source->size().width(), source->size().height(), "#000000", 0, 2); + + // Add Image data to frame + image_frame->AddImage(source); + + // Update image properties + info.has_audio = false; + info.has_video = true; + info.file_size = source->fileSize(); + info.vcodec = source->format(); + info.width = source->size().width(); + info.height = source->size().height(); + info.pixel_ratio.num = 1; + info.pixel_ratio.den = 1; + info.duration = 60 * 60 * 24; // 24 hour duration + info.fps.num = 30; + info.fps.den = 1; + info.video_timebase.num = 1; + info.video_timebase.den = 30; + info.video_length = round(info.duration * info.fps.ToDouble()); + + // Calculate the DAR (display aspect ratio) + Fraction size(info.width * info.pixel_ratio.num, info.height * info.pixel_ratio.den); + + // Reduce size fraction + size.Reduce(); + + // Set the ratio based on the reduced fraction + info.display_ratio.num = size.num; + info.display_ratio.den = size.den; + + // Mark as "open" + is_open = true; + + // Get 1st frame + GetFrame(1); } - catch (Magick::Exception e) { - // raise exception - throw InvalidFile("File could not be opened.", path); - } - - // Create or get frame object - image_frame = new Frame(1, source->size().width(), source->size().height(), "#000000", 0, 2); - - // Add Image data to frame - image_frame->AddImage(source); - - - // Update image properties - info.has_audio = false; - info.has_video = true; - info.file_size = source->fileSize(); - info.vcodec = source->format(); - info.width = source->size().width(); - info.height = source->size().height(); - info.pixel_ratio.num = 1; - info.pixel_ratio.den = 1; - info.duration = 60 * 60 * 24; // 24 hour duration - info.fps.num = 30; - info.fps.den = 1; - info.video_timebase.num = 1; - info.video_timebase.den = 30; - info.video_length = round(info.duration * info.fps.ToDouble()); - - // Calculate the DAR (display aspect ratio) - Fraction size(info.width * info.pixel_ratio.num, info.height * info.pixel_ratio.den); - - // Reduce size fraction - size.Reduce(); - - // Set the ratio based on the reduced fraction - info.display_ratio.num = size.num; - info.display_ratio.den = size.den; } // Close image file void ImageReader::Close() { - // Deallocate frame - delete image_frame; + // Close all objects, if reader is 'open' + if (is_open) + { + // Deallocate frame + delete image_frame; + + // Mark as "closed" + is_open = false; + } } // Get an openshot::Frame object for a specific frame number of this reader. -Frame* ImageReader::GetFrame(int requested_frame) throw(InvalidFile) +Frame* ImageReader::GetFrame(int requested_frame) throw(ReaderClosed) { + // Check for open reader (or throw exception) + if (!is_open) + throw ReaderClosed("The ImageReader is closed. Call Open() before calling this method.", path); + if (image_frame) // Always return same frame (regardless of which frame number was requested) return image_frame; diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 75e20b9c..31f8c592 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -52,7 +52,7 @@ void Timeline::Open() } // Get an openshot::Frame object for a specific frame number of this reader. -Frame* Timeline::GetFrame(int requested_frame) +Frame* Timeline::GetFrame(int requested_frame) throw(ReaderClosed) { // Adjust out of bounds frame number if (requested_frame < 1) diff --git a/tests/Clip_Tests.cpp b/tests/Clip_Tests.cpp index 03bb770d..bb43422f 100644 --- a/tests/Clip_Tests.cpp +++ b/tests/Clip_Tests.cpp @@ -23,6 +23,7 @@ TEST(Clip_Constructor) { // Create a empty clip Clip c1("../../src/examples/piano.wav"); + c1.Open(); // Check basic settings CHECK_EQUAL(ANCHOR_CANVAS, c1.anchor); @@ -38,6 +39,7 @@ TEST(Clip_Basic_Gettings_and_Setters) { // Create a empty clip Clip c1; + c1.Open(); // Check basic settings CHECK_EQUAL(ANCHOR_CANVAS, c1.anchor); diff --git a/tests/FFmpegReader_Tests.cpp b/tests/FFmpegReader_Tests.cpp index acebeab3..5a1efb06 100644 --- a/tests/FFmpegReader_Tests.cpp +++ b/tests/FFmpegReader_Tests.cpp @@ -6,14 +6,27 @@ using namespace openshot; TEST(FFmpegReader_Invalid_Path) { + // Create reader with invalid path + FFmpegReader r(""); + // Check invalid path - CHECK_THROW(FFmpegReader r(""), InvalidFile); + CHECK_THROW(r.Open(), InvalidFile); +} + +TEST(FFmpegReader_GetFrame_Before_Opening) +{ + // Create a reader + FFmpegReader r("../../src/examples/piano.wav"); + + // Check invalid path + CHECK_THROW(r.GetFrame(1), ReaderClosed); } TEST(FFmpegReader_Check_Audio_File) { // Create a reader FFmpegReader r("../../src/examples/piano.wav"); + r.Open(); // Get frame 1 Frame *f = r.GetFrame(1); @@ -41,6 +54,7 @@ TEST(FFmpegReader_Check_Video_File) { // Create a reader FFmpegReader r("../../src/examples/test.mp4"); + r.Open(); // Get frame 1 Frame *f = r.GetFrame(1);