Panda3D

ffmpegVirtualFile.cxx

00001 // Filename: ffmpegVirtualFile.cxx
00002 // Created by: jyelon (02Jul07)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifdef HAVE_FFMPEG
00016 
00017 #include "pandabase.h"
00018 #include "config_movies.h"
00019 #include "ffmpegVirtualFile.h"
00020 #include "virtualFileSystem.h"
00021 extern "C" {
00022   #include "libavformat/avio.h"
00023 }
00024 
00025 #ifndef AVSEEK_SIZE
00026   #define AVSEEK_SIZE 0x10000
00027 #endif
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 // These functions need to use C calling conventions.
00031 ////////////////////////////////////////////////////////////////////
00032 extern "C" {
00033   static int       pandavfs_open(URLContext *h, const char *filename, int flags);
00034   static int       pandavfs_read(URLContext *h, unsigned char *buf, int size);
00035 // This change happened a few days before 52.68.0
00036 #if LIBAVFORMAT_VERSION_INT < 3425280
00037   static int       pandavfs_write(URLContext *h, unsigned char *buf, int size);
00038 #else
00039   static int       pandavfs_write(URLContext *h, const unsigned char *buf, int size);
00040 #endif
00041   static PN_int64  pandavfs_seek(URLContext *h, PN_int64 pos, int whence);
00042   static int       pandavfs_close(URLContext *h);
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: pandavfs_open
00047 //       Access: Static Function
00048 //  Description: A hook to open a panda VFS file.
00049 ////////////////////////////////////////////////////////////////////
00050 static int
00051 pandavfs_open(URLContext *h, const char *filename, int flags) {
00052   if (flags != 0) {
00053     movies_cat.error() << "ffmpeg is trying to write to the VFS.\n";
00054     return -1;
00055   }
00056   filename += 9; // Skip over "pandavfs:"
00057   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00058   istream *s = vfs->open_read_file(filename, true);
00059   if (s == 0) {
00060     return -1;
00061   }
00062   // Test whether seek works.
00063   s->seekg(1, ios::beg);
00064   int tel1 = s->tellg();
00065   s->seekg(0, ios::beg);
00066   int tel2 = s->tellg();
00067   if (s->fail() || (tel1!=1) || (tel2!=0)) {
00068     movies_cat.error() << "cannot play movie (not seekable): " << h->filename << "\n";
00069     delete s;
00070     return -1;
00071   }
00072   h->priv_data = s;
00073   return 0;
00074 }
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: pandavfs_read
00078 //       Access: Static Function
00079 //  Description: A hook to read a panda VFS file.
00080 ////////////////////////////////////////////////////////////////////
00081 static int
00082 pandavfs_read(URLContext *h, unsigned char *buf, int size) {
00083   istream *s = (istream*)(h->priv_data);
00084   s->read((char*)buf, size);
00085   int gc = s->gcount();
00086   s->clear();
00087   return gc;
00088 }
00089 
00090 ////////////////////////////////////////////////////////////////////
00091 //     Function: pandavfs_write
00092 //       Access: Static Function
00093 //  Description: A hook to write a panda VFS file.
00094 ////////////////////////////////////////////////////////////////////
00095 static int
00096 #if LIBAVFORMAT_VERSION_INT < 3425280
00097 pandavfs_write(URLContext *h, unsigned char *buf, int size) {
00098 #else
00099 pandavfs_write(URLContext *h, const unsigned char *buf, int size) {
00100 #endif
00101   movies_cat.error() << "ffmpeg is trying to write to the VFS.\n";
00102   return -1;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: pandavfs_seek
00107 //       Access: Static Function
00108 //  Description: A hook to seek a panda VFS file.
00109 ////////////////////////////////////////////////////////////////////
00110 static PN_int64
00111 pandavfs_seek(URLContext *h, PN_int64 pos, int whence) {
00112   istream *s = (istream*)(h->priv_data);
00113   switch(whence) {
00114   case SEEK_SET: s->seekg(pos, ios::beg); break;
00115   case SEEK_CUR: s->seekg(pos, ios::cur); break;
00116   case SEEK_END: s->seekg(pos, ios::end); break;
00117   case AVSEEK_SIZE: {
00118     s->seekg(0, ios::cur);
00119     int p = s->tellg();
00120     s->seekg(-1, ios::end);
00121     int size = s->tellg();
00122     if (size < 0) {
00123       movies_cat.error() << "Failed to determine filesize in ffmpegVirtualFile\n";
00124       s->clear();
00125       return -1;
00126     }
00127     size++;
00128     s->seekg(p, ios::beg);
00129     s->clear();
00130     return size; }
00131   default:
00132     movies_cat.error() << "Illegal parameter to seek in ffmpegVirtualFile\n";
00133     s->clear();
00134     return -1;
00135   }
00136   s->clear();
00137   int tl = s->tellg();
00138   return tl;
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: pandavfs_close
00143 //       Access: Static Function
00144 //  Description: A hook to close a panda VFS file.
00145 ////////////////////////////////////////////////////////////////////
00146 static int
00147 pandavfs_close(URLContext *h) {
00148   istream *s = (istream*)(h->priv_data);
00149   delete s;
00150   h->priv_data = 0;
00151   return 0;
00152 }
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: FfmpegVirtualFile::register_protocol
00156 //       Access: Public, Static
00157 //  Description: Enables ffmpeg to access panda's VFS.
00158 //
00159 //               After calling this method, ffmpeg will be
00160 //               able to open "URLs" that look like this:
00161 //               
00162 //               pandavfs:/c/mygame/foo.avi
00163 //
00164 ////////////////////////////////////////////////////////////////////
00165 void FfmpegVirtualFile::
00166 register_protocol() {
00167   static bool initialized = false;
00168   if (initialized) {
00169     return;
00170   }
00171   static URLProtocol protocol;
00172   protocol.name = "pandavfs";
00173   protocol.url_open  = pandavfs_open;
00174   protocol.url_read  = pandavfs_read;
00175   protocol.url_write = pandavfs_write;
00176   protocol.url_seek  = pandavfs_seek;
00177   protocol.url_close = pandavfs_close;
00178 #if LIBAVFORMAT_VERSION_INT < 3415296
00179   ::register_protocol(&protocol);
00180 #else
00181   av_register_protocol(&protocol);
00182 #endif
00183 }
00184 
00185 #endif // HAVE_FFMPEG
 All Classes Functions Variables Enumerations