[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libcvd-members] libcvd cvd/videofilebuffer.h cvd/videofilebuffe...
From: |
Colin Starr |
Subject: |
[Libcvd-members] libcvd cvd/videofilebuffer.h cvd/videofilebuffe... |
Date: |
Wed, 24 May 2006 13:09:18 +0000 |
CVSROOT: /cvsroot/libcvd
Module name: libcvd
Branch:
Changes by: Colin Starr <address@hidden> 06/05/24 13:09:18
Modified files:
cvd : videofilebuffer.h videofilebuffer_frame.h
cvd_src : videofilebuffer.cc
Log message:
Rewritten changes to VideoFileBuffer to fix the bug that caused
Rgb<byte> images to be deallocated as images of <byte>. The bulk of the code is
back in the .cc file, which is now un-deprecated. Thanks Ed and Ethan.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/libcvd/cvd/videofilebuffer.h.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/libcvd/libcvd/cvd/videofilebuffer_frame.h.diff?tr1=1.7&tr2=1.8&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/libcvd/libcvd/cvd_src/videofilebuffer.cc.diff?tr1=1.11&tr2=1.12&r1=text&r2=text
Patches:
Index: libcvd/cvd/videofilebuffer.h
diff -u libcvd/cvd/videofilebuffer.h:1.12 libcvd/cvd/videofilebuffer.h:1.13
--- libcvd/cvd/videofilebuffer.h:1.12 Tue May 23 15:25:33 2006
+++ libcvd/cvd/videofilebuffer.h Wed May 24 13:09:18 2006
@@ -1,22 +1,22 @@
/*
- This file is part of the CVD Library.
+ This file is part of the CVD Library.
- Copyright (C) 2005 The Authors
+ Copyright (C) 2005 The Authors
- This library is free software; you can redistribute it
and/or
- modify it under the terms of the GNU Lesser General
Public
- License as published by the Free Software Foundation;
either
- version 2.1 of the License, or (at your option) any
later version.
-
- This library is distributed in the hope that it will
be useful,
- but WITHOUT ANY WARRANTY; without even the implied
warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser
General Public
- License along with this library; if not, write to the
Free Software
- Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CVD_VIDEOFILEBUFFER_H
@@ -24,7 +24,6 @@
#include <vector>
#include <string>
-#include <sstream>
#include <fstream>
#include <errno.h>
@@ -44,545 +43,226 @@
namespace CVD
{
- namespace Exceptions
- {
- /// %Exceptions specific to VideoFileBuffer
- /// @ingroup gException
- namespace VideoFileBuffer
- {
- /// Base class for all VideoFileBuffer exceptions
- /// @ingroup gException
- struct All: public CVD::Exceptions::VideoBuffer::All { };
- /// Unable to open the file as a video stream, for various reasons
- /// @ingroup gException
-
- struct FileOpen: public All {
- FileOpen(const std::string& file, const std::string& error) ///<
Construt from filename and error message
- {
- what = "RawVideoFileBuffer: Error opening file \"" + file + "\": "
+ error;
- }
- };
-
- /// Unable to open allocate a video frame
- /// @ingroup gException
- struct BadFrameAlloc: public All {
- BadFrameAlloc()
- {
- what = "RawVideoFileBuffer: Unable to allocate video frame.";
- }
- };
-
- /// Unable to decode the video frame
- /// @ingroup gException
- struct BadDecode: public All {
- BadDecode(double t) ///< Construt from frame timestamp
- {
- std::ostringstream os;
- os << "RawVideoFileBuffer: Error decoding video frame at time " <<
t << ".";
- what = os.str();
- }
+ namespace Exceptions
+ {
+ /// %Exceptions specific to VideoFileBuffer
+ /// @ingroup gException
+ namespace VideoFileBuffer
+ {
+ /// Base class for all VideoFileBuffer exceptions
+ /// @ingroup gException
+ struct All: public CVD::Exceptions::VideoBuffer::All {
};
+ /// Unable to open the file as a video stream, for
various reasons
+ /// @ingroup gException
+ struct FileOpen: public All { FileOpen(const
std::string& file, const std::string& error); ///< Construt from filename and
error message
+ };
+ /// Unable to open allocate a video frame
+ /// @ingroup gException
+ struct BadFrameAlloc: public All { BadFrameAlloc(); };
+ /// Unable to decode the video frame
+ /// @ingroup gException
+ struct BadDecode: public All { BadDecode(double t);
///< Construt from frame timestamp
+ };
+ /// get_frame() was called when at the end of the buffer
+ /// @ingroup gException
+ struct EndOfFile: public All { EndOfFile(); };
+ /// seek_to() was called for an invalid timestamp
+ /// @ingroup gException
+ struct BadSeek: public All { BadSeek(double t); ///<
Construt from timestamp
+ };
+ }
+ }
+
+ /// Internal VideoFileBuffer helpers
+ namespace VFB
+ {
+
+ #ifndef DOXYGEN_IGNORE_INTERNAL
+ template<class C> struct rgb
+ {
+ static const bool
p=C::Error__type_not_valid___Use_byte_or_rgb_of_byte;
};
-
- /// get_frame() was called when at the end of the buffer
- /// @ingroup gException
- struct EndOfFile: public All {
- EndOfFile()
- {
- what = "RawVideoFileBuffer: Tried to read off the end of the
file.";
- }
+
+ template<> struct rgb<CVD::byte>
+ {
+ static const bool p=false;
};
-
- /// seek_to() was called for an invalid timestamp
- /// @ingroup gException
- struct BadSeek: public All {
- BadSeek(double t) ///< Construt from timestamp
- {
- std::ostringstream ss;
- ss << "RawVideoFileBuffer: Seek to time " << t << "s failed.";
- what = ss.str();
- }
+
+ template<> struct rgb<CVD::Rgb<CVD::byte> >
+ {
+ static const bool p=true;
};
- }
- }
-
-
- /// Internal VideoFileBuffer helpers
- namespace VFB
- {
-
-#ifndef DOXYGEN_IGNORE_INTERNAL
- template<class C> struct rgb
- {
- static const bool p=C::Error__type_not_valid___Use_byte_or_rgb_of_byte;
- };
-
- template<> struct rgb<CVD::byte>
- {
- static const bool p=false;
- };
-
- template<> struct rgb<CVD::Rgb<CVD::byte> >
- {
- static const bool p=true;
- };
-#endif
-
- /// Internal (non type-safe) class used by VideoFileBuffer
- /// This does the real interfacing with the ffmpeg library
- template<typename T>
- class RawVideoFileBuffer
+ #endif
+
+
+ class A_Frame;
+
+ /// Internal (non type-safe) class used by VideoFileBuffer
+ /// This does the real interfacing with the ffmpeg library
+ class RawVideoFileBuffer
{
- public:
- /// Construct a video buffer to play this file
- /// @param file The path to the video file
- /// @param is_rgb Is RGB data wanted?
- RawVideoFileBuffer(const std::string& file, bool rgbp) :
- end_of_buffer_behaviour(VideoBufferFlags::RepeatLastFrame),
- pFormatContext(0),
- pCodecContext(0),
- pFrame(0),
- pFrameRGB(0),
- //buffer(0),
- frame_time(0.0),
- is_rgb(rgbp)
- {
- try
- {
- // Register the formats and codecs
- av_register_all();
-
- // Now open the video file (and read the header, if present)
- if(av_open_input_file(&pFormatContext, file.c_str(), NULL, 0,
NULL) != 0)
- throw Exceptions::VideoFileBuffer::FileOpen(file, "File
could not be opened.");
-
- // Read the beginning of the file to get stream information
(in case there is no header)
- if(av_find_stream_info(pFormatContext) < 0)
- throw Exceptions::VideoFileBuffer::FileOpen(file, "Stream
information could not be read.");
-
- // Dump details of the video to standard error
- //dump_format(pFormatContext, 0, file.c_str(), false);
-
- // We shall just use the first video stream
- video_stream = -1;
- for(int i=0; i < pFormatContext->nb_streams && video_stream
== -1; i++)
- {
-#if LIBAVFORMAT_BUILD >= 4629
- if(pFormatContext->streams[i]->codec->codec_type ==
CODEC_TYPE_VIDEO)
- video_stream = i; // Found one!
-#else
- if(pFormatContext->streams[i]->codec.codec_type ==
CODEC_TYPE_VIDEO)
- video_stream = i; // Found one!
-#endif
- }
- if(video_stream == -1)
- throw Exceptions::VideoFileBuffer::FileOpen(file, "No video
stream found.");
-
- // Get the codec context for this video stream
-#if LIBAVFORMAT_BUILD >= 4629
- pCodecContext = pFormatContext->streams[video_stream]->codec;
-#else
- pCodecContext = &pFormatContext->streams[video_stream]->codec;
-#endif
-
- // Find the decoder for the video stream
- AVCodec* pCodec =
avcodec_find_decoder(pCodecContext->codec_id);
- if(pCodec == NULL)
- {
- pCodecContext = 0; // Since it's not been opened yet
- throw Exceptions::VideoFileBuffer::FileOpen(file, "No
appropriate codec could be found.");
- }
-
- // Open codec
- if(avcodec_open(pCodecContext, pCodec) < 0)
- {
- pCodecContext = 0; // Since it's not been opened yet
- throw Exceptions::VideoFileBuffer::FileOpen(file,
std::string(pCodec->name) + " codec could not be initialised.");
- }
-
-#if LIBAVCODEC_BUILD < 4754
- // Hack to fix wrong frame rates
- if(pCodecContext->frame_rate > 1000 &&
pCodecContext->frame_rate_base == 1)
- pCodecContext->frame_rate_base = 1000;
-#endif
-
- // Allocate video frame
- pFrame = avcodec_alloc_frame();
- if(pFrame == NULL)
- throw Exceptions::VideoFileBuffer::BadFrameAlloc();
-
- // And a frame to hold the RGB version
- pFrameRGB = avcodec_alloc_frame();
- if(pFrameRGB == NULL)
- throw Exceptions::VideoFileBuffer::BadFrameAlloc();
-
- // How big is the buffer?
- //long num_bytes = avpicture_get_size(PIX_FMT_RGB24,
pCodecContext->width, pCodecContext->height);
- my_size = ImageRef(pCodecContext->width,
pCodecContext->height);
-
- // And allocate a contiguous buffer
- //buffer = new CVD::Rgb<CVD::byte>[my_size.x * my_size.y];
-
- // Assign this buffer to image planes in pFrameRGB
- //avpicture_fill((AVPicture *)pFrameRGB,
reinterpret_cast<uint8_t*>(buffer), PIX_FMT_RGB24, pCodecContext->width,
pCodecContext->height);
-
- // Now read the first frame
- if(!read_next_frame())
- throw Exceptions::VideoFileBuffer::EndOfFile();
-
- start_time = 0;
- frame_ready = true;
- }
- catch(CVD::Exceptions::All)
- {
- // Tidy things up on the heap if we failed part-way through
constructing
- if(pFormatContext != 0)
- av_close_input_file(pFormatContext);
-
- if(pCodecContext != 0)
- avcodec_close(pCodecContext);
-
- if(pFrame != 0)
- av_free(pFrame);
-
- if(pFrameRGB != 0)
- av_free(pFrameRGB);
-
- //if(buffer != 0)
- // delete[] buffer;
-
- // Now re-throw
- throw;
- }
- }
-
-
- ~RawVideoFileBuffer()
- {
- //delete [] buffer;
- av_free(pFrameRGB);
- av_free(pFrame);
- avcodec_close(pCodecContext);
- av_close_input_file(pFormatContext);
- }
-
- /// The size of the VideoFrames returned by this buffer
- ImageRef size()
- {
- return my_size;
- }
-
- /// Returns the next frame from the buffer. This function blocks
until a frame is ready.
- VideoFileFrame<T>* get_frame()
- {
- if(!frame_pending())
- throw Exceptions::VideoFileBuffer::EndOfFile();
-
- // Don't use - pCC->frame_number doesn't reset after a
seek!
- // Instead, we ask the packet its time when we decode it
- // double time = start_time + pCodecContext->frame_number
* pCodecContext->frame_rate_base /
static_cast<double>(pCodecContext->frame_rate);
- VideoFileFrame<T>* vf = new VideoFileFrame<T>(frame_time,
next_frame);
-
- if(!read_next_frame())
- {
- switch(end_of_buffer_behaviour)
- {
- case VideoBufferFlags::RepeatLastFrame:
- // next_frame is empty because there isn't one, so
- // I'll copy the one that I'm about to return so that
- // I can return it next time as well
- next_frame.copy_from(*vf);
- break;
-
- case VideoBufferFlags::UnsetPending:
- frame_ready = false;
- break;
-
- case VideoBufferFlags::Loop:
- seek_to(start_time);
- break;
- }
- }
- return vf;
- }
-
-
-
- /// Tell the buffer that you are finished with this frame.
- /// \param f The frame that you are finished with.
- void put_frame(VideoFrame<T>* f)
- {
- VideoFileFrame<T>* vff = dynamic_cast<VideoFileFrame<T> *>(f);
-
- if(!vff)
- throw Exceptions::VideoBuffer::BadPutFrame();
- else
- delete vff;
- }
-
- /// Is there a frame waiting in the buffer? This function does not
block.
- bool frame_pending()
- {
- return frame_ready;
- }
-
- /// Go to a particular point in the video buffer (only implemented in
buffers of recorded video)
- /// \param t The frame time in seconds
- void seek_to(double t)
- {
-#if LIBAVFORMAT_BUILD >= 4623
- if(av_seek_frame(pFormatContext, -1,
static_cast<int64_t>(t*AV_TIME_BASE+0.5), AVSEEK_FLAG_ANY) < 0)
-#else
- if(av_seek_frame(pFormatContext, -1,
static_cast<int64_t>(t*AV_TIME_BASE+0.5)) < 0)
-#endif
- {
- cerr << "av_seek_frame not supported by this codec:
performing (slow) manual seek" << endl;
-
- // Seeking is not properly sorted with some codecs
- // Fudge it by closing the file and starting again,
stepping through the frames
- std::string file = pFormatContext->filename;
- av_close_input_file(pFormatContext);
- avcodec_close(pCodecContext);
-
- // Now open the video file (and read the header, if present)
- if(av_open_input_file(&pFormatContext, file.c_str(), NULL,
0, NULL) != 0)
- throw Exceptions::VideoFileBuffer::FileOpen(file, "File
could not be opened.");
-
- // Read the beginning of the file to get stream information
(in case there is no header)
- if(av_find_stream_info(pFormatContext) < 0)
- throw Exceptions::VideoFileBuffer::FileOpen(file, "Stream
information could not be read.");
-
- // No need to find the stream--we know which one it is (in
video_stream)
-
- // Get the codec context for this video stream
-#if LIBAVFORMAT_BUILD >= 4629
- pCodecContext =
pFormatContext->streams[video_stream]->codec;
-#else
- pCodecContext =
&pFormatContext->streams[video_stream]->codec;
-#endif
-
- // Find the decoder for the video stream
- AVCodec* pCodec =
avcodec_find_decoder(pCodecContext->codec_id);
- if(pCodec == NULL)
- {
- pCodecContext = 0; // Since it's not been opened yet
- throw Exceptions::VideoFileBuffer::FileOpen(file, "No
appropriate codec could be found.");
- }
-
- // Open codec
- if(avcodec_open(pCodecContext, pCodec) < 0)
- {
- pCodecContext = 0; // Since it's not been opened yet
- throw Exceptions::VideoFileBuffer::FileOpen(file,
std::string(pCodec->name) + " codec could not be initialised.");
- }
-
- start_time = 0;
- frame_ready = true;
-
- // REOPENED FILE OK
- // Now read frames until we get to the time we want
-
- int frames = static_cast<int>((t * frames_per_second() +
0.5));
- for(int i = 0; i < frames; i++)
- {
- read_next_frame();
- }
- }
-
- if(!read_next_frame())
- throw Exceptions::VideoFileBuffer::BadSeek(t);
- }
-
-
- /// What should the buffer do when it reaches the end of the list of
files?
- /// @param behaviour The desired behaviour
- void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer behaviour)
- {
- end_of_buffer_behaviour = behaviour;
- }
-
- /// What is the (expected) frame rate of this video buffer, in frames
per second?
- double frames_per_second()
- {
-#if LIBAVCODEC_BUILD >= 4754
- return pCodecContext->time_base.den /
static_cast<double>(pCodecContext->time_base.num);
-#else
- return pCodecContext->frame_rate /
static_cast<double>(pCodecContext->frame_rate_base);
-#endif
- };
-
- /// What is the path to the video file?
- std::string file_name()
- {
- return pFormatContext->filename;
- }
-
- /// What codec is being used to decode this video?
- std::string codec_name()
- {
- return pCodecContext->codec_name;
- }
-
- private:
- bool read_next_frame()
- {
- //Make next_frame point to a new block of data
- Image<T> tmp(my_size);
- next_frame = tmp;
-
- //Assign this new memory block
- avpicture_fill((AVPicture *)pFrameRGB,
reinterpret_cast<uint8_t*>(next_frame.data()),
is_rgb?PIX_FMT_RGB24:PIX_FMT_GRAY8, pCodecContext->width,
pCodecContext->height);
-
- AVPacket packet;
- packet.stream_index = -1;
-
- // How many frames do we read looking for our video stream?
- // If we assume our streams are interlaced, and some might be
interlaced
- // 2:1, this should probably do
- const int max_loop = MAX_STREAMS * 2;
-
- int i;
- for(i = 0; packet.stream_index != video_stream && i < max_loop;
i++)
- {
- if(av_read_frame(pFormatContext, &packet) < 0)
- return false;
-
- if(packet.stream_index == video_stream)
- {
- // Ask this packet what time it is
- if(packet.pts >= 0)
- frame_time = packet.pts /
static_cast<double>(AV_TIME_BASE);
- else // sometimes this is reported incorrectly, so guess
- {
- frame_time = frame_time + 1.0 / frames_per_second();
- }
-
- // Decode video frame
- int got_picture;
- if(avcodec_decode_video(pCodecContext, pFrame,
&got_picture,
- packet.data, packet.size) == -1)
- {
- throw
Exceptions::VideoFileBuffer::BadDecode(frame_time);
- }
-
- // Did we get a video frame?
- if(got_picture)
- {
- // Convert the image from its native format to RGB
- img_convert((AVPicture *)pFrameRGB,
is_rgb?PIX_FMT_RGB24:PIX_FMT_GRAY8,
- (AVPicture*)pFrame,
pCodecContext->pix_fmt,
- pCodecContext->width,
pCodecContext->height);
-
- }
- }
-
- // Free the packet that was allocated by av_read_frame
- av_free_packet(&packet);
- }
+ public:
+ /// Construct a video buffer to play this file
+ /// @param file The path to the video file
+ /// @param is_rgb Is RGB data wanted?
+ RawVideoFileBuffer(const std::string& file, bool
is_rgb);
+ ~RawVideoFileBuffer();
+
+ /// The size of the VideoFrames returned by this buffer
+ ImageRef size()
+ {
+ return my_size;
+ }
+
+ /// Returns the next frame from the buffer. This
function blocks until a frame is ready.
+ void* get_frame();
+ /// Tell the buffer that you are finished with this
frame.
+ /// \param f The frame that you are finished with.
+ void put_frame(void* f);
- // Did we not find one?
- if(i == max_loop)
- return false;
-
- return true;
- }
-
- ImageRef my_size;
- VideoBufferFlags::OnEndOfBuffer end_of_buffer_behaviour;
- double start_time;
- bool frame_ready;
-
- AVFormatContext* pFormatContext;
- int video_stream;
- AVCodecContext* pCodecContext;
- AVFrame* pFrame;
- AVFrame* pFrameRGB;
- CVD::Image<T> next_frame;
- double frame_time;
- bool is_rgb;
+ /// Is there a frame waiting in the buffer? This
function does not block.
+ bool frame_pending()
+ {
+ return frame_ready;
+ }
+
+ /// Go to a particular point in the video buffer (only
implemented in buffers of recorded video)
+ /// \param t The frame time in seconds
+ void seek_to(double t);
+
+ /// What should the buffer do when it reaches the end
of the list of files?
+ /// @param behaviour The desired behaviour
+ void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer
behaviour)
+ {
+ end_of_buffer_behaviour = behaviour;
+ }
+
+ /// What is the (expected) frame rate of this video
buffer, in frames per second?
+ double frames_per_second()
+ {
+ #if LIBAVCODEC_BUILD >= 4754
+ return pCodecContext->time_base.den /
static_cast<double>(pCodecContext->time_base.num);
+ #else
+ return pCodecContext->frame_rate /
static_cast<double>(pCodecContext->frame_rate_base);
+ #endif
+ };
+
+ /// What is the path to the video file?
+ std::string file_name()
+ {
+ return pFormatContext->filename;
+ }
+
+ /// What codec is being used to decode this video?
+ std::string codec_name()
+ {
+ return pCodecContext->codec_name;
+ }
+
+ private:
+ bool read_next_frame();
+
+ private:
+ ImageRef my_size;
+ VideoBufferFlags::OnEndOfBuffer end_of_buffer_behaviour;
+ double start_time;
+ bool frame_ready;
+
+ AVFormatContext* pFormatContext;
+ int video_stream;
+ AVCodecContext* pCodecContext;
+ AVFrame* pFrame;
+ AVFrame* pFrameRGB;
+
+ CVD::Image<CVD::Rgb<byte> > next_frame_rgb;
+ CVD::Image<CVD::byte> next_frame;
+
+ double frame_time;
+ bool is_rgb;
};
- }
-
- /// A video buffer to play frames from a video file.
- /// This uses the ffmpeg library (http://ffmpeg.sourceforge.net/) to play
- /// a wide range of video formats, including MPEG (1, 2 and 4) and AVI
(including
- /// DivX and DV) files.
- /// Provides frames of type CVD::VideoFileFrame and throws exceptions of
type
- /// CVD::Exceptions::VideoFileBuffer
- /// @param T The pixel type of the video frames. Currently only
<code>CVD::Rgb<CVD::byte> ></code> and
- /// <code>CVD::byte></code> are supported.
- /// @ingroup gVideoBuffer
- template<typename T>
- class VideoFileBuffer : public CVD::LocalVideoBuffer<T>
- {
- private:
- VFB::RawVideoFileBuffer<T> vf;
+ }
+
+ /// A video buffer to play frames from a video file.
+ /// This uses the ffmpeg library (http://ffmpeg.sourceforge.net/) to
play
+ /// a wide range of video formats, including MPEG (1, 2 and 4) and AVI
(including
+ /// DivX and DV) files.
+ /// Provides frames of type CVD::VideoFileFrame and throws exceptions
of type
+ /// CVD::Exceptions::VideoFileBuffer
+ /// @param T The pixel type of the video frames. Currently only
<code>CVD::Rgb<CVD::byte> ></code> and
+ /// <code>CVD::byte></code> are supported.
+ /// @ingroup gVideoBuffer
+ template<typename T>
+ class VideoFileBuffer : public CVD::LocalVideoBuffer<T>
+ {
+ private:
+ VFB::RawVideoFileBuffer vf;
+
+
+ public:
+ /// Construct a VideoFileBuffer to play this file
+ /// @param file The path to the video file
+ VideoFileBuffer(const std::string& file)
+ :vf(file, VFB::rgb<T>::p)
+ {
+ }
+
+ ~VideoFileBuffer()
+ {
+ }
- public:
- /// Construct a VideoFileBuffer to play this file
- /// @param file The path to the video file
- VideoFileBuffer(const std::string& file)
- :vf(file, VFB::rgb<T>::p)
- {
- }
-
- ~VideoFileBuffer()
- {
- }
-
- virtual ImageRef size()
- {
- return vf.size();
- }
-
- virtual bool frame_pending()
- {
- return vf.frame_pending();
- }
-
- /// What should the buffer do when it reaches the end of the list of
files?
- /// @param behaviour The desired behaviour
- virtual void on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer
behaviour)
- {
- vf.on_end_of_buffer(behaviour);
- }
-
- virtual void seek_to(double t)
- {
- vf.seek_to(t);
- }
-
- virtual VideoFileFrame<T> * get_frame()
- {
- return vf.get_frame();
- }
-
- virtual void put_frame(VideoFrame<T>* f)
- {
- vf.put_frame(f);
- }
-
- // This class additions
-
- double frame_rate()
- {
- return vf.frames_per_second();
- }
-
- /// What is the path to the video file?
- std::string file_name()
- {
- return vf.file_name();
- }
-
- /// What codec is being used to decode this video?
- std::string codec_name()
- {
- return vf.codec_name();
- }
-
- private:
-
- };
+ virtual ImageRef size()
+ {
+ return vf.size();
+ }
+
+ virtual bool frame_pending()
+ {
+ return vf.frame_pending();
+ }
+
+ /// What should the buffer do when it reaches the end
of the list of files?
+ /// @param behaviour The desired behaviour
+ virtual void
on_end_of_buffer(VideoBufferFlags::OnEndOfBuffer behaviour)
+ {
+ vf.on_end_of_buffer(behaviour);
+ }
+
+ virtual void seek_to(double t)
+ {
+ vf.seek_to(t);
+ }
+
+ virtual VideoFileFrame<T> * get_frame()
+ {
+ return
reinterpret_cast<VideoFileFrame<T>*>(vf.get_frame());
+ }
+
+ virtual void put_frame(VideoFrame<T>* f)
+ {
+ vf.put_frame(f);
+ }
+
+ // This class additions
+
+ double frame_rate()
+ {
+ return vf.frames_per_second();
+ }
+
+ /// What is the path to the video file?
+ std::string file_name()
+ {
+ return vf.file_name();
+ }
+
+ /// What codec is being used to decode this video?
+ std::string codec_name()
+ {
+ return vf.codec_name();
+ }
+
+ private:
+ };
}
#endif
Index: libcvd/cvd/videofilebuffer_frame.h
diff -u libcvd/cvd/videofilebuffer_frame.h:1.7
libcvd/cvd/videofilebuffer_frame.h:1.8
--- libcvd/cvd/videofilebuffer_frame.h:1.7 Tue May 23 15:25:33 2006
+++ libcvd/cvd/videofilebuffer_frame.h Wed May 24 13:09:18 2006
@@ -32,36 +32,37 @@
namespace CVD
{
- namespace VFB
- {
- template<typename T>
- class RawVideoFileBuffer;
- }
-
- /// A frame from a VideoFileBuffer.
- /// @ingroup gVideoFrame
- /// @param T The pixel type of the video frames. Currently only
<code>CVD::Rgb<CVD::byte> ></code> and
- /// <code>CVD::byte></code> are supported.
- template<class T>
- class VideoFileFrame: public CVD::LocalVideoFrame<T>
- {
- friend class VFB::RawVideoFileBuffer<T>;
-
- protected:
- ~VideoFileFrame()
+ namespace VFB
{
+ class RawVideoFileBuffer;
}
-
- /// Construct a video frame from an Image and a timestamp
- /// @param time The timestamp of this frame
- /// @param local The Image to use for this frame
- VideoFileFrame(double time, CVD::Image<T>& local)
- :LocalVideoFrame<T>(time, local)
+
+ /// A frame from a VideoFileBuffer.
+ /// @ingroup gVideoFrame
+ /// @param T The pixel type of the video frames. Currently only
<code>CVD::Rgb<CVD::byte> ></code> and
+ /// <code>CVD::byte></code> are supported.
+ template<class T>
+ class VideoFileFrame: public CVD::LocalVideoFrame<T>
{
- }
-
- private:
- };
+ friend class VFB::RawVideoFileBuffer;
+
+ public:
+ inline void delete_self() { delete this; }
+ protected:
+ ~VideoFileFrame()
+ {
+ }
+
+ /// Construct a video frame from an Image and a
timestamp
+ /// @param time The timestamp of this frame
+ /// @param local The Image to use for this frame
+ VideoFileFrame(double time, CVD::Image<T>& local)
+ :LocalVideoFrame<T>(time, local)
+ {
+ }
+
+ private:
+ };
}
Index: libcvd/cvd_src/videofilebuffer.cc
diff -u libcvd/cvd_src/videofilebuffer.cc:1.11
libcvd/cvd_src/videofilebuffer.cc:1.12
--- libcvd/cvd_src/videofilebuffer.cc:1.11 Tue May 23 15:33:37 2006
+++ libcvd/cvd_src/videofilebuffer.cc Wed May 24 13:09:18 2006
@@ -21,15 +21,6 @@
// Paul Smith 1 March 2005
// Uses ffmpeg libraries to play most types of video file
-
-// ************************************************************
-// As RawVideoFileBuffer is now a templated class, the
-// code in this file has been moved to cvd/videofilebuffer.h.
-// Thus this file is now deprecated, and is no longer required.
-// ************************************************************
-#if 0
-
-
#include <string>
#include <sstream>
@@ -95,18 +86,18 @@
{
// Register the formats and codecs
av_register_all();
-
+
// Now open the video file (and read the header, if present)
if(av_open_input_file(&pFormatContext, file.c_str(), NULL, 0,
NULL) != 0)
throw FileOpen(file, "File could not be opened.");
-
+
// Read the beginning of the file to get stream information (in
case there is no header)
if(av_find_stream_info(pFormatContext) < 0)
throw FileOpen(file, "Stream information could not be
read.");
-
+
// Dump details of the video to standard error
- dump_format(pFormatContext, 0, file.c_str(), false);
-
+ //dump_format(pFormatContext, 0, file.c_str(), false);
+
// We shall just use the first video stream
video_stream = -1;
for(int i=0; i < pFormatContext->nb_streams && video_stream ==
-1; i++)
@@ -128,7 +119,7 @@
#else
pCodecContext = &pFormatContext->streams[video_stream]->codec;
#endif
-
+
// Find the decoder for the video stream
AVCodec* pCodec = avcodec_find_decoder(pCodecContext->codec_id);
if(pCodec == NULL)
@@ -150,11 +141,12 @@
pCodecContext->frame_rate_base = 1000;
#endif
+
// Allocate video frame
pFrame = avcodec_alloc_frame();
if(pFrame == NULL)
throw BadFrameAlloc();
-
+
// And a frame to hold the RGB version
pFrameRGB = avcodec_alloc_frame();
if(pFrameRGB == NULL)
@@ -218,23 +210,23 @@
//
bool RawVideoFileBuffer::read_next_frame()
{
+ uint8_t* data;
+
//Make next_frame point to a new block of data, getting the sizes
correct.
-
+ //Resize always causes seperation of data.
if(is_rgb)
{
- Image<Rgb<byte> > tmp(my_size);
- next_frame = (reinterpret_cast<Image<byte>&>(tmp));
- next_frame = tmp;
+ next_frame_rgb.resize(my_size);
+ data = reinterpret_cast<uint8_t*>(next_frame_rgb.data());
}
else
-
{
- Image<byte> tmp(my_size);
- next_frame = tmp;
+ next_frame.resize(my_size);
+ data = reinterpret_cast<uint8_t*>(next_frame.data());
}
//Assign this new memory block
- avpicture_fill((AVPicture *)pFrameRGB,
reinterpret_cast<uint8_t*>(next_frame.data()),
is_rgb?PIX_FMT_RGB24:PIX_FMT_GRAY8, pCodecContext->width,
pCodecContext->height);
+ avpicture_fill((AVPicture *)pFrameRGB, data,
is_rgb?PIX_FMT_RGB24:PIX_FMT_GRAY8, pCodecContext->width,
pCodecContext->height);
AVPacket packet;
@@ -296,7 +288,7 @@
//
// GET FRAME
//
-VideoFileFrame<byte>* RawVideoFileBuffer::get_frame()
+void* RawVideoFileBuffer::get_frame()
{
if(!frame_pending())
@@ -305,7 +297,15 @@
// Don't use - pCC->frame_number doesn't reset after a seek!
// Instead, we ask the packet its time when we decode it
// double time = start_time + pCodecContext->frame_number *
pCodecContext->frame_rate_base / static_cast<double>(pCodecContext->frame_rate);
- VideoFileFrame<byte>* vf = new VideoFileFrame<byte>(frame_time,
next_frame);
+
+ VideoFileFrame<byte> *vfb = NULL;
+ VideoFileFrame<Rgb<byte> > *vfrgb = NULL;
+
+ if(is_rgb)
+ vfrgb = new VideoFileFrame<Rgb<byte> >(frame_time,
next_frame_rgb);
+ else
+ vfb = new VideoFileFrame<byte>(frame_time, next_frame);
+
if(!read_next_frame())
{
@@ -316,15 +316,9 @@
// I'll copy the one that I'm about to return
so that
// I can return it next time as well
if(is_rgb)
- {
- Image<Rgb<byte> > tmp =
reinterpret_cast<Image<Rgb<byte> >&>(next_frame);
-
tmp.copy_from(reinterpret_cast<VideoFileFrame<Rgb<byte> >&>(*vf));
- next_frame =
(reinterpret_cast<Image<byte>&>(tmp));
- }
+ next_frame_rgb.copy_from(*vfrgb);
else
- {
- next_frame.copy_from(*vf);
- }
+ next_frame.copy_from(*vfb);
break;
case VideoBufferFlags::UnsetPending:
@@ -336,21 +330,34 @@
break;
}
}
+
+ if(vfb)
+ return vfb;
+ else
+ return vfrgb;
+}
+
+
+template<class C> void delete_frame_or_throw(void* f)
+{
+ VideoFrame<C>* vf = reinterpret_cast<VideoFrame<C>*>(f);
+ VideoFileFrame<C>* vff = dynamic_cast<VideoFileFrame<C>*>(vf);
- return vf;
+ if(!vff)
+ throw Exceptions::VideoBuffer::BadPutFrame();
+ else
+ vff->delete_self();
}
//
// PUT FRAME
//
-void RawVideoFileBuffer::put_frame(VideoFrame<byte>* f)
+void RawVideoFileBuffer::put_frame(void* f)
{
- VideoFileFrame<byte>* vff = dynamic_cast<VideoFileFrame<byte> *>(f);
-
- if(!vff)
- throw Exceptions::VideoBuffer::BadPutFrame();
+ if(is_rgb)
+ delete_frame_or_throw<Rgb<byte> >(f);
else
- delete vff;
+ delete_frame_or_throw<byte>(f);
}
//
@@ -423,7 +430,3 @@
}
} // namespace CVD
-
-
-
-#endif // #if 0
- [Libcvd-members] libcvd cvd/videofilebuffer.h cvd/videofilebuffe...,
Colin Starr <=