You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
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:
@@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
86
src/Main.cpp
86
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);
|
||||
|
||||
Reference in New Issue
Block a user