21 using std::streamsize;
24 #include <libavcodec/avcodec.h>
25 #include <libavformat/avformat.h>
29 #define AVSEEK_SIZE 0x10000
38 _format_context(nullptr),
41 _buffer_size(ffmpeg_read_buffer_size)
49 ~FfmpegVirtualFile() {
62 if (ffmpeg_cat.is_debug()) {
64 <<
"ffmpeg open_vfs(" << filename <<
")\n";
71 if (vfile ==
nullptr) {
75 _in = vfile->open_read_file(
true);
82 _size = vfile->get_file_size(_in);
88 unsigned char *buffer = (
unsigned char*) av_malloc(_buffer_size);
89 _io_context = avio_alloc_context(buffer, _buffer_size, 0, (
void*)
this,
90 &read_packet,
nullptr, &seek);
92 _format_context = avformat_alloc_context();
93 _format_context->pb = _io_context;
97 avformat_open_input(&_format_context,
"",
nullptr,
nullptr);
115 Filename fname = info.get_filename();
120 if (ffmpeg_cat.is_debug()) {
122 <<
"ffmpeg open_subfile(" << fname <<
")\n";
127 _start = info.get_start();
128 _size = info.get_size();
136 unsigned char *buffer = (
unsigned char*) av_malloc(_buffer_size);
137 _io_context = avio_alloc_context(buffer, _buffer_size, 0, (
void*)
this,
138 &read_packet,
nullptr, &seek);
140 _format_context = avformat_alloc_context();
141 _format_context->pb = _io_context;
145 avformat_open_input(&_format_context, fname.c_str(),
nullptr,
nullptr);
160 if (_format_context !=
nullptr) {
161 avformat_close_input(&_format_context);
164 if (_io_context !=
nullptr) {
165 if (_io_context->buffer !=
nullptr) {
166 av_free(_io_context->buffer);
168 av_free(_io_context);
169 _io_context =
nullptr;
173 nassertv(_in !=
nullptr);
186 static bool initialized =
false;
193 #if LIBAVFORMAT_VERSION_MICRO < 100 || LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
198 avformat_network_init();
201 av_log_set_callback(&log_callback);
207 int FfmpegVirtualFile::
208 read_packet(
void *opaque, uint8_t *buf,
int size) {
209 streampos ssize = (streampos)size;
211 std::istream *in =
self->_in;
215 streampos remaining =
self->_start + (streampos)self->_size - in->tellg();
216 if (remaining < ssize) {
217 if (remaining <= 0) {
224 in->read((
char *)buf, ssize);
225 streamsize gc = in->gcount();
234 int64_t FfmpegVirtualFile::
235 seek(
void *opaque, int64_t pos,
int whence) {
237 std::istream *in =
self->_in;
241 in->seekg(self->_start + (streampos)pos, std::ios::beg);
245 in->seekg(pos, std::ios::cur);
251 in->seekg(self->_start + (streampos)
self->_size + (streampos)pos, std::ios::beg);
259 <<
"Illegal parameter to seek in FfmpegVirtualFile\n";
265 return in->tellg() -
self->_start;
272 void FfmpegVirtualFile::
273 log_callback(
void *ptr,
int level,
const char *fmt, va_list v1) {
274 NotifySeverity severity;
276 if (level <= AV_LOG_PANIC) {
280 if (level <= AV_LOG_ERROR) {
282 #ifdef AV_LOG_WARNING
283 }
else if (level <= AV_LOG_WARNING) {
284 severity = NS_warning;
286 }
else if (level <= AV_LOG_INFO) {
288 #ifdef AV_LOG_VERBOSE
289 }
else if (level <= AV_LOG_VERBOSE) {
296 if (ffmpeg_cat.is_on(severity)) {
297 static const size_t buffer_size = 4096;
298 char *buffer = (
char *)alloca(buffer_size);
299 vsnprintf(buffer, buffer_size, fmt, v1);
300 nassertv(strlen(buffer) < buffer_size);
301 ffmpeg_cat.out(severity,
true)