mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
187 lines
5.7 KiB
C++
187 lines
5.7 KiB
C++
// Filename: ffmpegVirtualFile.cxx
|
|
// Created by: jyelon (02Jul07)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef HAVE_FFMPEG
|
|
|
|
#include "pandabase.h"
|
|
#include "config_movies.h"
|
|
#include "ffmpegVirtualFile.h"
|
|
#include "virtualFileSystem.h"
|
|
extern "C" {
|
|
#include "libavformat/avio.h"
|
|
}
|
|
#include <stdint.h>
|
|
|
|
#ifndef AVSEEK_SIZE
|
|
#define AVSEEK_SIZE 0x10000
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// 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);
|
|
// This change happened a few days before 52.68.0
|
|
#if LIBAVFORMAT_VERSION_INT < 3425280
|
|
static int pandavfs_write(URLContext *h, unsigned char *buf, int size);
|
|
#else
|
|
static int pandavfs_write(URLContext *h, const unsigned char *buf, int size);
|
|
#endif
|
|
static int64_t pandavfs_seek(URLContext *h, int64_t 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
|
|
#if LIBAVFORMAT_VERSION_INT < 3425280
|
|
pandavfs_write(URLContext *h, unsigned char *buf, int size) {
|
|
#else
|
|
pandavfs_write(URLContext *h, const unsigned char *buf, int size) {
|
|
#endif
|
|
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 int64_t
|
|
pandavfs_seek(URLContext *h, int64_t pos, int whence) {
|
|
istream *s = (istream*)(h->priv_data);
|
|
switch(whence) {
|
|
case SEEK_SET: s->seekg(pos, ios::beg); break;
|
|
case SEEK_CUR: s->seekg(pos, ios::cur); break;
|
|
case SEEK_END: s->seekg(pos, ios::end); break;
|
|
case AVSEEK_SIZE: {
|
|
s->seekg(0, ios::cur);
|
|
int p = s->tellg();
|
|
s->seekg(-1, ios::end);
|
|
int size = s->tellg();
|
|
if (size < 0) {
|
|
movies_cat.error() << "Failed to determine filesize in ffmpegVirtualFile\n";
|
|
s->clear();
|
|
return -1;
|
|
}
|
|
size++;
|
|
s->seekg(p, ios::beg);
|
|
s->clear();
|
|
return size; }
|
|
default:
|
|
movies_cat.error() << "Illegal parameter to seek in ffmpegVirtualFile\n";
|
|
s->clear();
|
|
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;
|
|
#if LIBAVFORMAT_VERSION_INT < 3415296
|
|
::register_protocol(&protocol);
|
|
#else
|
|
av_register_protocol(&protocol);
|
|
#endif
|
|
}
|
|
|
|
#endif // HAVE_FFMPEG
|