Commit 4dff974e authored by Alexander Reshetnikov's avatar Alexander Reshetnikov

Refactored new ffmpeg wrapper

parent d4fb5027
......@@ -39,24 +39,83 @@
//
//M*/
#include "cap_ffmpeg_api.hpp"
#include <assert.h>
#include <algorithm>
#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( disable: 4244 4510 4512 4610 )
#endif
#ifdef __cplusplus
extern "C" {
#endif
#undef UINT64_C
#define UINT64_C(val) val ## LL
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#if !defined(WIN32) || defined(__MINGW32__)
// some versions of FFMPEG assume a C99 compiler, and don't define INT64_C
#if !defined INT64_C || !defined UINT64_C
#define INT64_C
#define UINT64_C
#define __STDC_CONSTANT_MACROS
// force re-inclusion of stdint.h to get INT64_C macro
#undef _STDINT_H
#include <stdint.h>
#endif
#include <errno.h>
#endif
#ifdef WIN32
#define HAVE_FFMPEG_SWSCALE 1
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#else
// if the header path is not specified explicitly, let's deduce it
#if !defined HAVE_FFMPEG_AVCODEC_H && !defined HAVE_LIBAVCODEC_AVCODEC_H
#if defined(HAVE_GENTOO_FFMPEG)
#define HAVE_LIBAVCODEC_AVCODEC_H 1
#define HAVE_LIBAVFORMAT_AVFORMAT_H 1
#if defined(HAVE_FFMPEG_SWSCALE)
#define HAVE_LIBSWSCALE_SWSCALE_H 1
#endif
#elif defined HAVE_FFMPEG
#define HAVE_FFMPEG_AVCODEC_H 1
#define HAVE_FFMPEG_AVFORMAT_H 1
#if defined(HAVE_FFMPEG_SWSCALE)
#define HAVE_FFMPEG_SWSCALE_H 1
#endif
#endif
#endif
#if defined(HAVE_FFMPEG_AVCODEC_H)
#include <ffmpeg/avcodec.h>
#endif
#if defined(HAVE_FFMPEG_AVFORMAT_H)
#include <ffmpeg/avformat.h>
#endif
#if defined(HAVE_FFMPEG_SWSCALE_H)
#include <ffmpeg/swscale.h>
#endif
#if defined(HAVE_LIBAVFORMAT_AVFORMAT_H)
#include <libavformat/avformat.h>
#endif
#if defined(HAVE_LIBAVCODEC_AVCODEC_H)
#include <libavcodec/avcodec.h>
#endif
#if defined(HAVE_LIBSWSCALE_SWSCALE_H)
#include <libswscale/swscale.h>
#endif
#endif
#ifdef __cplusplus
}
#endif
#include "cap_ffmpeg_api.hpp"
#include <assert.h>
#include <algorithm>
#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( default: 4244 4510 4512 4610 )
#endif
......@@ -67,6 +126,7 @@ extern "C" {
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
#endif
#ifndef MKTAG
#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
#endif
......@@ -301,6 +361,7 @@ const AVCodecTag codec_bmp_tags[] = {
{ CODEC_ID_NONE, 0 },
};
struct Image_FFMPEG
{
unsigned char* data;
......@@ -310,419 +371,488 @@ struct Image_FFMPEG
int cn;
};
struct CvCapture_FFMPEG_2
inline void _opencv_ffmpeg_free(void** ptr)
{
CvCapture_FFMPEG_2(const char* filename);
CvCapture_FFMPEG_2(const CvCapture_FFMPEG_2& mf);
CvCapture_FFMPEG_2& operator=(const CvCapture_FFMPEG_2& mf);
~CvCapture_FFMPEG_2();
bool open( const char* filename );
void close();
bool setProperty(int, double);
double getProperty(int);
bool grabFrame();
bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn);
void init();
bool reopen();
cv::Mat read();
void seek(int64_t frame_number);
void seek(double sec);
int64_t get_total_frames();
int64_t get_frame_number();
private:
AVFormatContext * ic;
AVCodecContext * avcodec_context;
AVCodec * avcodec;
AVFrame * picture;
AVFrame * rgb_picture;
AVStream * video_st;
AVPacket packet;
Image_FFMPEG frame;
#if defined(HAVE_FFMPEG_SWSCALE)
struct SwsContext *img_convert_ctx;
#endif
if(*ptr) free(*ptr);
*ptr = 0;
}
char* filename;
struct CvCapture_FFMPEG
{
bool open( const char* filename );
void close();
int video_stream;
int64_t picture_pts;
double getProperty(int);
bool setProperty(int, double);
bool grabFrame();
bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn);
void init();
bool reopen();
size_t width, height;
int64_t frame_number;
void seek(int64_t frame_number);
void seek(double sec);
bool slowSeek( int framenumber );
double eps_zero;
int64_t get_total_frames();
double get_duration_sec();
double get_fps();
int get_bitrate();
double get_duration_sec();
double get_fps();
int get_bitrate();
double r2d(AVRational r);
int64_t dts_to_frame_number(int64_t dts);
double dts_to_sec(int64_t dts);
double r2d(AVRational r);
int64_t dts_to_frame_number(int64_t dts);
double dts_to_sec(int64_t dts);
AVFormatContext * ic;
AVCodecContext * avcodec_context;
AVCodec * avcodec;
int video_stream;
AVStream * video_st;
AVFrame * picture;
AVFrame rgb_picture;
int64_t picture_pts;
AVPacket packet;
Image_FFMPEG frame;
#if defined(HAVE_FFMPEG_SWSCALE)
struct SwsContext *img_convert_ctx;
#endif
int64_t frame_number;
double eps_zero;
/*
'filename' contains the filename of the videosource,
'filename==NULL' indicates that ffmpeg's seek support works
for the particular file.
'filename!=NULL' indicates that the slow fallback function is used for seeking,
and so the filename is needed to reopen the file on backward seeking.
*/
char * filename;
};
CvCapture_FFMPEG_2::CvCapture_FFMPEG_2(const char* filename) :
ic(0), avcodec_context(0), avcodec(0),
picture(0), rgb_picture(0), video_stream(-1),
width(0), height(0), frame_number(0), eps_zero(0.000025)
void CvCapture_FFMPEG::init()
{
av_register_all();
ic = 0;
video_stream = -1;
video_st = 0;
picture = 0;
picture_pts = 0;
memset( &rgb_picture, 0, sizeof(rgb_picture) );
memset( &frame, 0, sizeof(frame) );
filename = 0;
packet.data = NULL;
#if defined(HAVE_FFMPEG_SWSCALE)
img_convert_ctx = 0;
#endif
avcodec_context = 0;
avcodec = 0;
frame_number = 0;
eps_zero = 0.000025;
}
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
avformat_network_init();
#endif
// Open video file
avformat_open_input(&ic, filename, NULL, NULL);
void CvCapture_FFMPEG::close()
{
if( picture )
av_free(picture);
// Find the first video stream
for(int i = 0; i < static_cast<int>(ic->nb_streams); i++)
{
struct AVCodecContext * cc = ic->streams[i]->codec;
// set number of threads
cc->thread_count = 2;
if( video_st )
{
#if LIBAVFORMAT_BUILD > 4628
avcodec_close( video_st->codec );
if(cc->codec_type == AVMEDIA_TYPE_VIDEO && video_stream == -1)
{
AVCodec * codec = avcodec_find_decoder(cc->codec_id);
#else
avcodec_close( &(video_st->codec) );
if (codec == NULL)
CV_Error(0, "Unsupported codec !!!");
#endif
video_st = NULL;
}
avcodec_open2(cc, codec, NULL);
video_stream = i;
break;
}
if ( avcodec_context )
{
#if LIBAVFORMAT_BUILD > 4628
avcodec_close( avcodec_context );
#else
avcodec_close( &avcodec_context );
#endif
avcodec_context = NULL;
}
if(video_stream == -1)
CV_Error(0, "Didn't find a video stream");
if( ic )
{
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
av_close_input_file(ic);
#else
avformat_close_input(&ic);
#endif
// Get a pointer to the codec context for the video stream
avcodec_context = ic->streams[video_stream]->codec;
ic = NULL;
}
// Allocate video frame
picture = avcodec_alloc_frame();
}
if( rgb_picture.data[0] )
{
free( rgb_picture.data[0] );
rgb_picture.data[0] = 0;
}
CvCapture_FFMPEG_2::CvCapture_FFMPEG_2(const CvCapture_FFMPEG_2& vr) :
ic(vr.ic),
avcodec_context (vr.avcodec_context),
avcodec(0),
picture(0),
rgb_picture(0),
video_stream(-1),
width(0), height(0),
frame_number(0),
eps_zero(0.000001) {}
CvCapture_FFMPEG_2& CvCapture_FFMPEG_2::operator=(const CvCapture_FFMPEG_2& mf)
{
ic = mf.ic;
avcodec_context = mf.avcodec_context;
return *this;
// free last packet if exist
if (packet.data) {
av_free_packet (&packet);
}
init();
}
bool CvCapture_FFMPEG_2::open(const char* filename)
/*
Used to reopen a video if the slower fallback function for seeking is used.
*/
bool CvCapture_FFMPEG::reopen()
{
CvCapture_FFMPEG_2 cap(filename);
*this = cap;
if ( filename==NULL ) return false;
#if LIBAVFORMAT_BUILD > 4628
avcodec_close( video_st->codec );
avcodec_close( avcodec_context );
#else
avcodec_close( &video_st->codec );
avcodec_close( &avcodec_context );
#endif
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
av_close_input_file(ic);
#else
avformat_close_input(&ic);
#endif
// reopen video
avformat_open_input(&ic, filename, NULL, NULL);
av_find_stream_info(ic);
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext *enc = ic->streams[video_stream]->codec;
#else
AVCodecContext *enc = &ic->streams[video_stream]->codec;
#endif
#ifdef FF_API_THREAD_INIT
avcodec_thread_init(enc, std::min(get_number_of_cpus(), 16));
#endif
AVCodec *codec = avcodec_find_decoder(enc->codec_id);
#if FF_API_AVCODEC_OPEN
avcodec_open(enc, codec);
#else
avcodec_open_2(enc, codec, NULL);
#endif
video_st = ic->streams[video_stream];
// reset framenumber to zero
frame_number = 0;
picture_pts=0;
return true;
}
void CvCapture_FFMPEG_2::close()
#ifndef AVSEEK_FLAG_FRAME
#define AVSEEK_FLAG_FRAME 0
#endif
#ifndef AVSEEK_FLAG_ANY
#define AVSEEK_FLAG_ANY 1
#endif
bool CvCapture_FFMPEG::open( const char* _filename )
{
if( picture )
av_free(picture);
unsigned i;
bool valid = false;
if( video_st )
close();
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
avformat_network_init();
#endif
/* register all codecs, demux and protocols */
av_register_all();
#ifndef _DEBUG
// av_log_level = AV_LOG_QUIET;
#endif
int err = avformat_open_input(&ic, _filename, NULL, NULL);
if (err < 0) {
CV_WARN("Error opening file");
goto exit_func;
}
err = av_find_stream_info(ic);
if (err < 0) {
CV_WARN("Could not find codec parameters");
goto exit_func;
}
for(i = 0; i < ic->nb_streams; i++)
{
#if LIBAVFORMAT_BUILD > 4628
avcodec_close( video_st->codec );
#else
avcodec_close( &video_st->codec );
#endif
video_st = NULL;
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext *enc = ic->streams[i]->codec;
#else
AVCodecContext *enc = &ic->streams[i]->codec;
#endif
#ifdef FF_API_THREAD_INIT
avcodec_thread_init(enc, get_number_of_cpus());
#else
enc->thread_count = get_number_of_cpus();
#endif
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif
if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
AVCodec *codec = avcodec_find_decoder(enc->codec_id);
if (!codec ||
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
avcodec_open2(enc, codec, NULL)
#else
avcodec_open(enc, codec)
#endif
< 0) goto exit_func;
video_stream = i;
video_st = ic->streams[i];
picture = avcodec_alloc_frame();
rgb_picture.data[0] = (uint8_t*)malloc(
avpicture_get_size( PIX_FMT_BGR24,
enc->width, enc->height ));
avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
PIX_FMT_BGR24, enc->width, enc->height );
frame.width = enc->width;
frame.height = enc->height;
frame.cn = 3;
frame.step = rgb_picture.linesize[0];
frame.data = rgb_picture.data[0];
break;
}
}
if( ic )
if(video_stream >= 0) valid = true;
// perform check if source is seekable via ffmpeg's seek function av_seek_frame(...)
err = av_seek_frame(ic, video_stream, 10, 0);
if (err < 0)
{
av_close_input_file(ic);
ic = NULL;
filename=(char*)malloc(strlen(_filename)+1);
strcpy(filename, _filename);
// reopen videofile to 'seek' back to first frame
reopen();
}
if( rgb_picture->data[0] )
else
{
free( rgb_picture->data[0] );
rgb_picture->data[0] = 0;
// seek seems to work, so we don't need the filename,
// but we still need to seek back to filestart
filename=NULL;
int64_t ts = video_st->first_dts;
int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD;
av_seek_frame(ic, video_stream, ts, flags);
}
exit_func:
// free last packet if exist
if (packet.data) {
av_free_packet (&packet);
}
if( !valid )
close();
init();
return valid;
}
bool CvCapture_FFMPEG_2::grabFrame()
bool CvCapture_FFMPEG::grabFrame()
{
bool valid = false;
static bool bFirstTime = true;
int got_picture;
// First time we're called, set packet.data to NULL to indicate it
// doesn't have to be freed
if (bFirstTime) {
int count_errs = 0;
const int max_number_of_attempts = 64;
if (bFirstTime)
{
bFirstTime = false;
packet.data = NULL;
}
if( !ic || !video_st )
return false;
if( !ic || !video_st ) return false;
// free last packet if exist
if (packet.data != NULL) {
if (packet.data != NULL)
{
av_free_packet (&packet);
}
// get the next frame
while (!valid) {
while (!valid)
{
int ret = av_read_frame(ic, &packet);
if (ret == AVERROR(EAGAIN))
continue;
if (ret < 0)
break;
if( packet.stream_index != video_stream ) {
if (ret == AVERROR(EAGAIN)) continue;
/* else if (ret < 0) break; */
if( packet.stream_index != video_stream )
{
av_free_packet (&packet);
count_errs++;
if (count_errs > max_number_of_attempts) break; else
continue;
}
}
// Decode video frame
avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);
if (got_picture) {
// we have a new picture, so memorize it
picture_pts = packet.pts;
valid = 1;
}
// Did we get a video frame?
if(got_picture)
{
frame_number++;
picture_pts = packet.pts;
valid = true;
}
else
{
count_errs++;
if (count_errs > max_number_of_attempts)
break;
}
}
// return if we have a new picture or not
return valid;
}
bool CvCapture_FFMPEG_2::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn)
bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn)
{
if( !video_st || !picture->data[0] )
return false;
#if !defined(HAVE_FFMPEG_SWSCALE)
#if LIBAVFORMAT_BUILD > 4628
img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
(AVPicture*)picture,
video_st->codec->pix_fmt,
video_st->codec->width,
video_st->codec->height );
#else
img_convert( (AVPicture*)&rgb_picture, PIX_FMT_BGR24,
(AVPicture*)picture,
video_st->codec.pix_fmt,
video_st->codec.width,
video_st->codec.height );
#endif
#else
img_convert_ctx = sws_getContext(video_st->codec->width,
video_st->codec->height,
video_st->codec->pix_fmt,
video_st->codec->width,
video_st->codec->height,
PIX_FMT_BGR24,
SWS_BICUBIC,
NULL, NULL, NULL);
sws_scale(img_convert_ctx, picture->data,
picture->linesize, 0,
video_st->codec->height,
rgb_picture->data, rgb_picture->linesize);
sws_freeContext(img_convert_ctx);
#endif
*data = frame.data;
*step = frame.step;
*width = frame.width;
*height = frame.height;
*cn = frame.cn;
rgb_picture = *avcodec_alloc_frame();
return true;
}
avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], PIX_FMT_RGB24, video_st->codec->width, video_st->codec->height);
void CvCapture_FFMPEG_2::init()
{
ic = 0;
video_stream = -1;
video_st = 0;
picture = 0;
picture_pts = 0;
memset( &rgb_picture, 0, sizeof(rgb_picture) );
memset( &frame, 0, sizeof(frame) );
filename = 0;
packet.data = NULL;
#if defined(HAVE_FFMPEG_SWSCALE)
img_convert_ctx = 0;
#endif
}
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(6<<8)+0)
bool CvCapture_FFMPEG_2::reopen()
{
if ( filename==NULL ) return false;
frame.width = picture->width;
frame.height = picture->height;
#if LIBAVFORMAT_BUILD > 4628
avcodec_close( video_st->codec );
#else
avcodec_close( &video_st->codec );
#endif
av_close_input_file(ic);
#else
frame.width = video_st->codec->width;
frame.height = video_st->codec->height;
#endif
// reopen video
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0)
av_open_input_file(&ic, filename, NULL, 0, NULL);
#else
avformat_open_input(&ic, filename, NULL, NULL);
#endif
img_convert_ctx = sws_getContext(
video_st->codec->width, video_st->codec->height,
video_st->codec->pix_fmt,
video_st->codec->width, video_st->codec->height,
PIX_FMT_BGR24,
SWS_BICUBIC,
NULL, NULL, NULL
);
av_find_stream_info(ic);
img_convert_ctx = sws_getCachedContext(
img_convert_ctx,
video_st->codec->width, video_st->codec->height,
video_st->codec->pix_fmt,
video_st->codec->width, video_st->codec->height,
PIX_FMT_BGR24,
SWS_BICUBIC,
NULL, NULL, NULL
);
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext *enc = ic->streams[video_stream]->codec;
#else
AVCodecContext *enc = &ic->streams[video_stream]->codec;
#endif
if (img_convert_ctx == NULL)
CV_Error(0, "Cannot initialize the conversion context!");
#if FF_API_THREAD_INIT
avcodec_thread_init(enc, std::min(get_number_of_cpus(), 16));
#endif
sws_scale(
img_convert_ctx,
picture->data,
picture->linesize,
0, video_st->codec->height,
rgb_picture.data,
rgb_picture.linesize
);
AVCodec *codec = avcodec_find_decoder(enc->codec_id);
avcodec_open(enc, codec);
video_st = ic->streams[video_stream];
sws_freeContext(img_convert_ctx);
// reset framenumber to zero
picture_pts=0;
frame_number++;
*data = frame.data;
*step = frame.step;
*width = frame.width;
*height = frame.height;
*cn = frame.cn;
return true;
}
int64_t CvCapture_FFMPEG_2::get_frame_number()
{
return frame_number;
}
#if defined(__APPLE__)
#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL)
#else
#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE)
#endif
cv::Mat CvCapture_FFMPEG_2::read()
double CvCapture_FFMPEG::getProperty( int property_id )
{
int frame_finished = 0;
AVPacket packet;
// if( !capture || !video_st || !picture->data[0] ) return 0;
if( !video_st ) return 0;
int count_errs = 0;
const int max_number_of_attempts = 32;
// double frameScale = av_q2d (video_st->time_base) * av_q2d (video_st->r_frame_rate);
int64_t timestamp;
timestamp = picture_pts;
while(true)
switch( property_id )
{
av_read_frame(ic, &packet);
if(packet.stream_index == video_stream)
{
// Decode video frame
avcodec_decode_video2(avcodec_context, picture, &frame_finished, &packet);
// Did we get a video frame?
if(frame_finished)
{
rgb_picture = avcodec_alloc_frame();
cv::Mat img(static_cast<int>(avcodec_context->height), static_cast<int>(avcodec_context->width), CV_8UC3);
uint8_t * buffer = reinterpret_cast<uint8_t *>(img.ptr(0));
avpicture_fill(reinterpret_cast<AVPicture*>(rgb_picture), buffer, PIX_FMT_RGB24, avcodec_context->width, avcodec_context->height);
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(4<<8)+0)
width = picture->width;
height = picture->height;
#else
width = avcodec_context->width;
height = avcodec_context->height;
#endif
struct SwsContext * img_convert_ctx = sws_getContext(
width, height,
avcodec_context->pix_fmt,
width, height,
PIX_FMT_BGR24,
SWS_BICUBIC,
NULL, NULL, NULL
);
img_convert_ctx = sws_getCachedContext(
img_convert_ctx,
width, height,
avcodec_context->pix_fmt,
width, height,
PIX_FMT_BGR24,
SWS_BICUBIC,
NULL, NULL, NULL
);
if (img_convert_ctx == NULL)
CV_Error(0, "Cannot initialize the conversion context!");
sws_scale(
img_convert_ctx,
picture->data,
picture->linesize,
0, height,
rgb_picture->data,
rgb_picture->linesize
);
sws_freeContext(img_convert_ctx);
av_free(rgb_picture);
frame_number++;
//std::cout << "cur dts: " << ic->streams[video_stream]->cur_dts << std::endl;
return img;
}
else
{
count_errs ++;
if (count_errs > max_number_of_attempts)
break;
}
}
else
{
count_errs ++;
if (count_errs > max_number_of_attempts)
break;
}
case CV_FFMPEG_CAP_PROP_POS_MSEC:
return 1000.0*static_cast<int>(frame_number)/static_cast<int>(get_fps());
break;
case CV_FFMPEG_CAP_PROP_POS_FRAMES:
return (double)static_cast<int>(frame_number);
break;
case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
return r2d(ic->streams[video_stream]->time_base);
break;
case CV_FFMPEG_CAP_PROP_FRAME_COUNT:
return (double)static_cast<int>(get_total_frames());
break;
case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
return (double)frame.width;
break;
case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
return (double)frame.height;
break;
case CV_FFMPEG_CAP_PROP_FPS:
#if LIBAVCODEC_BUILD > 4753
return av_q2d (video_st->r_frame_rate);
#else
return (double)video_st->codec.frame_rate
/ (double)video_st->codec.frame_rate_base;
#endif
break;
case CV_FFMPEG_CAP_PROP_FOURCC:
#if LIBAVFORMAT_BUILD > 4628
return (double)video_st->codec->codec_tag;
#else
return (double)video_st->codec.codec_tag;
#endif
break;
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
return cv::Mat();
return 0;
}
double CvCapture_FFMPEG_2::r2d(AVRational r)
double CvCapture_FFMPEG::r2d(AVRational r)
{
if (r.num == 0 || r.den == 0)
{
......@@ -734,7 +864,7 @@ double CvCapture_FFMPEG_2::r2d(AVRational r)
}
}
double CvCapture_FFMPEG_2::get_duration_sec()
double CvCapture_FFMPEG::get_duration_sec()
{
double sec = static_cast<double>(ic->duration) / static_cast<double>(AV_TIME_BASE);
......@@ -747,15 +877,16 @@ double CvCapture_FFMPEG_2::get_duration_sec()
{
sec = static_cast<double>(static_cast<int64_t>(ic->streams[video_stream]->duration)) * r2d(ic->streams[video_stream]->time_base);
}
return sec;
}
int CvCapture_FFMPEG_2::get_bitrate()
int CvCapture_FFMPEG::get_bitrate()
{
return ic->bit_rate;
}
double CvCapture_FFMPEG_2::get_fps()
double CvCapture_FFMPEG::get_fps()
{
double fps = r2d(ic->streams[video_stream]->r_frame_rate);
......@@ -764,7 +895,6 @@ double CvCapture_FFMPEG_2::get_fps()
fps = r2d(ic->streams[video_stream]->avg_frame_rate);
}
// may be this is wrong
if (fps < eps_zero)
{
fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base);
......@@ -773,7 +903,7 @@ double CvCapture_FFMPEG_2::get_fps()
return fps;
}
int64_t CvCapture_FFMPEG_2::get_total_frames()
int64_t CvCapture_FFMPEG::get_total_frames()
{
int64_t nbf = ic->streams[video_stream]->nb_frames;
......@@ -784,30 +914,21 @@ int64_t CvCapture_FFMPEG_2::get_total_frames()
return nbf;
}
//#include <iostream>
double round(double d)
{
return std::floor(d + 0.5);
}
int64_t CvCapture_FFMPEG_2::dts_to_frame_number(int64_t dts)
int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts)
{
double sec = dts_to_sec(dts);
return static_cast<int64_t>(get_fps() * sec);
}
double CvCapture_FFMPEG_2::dts_to_sec(int64_t dts)
double CvCapture_FFMPEG::dts_to_sec(int64_t dts)
{
return static_cast<double>(dts - ic->streams[video_stream]->start_time) * r2d(ic->streams[video_stream]->time_base);
}
void CvCapture_FFMPEG_2::seek(int64_t frame_number)
void CvCapture_FFMPEG::seek(int64_t frame_number)
{
double sec = static_cast<double>(frame_number) / static_cast<double>(get_fps());
this->frame_number = std::min<int>(frame_number, get_total_frames());
seek(sec);
/* int64_t dts = dts_to_frame_number(ic->streams[video_stream]->cur_dts);
frame_number = std::min(frame_number, get_total_frames());
int64_t dts = dts_to_frame_number(ic->streams[video_stream]->cur_dts);
if (abs(dts - 2 - frame_number) > 16)
{
......@@ -820,38 +941,38 @@ void CvCapture_FFMPEG_2::seek(int64_t frame_number)
while(dts - 2 < frame_number)
{
cv::Mat i = read();
if (i.empty())
break;
/* cv::Mat imag = read(); */
if (!grabFrame()) break;
dts = dts_to_frame_number(ic->streams[video_stream]->cur_dts);
//std::cout << "cur dts: " << ic->streams[video_stream]->cur_dts << " f: " << dts << std::endl;
} */
}
}
void CvCapture_FFMPEG_2::seek(double sec)
void CvCapture_FFMPEG::seek(double sec)
{
// seek(static_cast<int64_t>(sec * get_fps()));
int64_t time_stamp = ic->streams[video_stream]->start_time;
double time_base = av_q2d(ic->streams[video_stream]->time_base);
time_stamp += static_cast<int64_t>(sec / time_base);
av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD);
seek(static_cast<int64_t>(sec * get_fps()));
}
CvCapture_FFMPEG_2::~CvCapture_FFMPEG_2()
// this is a VERY slow fallback function, ONLY used if ffmpeg's av_seek_frame delivers no correct result!
bool CvCapture_FFMPEG::slowSeek( int framenumber )
{
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
av_close_input_file(ic);
#else
avformat_close_input(&ic);
#endif
if ( framenumber>picture_pts )
{
while ( picture_pts<framenumber )
if ( !grabFrame() ) return false;
}
else if ( framenumber<picture_pts )
{
reopen();
while ( picture_pts<framenumber )
if ( !grabFrame() ) return false;
}
return true;
}
bool CvCapture_FFMPEG_2::setProperty( int property_id, double value )
bool CvCapture_FFMPEG::setProperty( int property_id, double value )
{
if (!video_stream) return false;
if( !video_st ) return false;
switch( property_id )
{
......@@ -859,46 +980,22 @@ bool CvCapture_FFMPEG_2::setProperty( int property_id, double value )
case CV_FFMPEG_CAP_PROP_POS_FRAMES:
case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
{
switch( property_id )
{
case CV_FFMPEG_CAP_PROP_POS_FRAMES:
seek(value/1000.0); break;
seek((int64_t)value);
break;
case CV_FFMPEG_CAP_PROP_POS_MSEC:
seek(value);
seek(value/1000.0);
break;
case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
seek(value*this->get_bitrate());
seek((int64_t)(value*ic->duration));
break;
}
/* if ( filename )
{
// ffmpeg's seek doesn't work...
if (!slowSeek((int)timestamp))
{
fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
(double)timestamp / AV_TIME_BASE);
return false;
}
}
else
{
int flags = AVSEEK_FLAG_ANY;
if (timestamp < ic->streams[video_stream]->cur_dts)
flags |= AVSEEK_FLAG_BACKWARD;
int ret = av_seek_frame(ic, video_stream, timestamp, flags);
if (ret < 0)
{
fprintf(stderr, "HIGHGUI ERROR: AVI: could not seek to position %0.3f\n",
(double)timestamp / AV_TIME_BASE);
return false;
}
}
picture_pts=(int64_t)value;*/
picture_pts=(int64_t)value;
}
break;
default:
......@@ -906,69 +1003,8 @@ bool CvCapture_FFMPEG_2::setProperty( int property_id, double value )
}
return true;
}
#if defined(__APPLE__)
#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL)
#else
#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE)
#endif
double CvCapture_FFMPEG_2::getProperty( int property_id )
{
// if( !capture || !video_st || !picture->data[0] ) return 0;
if( !video_stream ) return 0;
double frameScale = av_q2d (video_st->time_base) * av_q2d (video_st->r_frame_rate);
int64_t timestamp;
timestamp = picture_pts;
switch( property_id )
{
case CV_FFMPEG_CAP_PROP_POS_MSEC:
return 1000.0*static_cast<double>(dts_to_sec(frame_number));
break;
case CV_FFMPEG_CAP_PROP_POS_FRAMES:
return (double)static_cast<int>(get_frame_number());
break;
case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
return static_cast<double>(dts_to_frame_number(frame_number))/static_cast<double>(dts_to_sec(frame_number));
break;
case CV_FFMPEG_CAP_PROP_FRAME_COUNT:
return (double)static_cast<int>(get_total_frames());
break;
case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
return (double)static_cast<int>(width);
break;
case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
return (double)static_cast<int>(height);
break;
case CV_FFMPEG_CAP_PROP_FPS:
#if LIBAVCODEC_BUILD > 4753
return av_q2d (video_st->r_frame_rate);
#else
return (double)video_st->codec.frame_rate
/ (double)video_st->codec.frame_rate_base;
#endif
break;
case CV_FFMPEG_CAP_PROP_FOURCC:
#if LIBAVFORMAT_BUILD > 4628
return (double)video_st->codec->codec_tag;
#else
return (double)video_st->codec.codec_tag;
#endif
break;
}
return 0;
}
///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
struct CvVideoWriter_FFMPEG
......@@ -980,8 +1016,8 @@ struct CvVideoWriter_FFMPEG
void init();
AVOutputFormat *fmt;
AVFormatContext *oc;
AVOutputFormat * fmt;
AVFormatContext * oc;
uint8_t * outbuf;
uint32_t outbuf_size;
FILE * outfile;
......@@ -1067,9 +1103,9 @@ void CvVideoWriter_FFMPEG::init()
video_st = 0;
input_pix_fmt = 0;
memset(&temp_image, 0, sizeof(temp_image));
#if defined(HAVE_FFMPEG_SWSCALE)
img_convert_ctx = 0;
#endif
#if defined(HAVE_FFMPEG_SWSCALE)
img_convert_ctx = 0;
#endif
}
/**
......@@ -1115,21 +1151,21 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
st = av_new_stream(oc, 0);
if (!st) {
/* CV_WARN("Could not allocate stream"); */
CV_WARN("Could not allocate stream");
return NULL;
}
#if LIBAVFORMAT_BUILD > 4628
c = st->codec;
#else
c = &(st->codec);
#endif
#if LIBAVFORMAT_BUILD > 4628
c = st->codec;
#else
c = &(st->codec);
#endif
#if LIBAVFORMAT_BUILD > 4621
c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
#else
c->codec_id = oc->oformat->video_codec;
#endif
#if LIBAVFORMAT_BUILD > 4621
c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
#else
c->codec_id = oc->oformat->video_codec;
#endif
if(codec_id != CODEC_ID_NONE){
c->codec_id = codec_id;
......@@ -1157,30 +1193,30 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
frame_rate_base*=10;
frame_rate=(int)(fps*frame_rate_base + 0.5);
}
#if LIBAVFORMAT_BUILD > 4752
c->time_base.den = frame_rate;
c->time_base.num = frame_rate_base;
/* adjust time base for supported framerates */
if(codec && codec->supported_framerates){
const AVRational *p= codec->supported_framerates;
AVRational req = {frame_rate, frame_rate_base};
const AVRational *best=NULL;
AVRational best_error= {INT_MAX, 1};
for(; p->den!=0; p++){
AVRational error= av_sub_q(req, *p);
if(error.num <0) error.num *= -1;
if(av_cmp_q(error, best_error) < 0){
best_error= error;
best= p;
}
}
c->time_base.den= best->num;
c->time_base.num= best->den;
}
#else
c->frame_rate = frame_rate;
c->frame_rate_base = frame_rate_base;
#endif
#if LIBAVFORMAT_BUILD > 4752
c->time_base.den = frame_rate;
c->time_base.num = frame_rate_base;
/* adjust time base for supported framerates */
if(codec && codec->supported_framerates){
const AVRational *p= codec->supported_framerates;
AVRational req = {frame_rate, frame_rate_base};
const AVRational *best=NULL;
AVRational best_error= {INT_MAX, 1};
for(; p->den!=0; p++){
AVRational error= av_sub_q(req, *p);
if(error.num <0) error.num *= -1;
if(av_cmp_q(error, best_error) < 0){
best_error= error;
best= p;
}
}
c->time_base.den= best->num;
c->time_base.num= best->den;
}
#else
c->frame_rate = frame_rate;
c->frame_rate_base = frame_rate_base;
#endif
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = (PixelFormat) pixel_format;
......@@ -1195,25 +1231,24 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
/* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
c->mb_decision=2;
}
#if LIBAVCODEC_VERSION_INT>0x000409
// some formats want stream headers to be seperate
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
{
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
#endif
#if LIBAVCODEC_VERSION_INT>0x000409
// some formats want stream headers to be seperate
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
{
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
#endif
return st;
}
int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture )
{
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext * c = video_st->codec;
#else
AVCodecContext * c = &(video_st->codec);
#endif
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext * c = video_st->codec;
#else
AVCodecContext * c = &(video_st->codec);
#endif
int out_size;
int ret;
......@@ -1241,11 +1276,11 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
AVPacket pkt;
av_init_packet(&pkt);
#if LIBAVFORMAT_BUILD > 4752
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
#else
pkt.pts = c->coded_frame->pts;
#endif
#if LIBAVFORMAT_BUILD > 4752
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
#else
pkt.pts = c->coded_frame->pts;
#endif
if(c->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= video_st->index;
......@@ -1269,50 +1304,50 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
bool ret = false;
// typecast from opaque data type to implemented struct
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext *c = video_st->codec;
#else
AVCodecContext *c = &(video_st->codec);
#endif
#if LIBAVFORMAT_BUILD < 5231
// It is not needed in the latest versions of the ffmpeg
if( c->codec_id == CODEC_ID_RAWVIDEO && origin != 1 )
{
if( !temp_image.data )
{
temp_image.step = (width*cn + 3) & -4;
temp_image.width = width;
temp_image.height = height;
temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
}
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn);
data = temp_image.data;
step = temp_image.step;
}
#else
if( width*cn != step )
{
if( !temp_image.data )
{
temp_image.step = width*cn;
temp_image.width = width;
temp_image.height = height;
temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
}
if (origin == 1)
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, temp_image.step);
else
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + y*step, temp_image.step);
data = temp_image.data;
step = temp_image.step;
}
#endif
#if LIBAVFORMAT_BUILD > 4628
AVCodecContext *c = video_st->codec;
#else
AVCodecContext *c = &(video_st->codec);
#endif
#if LIBAVFORMAT_BUILD < 5231
// It is not needed in the latest versions of the ffmpeg
if( c->codec_id == CODEC_ID_RAWVIDEO && origin != 1 )
{
if( !temp_image.data )
{
temp_image.step = (width*cn + 3) & -4;
temp_image.width = width;
temp_image.height = height;
temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
}
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn);
data = temp_image.data;
step = temp_image.step;
}
#else
if( width*cn != step )
{
if( !temp_image.data )
{
temp_image.step = width*cn;
temp_image.width = width;
temp_image.height = height;
temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
}
if (origin == 1)
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, temp_image.step);
else
for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + y*step, temp_image.step);
data = temp_image.data;
step = temp_image.step;
}
#endif
// check parameters
if (input_pix_fmt == PIX_FMT_BGR24) {
......@@ -1329,13 +1364,6 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
assert(false);
}
// check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment)
/*#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(37<<8)+0)
assert (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height ));
#else
assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height ));
#endif*/
if ( c->pix_fmt != input_pix_fmt ) {
assert( input_picture );
// let input_picture point to the raw data buffer of 'image'
......@@ -1397,11 +1425,11 @@ void CvVideoWriter_FFMPEG::close()
av_write_trailer(oc);
// free pictures
#if LIBAVFORMAT_BUILD > 4628
if( video_st->codec->pix_fmt != input_pix_fmt){
#else
if( video_st->codec.pix_fmt != input_pix_fmt){
#endif
#if LIBAVFORMAT_BUILD > 4628
if( video_st->codec->pix_fmt != input_pix_fmt){
#else
if( video_st->codec.pix_fmt != input_pix_fmt){
#endif
if(picture->data[0])
free(picture->data[0]);
picture->data[0] = 0;
......@@ -1413,11 +1441,11 @@ void CvVideoWriter_FFMPEG::close()
}
/* close codec */
#if LIBAVFORMAT_BUILD > 4628
avcodec_close(video_st->codec);
#else
avcodec_close(&(video_st->codec));
#endif
#if LIBAVFORMAT_BUILD > 4628
avcodec_close(video_st->codec);
#else
avcodec_close(&(video_st->codec));
#endif
av_free(outbuf);
......@@ -1430,13 +1458,15 @@ void CvVideoWriter_FFMPEG::close()
if (!(fmt->flags & AVFMT_NOFILE)) {
/* close the output file */
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0) && LIBAVCODEC_VERSION_INT <= ((54<<16)+(5<<8)+0)
url_fclose(oc->pb);
#else
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
url_fclose(&oc->pb);
#endif
#endif
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
url_fclose(oc->pb);
#else
url_fclose(&oc->pb);
#endif
#else
avio_close(oc->pb);
#endif
}
......@@ -1471,11 +1501,11 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
/* auto detect the output format from the name and fourcc code. */
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
fmt = av_guess_format(NULL, filename, NULL);
#else
fmt = guess_format(NULL, filename, NULL);
#endif
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
fmt = av_guess_format(NULL, filename, NULL);
#else
fmt = guess_format(NULL, filename, NULL);
#endif
if (!fmt)
return false;
......@@ -1489,21 +1519,21 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
}
/* Lookup codec_id for given fourcc */
#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE )
return false;
#else
/* const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL};
if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE )
return false; */
#endif
#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE )
return false;
#else
const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL};
if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE )
return false;
#endif
// alloc memory for context
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
oc = avformat_alloc_context();
#else
oc = av_alloc_format_context();
#endif
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
oc = avformat_alloc_context();
#else
oc = av_alloc_format_context();
#endif
assert (oc);
/* set file name */
......@@ -1515,12 +1545,12 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
// set a few optimal pixel formats for lossless codecs of interest..
switch (codec_id) {
#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
case CODEC_ID_JPEGLS:
// BGR24 or GRAY8 depending on is_color...
codec_pix_fmt = input_pix_fmt;
break;
#endif
#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
case CODEC_ID_JPEGLS:
// BGR24 or GRAY8 depending on is_color...
codec_pix_fmt = input_pix_fmt;
break;
#endif
case CODEC_ID_HUFFYUV:
codec_pix_fmt = PIX_FMT_YUV422P;
break;
......@@ -1546,19 +1576,20 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
/* set the output parameters (must be done even if no
parameters). */
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
if (av_set_parameters(oc, NULL) < 0) {
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
if (av_set_parameters(oc, NULL) < 0)
#else
if (avformat_write_header(oc, NULL) < 0)
#endif
{
return false;
}
#endif
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
av_dump_format(oc, 0, filename, 1);
#else
dump_format(oc, 0, filename, 1);
#endif
#if FF_API_DUMP_FORMAT
dump_format(oc, 0, filename, 1);
#else
av_dump_format(oc, 0, filename, 1);
#endif
/* now that all the parameters are set, we can open the audio and
video codecs and allocate the necessary encode buffers */
......@@ -1569,11 +1600,11 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
AVCodec *codec;
AVCodecContext *c;
#if LIBAVFORMAT_BUILD > 4628
c = (video_st->codec);
#else
c = &(video_st->codec);
#endif
#if LIBAVFORMAT_BUILD > 4628
c = (video_st->codec);
#else
c = &(video_st->codec);
#endif
c->codec_tag = fourcc;
/* find the video encoder */
......@@ -1621,105 +1652,97 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
}
/* open the output file, if needed */
#ifndef URL_RDONLY
#define URL_RDONLY 1
#endif
#ifndef URL_WRONLY
#define URL_WRONLY 2
#endif
#ifndef URL_RWONLY
#define URL_RWONLY (URL_RDONLY|URL_WRONLY)
#endif
if (!(fmt->flags & AVFMT_NOFILE))
{
#if LIBAVCODEC_VERSION_INT <= ((54<<16)+(5<<8)+0)
if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)
if (!(fmt->flags & AVFMT_NOFILE)) {
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)
#else
if (avio_open(&oc->pb, filename, 1) < 0)
#endif
{
return false;
}
#endif
}
/* write the stream header, if any */
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
avformat_write_header(oc, NULL);
#else
av_write_header( oc );
#endif
return true;
}
CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
int width, int height, int isColor )
CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
{
CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer));
writer->init();
if( writer->open( filename, fourcc, fps, width, height, isColor != 0 ))
return writer;
writer->close();
free(writer);
CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
capture->init();
if( capture->open( filename ))
return capture;
capture->close();
free(capture);
return 0;
}
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
{
if( writer && *writer )
if( capture && *capture )
{
(*writer)->close();
free(*writer);
*writer = 0;
(*capture)->close();
free(*capture);
*capture = 0;
}
}
int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
const unsigned char* data, int step,
int width, int height, int cn, int origin)
{
return writer->writeFrame(data, step, width, height, cn, origin);
}
int cvSetCaptureProperty_FFMPEG_2(CvCapture_FFMPEG_2* capture, int prop_id, double value)
int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value)
{
return capture->setProperty(prop_id, value);
}
double cvGetCaptureProperty_FFMPEG_2(CvCapture_FFMPEG_2* capture, int prop_id)
double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id)
{
return capture->getProperty(prop_id);
}
int cvGrabFrame_FFMPEG_2(CvCapture_FFMPEG_2* capture)
int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)
{
return capture->grabFrame();
}
int cvRetrieveFrame_FFMPEG_2(CvCapture_FFMPEG_2* capture, unsigned char** data, int* step, int* width, int* height, int* cn)
int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* capture, unsigned char** data, int* step, int* width, int* height, int* cn)
{
return capture->retrieveFrame(0, data, step, width, height, cn);
}
CvCapture_FFMPEG_2* cvCreateFileCapture_FFMPEG_2( const char* filename )
CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
int width, int height, int isColor )
{
CvCapture_FFMPEG_2* capture = (CvCapture_FFMPEG_2*)malloc(sizeof(*capture));
capture->init();
if( capture->open( filename ))
return capture;
capture->close();
free(capture);
CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer));
writer->init();
if( writer->open( filename, fourcc, fps, width, height, isColor != 0 ))
return writer;
writer->close();
free(writer);
return 0;
}
void cvReleaseCapture_FFMPEG_2(CvCapture_FFMPEG_2** capture)
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
{
if( capture && *capture )
if( writer && *writer )
{
(*capture)->close();
free(*capture);
*capture = 0;
(*writer)->close();
free(*writer);
*writer = 0;
}
}
int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
const unsigned char* data, int step,
int width, int height, int cn, int origin)
{
return writer->writeFrame(data, step, width, height, cn, origin);
}
......@@ -74,17 +74,17 @@ icvInitFFMPEG(void)
if( icvFFOpenCV )
{
icvCreateFileCapture_FFMPEG_p =
(CvCreateFileCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateFileCapture_FFMPEG_2");
(CvCreateFileCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateFileCapture_FFMPEG");
icvReleaseCapture_FFMPEG_p =
(CvReleaseCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseCapture_FFMPEG_2");
(CvReleaseCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseCapture_FFMPEG");
icvGrabFrame_FFMPEG_p =
(CvGrabFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvGrabFrame_FFMPEG_2");
(CvGrabFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvGrabFrame_FFMPEG");
icvRetrieveFrame_FFMPEG_p =
(CvRetrieveFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvRetrieveFrame_FFMPEG_2");
(CvRetrieveFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvRetrieveFrame_FFMPEG");
icvSetCaptureProperty_FFMPEG_p =
(CvSetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvSetCaptureProperty_FFMPEG_2");
(CvSetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvSetCaptureProperty_FFMPEG");
icvGetCaptureProperty_FFMPEG_p =
(CvGetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvGetCaptureProperty_FFMPEG_2");
(CvGetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvGetCaptureProperty_FFMPEG");
icvCreateVideoWriter_FFMPEG_p =
(CvCreateVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateVideoWriter_FFMPEG");
icvReleaseVideoWriter_FFMPEG_p =
......@@ -112,12 +112,12 @@ icvInitFFMPEG(void)
#endif
}
#elif defined HAVE_FFMPEG
icvCreateFileCapture_FFMPEG_p = (CvCreateFileCapture_Plugin)cvCreateFileCapture_FFMPEG_2;
icvReleaseCapture_FFMPEG_p = (CvReleaseCapture_Plugin)cvReleaseCapture_FFMPEG_2;
icvGrabFrame_FFMPEG_p = (CvGrabFrame_Plugin)cvGrabFrame_FFMPEG_2;
icvRetrieveFrame_FFMPEG_p = (CvRetrieveFrame_Plugin)cvRetrieveFrame_FFMPEG_2;
icvSetCaptureProperty_FFMPEG_p = (CvSetCaptureProperty_Plugin)cvSetCaptureProperty_FFMPEG_2;
icvGetCaptureProperty_FFMPEG_p = (CvGetCaptureProperty_Plugin)cvGetCaptureProperty_FFMPEG_2;
icvCreateFileCapture_FFMPEG_p = (CvCreateFileCapture_Plugin)cvCreateFileCapture_FFMPEG;
icvReleaseCapture_FFMPEG_p = (CvReleaseCapture_Plugin)cvReleaseCapture_FFMPEG;
icvGrabFrame_FFMPEG_p = (CvGrabFrame_Plugin)cvGrabFrame_FFMPEG;
icvRetrieveFrame_FFMPEG_p = (CvRetrieveFrame_Plugin)cvRetrieveFrame_FFMPEG;
icvSetCaptureProperty_FFMPEG_p = (CvSetCaptureProperty_Plugin)cvSetCaptureProperty_FFMPEG;
icvGetCaptureProperty_FFMPEG_p = (CvGetCaptureProperty_Plugin)cvGetCaptureProperty_FFMPEG;
icvCreateVideoWriter_FFMPEG_p = (CvCreateVideoWriter_Plugin)cvCreateVideoWriter_FFMPEG;
icvReleaseVideoWriter_FFMPEG_p = (CvReleaseVideoWriter_Plugin)cvReleaseVideoWriter_FFMPEG;
icvWriteFrame_FFMPEG_p = (CvWriteFrame_Plugin)cvWriteFrame_FFMPEG;
......@@ -152,7 +152,7 @@ public:
int step=0, width=0, height=0, cn=0;
if(!ffmpegCapture ||
!icvRetrieveFrame_FFMPEG_p(ffmpegCapture, &data, &step, &width, &height, &cn))
!icvRetrieveFrame_FFMPEG_p(ffmpegCapture,&data,&step,&width,&height,&cn))
return 0;
cvInitImageHeader(&frame, cvSize(width, height), 8, cn);
cvSetData(&frame, data, step);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment