[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: |
Tue, 23 May 2006 15:25:33 +0000 |
CVSROOT: /cvsroot/libcvd
Module name: libcvd
Branch:
Changes by: Colin Starr <address@hidden> 06/05/23 15:25:33
Modified files:
cvd : videofilebuffer.h videofilebuffer_frame.h
cvd_src : videofilebuffer.cc
Log message:
RawVideoFileBuffer is now a templated class. This allows the
VideoFileBuffer to correctly return frames of type Rgb<byte>.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/libcvd/libcvd/cvd/videofilebuffer.h.diff?tr1=1.11&tr2=1.12&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/libcvd/libcvd/cvd/videofilebuffer_frame.h.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/libcvd/libcvd/cvd_src/videofilebuffer.cc.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
Patches:
Index: libcvd/cvd/videofilebuffer.h
diff -u libcvd/cvd/videofilebuffer.h:1.11 libcvd/cvd/videofilebuffer.h:1.12
--- libcvd/cvd/videofilebuffer.h:1.11 Tue Sep 13 11:22:22 2005
+++ libcvd/cvd/videofilebuffer.h Tue May 23 15:25:33 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,6 +24,7 @@
#include <vector>
#include <string>
+#include <sstream>
#include <fstream>
#include <errno.h>
@@ -43,220 +44,545 @@
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
- };
- /// 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;
+ 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;
+ }
};
-
- template<> struct rgb<CVD::byte>
- {
- static const bool p=false;
+
+ /// Unable to open allocate a video frame
+ /// @ingroup gException
+ struct BadFrameAlloc: public All {
+ BadFrameAlloc()
+ {
+ what = "RawVideoFileBuffer: Unable to allocate video frame.";
+ }
};
-
- template<> struct rgb<CVD::Rgb<CVD::byte> >
- {
- static const bool p=true;
+
+ /// 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();
+ }
};
- #endif
-
- /// 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
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.
- VideoFileFrame<byte>* get_frame();
- /// Tell the buffer that you are finished with this
frame.
- /// \param f The frame that you are finished with.
- void put_frame(VideoFrame<CVD::byte>* f);
-
- /// 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::byte> next_frame;
- double frame_time;
- bool is_rgb;
+
+ /// 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.";
+ }
};
- }
-
- /// 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>
+
+ /// 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();
+ }
+ };
+ }
+ }
+
+
+ /// 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
{
- 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()
- {
- }
-
- 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(reinterpret_cast<VideoFrame<byte>*>(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();
- }
+ 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);
+ }
- /// What codec is being used to decode this video?
- std::string codec_name()
- {
- return vf.codec_name();
- }
-
- private:
+ // 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;
};
+ }
+
+ /// 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;
+
+ 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:
+
+ };
}
#endif
Index: libcvd/cvd/videofilebuffer_frame.h
diff -u libcvd/cvd/videofilebuffer_frame.h:1.6
libcvd/cvd/videofilebuffer_frame.h:1.7
--- libcvd/cvd/videofilebuffer_frame.h:1.6 Mon May 9 11:54:58 2005
+++ libcvd/cvd/videofilebuffer_frame.h Tue May 23 15:25:33 2006
@@ -32,35 +32,36 @@
namespace CVD
{
- namespace VFB
+ 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()
{
- 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>
+
+ /// 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)
{
- friend class VFB::RawVideoFileBuffer;
-
- 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:
- };
+ }
+
+ private:
+ };
}
Index: libcvd/cvd_src/videofilebuffer.cc
diff -u libcvd/cvd_src/videofilebuffer.cc:1.9
libcvd/cvd_src/videofilebuffer.cc:1.10
--- libcvd/cvd_src/videofilebuffer.cc:1.9 Thu Sep 1 11:52:04 2005
+++ libcvd/cvd_src/videofilebuffer.cc Tue May 23 15:25:33 2006
@@ -21,6 +21,15 @@
// 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>
@@ -86,18 +95,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);
-
+
// We shall just use the first video stream
video_stream = -1;
for(int i=0; i < pFormatContext->nb_streams && video_stream ==
-1; i++)
@@ -119,7 +128,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)
@@ -141,12 +150,11 @@
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)
@@ -211,12 +219,25 @@
bool RawVideoFileBuffer::read_next_frame()
{
//Make next_frame point to a new block of data, getting the sizes
correct.
+
if(is_rgb)
{
+ printf("Before creating tmp\n");
+
+
+
Image<Rgb<byte> > tmp(my_size);
- next_frame = (reinterpret_cast<Image<byte>&>(tmp));
+ //next_frame = (reinterpret_cast<Image<byte>&>(tmp));
+ next_frame = tmp;
+
+ printf("RawVideoFileBuffer::read_next_frame(): tmp = %p\n",
(void *) &tmp);
+
+ std::cout << next_frame.size() << " " << my_size << std::endl;
+ std::cout << sizeof(tmp) << " " << sizeof(next_frame) <<
std::endl;
+ printf("RawVideoFileBuffer::read_next_frame(): next_frame =
%p\n", (void *) &next_frame);
}
else
+
{
Image<byte> tmp(my_size);
next_frame = tmp;
@@ -285,7 +306,9 @@
//
// GET FRAME
//
-VideoFileFrame<byte>* RawVideoFileBuffer::get_frame()
+//CCS36
+//VideoFileFrame<byte>* RawVideoFileBuffer::get_frame()
+VideoFileFrame<T>* RawVideoFileBuffer::get_frame()
{
if(!frame_pending())
@@ -294,7 +317,11 @@
// 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);
+ puts("get_frame: before vf");
+ //CCS36
+ //VideoFileFrame<byte>* vf = new VideoFileFrame<byte>(frame_time,
next_frame);
+ VideoFileFrame<T>* vf = new VideoFileFrame<T>(frame_time, next_frame);
+ printf("get_frame: after vf; vf = %p\n", (void *) vf);
if(!read_next_frame())
{
@@ -306,9 +333,11 @@
// 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));
+ //CCS36
+ //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.copy_from(*vf);
}
else
{
@@ -332,9 +361,13 @@
//
// PUT FRAME
//
-void RawVideoFileBuffer::put_frame(VideoFrame<byte>* f)
-{
- VideoFileFrame<byte>* vff = dynamic_cast<VideoFileFrame<byte> *>(f);
+//CCS36
+//void RawVideoFileBuffer::put_frame(VideoFrame<byte>* f)
+void RawVideoFileBuffer::put_frame(VideoFrame<T>* f)
+{
+ //CCS36
+ //VideoFileFrame<byte>* vff = dynamic_cast<VideoFileFrame<byte> *>(f);
+ VideoFileFrame<T>* vff = dynamic_cast(VideoFileFrame<T> *>(f);
if(!vff)
throw Exceptions::VideoBuffer::BadPutFrame();
@@ -412,3 +445,7 @@
}
} // namespace CVD
+
+
+
+#endif // #if 0
- [Libcvd-members] libcvd cvd/videofilebuffer.h cvd/videofilebuffe...,
Colin Starr <=