diff --git a/panda/src/movies/ffmpegVideoCursor.cxx b/panda/src/movies/ffmpegVideoCursor.cxx index dd4a3f3b8f..79a4847ec3 100644 --- a/panda/src/movies/ffmpegVideoCursor.cxx +++ b/panda/src/movies/ffmpegVideoCursor.cxx @@ -22,6 +22,8 @@ #include "config_movies.h" #include "avcodec.h" #include "avformat.h" +#include "pStatCollector.h" +#include "pStatTimer.h" // Earlier versions of ffmpeg didn't define this symbol. #ifndef PIX_FMT_BGRA @@ -162,16 +164,18 @@ cleanup() { // Description: Exports the contents of the frame buffer into the // user's target buffer. //////////////////////////////////////////////////////////////////// +static PStatCollector export_frame_collector("*:FFMPEG Convert Video to BGR"); void FfmpegVideoCursor:: -export_frame(unsigned char *data, bool bgra) { +export_frame(unsigned char *data, bool bgra, int bufx) { + PStatTimer timer(export_frame_collector); if (bgra) { - _frame_out->data[0] = data + ((_size_y - 1) * _size_x * 4); - _frame_out->linesize[0] = _size_x * -4; + _frame_out->data[0] = data + ((_size_y - 1) * bufx * 4); + _frame_out->linesize[0] = bufx * -4; img_convert((AVPicture *)_frame_out, PIX_FMT_BGRA, (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y); } else { - _frame_out->data[0] = data + ((_size_y - 1) * _size_x * 3); - _frame_out->linesize[0] = _size_x * -3; + _frame_out->data[0] = data + ((_size_y - 1) * bufx * 3); + _frame_out->linesize[0] = bufx * -3; img_convert((AVPicture *)_frame_out, PIX_FMT_BGR24, (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y); } @@ -261,23 +265,13 @@ seek(double t) { } //////////////////////////////////////////////////////////////////// -// Function: FfmpegVideoCursor::fetch_into_buffer +// Function: FfmpegVideoCursor::fetch_time // Access: Public, Virtual -// Description: See MovieVideoCursor::fetch_into_buffer. +// Description: Advance until the specified time is in the +// export buffer. //////////////////////////////////////////////////////////////////// void FfmpegVideoCursor:: -fetch_into_buffer(double time, unsigned char *data, bool bgra) { - - // If there was an error at any point, synthesize black. - if (_format_ctx==0) { - if (data) { - memset(data,0,size_x()*size_y()*(bgra?4:3)); - } - _last_start = time; - _next_start = time + 1.0; - return; - } - +fetch_time(double time) { if (time < _last_start) { // Time is in the past. seek(time); @@ -309,7 +303,64 @@ fetch_into_buffer(double time, unsigned char *data, bool bgra) { fetch_frame(); } } - export_frame(data, bgra); +} + +//////////////////////////////////////////////////////////////////// +// Function: FfmpegVideoCursor::fetch_into_texture +// Access: Public, Virtual +// Description: See MovieVideoCursor::fetch_into_texture. +//////////////////////////////////////////////////////////////////// +static PStatCollector fetch_into_texture_pcollector("*:FFMPEG Video Decoding"); +void FfmpegVideoCursor:: +fetch_into_texture(double time, Texture *t, int page) { + PStatTimer timer(fetch_into_texture_pcollector); + + nassertv(t->get_x_size() >= size_x()); + nassertv(t->get_y_size() >= size_y()); + nassertv((t->get_num_components() == 3) || (t->get_num_components() == 4)); + nassertv(t->get_component_width() == 1); + nassertv(page < t->get_z_size()); + + PTA_uchar img = t->modify_ram_image(); + + unsigned char *data = img.p() + page * t->get_expected_ram_page_size(); + + // If there was an error at any point, synthesize black. + if (_format_ctx==0) { + if (data) { + memset(data,0,t->get_x_size() * t->get_y_size() * t->get_num_components()); + } + _last_start = time; + _next_start = time + 1.0; + return; + } + + fetch_time(time); + export_frame(data, (t->get_num_components()==4), t->get_x_size()); +} + +//////////////////////////////////////////////////////////////////// +// Function: FfmpegVideoCursor::fetch_into_buffer +// Access: Public, Virtual +// Description: See MovieVideoCursor::fetch_into_buffer. +//////////////////////////////////////////////////////////////////// +static PStatCollector fetch_into_buffer_pcollector("*:FFMPEG Video Decoding"); +void FfmpegVideoCursor:: +fetch_into_buffer(double time, unsigned char *data, bool bgra) { + PStatTimer timer(fetch_into_buffer_pcollector); + + // If there was an error at any point, synthesize black. + if (_format_ctx==0) { + if (data) { + memset(data,0,size_x()*size_y()*(bgra?4:3)); + } + _last_start = time; + _next_start = time + 1.0; + return; + } + + fetch_time(time); + export_frame(data, bgra, _size_x); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/movies/ffmpegVideoCursor.h b/panda/src/movies/ffmpegVideoCursor.h index 07fcca275d..164d9c0208 100644 --- a/panda/src/movies/ffmpegVideoCursor.h +++ b/panda/src/movies/ffmpegVideoCursor.h @@ -42,13 +42,15 @@ class EXPCL_PANDA_MOVIES FfmpegVideoCursor : public MovieVideoCursor { virtual ~FfmpegVideoCursor(); public: + virtual void fetch_into_texture(double time, Texture *t, int page); virtual void fetch_into_buffer(double time, unsigned char *block, bool rgba); protected: void fetch_packet(double default_time); void fetch_frame(); void seek(double t); - void export_frame(unsigned char *data, bool bgra); + void fetch_time(double time); + void export_frame(unsigned char *data, bool bgra, int bufx); void cleanup(); Filename _filename; diff --git a/panda/src/movies/movieVideoCursor.cxx b/panda/src/movies/movieVideoCursor.cxx index 6ab40981c0..93312c807d 100644 --- a/panda/src/movies/movieVideoCursor.cxx +++ b/panda/src/movies/movieVideoCursor.cxx @@ -18,6 +18,8 @@ #include "movieVideoCursor.h" #include "config_movies.h" +#include "pStatCollector.h" +#include "pStatTimer.h" TypeHandle MovieVideoCursor::_type_handle; @@ -71,6 +73,26 @@ allocate_conversion_buffer() { } } +//////////////////////////////////////////////////////////////////// +// Function: MovieVideoCursor::setup_texture +// Access: Published +// Description: Set up the specified Texture object to contain +// content from this movie. This should be called +// once, not every frame. +//////////////////////////////////////////////////////////////////// +void MovieVideoCursor:: +setup_texture(Texture *tex) const { + int fullx = size_x(); + int fully = size_y(); + if (textures_power_2) { + fullx = Texture::up_to_power_2(fullx); + fully = Texture::up_to_power_2(fully); + } + Texture::Format fmt = (get_num_components() == 4) ? Texture::F_rgba : Texture::F_rgb; + tex->setup_texture(Texture::TT_2d_texture, fullx, fully, 1, Texture::T_unsigned_byte, fmt); + tex->set_pad_size(fullx - size_x(), fully - size_y()); +} + //////////////////////////////////////////////////////////////////// // Function: MovieVideoCursor::fetch_into_bitbucket // Access: Published, Virtual @@ -100,8 +122,10 @@ fetch_into_bitbucket(double time) { // // See fetch_into_buffer for more details. //////////////////////////////////////////////////////////////////// +static PStatCollector fetch_into_texture_collector("*:Decode Video into Texture"); void MovieVideoCursor:: fetch_into_texture(double time, Texture *t, int page) { + PStatTimer timer(fetch_into_texture_collector); // This generic implementation is layered on fetch_into_buffer. // It will work for any derived class, so it is never necessary to diff --git a/panda/src/movies/movieVideoCursor.h b/panda/src/movies/movieVideoCursor.h index b18b1cb510..943882e3a8 100644 --- a/panda/src/movies/movieVideoCursor.h +++ b/panda/src/movies/movieVideoCursor.h @@ -53,6 +53,7 @@ class EXPCL_PANDA_MOVIES MovieVideoCursor : public TypedWritableReferenceCount { INLINE bool aborted() const; INLINE double last_start() const; INLINE double next_start() const; + void setup_texture(Texture *tex) const; virtual void fetch_into_bitbucket(double time); virtual void fetch_into_texture(double time, Texture *t, int page); virtual void fetch_into_texture_rgb(double time, Texture *t, int page);