integrate with latest ffmpeg

This commit is contained in:
David Rose 2011-06-16 20:23:30 +00:00
parent 43763f0b87
commit 830bfcb056
8 changed files with 110 additions and 34 deletions

View File

@ -1229,18 +1229,25 @@ load_image_as_model(const Filename &filename) {
// Choose the dimensions of the polygon appropriately. // Choose the dimensions of the polygon appropriately.
float left,right,top,bottom; float left,right,top,bottom;
static const float scale = 10.0;
if (x_size > y_size) { if (x_size > y_size) {
float scale = 10.0;
left = -scale; left = -scale;
right = scale; right = scale;
top = (scale * y_size) / x_size; top = (scale * y_size) / x_size;
bottom = -(scale * y_size) / x_size; bottom = -(scale * y_size) / x_size;
} else { } else if (y_size != 0) {
float scale = 10.0;
left = -(scale * x_size) / y_size; left = -(scale * x_size) / y_size;
right = (scale * x_size) / y_size; right = (scale * x_size) / y_size;
top = scale; top = scale;
bottom = -scale; bottom = -scale;
} else {
framework_cat.warning()
<< "Texture size is 0 0: " << *tex << "\n";
left = -scale;
right = scale;
top = scale;
bottom = -scale;
} }
PT(GeomNode) card_node = new GeomNode("card"); PT(GeomNode) card_node = new GeomNode("card");

View File

@ -24,6 +24,10 @@
TypeHandle FFMpegTexture::_type_handle; TypeHandle FFMpegTexture::_type_handle;
#if LIBAVFORMAT_VERSION_MAJOR < 53
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: FFMpegTexture::Constructor // Function: FFMpegTexture::Constructor
// Access: Published // Access: Published
@ -271,9 +275,8 @@ update_frame(int frame) {
source -= source_row_width; source -= source_row_width;
} }
} }
} }
++_image_modified;
} }
if (page._alpha.is_valid()) { if (page._alpha.is_valid()) {
@ -301,8 +304,8 @@ update_frame(int frame) {
dest += dest_row_width; dest += dest_row_width;
source -= source_row_width; source -= source_row_width;
} }
} }
++_image_modified;
} }
} }
} }
@ -513,12 +516,12 @@ get_frame_data(int frame_number) {
if (frame_number > coming_from) { if (frame_number > coming_from) {
// Ok, we do have to skip a few frames. // Ok, we do have to skip a few frames.
_codec_context->hurry_up = true; _codec_context->skip_frame = AVDISCARD_BIDIR;
while (frame_number > coming_from) { while (frame_number > coming_from) {
int err = read_video_frame(&packet); int err = read_video_frame(&packet);
if (err < 0) { if (err < 0) {
return false; return false;
} }
#if LIBAVCODEC_VERSION_INT < 3414272 #if LIBAVCODEC_VERSION_INT < 3414272
avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size); avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size);
@ -528,7 +531,7 @@ get_frame_data(int frame_number) {
av_free_packet(&packet); av_free_packet(&packet);
++coming_from; ++coming_from;
} }
_codec_context->hurry_up = false; _codec_context->skip_frame = AVDISCARD_DEFAULT;
} }
// Now we're ready to read a frame. // Now we're ready to read a frame.
@ -550,7 +553,7 @@ get_frame_data(int frame_number) {
// Okay, now we're at the nearest keyframe behind our timestamp. // Okay, now we're at the nearest keyframe behind our timestamp.
// Hurry up and move through frames until we find a frame just after it. // Hurry up and move through frames until we find a frame just after it.
_codec_context->hurry_up = true; _codec_context->skip_frame = AVDISCARD_BIDIR;
do { do {
int err = read_video_frame(&packet); int err = read_video_frame(&packet);
if (err < 0) { if (err < 0) {
@ -564,15 +567,15 @@ get_frame_data(int frame_number) {
} }
#if LIBAVCODEC_VERSION_INT < 3414272 #if LIBAVCODEC_VERSION_INT < 3414272
avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size); avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size);
#else #else
avcodec_decode_video2(_codec_context, _frame, &got_frame, &packet); avcodec_decode_video2(_codec_context, _frame, &got_frame, &packet);
#endif #endif
av_free_packet(&packet); av_free_packet(&packet);
} while (true); } while (true);
_codec_context->hurry_up = false; _codec_context->skip_frame = AVDISCARD_DEFAULT;
// Now near frame with Packet ready for decode (and free) // Now near frame with Packet ready for decode (and free)
} }
@ -584,9 +587,9 @@ get_frame_data(int frame_number) {
if (packet.stream_index == _stream_number) { if (packet.stream_index == _stream_number) {
// Decode video frame // Decode video frame
#if LIBAVCODEC_VERSION_INT < 3414272 #if LIBAVCODEC_VERSION_INT < 3414272
avcodec_decode_video(_codec_context, _frame, &frame_finished, packet.data, packet.size); avcodec_decode_video(_codec_context, _frame, &frame_finished, packet.data, packet.size);
#else #else
avcodec_decode_video2(_codec_context, _frame, &frame_finished, &packet); avcodec_decode_video2(_codec_context, _frame, &frame_finished, &packet);
#endif #endif
// Did we get a video frame? // Did we get a video frame?
@ -603,9 +606,10 @@ get_frame_data(int frame_number) {
} else { } else {
dst_format = PIX_FMT_RGB32; dst_format = PIX_FMT_RGB32;
} }
struct SwsContext *convert_ctx = sws_getContext(_codec_context->width, _codec_context->height, struct SwsContext *convert_ctx =
_codec_context->pix_fmt, _codec_context->width, _codec_context->height, sws_getContext(_codec_context->width, _codec_context->height,
dst_format, 2, NULL, NULL, NULL); _codec_context->pix_fmt, _codec_context->width, _codec_context->height,
dst_format, SWS_FAST_BILINEAR, NULL, NULL, NULL);
nassertr(convert_ctx != NULL, false); nassertr(convert_ctx != NULL, false);
sws_scale(convert_ctx, _frame->data, _frame->linesize, sws_scale(convert_ctx, _frame->data, _frame->linesize,
0, _codec_context->height, _frame_out->data, _frame_out->linesize); 0, _codec_context->height, _frame_out->data, _frame_out->linesize);
@ -663,7 +667,7 @@ read(const Filename &filename) {
_stream_number = -1; _stream_number = -1;
for(int i = 0; i < _format_context->nb_streams; i++) { for(int i = 0; i < _format_context->nb_streams; i++) {
if ((*_format_context->streams[i]->codec).codec_type == CODEC_TYPE_VIDEO) { if ((*_format_context->streams[i]->codec).codec_type == AVMEDIA_TYPE_VIDEO) {
_stream_number = i; _stream_number = i;
break; break;
} }
@ -671,7 +675,7 @@ read(const Filename &filename) {
if (_stream_number == -1) { if (_stream_number == -1) {
grutil_cat.error() grutil_cat.error()
<< "ffmpeg: no stream found with codec of type CODEC_TYPE_VIDEO" << endl; << "ffmpeg: no stream found with codec of type AVMEDIA_TYPE_VIDEO" << endl;
clear(); clear();
return false; return false;
} }
@ -796,6 +800,10 @@ clear() {
int FFMpegTexture::VideoStream:: int FFMpegTexture::VideoStream::
read_video_frame(AVPacket *packet) { read_video_frame(AVPacket *packet) {
int err = av_read_frame(_format_context, packet); int err = av_read_frame(_format_context, packet);
if (grutil_cat.is_spam()) {
grutil_cat.spam()
<< "av_read_frame() = " << err << "\n";
}
if (err < 0) { if (err < 0) {
return err; return err;
} }
@ -805,9 +813,15 @@ read_video_frame(AVPacket *packet) {
av_free_packet(packet); av_free_packet(packet);
err = av_read_frame(_format_context, packet); err = av_read_frame(_format_context, packet);
if (grutil_cat.is_spam()) {
grutil_cat.spam()
<< "av_read_frame() = " << err << "\n";
}
if (err < 0) { if (err < 0) {
grutil_cat.debug() if (grutil_cat.is_debug()) {
<< "Got error " << err << " reading frame.\n"; grutil_cat.debug()
<< "Got error " << err << " reading frame.\n";
}
return err; return err;
} }
} }

View File

@ -23,6 +23,7 @@ extern "C" {
ConfigureDef(config_movies); ConfigureDef(config_movies);
NotifyCategoryDef(movies, ""); NotifyCategoryDef(movies, "");
NotifyCategoryDef(ffmpeg, "movies");
ConfigureFn(config_movies) { ConfigureFn(config_movies) {
init_libmovies(); init_libmovies();

View File

@ -38,6 +38,7 @@
ConfigureDecl(config_movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES); ConfigureDecl(config_movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES);
NotifyCategoryDecl(movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES); NotifyCategoryDecl(movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES);
NotifyCategoryDecl(ffmpeg, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES);
extern EXPCL_PANDA_MOVIES void init_libmovies(); extern EXPCL_PANDA_MOVIES void init_libmovies();

View File

@ -22,6 +22,10 @@ extern "C" {
TypeHandle FfmpegAudioCursor::_type_handle; TypeHandle FfmpegAudioCursor::_type_handle;
#if LIBAVFORMAT_VERSION_MAJOR < 53
#define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
#endif
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: FfmpegAudioCursor::Constructor // Function: FfmpegAudioCursor::Constructor
// Access: Protected // Access: Protected
@ -51,8 +55,8 @@ FfmpegAudioCursor(FfmpegAudio *src) :
} }
// Find the audio stream // Find the audio stream
for(int i=0; i<_format_ctx->nb_streams; i++) { for(int i = 0; i < (int)_format_ctx->nb_streams; i++) {
if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) { if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
_audio_index = i; _audio_index = i;
_audio_ctx = _format_ctx->streams[i]->codec; _audio_ctx = _format_ctx->streams[i]->codec;
_audio_timebase = av_q2d(_format_ctx->streams[i]->time_base); _audio_timebase = av_q2d(_format_ctx->streams[i]->time_base);

View File

@ -28,6 +28,11 @@ extern "C" {
TypeHandle FfmpegVideoCursor::_type_handle; TypeHandle FfmpegVideoCursor::_type_handle;
#if LIBAVFORMAT_VERSION_MAJOR < 53
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: FfmpegVideoCursor::Constructor // Function: FfmpegVideoCursor::Constructor
// Access: Public // Access: Public
@ -58,8 +63,8 @@ FfmpegVideoCursor(FfmpegVideo *src) :
} }
// Find the video stream // Find the video stream
for(int i=0; i<_format_ctx->nb_streams; i++) { for(int i = 0; i < (int)_format_ctx->nb_streams; i++) {
if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
_video_index = i; _video_index = i;
_video_ctx = _format_ctx->streams[i]->codec; _video_ctx = _format_ctx->streams[i]->codec;
_video_timebase = av_q2d(_format_ctx->streams[i]->time_base); _video_timebase = av_q2d(_format_ctx->streams[i]->time_base);

View File

@ -50,9 +50,13 @@ extern "C" {
static int static int
pandavfs_open(URLContext *h, const char *filename, int flags) { pandavfs_open(URLContext *h, const char *filename, int flags) {
if (flags != 0) { if (flags != 0) {
movies_cat.error() << "ffmpeg is trying to write to the VFS.\n"; if (movies_cat.is_debug()) {
return -1; movies_cat.debug()
<< "ffmpeg is trying to write to the VFS.\n";
}
// We'll allow this, but just fail any actual writes.
} }
filename += 9; // Skip over "pandavfs:" filename += 9; // Skip over "pandavfs:"
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
istream *s = vfs->open_read_file(filename, true); istream *s = vfs->open_read_file(filename, true);
@ -98,7 +102,8 @@ pandavfs_write(URLContext *h, unsigned char *buf, int size) {
#else #else
pandavfs_write(URLContext *h, const unsigned char *buf, int size) { pandavfs_write(URLContext *h, const unsigned char *buf, int size) {
#endif #endif
movies_cat.error() << "ffmpeg is trying to write to the VFS.\n"; movies_cat.warning()
<< "ffmpeg is trying to write to the VFS.\n";
return -1; return -1;
} }
@ -177,9 +182,46 @@ register_protocol() {
protocol.url_close = pandavfs_close; protocol.url_close = pandavfs_close;
#if LIBAVFORMAT_VERSION_INT < 3415296 #if LIBAVFORMAT_VERSION_INT < 3415296
::register_protocol(&protocol); ::register_protocol(&protocol);
#else #elif LIBAVFORMAT_VERSION_MAJOR < 53
av_register_protocol(&protocol); av_register_protocol(&protocol);
#else
av_register_protocol2(&protocol, sizeof(protocol));
#endif #endif
// Let's also register the logging to Panda's notify callback.
av_log_set_callback(&log_callback);
}
////////////////////////////////////////////////////////////////////
// Function: FfmpegVirtualFile::log_callback
// Access: Private, Static
// Description: These callbacks are made when ffmpeg wants to write a
// log entry; it redirects into Panda's notify.
////////////////////////////////////////////////////////////////////
void FfmpegVirtualFile::
log_callback(void *ptr, int level, const char *fmt, va_list v1) {
NotifySeverity severity;
if (level <= AV_LOG_PANIC) {
severity = NS_fatal;
} else if (level <= AV_LOG_ERROR) {
severity = NS_error;
} else if (level <= AV_LOG_WARNING) {
severity = NS_warning;
} else if (level <= AV_LOG_INFO) {
severity = NS_info;
} else if (level <= AV_LOG_VERBOSE) {
severity = NS_debug;
} else /* level <= AV_LOG_DEBUG */ {
severity = NS_spam;
}
if (ffmpeg_cat.is_on(severity)) {
static const size_t buffer_size = 4096;
static char buffer[buffer_size];
vsnprintf(buffer, buffer_size, fmt, v1);
ffmpeg_cat.out(severity, true)
<< buffer;
}
} }
#endif // HAVE_FFMPEG #endif // HAVE_FFMPEG

View File

@ -17,15 +17,14 @@
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
#include "config_movies.h" #include "config_movies.h"
#include <stdarg.h>
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : FfmpegVirtualFile // Class : FfmpegVirtualFile
// Description : Enables ffmpeg to access panda's VFS. // Description : Enables ffmpeg to access panda's VFS.
// //
// This class only has one public method, // Once register_protocol() is called, ffmpeg will be
// register_hooks. Once the hooks are registered, // able to open "URLs" that look like this:
// ffmpeg will be able to open "URLs" that look
// like this:
// //
// pandavfs:/c/mygame/foo.avi // pandavfs:/c/mygame/foo.avi
// //
@ -33,6 +32,9 @@
class EXPCL_PANDA_MOVIES FfmpegVirtualFile { class EXPCL_PANDA_MOVIES FfmpegVirtualFile {
public: public:
static void register_protocol(); static void register_protocol();
private:
static void log_callback(void *ptr, int level, const char *fmt, va_list v1);
}; };
#include "ffmpegVirtualFile.I" #include "ffmpegVirtualFile.I"