mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
integrate with latest ffmpeg
This commit is contained in:
parent
43763f0b87
commit
830bfcb056
@ -1229,18 +1229,25 @@ load_image_as_model(const Filename &filename) {
|
||||
|
||||
// Choose the dimensions of the polygon appropriately.
|
||||
float left,right,top,bottom;
|
||||
static const float scale = 10.0;
|
||||
if (x_size > y_size) {
|
||||
float scale = 10.0;
|
||||
left = -scale;
|
||||
right = scale;
|
||||
top = (scale * y_size) / x_size;
|
||||
bottom = -(scale * y_size) / x_size;
|
||||
} else {
|
||||
float scale = 10.0;
|
||||
} else if (y_size != 0) {
|
||||
left = -(scale * x_size) / y_size;
|
||||
right = (scale * x_size) / y_size;
|
||||
top = 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");
|
||||
|
@ -24,6 +24,10 @@
|
||||
|
||||
TypeHandle FFMpegTexture::_type_handle;
|
||||
|
||||
#if LIBAVFORMAT_VERSION_MAJOR < 53
|
||||
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FFMpegTexture::Constructor
|
||||
// Access: Published
|
||||
@ -271,9 +275,8 @@ update_frame(int frame) {
|
||||
source -= source_row_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
++_image_modified;
|
||||
}
|
||||
|
||||
if (page._alpha.is_valid()) {
|
||||
@ -301,8 +304,8 @@ update_frame(int frame) {
|
||||
dest += dest_row_width;
|
||||
source -= source_row_width;
|
||||
}
|
||||
|
||||
}
|
||||
++_image_modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -513,12 +516,12 @@ get_frame_data(int frame_number) {
|
||||
|
||||
if (frame_number > coming_from) {
|
||||
// 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) {
|
||||
int err = read_video_frame(&packet);
|
||||
if (err < 0) {
|
||||
return false;
|
||||
|
||||
}
|
||||
#if LIBAVCODEC_VERSION_INT < 3414272
|
||||
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);
|
||||
++coming_from;
|
||||
}
|
||||
_codec_context->hurry_up = false;
|
||||
_codec_context->skip_frame = AVDISCARD_DEFAULT;
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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 {
|
||||
int err = read_video_frame(&packet);
|
||||
if (err < 0) {
|
||||
@ -564,15 +567,15 @@ get_frame_data(int frame_number) {
|
||||
}
|
||||
|
||||
#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
|
||||
avcodec_decode_video2(_codec_context, _frame, &got_frame, &packet);
|
||||
avcodec_decode_video2(_codec_context, _frame, &got_frame, &packet);
|
||||
#endif
|
||||
|
||||
av_free_packet(&packet);
|
||||
} while (true);
|
||||
|
||||
_codec_context->hurry_up = false;
|
||||
_codec_context->skip_frame = AVDISCARD_DEFAULT;
|
||||
// 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) {
|
||||
// Decode video frame
|
||||
#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
|
||||
avcodec_decode_video2(_codec_context, _frame, &frame_finished, &packet);
|
||||
avcodec_decode_video2(_codec_context, _frame, &frame_finished, &packet);
|
||||
#endif
|
||||
|
||||
// Did we get a video frame?
|
||||
@ -603,9 +606,10 @@ get_frame_data(int frame_number) {
|
||||
} else {
|
||||
dst_format = PIX_FMT_RGB32;
|
||||
}
|
||||
struct SwsContext *convert_ctx = sws_getContext(_codec_context->width, _codec_context->height,
|
||||
_codec_context->pix_fmt, _codec_context->width, _codec_context->height,
|
||||
dst_format, 2, NULL, NULL, NULL);
|
||||
struct SwsContext *convert_ctx =
|
||||
sws_getContext(_codec_context->width, _codec_context->height,
|
||||
_codec_context->pix_fmt, _codec_context->width, _codec_context->height,
|
||||
dst_format, SWS_FAST_BILINEAR, NULL, NULL, NULL);
|
||||
nassertr(convert_ctx != NULL, false);
|
||||
sws_scale(convert_ctx, _frame->data, _frame->linesize,
|
||||
0, _codec_context->height, _frame_out->data, _frame_out->linesize);
|
||||
@ -663,7 +667,7 @@ read(const Filename &filename) {
|
||||
|
||||
_stream_number = -1;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -671,7 +675,7 @@ read(const Filename &filename) {
|
||||
|
||||
if (_stream_number == -1) {
|
||||
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();
|
||||
return false;
|
||||
}
|
||||
@ -796,6 +800,10 @@ clear() {
|
||||
int FFMpegTexture::VideoStream::
|
||||
read_video_frame(AVPacket *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) {
|
||||
return err;
|
||||
}
|
||||
@ -805,9 +813,15 @@ read_video_frame(AVPacket *packet) {
|
||||
av_free_packet(packet);
|
||||
|
||||
err = av_read_frame(_format_context, packet);
|
||||
if (grutil_cat.is_spam()) {
|
||||
grutil_cat.spam()
|
||||
<< "av_read_frame() = " << err << "\n";
|
||||
}
|
||||
if (err < 0) {
|
||||
grutil_cat.debug()
|
||||
<< "Got error " << err << " reading frame.\n";
|
||||
if (grutil_cat.is_debug()) {
|
||||
grutil_cat.debug()
|
||||
<< "Got error " << err << " reading frame.\n";
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ extern "C" {
|
||||
|
||||
ConfigureDef(config_movies);
|
||||
NotifyCategoryDef(movies, "");
|
||||
NotifyCategoryDef(ffmpeg, "movies");
|
||||
|
||||
ConfigureFn(config_movies) {
|
||||
init_libmovies();
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
ConfigureDecl(config_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();
|
||||
|
||||
|
@ -22,6 +22,10 @@ extern "C" {
|
||||
|
||||
TypeHandle FfmpegAudioCursor::_type_handle;
|
||||
|
||||
#if LIBAVFORMAT_VERSION_MAJOR < 53
|
||||
#define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FfmpegAudioCursor::Constructor
|
||||
// Access: Protected
|
||||
@ -51,8 +55,8 @@ FfmpegAudioCursor(FfmpegAudio *src) :
|
||||
}
|
||||
|
||||
// Find the audio stream
|
||||
for(int i=0; i<_format_ctx->nb_streams; i++) {
|
||||
if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
|
||||
for(int i = 0; i < (int)_format_ctx->nb_streams; i++) {
|
||||
if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
_audio_index = i;
|
||||
_audio_ctx = _format_ctx->streams[i]->codec;
|
||||
_audio_timebase = av_q2d(_format_ctx->streams[i]->time_base);
|
||||
|
@ -28,6 +28,11 @@ extern "C" {
|
||||
|
||||
TypeHandle FfmpegVideoCursor::_type_handle;
|
||||
|
||||
#if LIBAVFORMAT_VERSION_MAJOR < 53
|
||||
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FfmpegVideoCursor::Constructor
|
||||
// Access: Public
|
||||
@ -58,8 +63,8 @@ FfmpegVideoCursor(FfmpegVideo *src) :
|
||||
}
|
||||
|
||||
// Find the video stream
|
||||
for(int i=0; i<_format_ctx->nb_streams; i++) {
|
||||
if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
|
||||
for(int i = 0; i < (int)_format_ctx->nb_streams; i++) {
|
||||
if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
_video_index = i;
|
||||
_video_ctx = _format_ctx->streams[i]->codec;
|
||||
_video_timebase = av_q2d(_format_ctx->streams[i]->time_base);
|
||||
|
@ -50,9 +50,13 @@ extern "C" {
|
||||
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;
|
||||
if (movies_cat.is_debug()) {
|
||||
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:"
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
istream *s = vfs->open_read_file(filename, true);
|
||||
@ -98,7 +102,8 @@ 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";
|
||||
movies_cat.warning()
|
||||
<< "ffmpeg is trying to write to the VFS.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -177,9 +182,46 @@ register_protocol() {
|
||||
protocol.url_close = pandavfs_close;
|
||||
#if LIBAVFORMAT_VERSION_INT < 3415296
|
||||
::register_protocol(&protocol);
|
||||
#else
|
||||
#elif LIBAVFORMAT_VERSION_MAJOR < 53
|
||||
av_register_protocol(&protocol);
|
||||
#else
|
||||
av_register_protocol2(&protocol, sizeof(protocol));
|
||||
#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
|
||||
|
@ -17,15 +17,14 @@
|
||||
#ifdef HAVE_FFMPEG
|
||||
|
||||
#include "config_movies.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : FfmpegVirtualFile
|
||||
// Description : Enables ffmpeg to access panda's VFS.
|
||||
//
|
||||
// This class only has one public method,
|
||||
// register_hooks. Once the hooks are registered,
|
||||
// ffmpeg will be able to open "URLs" that look
|
||||
// like this:
|
||||
// Once register_protocol() is called, ffmpeg will be
|
||||
// able to open "URLs" that look like this:
|
||||
//
|
||||
// pandavfs:/c/mygame/foo.avi
|
||||
//
|
||||
@ -33,6 +32,9 @@
|
||||
class EXPCL_PANDA_MOVIES FfmpegVirtualFile {
|
||||
public:
|
||||
static void register_protocol();
|
||||
|
||||
private:
|
||||
static void log_callback(void *ptr, int level, const char *fmt, va_list v1);
|
||||
};
|
||||
|
||||
#include "ffmpegVirtualFile.I"
|
||||
|
Loading…
x
Reference in New Issue
Block a user