From 39662c86e0f902ffa102ec17b8dacd6067f0b848 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Wed, 15 Aug 2007 22:03:45 +0000 Subject: [PATCH] Added VFS support --- panda/src/movies/Sources.pp | 3 + panda/src/movies/config_movies.cxx | 1 + panda/src/movies/ffmpegVideo.cxx | 7 +- panda/src/movies/ffmpegVirtualFile.I | 17 +++ panda/src/movies/ffmpegVirtualFile.cxx | 155 +++++++++++++++++++++++++ panda/src/movies/ffmpegVirtualFile.h | 46 ++++++++ panda/src/movies/movies_composite1.cxx | 1 + 7 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 panda/src/movies/ffmpegVirtualFile.I create mode 100644 panda/src/movies/ffmpegVirtualFile.cxx create mode 100644 panda/src/movies/ffmpegVirtualFile.h diff --git a/panda/src/movies/Sources.pp b/panda/src/movies/Sources.pp index 866360da84..7d43ee4863 100644 --- a/panda/src/movies/Sources.pp +++ b/panda/src/movies/Sources.pp @@ -16,6 +16,7 @@ inkblotVideo.h inkblotVideo.I \ ffmpegVideo.h ffmpegVideo.I \ ffmpegAudio.h ffmpegAudio.I \ + ffmpegVirtualFile.h ffmpegVirtualFile.I \ config_movies.h #define INCLUDED_SOURCES \ @@ -24,6 +25,7 @@ inkblotVideo.cxx \ ffmpegVideo.cxx \ ffmpegAudio.cxx \ + ffmpegVirtualFile.cxx \ config_movies.cxx #define INSTALL_HEADERS \ @@ -32,6 +34,7 @@ inkblotVideo.h inkblotVideo.I \ ffmpegVideo.h ffmpegVideo.I \ ffmpegAudio.h ffmpegAudio.I \ + ffmpegVirtualFile.h ffmpegVirtualFile.I \ config_movies.h #define IGATESCAN all diff --git a/panda/src/movies/config_movies.cxx b/panda/src/movies/config_movies.cxx index d22086f304..4786ef3d27 100644 --- a/panda/src/movies/config_movies.cxx +++ b/panda/src/movies/config_movies.cxx @@ -53,6 +53,7 @@ init_libmovies() { FfmpegVideo::init_type(); FfmpegAudio::init_type(); av_register_all(); + FfmpegVirtualFile::register_protocol(); #endif } diff --git a/panda/src/movies/ffmpegVideo.cxx b/panda/src/movies/ffmpegVideo.cxx index 42f5710739..eda5673b10 100644 --- a/panda/src/movies/ffmpegVideo.cxx +++ b/panda/src/movies/ffmpegVideo.cxx @@ -41,8 +41,9 @@ FfmpegVideo(const Filename &name) : _frame_out(0), _min_fseek(3.0) { - string osname = _filename.to_os_specific(); - if (av_open_input_file(&_format_ctx, osname.c_str(), NULL, 0, NULL)!=0) { + string url = "pandavfs:"; + url += name; + if (av_open_input_file(&_format_ctx, url.c_str(), NULL, 0, NULL)!=0) { cleanup(); return; } @@ -203,7 +204,6 @@ fetch_frame() { fetch_packet(_last_start + 1.0); } _next_start = _packet_time; - cerr << "Fetch yields " << _last_start << " - " << _next_start << "\n"; } //////////////////////////////////////////////////////////////////// @@ -230,7 +230,6 @@ seek(double t) { return; } fetch_packet(t); - cerr << "Seeking to " << t << " yields " << _packet_time << "\n"; if (_packet_time > t) { _packet_time = t; } diff --git a/panda/src/movies/ffmpegVirtualFile.I b/panda/src/movies/ffmpegVirtualFile.I new file mode 100644 index 0000000000..77f1b03103 --- /dev/null +++ b/panda/src/movies/ffmpegVirtualFile.I @@ -0,0 +1,17 @@ +// Filename: ffmpegVirtualFile.I +// Created by: jyelon (01Aug2007) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2007, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// diff --git a/panda/src/movies/ffmpegVirtualFile.cxx b/panda/src/movies/ffmpegVirtualFile.cxx new file mode 100644 index 0000000000..228350e41b --- /dev/null +++ b/panda/src/movies/ffmpegVirtualFile.cxx @@ -0,0 +1,155 @@ +// Filename: ffmpegVirtualFile.cxx +// Created by: jyelon (02Jul07) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2007, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifdef HAVE_FFMPEG + +#include "pandabase.h" +#include "config_movies.h" +#include "ffmpegVirtualFile.h" +#include "virtualFileSystem.h" +#include "avio.h" + +//////////////////////////////////////////////////////////////////// +// These functions need to use C calling conventions. +//////////////////////////////////////////////////////////////////// +extern "C" { + static int pandavfs_open(URLContext *h, const char *filename, int flags); + static int pandavfs_read(URLContext *h, unsigned char *buf, int size); + static int pandavfs_write(URLContext *h, unsigned char *buf, int size); + static PN_int64 pandavfs_seek(URLContext *h, PN_int64 pos, int whence); + static int pandavfs_close(URLContext *h); +} + +//////////////////////////////////////////////////////////////////// +// Function: pandavfs_open +// Access: Static Function +// Description: A hook to open a panda VFS file. +//////////////////////////////////////////////////////////////////// +static int +pandavfs_open(URLContext *h, const char *filename, int flags) { + if (flags != 0) { + movies_cat.error() << "ffmpeg is trying to write to the VFS.\n"; + return -1; + } + filename += 9; // Skip over "pandavfs:" + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + istream *s = vfs->open_read_file(filename, true); + if (s == 0) { + return -1; + } + // Test whether seek works. + s->seekg(1, ios::beg); + int tel1 = s->tellg(); + s->seekg(0, ios::beg); + int tel2 = s->tellg(); + if (s->fail() || (tel1!=1) || (tel2!=0)) { + movies_cat.error() << "cannot play movie (not seekable): " << h->filename << "\n"; + delete s; + return -1; + } + h->priv_data = s; + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: pandavfs_read +// Access: Static Function +// Description: A hook to read a panda VFS file. +//////////////////////////////////////////////////////////////////// +static int +pandavfs_read(URLContext *h, unsigned char *buf, int size) { + istream *s = (istream*)(h->priv_data); + s->read((char*)buf, size); + int gc = s->gcount(); + s->clear(); + return gc; +} + +//////////////////////////////////////////////////////////////////// +// Function: pandavfs_write +// Access: Static Function +// Description: A hook to write a panda VFS file. +//////////////////////////////////////////////////////////////////// +static int +pandavfs_write(URLContext *h, unsigned char *buf, int size) { + movies_cat.error() << "ffmpeg is trying to write to the VFS.\n"; + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: pandavfs_seek +// Access: Static Function +// Description: A hook to seek a panda VFS file. +//////////////////////////////////////////////////////////////////// +static PN_int64 +pandavfs_seek(URLContext *h, PN_int64 pos, int whence) { + istream *s = (istream*)(h->priv_data); + switch(whence) { + case 0: s->seekg(pos, ios::beg); break; + case 1: s->seekg(pos, ios::cur); break; + case 2: s->seekg(pos, ios::end); break; + default: + movies_cat.error() << "Illegal parameter to seek in ffmpegVirtualFile\n"; + return -1; + } + s->clear(); + int tl = s->tellg(); + return tl; +} + +//////////////////////////////////////////////////////////////////// +// Function: pandavfs_close +// Access: Static Function +// Description: A hook to close a panda VFS file. +//////////////////////////////////////////////////////////////////// +static int +pandavfs_close(URLContext *h) { + istream *s = (istream*)(h->priv_data); + delete s; + h->priv_data = 0; + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: FfmpegVirtualFile::register_protocol +// Access: Public, Static +// Description: Enables ffmpeg to access panda's VFS. +// +// After calling this method, ffmpeg will be +// able to open "URLs" that look like this: +// +// pandavfs:/c/mygame/foo.avi +// +//////////////////////////////////////////////////////////////////// +void FfmpegVirtualFile:: +register_protocol() { + static bool initialized = false; + if (initialized) { + return; + } + static URLProtocol protocol; + protocol.name = "pandavfs"; + protocol.url_open = pandavfs_open; + protocol.url_read = pandavfs_read; + protocol.url_write = pandavfs_write; + protocol.url_seek = pandavfs_seek; + protocol.url_close = pandavfs_close; + ::register_protocol(&protocol); +} + +#endif // HAVE_FFMPEG diff --git a/panda/src/movies/ffmpegVirtualFile.h b/panda/src/movies/ffmpegVirtualFile.h new file mode 100644 index 0000000000..cd8b12fb73 --- /dev/null +++ b/panda/src/movies/ffmpegVirtualFile.h @@ -0,0 +1,46 @@ +// Filename: ffmpegVirtualFile.h +// Created by: jyelon (01Aug2007) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2007, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef FFMPEGVIRTUALFILE_H +#define FFMPEGVIRTUALFILE_H +#ifdef HAVE_FFMPEG + +#include "config_movies.h" + +//////////////////////////////////////////////////////////////////// +// Class : FfmpegVirtualFile +// Description : Enables ffmpeg to access panda's VFS. +// +// This class only has one public method, +// register_hooks. Once the hooks are registered, +// ffmpeg will be able to open "URLs" that look +// like this: +// +// pandavfs:/c/mygame/foo.avi +// +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_MOVIES FfmpegVirtualFile { + public: + static void register_protocol(); +}; + +#include "ffmpegVirtualFile.I" + +#endif // HAVE_FFMPEG +#endif // FFMPEGVIRTUALFILE_H + diff --git a/panda/src/movies/movies_composite1.cxx b/panda/src/movies/movies_composite1.cxx index 22f9dec06a..e7ba3026aa 100644 --- a/panda/src/movies/movies_composite1.cxx +++ b/panda/src/movies/movies_composite1.cxx @@ -3,4 +3,5 @@ #include "inkblotVideo.cxx" #include "ffmpegAudio.cxx" #include "ffmpegVideo.cxx" +#include "ffmpegVirtualFile.cxx" #include "config_movies.cxx"