@ -12,22 +12,13 @@
# include "config.h"
# include "k9avidecode.h"
# ifdef OLD_FFMPEG
# include <ffmpeg/avcodec.h>
# endif
# ifdef NEW_FFMPEG
# include <libavcodec/avcodec.h>
# include <libavformat/avformat.h>
# include <libavutil/avutil.h>
# endif
// This is probably the incorrect revision for when CODEC_TYPE_VIDEO was removed
// Please update the comparison below if you know the exact revision that CODEC_TYPE_VIDEO was removed in!
# if LIBAVCODEC_VERSION_INT < (AV_VERSION_INT(52,72,2))
# define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
# endif
# if !defined(NEW_FFMPEG) || LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,42,0)
# if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,42,0)
# define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
# endif
@ -37,125 +28,17 @@
# include <cstdlib>
# include "ac.h"
void * CodecHandle = 0 ;
void * FormatHandle = 0 ;
void * UtilHandle = 0 ;
void * SwscaleHandle = 0 ;
int glibref = 0 ;
# ifdef NEW_FFMPEG
void av_free_packet_internal ( AVPacket * pkt )
{
if ( pkt ) {
# if LIBAVCODEC_VERSION_INT < (AV_VERSION_INT(56,0,0))
if ( pkt - > destruct ) pkt - > destruct ( pkt ) ;
# endif
pkt - > data = NULL ; pkt - > size = 0 ;
}
}
# endif
# ifdef HAVE_SWSCALE
# include "libswscale/swscale.h"
static int sws_flags = SWS_BICUBIC ;
# endif
k9AviDecode : : k9AviDecode ( TQObject * parent , const char * name )
: TQObject ( parent , name ) {
if ( glibref = = 0 ) {
CodecHandle = dlopen ( " libavcodec.so " , RTLD_LAZY | RTLD_GLOBAL ) ;
FormatHandle = dlopen ( " libavformat.so " , RTLD_LAZY | RTLD_GLOBAL ) ;
UtilHandle = dlopen ( " libavutil.so " , RTLD_LAZY | RTLD_GLOBAL ) ;
# ifdef HAVE_SWSCALE
SwscaleHandle = dlopen ( " libswscale.so " , RTLD_LAZY ) ;
if ( SwscaleHandle = = 0 )
SwscaleHandle = dlopen ( " libswscale.so.2 " , RTLD_LAZY ) ;
# endif
}
if ( ! CodecHandle ) {
m_error = i18n ( " Cannot open then library %1 " ) . arg ( " libavcodec " ) ;
return ;
}
if ( ! FormatHandle ) {
m_error = i18n ( " Cannot open then library %1 " ) . arg ( " libavformat " ) ;
return ;
}
# if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 33, 0)
if ( ! UtilHandle ) {
m_error = i18n ( " Cannot open then library %1 " ) . arg ( " libavutil " ) ;
return ;
}
# endif
# ifdef HAVE_SWSCALE
if ( ! SwscaleHandle ) {
m_error = i18n ( " Cannot open the library %1 " ) . arg ( " libswscale " ) ;
}
# endif
m_error = " " ;
av_register_all = ( av_register_all_t ) dlsym ( FormatHandle , " av_register_all " ) ;
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0)
avformat_open_input = ( avformat_open_input_t ) dlsym ( FormatHandle , " avformat_open_input " ) ;
# else
av_open_input_file = ( av_open_input_file_t ) dlsym ( FormatHandle , " av_open_input_file " ) ;
# endif
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0)
avformat_find_stream_info = ( avformat_find_stream_info_t ) dlsym ( FormatHandle , " avformat_find_stream_info " ) ;
# else
av_find_stream_info = ( av_find_stream_info_t ) dlsym ( FormatHandle , " av_find_stream_info " ) ;
# endif
avcodec_find_decoder = ( avcodec_find_decoder_t ) dlsym ( CodecHandle , " avcodec_find_decoder " ) ;
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
avcodec_open2 = ( avcodec_open2_t ) dlsym ( CodecHandle , " avcodec_open2 " ) ;
# else
avcodec_open = ( avcodec_open_t ) dlsym ( CodecHandle , " avcodec_open " ) ;
# endif
avcodec_alloc_frame = ( avcodec_alloc_frame_t ) dlsym ( CodecHandle , " avcodec_alloc_frame " ) ;
avpicture_get_size = ( avpicture_get_size_t ) dlsym ( CodecHandle , " avpicture_get_size " ) ;
av_malloc = ( av_malloc_t ) dlsym ( CodecHandle , " av_malloc " ) ;
avpicture_fill = ( avpicture_fill_t ) dlsym ( CodecHandle , " avpicture_fill " ) ;
av_read_frame = ( av_read_frame_t ) dlsym ( FormatHandle , " av_read_frame " ) ;
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0)
avcodec_decode_video2 = ( avcodec_decode_video2_t ) dlsym ( CodecHandle , " avcodec_decode_video2 " ) ;
# else
avcodec_decode_video = ( avcodec_decode_video_t ) dlsym ( CodecHandle , " avcodec_decode_video " ) ;
# endif
# ifndef HAVE_SWSCALE
img_convert = ( img_convert_t ) dlsym ( CodecHandle , " img_convert " ) ;
//if img_convert is null (deprecated in ffmpeg), we need libswscale
if ( ! img_convert ) {
m_error = i18n ( " Cannot open the library %1 " ) . arg ( " libswscale " ) ;
return ;
}
# endif
av_free = ( av_free_t ) dlsym ( CodecHandle , " av_free " ) ;
av_free_packet = ( av_free_packet_t ) dlsym ( CodecHandle , " av_free_packet " ) ;
if ( av_free_packet = = 0 )
av_free_packet = av_free_packet_internal ;
avcodec_close = ( avcodec_close_t ) dlsym ( FormatHandle , " avcodec_close " ) ;
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0)
avformat_close_input = ( avformat_close_input_t ) dlsym ( FormatHandle , " avformat_close_input " ) ;
# else
av_close_input_file = ( av_close_input_file_t ) dlsym ( FormatHandle , " av_close_input_file " ) ;
# endif
av_seek_frame = ( av_seek_frame_t ) dlsym ( FormatHandle , " av_seek_frame " ) ;
av_rescale_q = ( av_rescale_q_t ) dlsym ( FormatHandle , " av_rescale_q " ) ;
avcodec_flush_buffers = ( avcodec_flush_buffers_t ) dlsym ( CodecHandle , " avcodec_flush_buffers " ) ;
# ifdef HAVE_SWSCALE
sws_freeContext = ( sws_freeContext_t ) dlsym ( SwscaleHandle , " sws_freeContext " ) ;
sws_getContext = ( sws_getContext_t ) dlsym ( SwscaleHandle , " sws_getContext " ) ;
sws_scale = ( sws_scale_t ) dlsym ( SwscaleHandle , " sws_scale " ) ;
# endif
# if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 33, 0)
av_gettime = ( av_gettime_t ) dlsym ( UtilHandle , " av_gettime " ) ;
# else
av_gettime = ( av_gettime_t ) dlsym ( FormatHandle , " av_gettime " ) ;
# endif
# if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100)
av_register_all ( ) ;
# endif
m_opened = false ;
glibref + + ;
m_FormatCtx = NULL ;
m_CodecCtx = NULL ;
m_Codec = NULL ;
@ -168,20 +51,6 @@ k9AviDecode::k9AviDecode(TQObject *parent, const char *name)
k9AviDecode : : ~ k9AviDecode ( ) {
if ( m_opened )
close ( ) ;
glibref - - ;
if ( glibref = = 0 ) {
dlclose ( FormatHandle ) ;
dlclose ( CodecHandle ) ;
if ( UtilHandle ) {
dlclose ( UtilHandle ) ;
}
# ifdef HAVE_SWSCALE
if ( SwscaleHandle ) {
dlclose ( CodecHandle ) ;
}
# endif
}
}
@ -194,33 +63,36 @@ bool k9AviDecode::open(const TQString & _fileName) {
close ( ) ;
// Open video file
if (
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0)
avformat_open_input ( & m_FormatCtx , _fileName . utf8 ( ) , NULL , NULL ) ! = 0
# else
av_open_input_file ( & m_FormatCtx , _fileName . utf8 ( ) , NULL , 0 , NULL ) ! = 0
# endif
) {
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0)
if ( avformat_open_input ( & m_FormatCtx , _fileName . utf8 ( ) , NULL , NULL ) ! = 0 )
# else
if ( av_open_input_file ( & m_FormatCtx , _fileName . utf8 ( ) , NULL , 0 , NULL ) ! = 0 )
# endif
{
m_error = i18n ( " Couldn't open the file %1 " ) . arg ( _fileName ) ;
return false ; // Couldn't open file}
}
// Retrieve stream information
if (
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0)
avformat_find_stream_info ( m_FormatCtx , NULL ) < 0
# else
av_find_stream_info ( m_FormatCtx ) < 0
# endif
) {
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0)
if ( avformat_find_stream_info ( m_FormatCtx , NULL ) < 0 )
# else
if ( av_find_stream_info ( m_FormatCtx ) < 0 )
# endif
{
m_error = i18n ( " Couldn't find stream information " ) ;
return false ; // Couldn't find stream information
}
int i ;
unsigned int i ;
// Find the first video stream
m_videoStream = - 1 ;
for ( i = 0 ; i < m_FormatCtx - > nb_streams ; i + + )
if ( m_FormatCtx - > streams [ i ] - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
if ( m_FormatCtx - > streams [ i ] - > codecpar - > codec_type = = AVMEDIA_TYPE_VIDEO )
# else
if ( m_FormatCtx - > streams [ i ] - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO )
# endif
{
m_videoStream = i ;
break ;
}
@ -229,34 +101,56 @@ bool k9AviDecode::open(const TQString & _fileName) {
return false ; // Didn't find a video stream
}
// Get a pointer to the codec context for the video stream
m_CodecCtx = m_FormatCtx - > streams [ m_videoStream ] - > codec ;
// Find the decoder for the video stream
m_Codec = avcodec_find_decoder ( m_CodecCtx - > codec_id ) ;
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
m_Codec = ( AVCodec * ) avcodec_find_decoder ( m_FormatCtx - > streams [ m_videoStream ] - > codecpar - > codec_id ) ;
# else
m_Codec = ( AVCodec * ) avcodec_find_decoder ( m_FormatCtx - > streams [ m_videoStream ] - > codec - > codec_id ) ;
# endif
if ( m_Codec = = NULL ) {
m_error = i18n ( " Unsupported codec " ) ;
return false ; // Codec not found
}
// Get/allocate a pointer to the codec context for the video stream
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
m_CodecCtx = avcodec_alloc_context3 ( m_Codec ) ;
if ( m_CodecCtx ) {
avcodec_parameters_to_context ( m_CodecCtx , m_FormatCtx - > streams [ m_videoStream ] - > codecpar ) ;
}
else {
m_error = i18n ( " Failed to allocate a codec context " ) ;
return false ;
}
# else
m_CodecCtx = m_FormatCtx - > streams [ m_videoStream ] - > codec ;
# endif
// Open codec
if (
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
avcodec_open2 ( m_CodecCtx , m_Codec , NULL ) < 0
# else
avcodec_open ( m_CodecCtx , m_Codec ) < 0
# endif
) {
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0)
if ( avcodec_open2 ( m_CodecCtx , m_Codec , NULL ) < 0 )
# else
if ( avcodec_open ( m_CodecCtx , m_Codec ) < 0 )
# endif
{
m_error = i18n ( " Could'nt open the codec " ) ;
return false ; // Could not open codec
}
// Allocate video frame
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101)
m_Frame = av_frame_alloc ( ) ;
# else
m_Frame = avcodec_alloc_frame ( ) ;
# endif
// Allocate an AVFrame structure
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101)
m_FrameRGB = av_frame_alloc ( ) ;
# else
m_FrameRGB = avcodec_alloc_frame ( ) ;
# endif
if ( m_FrameRGB = = NULL ) {
m_error = i18n ( " Unable to allocate memory for frames " ) ;
return false ;
@ -265,15 +159,25 @@ bool k9AviDecode::open(const TQString & _fileName) {
int numBytes ;
// Determine required buffer size and allocate buffer
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 100)
numBytes = av_image_get_buffer_size ( AV_PIX_FMT_RGB24 , m_CodecCtx - > width ,
m_CodecCtx - > height , 1 ) ;
# else
numBytes = avpicture_get_size ( AV_PIX_FMT_RGB24 , m_CodecCtx - > width ,
m_CodecCtx - > height ) ;
# endif
m_buffer = ( uint8_t * ) av_malloc ( numBytes * sizeof ( uint8_t ) ) ;
// Assign appropriate parts of buffer to image planes in pFrameRGB
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
// of AVPicture
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 100)
av_image_fill_arrays ( m_FrameRGB - > data , m_FrameRGB - > linesize , m_buffer ,
AV_PIX_FMT_RGB24 , m_CodecCtx - > width , m_CodecCtx - > height , 1 ) ;
# else
avpicture_fill ( ( AVPicture * ) m_FrameRGB , m_buffer , AV_PIX_FMT_RGB24 ,
m_CodecCtx - > width , m_CodecCtx - > height ) ;
# endif
m_duration = ( double ) m_FormatCtx - > duration / AV_TIME_BASE ;
m_opened = true ;
@ -296,60 +200,70 @@ void k9AviDecode::readFrame(double _seconds) {
int res = av_seek_frame ( m_FormatCtx , m_videoStream , fspos , AVSEEK_FLAG_BACKWARD ) ;
avcodec_flush_buffers ( m_CodecCtx ) ;
int frameFinished = 0 ;
AVPacket packet ;
AVPacket * packet ;
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
packet = av_packet_alloc ( ) ;
# else
AVPacket _packet ;
av_init_packet ( & _packet ) ;
packet = & _packet ;
# endif
# ifdef HAVE_SWSCALE
struct SwsContext * toRGB_convert_ctx ;
# endif
bool bFound = false ;
while ( av_read_frame ( m_FormatCtx , & packet ) > = 0 & & ! bFound ) {
while ( av_read_frame ( m_FormatCtx , packet ) > = 0 & & ! bFound ) {
// Is this a packet from the video stream?
if ( packet . stream_index = = m_videoStream ) {
if ( packet - > stream_index = = m_videoStream ) {
// Decode video frame
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0)
avcodec_decode_video2 ( m_CodecCtx , m_Frame , & frameFinished , & packet ) ;
# else
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100)
int ret = avcodec_receive_frame ( m_CodecCtx , m_Frame ) ;
if ( ret = = 0 )
frameFinished = 1 ;
else if ( ret = = AVERROR ( EAGAIN ) )
ret = 0 ;
if ( ret = = 0 )
ret = avcodec_send_packet ( m_CodecCtx , packet ) ;
# elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0)
avcodec_decode_video2 ( m_CodecCtx , m_Frame , & frameFinished , packet ) ;
# else
avcodec_decode_video ( m_CodecCtx , m_Frame , & frameFinished ,
packet . data , packet . size ) ;
# endif
packet - > data , packet - > size ) ;
# endif
// Did we get a video frame?
if ( frameFinished ) {
// if (m_Frame->pts >=fspos)
int64_t cur_dts = fspos ;
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(54, 2, 0)
cur_dts = packet . dts ;
# else
if ( m_FormatCtx - > cur_st )
cur_dts = m_FormatCtx - > cur_st - > cur_dts ;
# endif
int64_t cur_dts = fspos ;
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(54, 2, 0)
cur_dts = packet - > dts ;
# else
if ( m_FormatCtx - > cur_st )
cur_dts = m_FormatCtx - > cur_st - > cur_dts ;
# endif
if ( cur_dts > = fspos ) {
bFound = true ;
# ifndef HAVE_SWSCALE
// Convert the image from its native format to RGB
img_convert ( ( AVPicture * ) m_FrameRGB , AV_PIX_FMT_RGB24 ,
( AVPicture * ) m_Frame , m_CodecCtx - > pix_fmt ,
m_CodecCtx - > width , m_CodecCtx - > height ) ;
// convert frame to TQImage
SaveFrame ( m_FrameRGB , m_CodecCtx - > width ,
m_CodecCtx - > height ) ;
# else
toRGB_convert_ctx = sws_getContext ( m_CodecCtx - > width , m_CodecCtx - > height , m_CodecCtx - > pix_fmt , m_CodecCtx - > width , m_CodecCtx - > height , AV_PIX_FMT_RGB24 , sws_flags , NULL , NULL , NULL ) ;
sws_scale ( toRGB_convert_ctx , m_Frame - > data , m_Frame - > linesize , 0 , m_CodecCtx - > height , m_FrameRGB - > data , m_FrameRGB - > linesize ) ;
sws_scale ( toRGB_convert_ctx , m_Frame - > data , m_Frame - > linesize , 0 , m_CodecCtx - > height , m_FrameRGB - > data , m_FrameRGB - > linesize ) ;
// convert frame to QImage
SaveFrame ( m_FrameRGB , m_CodecCtx - > width ,
m_CodecCtx - > height ) ;
sws_freeContext ( toRGB_convert_ctx ) ;
# endif
}
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet ( & packet ) ;
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 25, 100)
// Unreference the packet from av_read_frame
av_packet_unref ( packet ) ;
# else
// Free the packet from av_read_frame
av_free_packet ( packet ) ;
# endif
}
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
av_packet_free ( & packet ) ;
# endif
}
void k9AviDecode : : SaveFrame ( AVFrame * pFrame , int width , int height ) {
@ -380,11 +294,16 @@ void k9AviDecode::close() {
avcodec_close ( m_CodecCtx ) ;
// Close the video file
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0)
# if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0)
avformat_close_input ( & m_FormatCtx ) ;
# else
# else
av_close_input_file ( m_FormatCtx ) ;
# endif
# endif
# if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 63, 100)
avcodec_free_context ( & m_CodecCtx ) ;
# endif
m_opened = false ;
}
}