15 #include "pandabase.h"
17 #include "config_ffmpeg.h"
18 #include "ffmpegVirtualFile.h"
19 #include "virtualFileSystem.h"
22 #include "libavcodec/avcodec.h"
23 #include "libavformat/avformat.h"
27 #define AVSEEK_SIZE 0x10000
38 _format_context(NULL),
41 _buffer_size(ffmpeg_read_buffer_size)
51 ~FfmpegVirtualFile() {
70 void FfmpegVirtualFile::
86 if (ffmpeg_cat.is_debug()) {
88 <<
"ffmpeg open_vfs(" << filename <<
")\n";
99 _in = vfile->open_read_file(
true);
106 _size = vfile->get_file_size(_in);
111 unsigned char *buffer = (
unsigned char*) av_malloc(_buffer_size);
112 _io_context = avio_alloc_context(buffer, _buffer_size, 0, (
void*)
this,
113 &read_packet, 0, &seek);
115 _format_context = avformat_alloc_context();
116 _format_context->pb = _io_context;
120 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 4, 0)
121 avformat_open_input(&_format_context,
"", NULL, NULL);
123 av_open_input_file(&_format_context,
"", NULL, 0, NULL);
150 if (ffmpeg_cat.is_debug()) {
152 <<
"ffmpeg open_subfile(" << fname <<
")\n";
165 unsigned char *buffer = (
unsigned char*) av_malloc(_buffer_size);
166 _io_context = avio_alloc_context(buffer, _buffer_size, 0, (
void*)
this,
167 &read_packet, 0, &seek);
169 _format_context = avformat_alloc_context();
170 _format_context->pb = _io_context;
174 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 4, 0)
175 avformat_open_input(&_format_context, fname.c_str(), NULL, NULL);
177 av_open_input_file(&_format_context, fname.c_str(), NULL, 0, NULL);
195 if (_format_context != NULL) {
196 #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0)
197 avformat_close_input(&_format_context);
199 av_close_input_file(_format_context);
200 _format_context = NULL;
204 if (_io_context != NULL) {
205 if (_io_context->buffer != NULL) {
206 av_free(_io_context->buffer);
208 av_free(_io_context);
213 nassertv(_in != NULL);
228 static bool initialized =
false;
238 #if LIBAVFORMAT_VERSION_INT >= 0x351400
239 avformat_network_init();
243 av_log_set_callback(&log_callback);
251 int FfmpegVirtualFile::
252 read_packet(
void *opaque, uint8_t *buf,
int size) {
253 streampos ssize = (streampos)size;
255 istream *in =
self->_in;
259 streampos remaining =
self->_start + (streampos)self->_size - in->tellg();
260 if (remaining < ssize) {
261 if (remaining <= 0) {
268 in->read((
char *)buf, ssize);
269 streamsize gc = in->gcount();
280 int64_t FfmpegVirtualFile::
281 seek(
void *opaque, int64_t pos,
int whence) {
283 istream *in =
self->_in;
287 in->seekg(self->_start + (streampos)pos, ios::beg);
291 in->seekg(pos, ios::cur);
297 in->seekg(self->_start + (streampos)self->_size + (streampos)pos, ios::beg);
305 <<
"Illegal parameter to seek in FfmpegVirtualFile\n";
311 return in->tellg() -
self->_start;
320 void FfmpegVirtualFile::
321 log_callback(
void *ptr,
int level,
const char *fmt, va_list v1) {
322 NotifySeverity severity;
324 if (level <= AV_LOG_PANIC) {
328 if (level <= AV_LOG_ERROR) {
330 #ifdef AV_LOG_WARNING
331 }
else if (level <= AV_LOG_WARNING) {
332 severity = NS_warning;
334 }
else if (level <= AV_LOG_INFO) {
336 #ifdef AV_LOG_VERBOSE
337 }
else if (level <= AV_LOG_VERBOSE) {
344 if (ffmpeg_cat.is_on(severity)) {
345 static const size_t buffer_size = 4096;
346 char *buffer = (
char *)alloca(buffer_size);
347 vsnprintf(buffer, buffer_size, fmt, v1);
348 nassertv(strlen(buffer) < buffer_size);
349 ffmpeg_cat.out(severity,
true)
streamsize get_size() const
Returns the number of consecutive bytes, beginning at get_start(), that correspond to this file data...
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
bool open_vfs(const Filename &filename)
Opens the movie file via Panda's VFS.
void set_binary()
Indicates that the filename represents a binary file.
bool open_read(ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
static void register_protocol()
Should be called at startup to attach the appropriate hooks between Panda and FFMpeg.
void close()
Explicitly closes the opened file.
streampos get_start() const
Returns the offset within the file at which this file data begins.
The abstract base class for a file or directory within the VirtualFileSystem.
Enables ffmpeg to access panda's VFS.
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
The name of a file, such as a texture file or an Egg file.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
const Filename & get_filename() const
A shortcut to the filename.
This class records a particular byte sub-range within an existing file on disk.
bool open_subfile(const SubfileInfo &info)
Opens the movie file directly from a file on disk (does not go through the VFS).