Commit d9e4ad3f authored by Alexander Reshetnikov's avatar Alexander Reshetnikov

Code style refactoring for ffmpeg wrappers

parent 3514042b
...@@ -245,7 +245,7 @@ void CvCapture_FFMPEG::init() ...@@ -245,7 +245,7 @@ void CvCapture_FFMPEG::init()
void CvCapture_FFMPEG::close() void CvCapture_FFMPEG::close()
{ {
if( picture ) if( picture )
av_free(picture); av_free(picture);
if( video_st ) if( video_st )
{ {
...@@ -316,13 +316,13 @@ bool CvCapture_FFMPEG::reopen() ...@@ -316,13 +316,13 @@ bool CvCapture_FFMPEG::reopen()
} }
#ifndef AVSEEK_FLAG_FRAME #ifndef AVSEEK_FLAG_FRAME
#define AVSEEK_FLAG_FRAME 0 #define AVSEEK_FLAG_FRAME 0
#endif #endif
#ifndef AVSEEK_FLAG_ANY #ifndef AVSEEK_FLAG_ANY
#define AVSEEK_FLAG_ANY 1 #define AVSEEK_FLAG_ANY 1
#endif #endif
#ifndef SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER #ifndef SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER
#define SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER 25 #define SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER 25
#endif #endif
bool CvCapture_FFMPEG::open( const char* _filename ) bool CvCapture_FFMPEG::open( const char* _filename )
...@@ -358,24 +358,24 @@ bool CvCapture_FFMPEG::open( const char* _filename ) ...@@ -358,24 +358,24 @@ bool CvCapture_FFMPEG::open( const char* _filename )
avcodec_thread_init(enc, get_number_of_cpus()); avcodec_thread_init(enc, get_number_of_cpus());
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif #endif
if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) { if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
AVCodec *codec = avcodec_find_decoder(enc->codec_id); AVCodec *codec = avcodec_find_decoder(enc->codec_id);
if (!codec || if (!codec ||
avcodec_open(enc, codec) < 0) avcodec_open(enc, codec) < 0)
goto exit_func; goto exit_func;
video_stream = i; video_stream = i;
video_st = ic->streams[i]; video_st = ic->streams[i];
picture = avcodec_alloc_frame(); picture = avcodec_alloc_frame();
rgb_picture.data[0] = (uint8_t*)malloc( rgb_picture.data[0] = (uint8_t*)malloc(
avpicture_get_size( PIX_FMT_BGR24, avpicture_get_size( PIX_FMT_BGR24,
enc->width, enc->height )); enc->width, enc->height ));
avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
PIX_FMT_BGR24, enc->width, enc->height ); PIX_FMT_BGR24, enc->width, enc->height );
frame.width = enc->width; frame.width = enc->width;
frame.height = enc->height; frame.height = enc->height;
...@@ -406,7 +406,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) ...@@ -406,7 +406,7 @@ bool CvCapture_FFMPEG::open( const char* _filename )
int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD; int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD;
av_seek_frame(ic, video_stream, ts, flags); av_seek_frame(ic, video_stream, ts, flags);
} }
exit_func: exit_func:
if( !valid ) if( !valid )
close(); close();
...@@ -445,22 +445,22 @@ bool CvCapture_FFMPEG::grabFrame() ...@@ -445,22 +445,22 @@ bool CvCapture_FFMPEG::grabFrame()
break; break;
if( packet.stream_index != video_stream ) { if( packet.stream_index != video_stream ) {
av_free_packet (&packet); av_free_packet (&packet);
continue; continue;
} }
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet); avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);
#else
#if LIBAVFORMAT_BUILD > 4628
avcodec_decode_video(video_st->codec,
picture, &got_picture,
packet.data, packet.size);
#else #else
#if LIBAVFORMAT_BUILD > 4628 avcodec_decode_video(&video_st->codec,
avcodec_decode_video(video_st->codec, picture, &got_picture,
picture, &got_picture, packet.data, packet.size);
packet.data, packet.size); #endif
#else
avcodec_decode_video(&video_st->codec,
picture, &got_picture,
packet.data, packet.size);
#endif
#endif #endif
if (got_picture) { if (got_picture) {
...@@ -496,18 +496,18 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* ...@@ -496,18 +496,18 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int*
#endif #endif
#else #else
img_convert_ctx = sws_getContext(video_st->codec->width, img_convert_ctx = sws_getContext(video_st->codec->width,
video_st->codec->height, video_st->codec->height,
video_st->codec->pix_fmt, video_st->codec->pix_fmt,
video_st->codec->width, video_st->codec->width,
video_st->codec->height, video_st->codec->height,
PIX_FMT_BGR24, PIX_FMT_BGR24,
SWS_BICUBIC, SWS_BICUBIC,
NULL, NULL, NULL); NULL, NULL, NULL);
sws_scale(img_convert_ctx, picture->data, sws_scale(img_convert_ctx, picture->data,
picture->linesize, 0, picture->linesize, 0,
video_st->codec->height, video_st->codec->height,
rgb_picture.data, rgb_picture.linesize); rgb_picture.data, rgb_picture.linesize);
sws_freeContext(img_convert_ctx); sws_freeContext(img_convert_ctx);
#endif #endif
*data = frame.data; *data = frame.data;
...@@ -556,41 +556,41 @@ double CvCapture_FFMPEG::getProperty( int property_id ) ...@@ -556,41 +556,41 @@ double CvCapture_FFMPEG::getProperty( int property_id )
break; break;
case CV_FFMPEG_CAP_PROP_FRAME_COUNT: case CV_FFMPEG_CAP_PROP_FRAME_COUNT:
{ {
int64_t nbf = ic->streams[video_stream]->nb_frames; int64_t nbf = ic->streams[video_stream]->nb_frames;
double eps = 0.000025; double eps = 0.000025;
if (nbf == 0) if (nbf == 0)
{
double fps = static_cast<double>(ic->streams[video_stream]->r_frame_rate.num) / static_cast<double>(ic->streams[video_stream]->r_frame_rate.den);
if (fps < eps)
{ {
fps = 1.0 / (static_cast<double>(ic->streams[video_stream]->codec->time_base.num) / static_cast<double>(ic->streams[video_stream]->codec->time_base.den)); double fps = static_cast<double>(ic->streams[video_stream]->r_frame_rate.num) / static_cast<double>(ic->streams[video_stream]->r_frame_rate.den);
if (fps < eps)
{
fps = 1.0 / (static_cast<double>(ic->streams[video_stream]->codec->time_base.num) / static_cast<double>(ic->streams[video_stream]->codec->time_base.den));
}
nbf = static_cast<int64_t>(round(ic->duration * fps) / AV_TIME_BASE);
} }
nbf = static_cast<int64_t>(round(ic->duration * fps) / AV_TIME_BASE); return nbf;
}
return nbf;
} }
break; break;
case CV_FFMPEG_CAP_PROP_FRAME_WIDTH: case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
return (double)frame.width; return (double)frame.width;
break; break;
case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT: case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
return (double)frame.height; return (double)frame.height;
break; break;
case CV_FFMPEG_CAP_PROP_FPS: case CV_FFMPEG_CAP_PROP_FPS:
#if LIBAVCODEC_BUILD > 4753 #if LIBAVCODEC_BUILD > 4753
return av_q2d (video_st->r_frame_rate); return av_q2d (video_st->r_frame_rate);
#else #else
return (double)video_st->codec.frame_rate return (double)video_st->codec.frame_rate
/ (double)video_st->codec.frame_rate_base; / (double)video_st->codec.frame_rate_base;
#endif #endif
break; break;
case CV_FFMPEG_CAP_PROP_FOURCC: case CV_FFMPEG_CAP_PROP_FOURCC:
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
return (double)video_st->codec->codec_tag; return (double)video_st->codec->codec_tag;
#else #else
return (double)video_st->codec.codec_tag; return (double)video_st->codec.codec_tag;
#endif #endif
break; break;
} }
return 0; return 0;
...@@ -617,24 +617,24 @@ bool CvCapture_FFMPEG::seekKeyAndRunOverFrames(int framenumber) ...@@ -617,24 +617,24 @@ bool CvCapture_FFMPEG::seekKeyAndRunOverFrames(int framenumber)
{ {
int ret; int ret;
if (framenumber > video_st->cur_dts-1) { if (framenumber > video_st->cur_dts-1) {
if (framenumber-(video_st->cur_dts-1) > SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER) { if (framenumber-(video_st->cur_dts-1) > SHORTER_DISTANCE_FOR_SEEK_TO_MAKE_IT_FASTER) {
ret = av_seek_frame(ic, video_stream, framenumber, 1); ret = av_seek_frame(ic, video_stream, framenumber, 1);
assert(ret >= 0); assert(ret >= 0);
if( ret < 0 ) if( ret < 0 )
return false; return false;
} }
grabFrame(); grabFrame();
while ((video_st->cur_dts-1) < framenumber) while ((video_st->cur_dts-1) < framenumber)
if ( !grabFrame() ) return false; if ( !grabFrame() ) return false;
} }
else if ( framenumber < (video_st->cur_dts-1) ) { else if ( framenumber < (video_st->cur_dts-1) ) {
ret=av_seek_frame(ic, video_stream, framenumber, 1); ret=av_seek_frame(ic, video_stream, framenumber, 1);
assert( ret >= 0 ); assert( ret >= 0 );
if( ret < 0 ) if( ret < 0 )
return false; return false;
grabFrame(); grabFrame();
while ((video_st->cur_dts-1) < framenumber ) while ((video_st->cur_dts-1) < framenumber )
if ( !grabFrame() ) return false; if ( !grabFrame() ) return false;
} }
return true; return true;
} }
...@@ -678,7 +678,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value ) ...@@ -678,7 +678,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
if (!slowSeek((int)timestamp)) if (!slowSeek((int)timestamp))
{ {
fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n", fprintf(stderr, "HIGHGUI ERROR: AVI: could not (slow) seek to position %0.3f\n",
(double)timestamp / AV_TIME_BASE); (double)timestamp / AV_TIME_BASE);
return false; return false;
} }
} }
...@@ -686,7 +686,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value ) ...@@ -686,7 +686,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
{ {
int flags = AVSEEK_FLAG_ANY; int flags = AVSEEK_FLAG_ANY;
if (timestamp < ic->streams[video_stream]->cur_dts) if (timestamp < ic->streams[video_stream]->cur_dts)
flags |= AVSEEK_FLAG_BACKWARD; flags |= AVSEEK_FLAG_BACKWARD;
int ret = av_seek_frame(ic, video_stream, timestamp, flags); int ret = av_seek_frame(ic, video_stream, timestamp, flags);
if (ret < 0) if (ret < 0)
{ {
...@@ -710,7 +710,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value ) ...@@ -710,7 +710,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
struct CvVideoWriter_FFMPEG struct CvVideoWriter_FFMPEG
{ {
bool open( const char* filename, int fourcc, bool open( const char* filename, int fourcc,
double fps, int width, int height, bool isColor ); double fps, int width, int height, bool isColor );
void close(); void close();
bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin ); bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin );
...@@ -736,34 +736,34 @@ static const char * icvFFMPEGErrStr(int err) ...@@ -736,34 +736,34 @@ static const char * icvFFMPEGErrStr(int err)
{ {
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
switch(err) { switch(err) {
case AVERROR_BSF_NOT_FOUND: case AVERROR_BSF_NOT_FOUND:
return "Bitstream filter not found"; return "Bitstream filter not found";
case AVERROR_DECODER_NOT_FOUND: case AVERROR_DECODER_NOT_FOUND:
return "Decoder not found"; return "Decoder not found";
case AVERROR_DEMUXER_NOT_FOUND: case AVERROR_DEMUXER_NOT_FOUND:
return "Demuxer not found"; return "Demuxer not found";
case AVERROR_ENCODER_NOT_FOUND: case AVERROR_ENCODER_NOT_FOUND:
return "Encoder not found"; return "Encoder not found";
case AVERROR_EOF: case AVERROR_EOF:
return "End of file"; return "End of file";
case AVERROR_EXIT: case AVERROR_EXIT:
return "Immediate exit was requested; the called function should not be restarted"; return "Immediate exit was requested; the called function should not be restarted";
case AVERROR_FILTER_NOT_FOUND: case AVERROR_FILTER_NOT_FOUND:
return "Filter not found"; return "Filter not found";
case AVERROR_INVALIDDATA: case AVERROR_INVALIDDATA:
return "Invalid data found when processing input"; return "Invalid data found when processing input";
case AVERROR_MUXER_NOT_FOUND: case AVERROR_MUXER_NOT_FOUND:
return "Muxer not found"; return "Muxer not found";
case AVERROR_OPTION_NOT_FOUND: case AVERROR_OPTION_NOT_FOUND:
return "Option not found"; return "Option not found";
case AVERROR_PATCHWELCOME: case AVERROR_PATCHWELCOME:
return "Not yet implemented in FFmpeg, patches welcome"; return "Not yet implemented in FFmpeg, patches welcome";
case AVERROR_PROTOCOL_NOT_FOUND: case AVERROR_PROTOCOL_NOT_FOUND:
return "Protocol not found"; return "Protocol not found";
case AVERROR_STREAM_NOT_FOUND: case AVERROR_STREAM_NOT_FOUND:
return "Stream not found"; return "Stream not found";
default: default:
break; break;
} }
#else #else
switch(err) { switch(err) {
...@@ -830,7 +830,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo ...@@ -830,7 +830,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo
return NULL; return NULL;
} }
avpicture_fill((AVPicture *)picture, picture_buf, avpicture_fill((AVPicture *)picture, picture_buf,
(PixelFormat) pix_fmt, width, height); (PixelFormat) pix_fmt, width, height);
} }
else { else {
} }
...@@ -887,11 +887,11 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, ...@@ -887,11 +887,11 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
of which frame timestamps are represented. for fixed-fps content, of which frame timestamps are represented. for fixed-fps content,
timebase should be 1/framerate and timestamp increments should be timebase should be 1/framerate and timestamp increments should be
identically 1. */ identically 1. */
frame_rate = static_cast<int>(fps+0.5); frame_rate = static_cast<int>(fps+0.5);
frame_rate_base = 1; frame_rate_base = 1;
while (fabs(static_cast<double>(frame_rate)/frame_rate_base) - fps > 0.001){ while (fabs(static_cast<double>(frame_rate)/frame_rate_base) - fps > 0.001){
frame_rate_base *= 10; frame_rate_base *= 10;
frame_rate = static_cast<int>(fps*frame_rate_base + 0.5); frame_rate = static_cast<int>(fps*frame_rate_base + 0.5);
} }
#if LIBAVFORMAT_BUILD > 4752 #if LIBAVFORMAT_BUILD > 4752
c->time_base.den = frame_rate; c->time_base.den = frame_rate;
...@@ -959,9 +959,9 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_ ...@@ -959,9 +959,9 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
AVPacket pkt; AVPacket pkt;
av_init_packet(&pkt); av_init_packet(&pkt);
#ifndef PKT_FLAG_KEY #ifndef PKT_FLAG_KEY
#define PKT_FLAG_KEY AV_PKT_FLAG_KEY #define PKT_FLAG_KEY AV_PKT_FLAG_KEY
#endif #endif
pkt.flags |= PKT_FLAG_KEY; pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= video_st->index; pkt.stream_index= video_st->index;
...@@ -979,7 +979,7 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_ ...@@ -979,7 +979,7 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
#if LIBAVFORMAT_BUILD > 4752 #if LIBAVFORMAT_BUILD > 4752
if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE) if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base); pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
#else #else
pkt.pts = c->coded_frame->pts; pkt.pts = c->coded_frame->pts;
#endif #endif
...@@ -1067,7 +1067,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1067,7 +1067,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
} }
// check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment) // check if buffer sizes match, i.e. image has expected format (size, channels, bitdepth, alignment)
/*#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(37<<8)+0) /*#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(37<<8)+0)
assert (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height )); assert (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height ));
#else #else
assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height )); assert (image->imageSize == avpicture_get_size( input_pix_fmt, image->width, image->height ));
...@@ -1077,38 +1077,38 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1077,38 +1077,38 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
assert( input_picture ); assert( input_picture );
// let input_picture point to the raw data buffer of 'image' // let input_picture point to the raw data buffer of 'image'
avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, avpicture_fill((AVPicture *)input_picture, (uint8_t *) data,
(PixelFormat)input_pix_fmt, width, height); (PixelFormat)input_pix_fmt, width, height);
#if !defined(HAVE_FFMPEG_SWSCALE) #if !defined(HAVE_FFMPEG_SWSCALE)
// convert to the color format needed by the codec // convert to the color format needed by the codec
if( img_convert((AVPicture *)picture, c->pix_fmt, if( img_convert((AVPicture *)picture, c->pix_fmt,
(AVPicture *)input_picture, (PixelFormat)input_pix_fmt, (AVPicture *)input_picture, (PixelFormat)input_pix_fmt,
width, height) < 0){ width, height) < 0){
return false; return false;
} }
#else #else
img_convert_ctx = sws_getContext(width, img_convert_ctx = sws_getContext(width,
height, height,
(PixelFormat)input_pix_fmt, (PixelFormat)input_pix_fmt,
c->width, c->width,
c->height, c->height,
c->pix_fmt, c->pix_fmt,
SWS_BICUBIC, SWS_BICUBIC,
NULL, NULL, NULL); NULL, NULL, NULL);
if ( sws_scale(img_convert_ctx, input_picture->data, if ( sws_scale(img_convert_ctx, input_picture->data,
input_picture->linesize, 0, input_picture->linesize, 0,
height, height,
picture->data, picture->linesize) < 0 ) picture->data, picture->linesize) < 0 )
{ {
return false; return false;
} }
sws_freeContext(img_convert_ctx); sws_freeContext(img_convert_ctx);
#endif #endif
} }
else{ else{
avpicture_fill((AVPicture *)picture, (uint8_t *) data, avpicture_fill((AVPicture *)picture, (uint8_t *) data,
(PixelFormat)input_pix_fmt, width, height); (PixelFormat)input_pix_fmt, width, height);
} }
ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0; ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
...@@ -1137,306 +1137,306 @@ void CvVideoWriter_FFMPEG::close() ...@@ -1137,306 +1137,306 @@ void CvVideoWriter_FFMPEG::close()
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
if( video_st->codec->pix_fmt != input_pix_fmt){ if( video_st->codec->pix_fmt != input_pix_fmt){
#else #else
if( video_st->codec.pix_fmt != input_pix_fmt){ if( video_st->codec.pix_fmt != input_pix_fmt){
#endif #endif
if(picture->data[0]) if(picture->data[0])
free(picture->data[0]); free(picture->data[0]);
picture->data[0] = 0; picture->data[0] = 0;
} }
av_free(picture); av_free(picture);
if (input_picture) { if (input_picture) {
av_free(input_picture); av_free(input_picture);
} }
/* close codec */ /* close codec */
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
avcodec_close(video_st->codec); avcodec_close(video_st->codec);
#else #else
avcodec_close(&(video_st->codec)); avcodec_close(&(video_st->codec));
#endif #endif
av_free(outbuf); av_free(outbuf);
/* free the streams */ /* free the streams */
for(i = 0; i < oc->nb_streams; i++) { for(i = 0; i < oc->nb_streams; i++) {
av_freep(&oc->streams[i]->codec); av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]); av_freep(&oc->streams[i]);
} }
if (!(fmt->flags & AVFMT_NOFILE)) { if (!(fmt->flags & AVFMT_NOFILE)) {
/* close the output file */ /* close the output file */
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0) #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
url_fclose(oc->pb); url_fclose(oc->pb);
#else #else
url_fclose(&oc->pb); url_fclose(&oc->pb);
#endif #endif
} }
/* free the stream */ /* free the stream */
av_free(oc); av_free(oc);
if( temp_image.data ) if( temp_image.data )
{ {
free(temp_image.data); free(temp_image.data);
temp_image.data = 0; temp_image.data = 0;
} }
init(); init();
} }
/// Create a video writer object that uses FFMPEG /// Create a video writer object that uses FFMPEG
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
double fps, int width, int height, bool is_color ) double fps, int width, int height, bool is_color )
{ {
CodecID codec_id = CODEC_ID_NONE; CodecID codec_id = CODEC_ID_NONE;
int err, codec_pix_fmt, bitrate_scale = 64; int err, codec_pix_fmt, bitrate_scale = 64;
close(); close();
// check arguments // check arguments
assert(filename); assert(filename);
assert(fps > 0); assert(fps > 0);
assert(width > 0 && height > 0); assert(width > 0 && height > 0);
// tell FFMPEG to register codecs // tell FFMPEG to register codecs
av_register_all(); av_register_all();
/* auto detect the output format from the name and fourcc code. */ /* auto detect the output format from the name and fourcc code. */
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
fmt = av_guess_format(NULL, filename, NULL); fmt = av_guess_format(NULL, filename, NULL);
#else #else
fmt = guess_format(NULL, filename, NULL); fmt = guess_format(NULL, filename, NULL);
#endif #endif
if (!fmt)
return false;
/* determine optimal pixel format */ if (!fmt)
if (is_color) { return false;
input_pix_fmt = PIX_FMT_BGR24;
} /* determine optimal pixel format */
else { if (is_color) {
input_pix_fmt = PIX_FMT_GRAY8; input_pix_fmt = PIX_FMT_BGR24;
} }
else {
input_pix_fmt = PIX_FMT_GRAY8;
}
/* Lookup codec_id for given fourcc */ /* Lookup codec_id for given fourcc */
#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ) if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE )
return false; return false;
#else #else
const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL}; const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL};
if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ) if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE )
return false; return false;
#endif #endif
// alloc memory for context // alloc memory for context
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
oc = avformat_alloc_context(); oc = avformat_alloc_context();
#else #else
oc = av_alloc_format_context(); oc = av_alloc_format_context();
#endif #endif
assert (oc); assert (oc);
/* set file name */ /* set file name */
oc->oformat = fmt; oc->oformat = fmt;
snprintf(oc->filename, sizeof(oc->filename), "%s", filename); snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
/* set some options */ /* set some options */
oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */ oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */
// set a few optimal pixel formats for lossless codecs of interest.. // set a few optimal pixel formats for lossless codecs of interest..
switch (codec_id) { switch (codec_id) {
#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
case CODEC_ID_JPEGLS: case CODEC_ID_JPEGLS:
// BGR24 or GRAY8 depending on is_color... // BGR24 or GRAY8 depending on is_color...
codec_pix_fmt = input_pix_fmt; codec_pix_fmt = input_pix_fmt;
break; break;
#endif #endif
case CODEC_ID_HUFFYUV: case CODEC_ID_HUFFYUV:
codec_pix_fmt = PIX_FMT_YUV422P; codec_pix_fmt = PIX_FMT_YUV422P;
break; break;
case CODEC_ID_MJPEG: case CODEC_ID_MJPEG:
case CODEC_ID_LJPEG: case CODEC_ID_LJPEG:
codec_pix_fmt = PIX_FMT_YUVJ420P; codec_pix_fmt = PIX_FMT_YUVJ420P;
bitrate_scale = 128; bitrate_scale = 128;
break; break;
case CODEC_ID_RAWVIDEO: case CODEC_ID_RAWVIDEO:
codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 || codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 ||
input_pix_fmt == PIX_FMT_GRAY16LE || input_pix_fmt == PIX_FMT_GRAY16LE ||
input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P; input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P;
break; break;
default: default:
// good for lossy formats, MPEG, etc. // good for lossy formats, MPEG, etc.
codec_pix_fmt = PIX_FMT_YUV420P; codec_pix_fmt = PIX_FMT_YUV420P;
break; break;
} }
// TODO -- safe to ignore output audio stream? // TODO -- safe to ignore output audio stream?
video_st = icv_add_video_stream_FFMPEG(oc, codec_id, video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
width, height, width*height*bitrate_scale, width, height, width*height*bitrate_scale,
fps, codec_pix_fmt); fps, codec_pix_fmt);
/* set the output parameters (must be done even if no /* set the output parameters (must be done even if no
parameters). */ parameters). */
if (av_set_parameters(oc, NULL) < 0) { if (av_set_parameters(oc, NULL) < 0) {
return false; return false;
} }
dump_format(oc, 0, filename, 1); dump_format(oc, 0, filename, 1);
/* now that all the parameters are set, we can open the audio and /* now that all the parameters are set, we can open the audio and
video codecs and allocate the necessary encode buffers */ video codecs and allocate the necessary encode buffers */
if (!video_st){ if (!video_st){
return false; return false;
} }
AVCodec *codec; AVCodec *codec;
AVCodecContext *c; AVCodecContext *c;
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
c = (video_st->codec); c = (video_st->codec);
#else #else
c = &(video_st->codec); c = &(video_st->codec);
#endif #endif
c->codec_tag = fourcc; c->codec_tag = fourcc;
/* find the video encoder */ /* find the video encoder */
codec = avcodec_find_encoder(c->codec_id); codec = avcodec_find_encoder(c->codec_id);
if (!codec) { if (!codec) {
return false; return false;
} }
c->bit_rate_tolerance = c->bit_rate; c->bit_rate_tolerance = c->bit_rate;
/* open the codec */ /* open the codec */
if ( (err=avcodec_open(c, codec)) < 0) { if ( (err=avcodec_open(c, codec)) < 0) {
char errtext[256]; char errtext[256];
sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err)); sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err));
return false; return false;
} }
outbuf = NULL; outbuf = NULL;
if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
/* allocate output buffer */ /* allocate output buffer */
/* assume we will never get codec output with more than 4 bytes per pixel... */ /* assume we will never get codec output with more than 4 bytes per pixel... */
outbuf_size = width*height*4; outbuf_size = width*height*4;
outbuf = (uint8_t *) av_malloc(outbuf_size); outbuf = (uint8_t *) av_malloc(outbuf_size);
} }
bool need_color_convert; bool need_color_convert;
need_color_convert = (c->pix_fmt != input_pix_fmt); need_color_convert = (c->pix_fmt != input_pix_fmt);
/* allocate the encoded raw picture */ /* allocate the encoded raw picture */
picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
if (!picture) { if (!picture) {
return false; return false;
} }
/* if the output format is not our input format, then a temporary /* if the output format is not our input format, then a temporary
picture of the input format is needed too. It is then converted picture of the input format is needed too. It is then converted
to the required output format */ to the required output format */
input_picture = NULL; input_picture = NULL;
if ( need_color_convert ) { if ( need_color_convert ) {
input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false); input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
if (!input_picture) { if (!input_picture) {
return false; return false;
}
} }
}
/* open the output file, if needed */ /* open the output file, if needed */
if (!(fmt->flags & AVFMT_NOFILE)) { if (!(fmt->flags & AVFMT_NOFILE)) {
if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) { if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
return false; return false;
}
} }
}
/* write the stream header, if any */ /* write the stream header, if any */
av_write_header( oc ); av_write_header( oc );
return true; return true;
} }
CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename ) CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
{ {
CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture)); CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
capture->init(); capture->init();
if( capture->open( filename )) if( capture->open( filename ))
return capture; return capture;
capture->close(); capture->close();
free(capture); free(capture);
return 0; return 0;
} }
void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture) void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
{
if( capture && *capture )
{ {
(*capture)->close(); if( capture && *capture )
free(*capture); {
*capture = 0; (*capture)->close();
free(*capture);
*capture = 0;
}
} }
}
int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value) int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value)
{ {
return capture->setProperty(prop_id, value); return capture->setProperty(prop_id, value);
} }
double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id) double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id)
{ {
return capture->getProperty(prop_id); return capture->getProperty(prop_id);
} }
int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture) int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)
{ {
return capture->grabFrame(); return capture->grabFrame();
} }
int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* 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); return capture->retrieveFrame(0, data, step, width, height, cn);
} }
CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps, CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
int width, int height, int isColor ) int width, int height, int isColor )
{ {
CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer)); CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer));
writer->init(); writer->init();
if( writer->open( filename, fourcc, fps, width, height, isColor != 0 )) if( writer->open( filename, fourcc, fps, width, height, isColor != 0 ))
return writer; return writer;
writer->close(); writer->close();
free(writer); free(writer);
return 0; return 0;
} }
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer ) void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
{
if( writer && *writer )
{ {
(*writer)->close(); if( writer && *writer )
free(*writer); {
*writer = 0; (*writer)->close();
free(*writer);
*writer = 0;
}
} }
}
int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer, int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
const unsigned char* data, int step, const unsigned char* data, int step,
int width, int height, int cn, int origin) int width, int height, int cn, int origin)
{ {
return writer->writeFrame(data, step, width, height, cn, origin); return writer->writeFrame(data, step, width, height, cn, origin);
} }
...@@ -255,9 +255,9 @@ void CvCapture_FFMPEG::init() ...@@ -255,9 +255,9 @@ void CvCapture_FFMPEG::init()
memset( &frame, 0, sizeof(frame) ); memset( &frame, 0, sizeof(frame) );
filename = 0; filename = 0;
packet.data = NULL; packet.data = NULL;
#if defined(HAVE_FFMPEG_SWSCALE) #if defined(HAVE_FFMPEG_SWSCALE)
img_convert_ctx = 0; img_convert_ctx = 0;
#endif #endif
avcodec = 0; avcodec = 0;
frame_number = 0; frame_number = 0;
...@@ -268,29 +268,29 @@ void CvCapture_FFMPEG::init() ...@@ -268,29 +268,29 @@ void CvCapture_FFMPEG::init()
void CvCapture_FFMPEG::close() void CvCapture_FFMPEG::close()
{ {
if( picture ) if( picture )
av_free(picture); av_free(picture);
if( video_st ) if( video_st )
{ {
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
avcodec_close( video_st->codec ); avcodec_close( video_st->codec );
#else #else
avcodec_close( &(video_st->codec) ); avcodec_close( &(video_st->codec) );
#endif #endif
video_st = NULL; video_st = NULL;
} }
if( ic ) if( ic )
{ {
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2) #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
av_close_input_file(ic); av_close_input_file(ic);
#else #else
avformat_close_input(&ic); avformat_close_input(&ic);
#endif #endif
ic = NULL; ic = NULL;
} }
if( rgb_picture.data[0] ) if( rgb_picture.data[0] )
...@@ -363,10 +363,10 @@ bool CvCapture_FFMPEG::reopen() ...@@ -363,10 +363,10 @@ bool CvCapture_FFMPEG::reopen()
} }
#ifndef AVSEEK_FLAG_FRAME #ifndef AVSEEK_FLAG_FRAME
#define AVSEEK_FLAG_FRAME 0 #define AVSEEK_FLAG_FRAME 0
#endif #endif
#ifndef AVSEEK_FLAG_ANY #ifndef AVSEEK_FLAG_ANY
#define AVSEEK_FLAG_ANY 1 #define AVSEEK_FLAG_ANY 1
#endif #endif
bool CvCapture_FFMPEG::open( const char* _filename ) bool CvCapture_FFMPEG::open( const char* _filename )
...@@ -376,9 +376,9 @@ bool CvCapture_FFMPEG::open( const char* _filename ) ...@@ -376,9 +376,9 @@ bool CvCapture_FFMPEG::open( const char* _filename )
close(); close();
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
avformat_network_init(); avformat_network_init();
#endif #endif
/* register all codecs, demux and protocols */ /* register all codecs, demux and protocols */
av_register_all(); av_register_all();
...@@ -391,56 +391,56 @@ bool CvCapture_FFMPEG::open( const char* _filename ) ...@@ -391,56 +391,56 @@ bool CvCapture_FFMPEG::open( const char* _filename )
goto exit_func; goto exit_func;
} }
err = err =
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2) #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
avformat_find_stream_info(ic); avformat_find_stream_info(ic);
#else #else
avformat_find_stream_info(ic, NULL); avformat_find_stream_info(ic, NULL);
#endif #endif
#else #else
av_find_stream_info(ic); av_find_stream_info(ic);
#endif #endif
if (err < 0) { if (err < 0) {
CV_WARN("Could not find codec parameters"); CV_WARN("Could not find codec parameters");
goto exit_func; goto exit_func;
} }
for(i = 0; i < ic->nb_streams; i++) for(i = 0; i < ic->nb_streams; i++)
{ {
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
AVCodecContext *enc = ic->streams[i]->codec; AVCodecContext *enc = ic->streams[i]->codec;
#else #else
AVCodecContext *enc = &ic->streams[i]->codec; AVCodecContext *enc = &ic->streams[i]->codec;
#endif #endif
#ifdef FF_API_THREAD_INIT #ifdef FF_API_THREAD_INIT
avcodec_thread_init(enc, get_number_of_cpus()); avcodec_thread_init(enc, get_number_of_cpus());
#else #else
enc->thread_count = get_number_of_cpus(); enc->thread_count = get_number_of_cpus();
#endif #endif
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif #endif
if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) { if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
AVCodec *codec = avcodec_find_decoder(enc->codec_id); AVCodec *codec = avcodec_find_decoder(enc->codec_id);
if (!codec || if (!codec ||
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0) #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
avcodec_open2(enc, codec, NULL) avcodec_open2(enc, codec, NULL)
#else #else
avcodec_open(enc, codec) avcodec_open(enc, codec)
#endif #endif
< 0) goto exit_func; < 0) goto exit_func;
video_stream = i; video_stream = i;
video_st = ic->streams[i]; video_st = ic->streams[i];
picture = avcodec_alloc_frame(); picture = avcodec_alloc_frame();
rgb_picture.data[0] = (uint8_t*)malloc( rgb_picture.data[0] = (uint8_t*)malloc(
avpicture_get_size( PIX_FMT_BGR24, avpicture_get_size( PIX_FMT_BGR24,
enc->width, enc->height )); enc->width, enc->height ));
avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
PIX_FMT_BGR24, enc->width, enc->height ); PIX_FMT_BGR24, enc->width, enc->height );
frame.width = enc->width; frame.width = enc->width;
frame.height = enc->height; frame.height = enc->height;
...@@ -471,7 +471,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) ...@@ -471,7 +471,7 @@ bool CvCapture_FFMPEG::open( const char* _filename )
int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD; int flags = AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD;
av_seek_frame(ic, video_stream, ts, flags); av_seek_frame(ic, video_stream, ts, flags);
}*/ }*/
exit_func: exit_func:
if( !valid ) if( !valid )
close(); close();
...@@ -513,28 +513,28 @@ bool CvCapture_FFMPEG::grabFrame() ...@@ -513,28 +513,28 @@ bool CvCapture_FFMPEG::grabFrame()
if( packet.stream_index != video_stream ) if( packet.stream_index != video_stream )
{ {
av_free_packet (&packet); av_free_packet (&packet);
count_errs++; count_errs++;
if (count_errs > max_number_of_attempts) break; else if (count_errs > max_number_of_attempts) break; else
continue; continue;
} }
// Decode video frame // Decode video frame
avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet); avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);
// Did we get a video frame? // Did we get a video frame?
if(got_picture) if(got_picture)
{ {
frame_number++; frame_number++;
picture_pts = packet.pts; picture_pts = packet.pts;
valid = true; valid = true;
} }
else else
{ {
count_errs++; count_errs++;
if (count_errs > max_number_of_attempts) if (count_errs > max_number_of_attempts)
break; break;
} }
} }
...@@ -553,42 +553,42 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* ...@@ -553,42 +553,42 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int*
frame.width = video_st->codec->width; frame.width = video_st->codec->width;
frame.height = video_st->codec->height; frame.height = video_st->codec->height;
img_convert_ctx = sws_getContext( img_convert_ctx = sws_getContext(
video_st->codec->width, video_st->codec->height, video_st->codec->width, video_st->codec->height,
video_st->codec->pix_fmt, video_st->codec->pix_fmt,
video_st->codec->width, video_st->codec->height, video_st->codec->width, video_st->codec->height,
PIX_FMT_BGR24, PIX_FMT_BGR24,
SWS_BICUBIC, SWS_BICUBIC,
NULL, NULL, NULL NULL, NULL, NULL
); );
img_convert_ctx = sws_getCachedContext( img_convert_ctx = sws_getCachedContext(
img_convert_ctx, img_convert_ctx,
video_st->codec->width, video_st->codec->height, video_st->codec->width, video_st->codec->height,
video_st->codec->pix_fmt, video_st->codec->pix_fmt,
video_st->codec->width, video_st->codec->height, video_st->codec->width, video_st->codec->height,
PIX_FMT_BGR24, PIX_FMT_BGR24,
SWS_BICUBIC, SWS_BICUBIC,
NULL, NULL, NULL NULL, NULL, NULL
); );
if (img_convert_ctx == NULL) if (img_convert_ctx == NULL)
CV_Error(0, "Cannot initialize the conversion context!"); CV_Error(0, "Cannot initialize the conversion context!");
sws_scale( sws_scale(
img_convert_ctx, img_convert_ctx,
picture->data, picture->data,
picture->linesize, picture->linesize,
0, video_st->codec->height, 0, video_st->codec->height,
rgb_picture.data, rgb_picture.data,
rgb_picture.linesize rgb_picture.linesize
); );
sws_freeContext(img_convert_ctx); sws_freeContext(img_convert_ctx);
frame_number++; frame_number++;
*data = frame.data; *data = frame.data;
*step = frame.step; *step = frame.step;
...@@ -630,25 +630,25 @@ double CvCapture_FFMPEG::getProperty( int property_id ) ...@@ -630,25 +630,25 @@ double CvCapture_FFMPEG::getProperty( int property_id )
break; break;
case CV_FFMPEG_CAP_PROP_FRAME_WIDTH: case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
return (double)frame.width; return (double)frame.width;
break; break;
case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT: case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
return (double)frame.height; return (double)frame.height;
break; break;
case CV_FFMPEG_CAP_PROP_FPS: case CV_FFMPEG_CAP_PROP_FPS:
#if LIBAVCODEC_BUILD > 4753 #if LIBAVCODEC_BUILD > 4753
return av_q2d (video_st->r_frame_rate); return av_q2d (video_st->r_frame_rate);
#else #else
return (double)video_st->codec.frame_rate return (double)video_st->codec.frame_rate
/ (double)video_st->codec.frame_rate_base; / (double)video_st->codec.frame_rate_base;
#endif #endif
break; break;
case CV_FFMPEG_CAP_PROP_FOURCC: case CV_FFMPEG_CAP_PROP_FOURCC:
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
return (double)video_st->codec->codec_tag; return (double)video_st->codec->codec_tag;
#else #else
return (double)video_st->codec.codec_tag; return (double)video_st->codec.codec_tag;
#endif #endif
break; break;
} }
return 0; return 0;
...@@ -812,7 +812,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value ) ...@@ -812,7 +812,7 @@ bool CvCapture_FFMPEG::setProperty( int property_id, double value )
struct CvVideoWriter_FFMPEG struct CvVideoWriter_FFMPEG
{ {
bool open( const char* filename, int fourcc, bool open( const char* filename, int fourcc,
double fps, int width, int height, bool isColor ); double fps, int width, int height, bool isColor );
void close(); void close();
bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin ); bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin );
...@@ -839,34 +839,34 @@ static const char * icvFFMPEGErrStr(int err) ...@@ -839,34 +839,34 @@ static const char * icvFFMPEGErrStr(int err)
{ {
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
switch(err) { switch(err) {
case AVERROR_BSF_NOT_FOUND: case AVERROR_BSF_NOT_FOUND:
return "Bitstream filter not found"; return "Bitstream filter not found";
case AVERROR_DECODER_NOT_FOUND: case AVERROR_DECODER_NOT_FOUND:
return "Decoder not found"; return "Decoder not found";
case AVERROR_DEMUXER_NOT_FOUND: case AVERROR_DEMUXER_NOT_FOUND:
return "Demuxer not found"; return "Demuxer not found";
case AVERROR_ENCODER_NOT_FOUND: case AVERROR_ENCODER_NOT_FOUND:
return "Encoder not found"; return "Encoder not found";
case AVERROR_EOF: case AVERROR_EOF:
return "End of file"; return "End of file";
case AVERROR_EXIT: case AVERROR_EXIT:
return "Immediate exit was requested; the called function should not be restarted"; return "Immediate exit was requested; the called function should not be restarted";
case AVERROR_FILTER_NOT_FOUND: case AVERROR_FILTER_NOT_FOUND:
return "Filter not found"; return "Filter not found";
case AVERROR_INVALIDDATA: case AVERROR_INVALIDDATA:
return "Invalid data found when processing input"; return "Invalid data found when processing input";
case AVERROR_MUXER_NOT_FOUND: case AVERROR_MUXER_NOT_FOUND:
return "Muxer not found"; return "Muxer not found";
case AVERROR_OPTION_NOT_FOUND: case AVERROR_OPTION_NOT_FOUND:
return "Option not found"; return "Option not found";
case AVERROR_PATCHWELCOME: case AVERROR_PATCHWELCOME:
return "Not yet implemented in FFmpeg, patches welcome"; return "Not yet implemented in FFmpeg, patches welcome";
case AVERROR_PROTOCOL_NOT_FOUND: case AVERROR_PROTOCOL_NOT_FOUND:
return "Protocol not found"; return "Protocol not found";
case AVERROR_STREAM_NOT_FOUND: case AVERROR_STREAM_NOT_FOUND:
return "Stream not found"; return "Stream not found";
default: default:
break; break;
} }
#else #else
switch(err) { switch(err) {
...@@ -906,9 +906,9 @@ void CvVideoWriter_FFMPEG::init() ...@@ -906,9 +906,9 @@ void CvVideoWriter_FFMPEG::init()
video_st = 0; video_st = 0;
input_pix_fmt = 0; input_pix_fmt = 0;
memset(&temp_image, 0, sizeof(temp_image)); memset(&temp_image, 0, sizeof(temp_image));
#if defined(HAVE_FFMPEG_SWSCALE) #if defined(HAVE_FFMPEG_SWSCALE)
img_convert_ctx = 0; img_convert_ctx = 0;
#endif #endif
ok = false; ok = false;
} }
...@@ -934,7 +934,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo ...@@ -934,7 +934,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo
return NULL; return NULL;
} }
avpicture_fill((AVPicture *)picture, picture_buf, avpicture_fill((AVPicture *)picture, picture_buf,
(PixelFormat) pix_fmt, width, height); (PixelFormat) pix_fmt, width, height);
} }
else { else {
} }
...@@ -952,28 +952,28 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, ...@@ -952,28 +952,28 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
int frame_rate, frame_rate_base; int frame_rate, frame_rate_base;
AVCodec *codec; AVCodec *codec;
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
st = avformat_new_stream(oc, 0); st = avformat_new_stream(oc, 0);
#else #else
st = av_new_stream(oc, 0); st = av_new_stream(oc, 0);
#endif #endif
if (!st) { if (!st) {
CV_WARN("Could not allocate stream"); CV_WARN("Could not allocate stream");
return NULL; return NULL;
} }
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
c = st->codec; c = st->codec;
#else #else
c = &(st->codec); c = &(st->codec);
#endif #endif
#if LIBAVFORMAT_BUILD > 4621 #if LIBAVFORMAT_BUILD > 4621
c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO); c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
#else #else
c->codec_id = oc->oformat->video_codec; c->codec_id = oc->oformat->video_codec;
#endif #endif
if(codec_id != CODEC_ID_NONE){ if(codec_id != CODEC_ID_NONE){
c->codec_id = codec_id; c->codec_id = codec_id;
...@@ -1001,30 +1001,30 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, ...@@ -1001,30 +1001,30 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
frame_rate_base*=10; frame_rate_base*=10;
frame_rate=(int)(fps*frame_rate_base + 0.5); frame_rate=(int)(fps*frame_rate_base + 0.5);
} }
#if LIBAVFORMAT_BUILD > 4752 #if LIBAVFORMAT_BUILD > 4752
c->time_base.den = frame_rate; c->time_base.den = frame_rate;
c->time_base.num = frame_rate_base; c->time_base.num = frame_rate_base;
/* adjust time base for supported framerates */ /* adjust time base for supported framerates */
if(codec && codec->supported_framerates){ if(codec && codec->supported_framerates){
const AVRational *p= codec->supported_framerates; const AVRational *p= codec->supported_framerates;
AVRational req = {frame_rate, frame_rate_base}; AVRational req = {frame_rate, frame_rate_base};
const AVRational *best=NULL; const AVRational *best=NULL;
AVRational best_error= {INT_MAX, 1}; AVRational best_error= {INT_MAX, 1};
for(; p->den!=0; p++){ for(; p->den!=0; p++){
AVRational error= av_sub_q(req, *p); AVRational error= av_sub_q(req, *p);
if(error.num <0) error.num *= -1; if(error.num <0) error.num *= -1;
if(av_cmp_q(error, best_error) < 0){ if(av_cmp_q(error, best_error) < 0){
best_error= error; best_error= error;
best= p; best= p;
} }
} }
c->time_base.den= best->num; c->time_base.den= best->num;
c->time_base.num= best->den; c->time_base.num= best->den;
} }
#else #else
c->frame_rate = frame_rate; c->frame_rate = frame_rate;
c->frame_rate_base = frame_rate_base; c->frame_rate_base = frame_rate_base;
#endif #endif
c->gop_size = 12; /* emit one intra frame every twelve frames at most */ c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = (PixelFormat) pixel_format; c->pix_fmt = (PixelFormat) pixel_format;
...@@ -1039,24 +1039,24 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, ...@@ -1039,24 +1039,24 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
/* avoid FFMPEG warning 'clipping 1 dct coefficients...' */ /* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
c->mb_decision=2; c->mb_decision=2;
} }
#if LIBAVCODEC_VERSION_INT>0x000409 #if LIBAVCODEC_VERSION_INT>0x000409
// some formats want stream headers to be seperate // some formats want stream headers to be seperate
if(oc->oformat->flags & AVFMT_GLOBALHEADER) if(oc->oformat->flags & AVFMT_GLOBALHEADER)
{ {
c->flags |= CODEC_FLAG_GLOBAL_HEADER; c->flags |= CODEC_FLAG_GLOBAL_HEADER;
} }
#endif #endif
return st; return st;
} }
int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture ) int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture )
{ {
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
AVCodecContext * c = video_st->codec; AVCodecContext * c = video_st->codec;
#else #else
AVCodecContext * c = &(video_st->codec); AVCodecContext * c = &(video_st->codec);
#endif #endif
int out_size; int out_size;
int ret; int ret;
...@@ -1066,9 +1066,9 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_ ...@@ -1066,9 +1066,9 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
AVPacket pkt; AVPacket pkt;
av_init_packet(&pkt); av_init_packet(&pkt);
#ifndef PKT_FLAG_KEY #ifndef PKT_FLAG_KEY
#define PKT_FLAG_KEY AV_PKT_FLAG_KEY #define PKT_FLAG_KEY AV_PKT_FLAG_KEY
#endif #endif
pkt.flags |= PKT_FLAG_KEY; pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= video_st->index; pkt.stream_index= video_st->index;
...@@ -1084,12 +1084,12 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_ ...@@ -1084,12 +1084,12 @@ int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_
AVPacket pkt; AVPacket pkt;
av_init_packet(&pkt); av_init_packet(&pkt);
#if LIBAVFORMAT_BUILD > 4752 #if LIBAVFORMAT_BUILD > 4752
if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE) if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base); pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
#else #else
pkt.pts = c->coded_frame->pts; pkt.pts = c->coded_frame->pts;
#endif #endif
if(c->coded_frame->key_frame) if(c->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY; pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= video_st->index; pkt.stream_index= video_st->index;
...@@ -1113,50 +1113,50 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1113,50 +1113,50 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
bool ret = false; bool ret = false;
// typecast from opaque data type to implemented struct // typecast from opaque data type to implemented struct
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
AVCodecContext *c = video_st->codec; AVCodecContext *c = video_st->codec;
#else #else
AVCodecContext *c = &(video_st->codec); AVCodecContext *c = &(video_st->codec);
#endif #endif
#if LIBAVFORMAT_BUILD < 5231 #if LIBAVFORMAT_BUILD < 5231
// It is not needed in the latest versions of the ffmpeg // It is not needed in the latest versions of the ffmpeg
if( c->codec_id == CODEC_ID_RAWVIDEO && origin != 1 ) if( c->codec_id == CODEC_ID_RAWVIDEO && origin != 1 )
{ {
if( !temp_image.data ) if( !temp_image.data )
{ {
temp_image.step = (width*cn + 3) & -4; temp_image.step = (width*cn + 3) & -4;
temp_image.width = width; temp_image.width = width;
temp_image.height = height; temp_image.height = height;
temp_image.cn = cn; temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height); temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
} }
for( int y = 0; y < height; y++ ) for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn); memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, width*cn);
data = temp_image.data; data = temp_image.data;
step = temp_image.step; step = temp_image.step;
} }
#else #else
if( width*cn != step ) if( width*cn != step )
{ {
if( !temp_image.data ) if( !temp_image.data )
{ {
temp_image.step = width*cn; temp_image.step = width*cn;
temp_image.width = width; temp_image.width = width;
temp_image.height = height; temp_image.height = height;
temp_image.cn = cn; temp_image.cn = cn;
temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height); temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
} }
if (origin == 1) if (origin == 1)
for( int y = 0; y < height; y++ ) for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, temp_image.step); memcpy(temp_image.data + y*temp_image.step, data + (height-1-y)*step, temp_image.step);
else else
for( int y = 0; y < height; y++ ) for( int y = 0; y < height; y++ )
memcpy(temp_image.data + y*temp_image.step, data + y*step, temp_image.step); memcpy(temp_image.data + y*temp_image.step, data + y*step, temp_image.step);
data = temp_image.data; data = temp_image.data;
step = temp_image.step; step = temp_image.step;
} }
#endif #endif
// check parameters // check parameters
if (input_pix_fmt == PIX_FMT_BGR24) { if (input_pix_fmt == PIX_FMT_BGR24) {
...@@ -1177,38 +1177,38 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int ...@@ -1177,38 +1177,38 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int
assert( input_picture ); assert( input_picture );
// let input_picture point to the raw data buffer of 'image' // let input_picture point to the raw data buffer of 'image'
avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, avpicture_fill((AVPicture *)input_picture, (uint8_t *) data,
(PixelFormat)input_pix_fmt, width, height); (PixelFormat)input_pix_fmt, width, height);
#if !defined(HAVE_FFMPEG_SWSCALE) #if !defined(HAVE_FFMPEG_SWSCALE)
// convert to the color format needed by the codec // convert to the color format needed by the codec
if( img_convert((AVPicture *)picture, c->pix_fmt, if( img_convert((AVPicture *)picture, c->pix_fmt,
(AVPicture *)input_picture, (PixelFormat)input_pix_fmt, (AVPicture *)input_picture, (PixelFormat)input_pix_fmt,
width, height) < 0){ width, height) < 0){
return false; return false;
} }
#else #else
img_convert_ctx = sws_getContext(width, img_convert_ctx = sws_getContext(width,
height, height,
(PixelFormat)input_pix_fmt, (PixelFormat)input_pix_fmt,
c->width, c->width,
c->height, c->height,
c->pix_fmt, c->pix_fmt,
SWS_BICUBIC, SWS_BICUBIC,
NULL, NULL, NULL); NULL, NULL, NULL);
if ( sws_scale(img_convert_ctx, input_picture->data, if ( sws_scale(img_convert_ctx, input_picture->data,
input_picture->linesize, 0, input_picture->linesize, 0,
height, height,
picture->data, picture->linesize) < 0 ) picture->data, picture->linesize) < 0 )
{ {
return false; return false;
} }
sws_freeContext(img_convert_ctx); sws_freeContext(img_convert_ctx);
#endif #endif
} }
else{ else{
avpicture_fill((AVPicture *)picture, (uint8_t *) data, avpicture_fill((AVPicture *)picture, (uint8_t *) data,
(PixelFormat)input_pix_fmt, width, height); (PixelFormat)input_pix_fmt, width, height);
} }
ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0; ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
...@@ -1235,337 +1235,337 @@ void CvVideoWriter_FFMPEG::close() ...@@ -1235,337 +1235,337 @@ void CvVideoWriter_FFMPEG::close()
av_write_trailer(oc); av_write_trailer(oc);
// free pictures // free pictures
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
if( video_st->codec->pix_fmt != input_pix_fmt){ if( video_st->codec->pix_fmt != input_pix_fmt){
#else #else
if( video_st->codec.pix_fmt != input_pix_fmt){ if( video_st->codec.pix_fmt != input_pix_fmt){
#endif #endif
if(picture->data[0]) if(picture->data[0])
free(picture->data[0]); free(picture->data[0]);
picture->data[0] = 0; picture->data[0] = 0;
} }
av_free(picture); av_free(picture);
if (input_picture) { if (input_picture) {
av_free(input_picture); av_free(input_picture);
} }
/* close codec */ /* close codec */
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
avcodec_close(video_st->codec); avcodec_close(video_st->codec);
#else #else
avcodec_close(&(video_st->codec)); avcodec_close(&(video_st->codec));
#endif #endif
av_free(outbuf); av_free(outbuf);
/* free the streams */ /* free the streams */
for(i = 0; i < oc->nb_streams; i++) { for(i = 0; i < oc->nb_streams; i++) {
av_freep(&oc->streams[i]->codec); av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]); av_freep(&oc->streams[i]);
} }
if (!(fmt->flags & AVFMT_NOFILE)) { if (!(fmt->flags & AVFMT_NOFILE)) {
/* close the output file */ /* close the output file */
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0) #if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0) #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
url_fclose(oc->pb); url_fclose(oc->pb);
#else #else
url_fclose(&oc->pb); url_fclose(&oc->pb);
#endif #endif
#else #else
avio_close(oc->pb); avio_close(oc->pb);
#endif #endif
} }
/* free the stream */ /* free the stream */
av_free(oc); av_free(oc);
if( temp_image.data ) if( temp_image.data )
{ {
free(temp_image.data); free(temp_image.data);
temp_image.data = 0; temp_image.data = 0;
} }
init(); init();
} }
/// Create a video writer object that uses FFMPEG /// Create a video writer object that uses FFMPEG
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
double fps, int width, int height, bool is_color ) double fps, int width, int height, bool is_color )
{ {
CodecID codec_id = CODEC_ID_NONE; CodecID codec_id = CODEC_ID_NONE;
int err, codec_pix_fmt, bitrate_scale=64; int err, codec_pix_fmt, bitrate_scale=64;
close(); close();
// check arguments // check arguments
assert (filename); assert (filename);
assert (fps > 0); assert (fps > 0);
assert (width > 0 && height > 0); assert (width > 0 && height > 0);
// tell FFMPEG to register codecs // tell FFMPEG to register codecs
av_register_all (); av_register_all ();
/* auto detect the output format from the name and fourcc code. */ /* auto detect the output format from the name and fourcc code. */
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
fmt = av_guess_format(NULL, filename, NULL); fmt = av_guess_format(NULL, filename, NULL);
#else #else
fmt = guess_format(NULL, filename, NULL); fmt = guess_format(NULL, filename, NULL);
#endif #endif
if (!fmt) if (!fmt)
return false; return false;
/* determine optimal pixel format */ /* determine optimal pixel format */
if (is_color) { if (is_color) {
input_pix_fmt = PIX_FMT_BGR24; input_pix_fmt = PIX_FMT_BGR24;
} }
else { else {
input_pix_fmt = PIX_FMT_GRAY8; input_pix_fmt = PIX_FMT_GRAY8;
} }
/* Lookup codec_id for given fourcc */ /* Lookup codec_id for given fourcc */
#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ) if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE )
return false; return false;
#else #else
const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL}; const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL};
if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ) if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE )
return false; return false;
#endif #endif
// alloc memory for context // alloc memory for context
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
oc = avformat_alloc_context(); oc = avformat_alloc_context();
#else #else
oc = av_alloc_format_context(); oc = av_alloc_format_context();
#endif #endif
assert (oc); assert (oc);
/* set file name */ /* set file name */
oc->oformat = fmt; oc->oformat = fmt;
snprintf(oc->filename, sizeof(oc->filename), "%s", filename); snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
/* set some options */ /* set some options */
oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */ oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */
// set a few optimal pixel formats for lossless codecs of interest.. // set a few optimal pixel formats for lossless codecs of interest..
switch (codec_id) { switch (codec_id) {
#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
case CODEC_ID_JPEGLS: case CODEC_ID_JPEGLS:
// BGR24 or GRAY8 depending on is_color... // BGR24 or GRAY8 depending on is_color...
codec_pix_fmt = input_pix_fmt; codec_pix_fmt = input_pix_fmt;
break; break;
#endif #endif
case CODEC_ID_HUFFYUV: case CODEC_ID_HUFFYUV:
codec_pix_fmt = PIX_FMT_YUV422P; codec_pix_fmt = PIX_FMT_YUV422P;
break; break;
case CODEC_ID_MJPEG: case CODEC_ID_MJPEG:
case CODEC_ID_LJPEG: case CODEC_ID_LJPEG:
codec_pix_fmt = PIX_FMT_YUVJ420P; codec_pix_fmt = PIX_FMT_YUVJ420P;
bitrate_scale = 128; bitrate_scale = 128;
break; break;
case CODEC_ID_RAWVIDEO: case CODEC_ID_RAWVIDEO:
codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 || codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 ||
input_pix_fmt == PIX_FMT_GRAY16LE || input_pix_fmt == PIX_FMT_GRAY16LE ||
input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P; input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P;
break; break;
default: default:
// good for lossy formats, MPEG, etc. // good for lossy formats, MPEG, etc.
codec_pix_fmt = PIX_FMT_YUV420P; codec_pix_fmt = PIX_FMT_YUV420P;
break; break;
} }
// TODO -- safe to ignore output audio stream? // TODO -- safe to ignore output audio stream?
video_st = icv_add_video_stream_FFMPEG(oc, codec_id, video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
width, height, width*height*bitrate_scale, width, height, width*height*bitrate_scale,
fps, codec_pix_fmt); fps, codec_pix_fmt);
/* set the output parameters (must be done even if no /* set the output parameters (must be done even if no
parameters). */ parameters). */
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
if (av_set_parameters(oc, NULL) < 0) { if (av_set_parameters(oc, NULL) < 0) {
return false; return false;
} }
#endif #endif
#if 0 #if 0
#if FF_API_DUMP_FORMAT #if FF_API_DUMP_FORMAT
dump_format(oc, 0, filename, 1); dump_format(oc, 0, filename, 1);
#else #else
av_dump_format(oc, 0, filename, 1); av_dump_format(oc, 0, filename, 1);
#endif #endif
#endif #endif
/* now that all the parameters are set, we can open the audio and /* now that all the parameters are set, we can open the audio and
video codecs and allocate the necessary encode buffers */ video codecs and allocate the necessary encode buffers */
if (!video_st){ if (!video_st){
return false; return false;
} }
AVCodec *codec; AVCodec *codec;
AVCodecContext *c; AVCodecContext *c;
#if LIBAVFORMAT_BUILD > 4628 #if LIBAVFORMAT_BUILD > 4628
c = (video_st->codec); c = (video_st->codec);
#else #else
c = &(video_st->codec); c = &(video_st->codec);
#endif #endif
c->codec_tag = fourcc; c->codec_tag = fourcc;
/* find the video encoder */ /* find the video encoder */
codec = avcodec_find_encoder(c->codec_id); codec = avcodec_find_encoder(c->codec_id);
if (!codec) { if (!codec) {
return false; return false;
} }
c->bit_rate_tolerance = c->bit_rate; c->bit_rate_tolerance = c->bit_rate;
/* open the codec */ /* open the codec */
if ((err= if ((err=
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0) #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
avcodec_open2(c, codec, NULL) avcodec_open2(c, codec, NULL)
#else #else
avcodec_open(c, codec) avcodec_open(c, codec)
#endif #endif
) < 0) { ) < 0) {
char errtext[256]; char errtext[256];
sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err)); sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err));
return false; return false;
} }
outbuf = NULL; outbuf = NULL;
if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
/* allocate output buffer */ /* allocate output buffer */
/* assume we will never get codec output with more than 4 bytes per pixel... */ /* assume we will never get codec output with more than 4 bytes per pixel... */
outbuf_size = width*height*4; outbuf_size = width*height*4;
outbuf = (uint8_t *) av_malloc(outbuf_size); outbuf = (uint8_t *) av_malloc(outbuf_size);
} }
bool need_color_convert; bool need_color_convert;
need_color_convert = (c->pix_fmt != input_pix_fmt); need_color_convert = (c->pix_fmt != input_pix_fmt);
/* allocate the encoded raw picture */ /* allocate the encoded raw picture */
picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
if (!picture) { if (!picture) {
return false; return false;
} }
/* if the output format is not our input format, then a temporary /* if the output format is not our input format, then a temporary
picture of the input format is needed too. It is then converted picture of the input format is needed too. It is then converted
to the required output format */ to the required output format */
input_picture = NULL; input_picture = NULL;
if ( need_color_convert ) { if ( need_color_convert ) {
input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false); input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
if (!input_picture) { if (!input_picture) {
return false; return false;
}
} }
}
/* open the output file, if needed */ /* open the output file, if needed */
if (!(fmt->flags & AVFMT_NOFILE)) { if (!(fmt->flags & AVFMT_NOFILE)) {
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0) #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)
#else #else
if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0)
#endif #endif
{
return false;
}
}
/* write the stream header, if any */
err=avformat_write_header(oc, NULL);
if(err < 0)
{ {
close();
remove(filename);
return false; return false;
} }
ok = true;
return true;
} }
/* write the stream header, if any */
err=avformat_write_header(oc, NULL);
if(err < 0)
{
close();
remove(filename);
return false;
}
ok = true;
return true;
}
CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename ) CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
{ {
CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture)); CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
capture->init(); capture->init();
if( capture->open( filename )) if( capture->open( filename ))
return capture; return capture;
capture->close(); capture->close();
free(capture); free(capture);
return 0; return 0;
} }
void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture) void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
{
if( capture && *capture )
{ {
(*capture)->close(); if( capture && *capture )
free(*capture); {
*capture = 0; (*capture)->close();
free(*capture);
*capture = 0;
}
} }
}
int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value) int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value)
{ {
return capture->setProperty(prop_id, value); return capture->setProperty(prop_id, value);
} }
double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id) double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id)
{ {
return capture->getProperty(prop_id); return capture->getProperty(prop_id);
} }
int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture) int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)
{ {
return capture->grabFrame(); return capture->grabFrame();
} }
int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* 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); return capture->retrieveFrame(0, data, step, width, height, cn);
} }
CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps, CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
int width, int height, int isColor ) int width, int height, int isColor )
{ {
CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer)); CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer));
writer->init(); writer->init();
if( writer->open( filename, fourcc, fps, width, height, isColor != 0 )) if( writer->open( filename, fourcc, fps, width, height, isColor != 0 ))
return writer; return writer;
writer->close(); writer->close();
free(writer); free(writer);
return 0; return 0;
} }
void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer ) void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
{
if( writer && *writer )
{ {
(*writer)->close(); if( writer && *writer )
free(*writer); {
*writer = 0; (*writer)->close();
free(*writer);
*writer = 0;
}
} }
}
int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer, int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
const unsigned char* data, int step, const unsigned char* data, int step,
int width, int height, int cn, int origin) int width, int height, int cn, int origin)
{ {
return writer->writeFrame(data, step, width, height, cn, origin); return writer->writeFrame(data, step, width, height, cn, origin);
} }
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