mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-17 12:12:10 -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.
|
// 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");
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user