cap_ffmpeg_impl.hpp 41.9 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
10
//                          License Agreement
11 12
//                For Open Source Computer Vision Library
//
13 14
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 16 17 18 19 20 21 22 23 24 25 26
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
27
//   * The name of the copyright holders may not be used to endorse or promote products
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "cap_ffmpeg_api.hpp"
#include <assert.h>
45
#include <algorithm>
46
#include <limits>
47 48 49 50 51 52 53 54 55

#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( disable: 4244 4510 4512 4610 )
#endif

#ifdef __cplusplus
extern "C" {
#endif

56 57
#include "ffmpeg_codecs.hpp"

58 59
#include <libavutil/mathematics.h>

60 61 62 63 64 65
#ifdef WIN32
  #define HAVE_FFMPEG_SWSCALE 1
  #include <libavcodec/avcodec.h>
  #include <libswscale/swscale.h>
#else

66 67 68
#ifndef HAVE_FFMPEG_SWSCALE
    #error "libswscale is necessary to build the newer OpenCV ffmpeg wrapper"
#endif
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
// 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
  #if defined(HAVE_FFMPEG_SWSCALE)
    #define HAVE_LIBSWSCALE_SWSCALE_H 1
  #endif
#elif defined HAVE_FFMPEG
  #define HAVE_FFMPEG_AVCODEC_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_SWSCALE_H)
  #include <ffmpeg/swscale.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

#if defined _MSC_VER && _MSC_VER >= 1200
#pragma warning( default: 4244 4510 4512 4610 )
#endif

#ifdef NDEBUG
#define CV_WARN(message)
#else
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
#endif

/* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */
#ifndef PIX_FMT_RGBA32
#define PIX_FMT_RGBA32 PIX_FMT_RGB32
#endif

122
#define CALC_FFMPEG_VERSION(a,b,c) ( a<<16 | b<<8 | c )
123

124 125 126 127 128
#if defined WIN32 || defined _WIN32
    #include <windows.h>
#elif defined __linux__ || defined __APPLE__
    #include <unistd.h>
    #include <stdio.h>
129
    #include <sys/types.h>
130 131 132
    #include <sys/sysctl.h>
#endif

133 134 135 136 137 138 139 140 141 142
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif

#if defined(__APPLE__)
#define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL)
#else
#define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE)
#endif

143
static int get_number_of_cpus(void)
144
{
145 146 147
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0)
    return 1;
#elif defined WIN32 || defined _WIN32
148 149
    SYSTEM_INFO sysinfo;
    GetSystemInfo( &sysinfo );
150

151 152 153 154 155 156
    return (int)sysinfo.dwNumberOfProcessors;
#elif defined __linux__
    return (int)sysconf( _SC_NPROCESSORS_ONLN );
#elif defined __APPLE__
    int numCPU=0;
    int mib[4];
157 158 159
    size_t len = sizeof(numCPU);

    // set the mib for hw.ncpu
160 161
    mib[0] = CTL_HW;
    mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
162 163

    // get the number of CPUs from the system
164
    sysctl(mib, 2, &numCPU, &len, NULL, 0);
165 166

    if( numCPU < 1 )
167 168 169
    {
        mib[1] = HW_NCPU;
        sysctl( mib, 2, &numCPU, &len, NULL, 0 );
170

171 172 173 174 175 176 177 178 179 180 181
        if( numCPU < 1 )
            numCPU = 1;
    }

    return (int)numCPU;
#else
    return 1;
#endif
}


182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
struct Image_FFMPEG
{
    unsigned char* data;
    int step;
    int width;
    int height;
    int cn;
};


inline void _opencv_ffmpeg_free(void** ptr)
{
    if(*ptr) free(*ptr);
    *ptr = 0;
}


struct CvCapture_FFMPEG
{
    bool open( const char* filename );
    void close();

    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();
210 211 212

    void    seek(int64_t frame_number);
    void    seek(double sec);
213
    bool    slowSeek( int framenumber );
214 215 216 217 218 219 220 221 222 223 224 225 226 227

    int64_t get_total_frames();
    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);

    AVFormatContext * ic;
    AVCodec         * avcodec;
    int               video_stream;
    AVStream        * video_st;
228 229
    AVFrame         * picture;
    AVFrame           rgb_picture;
230 231 232 233
    int64_t           picture_pts;

    AVPacket          packet;
    Image_FFMPEG      frame;
234
    struct SwsContext *img_convert_ctx;
235 236 237 238

    int64_t frame_number, first_frame_number;

    double eps_zero;
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*
   '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;
};

void CvCapture_FFMPEG::init()
{
    ic = 0;
    video_stream = -1;
    video_st = 0;
    picture = 0;
255 256
    picture_pts = AV_NOPTS_VALUE_;
    first_frame_number = -1;
257 258 259
    memset( &rgb_picture, 0, sizeof(rgb_picture) );
    memset( &frame, 0, sizeof(frame) );
    filename = 0;
260 261
    memset(&packet, 0, sizeof(packet));
    av_init_packet(&packet);
262
    img_convert_ctx = 0;
263 264 265 266

    avcodec = 0;
    frame_number = 0;
    eps_zero = 0.000025;
267 268 269 270 271
}


void CvCapture_FFMPEG::close()
{
272 273 274 275 276
    if( img_convert_ctx )
    {
        sws_freeContext(img_convert_ctx);
        img_convert_ctx = 0;
    }
277

278
    if( picture )
279
        av_free(picture);
280 281 282 283 284

    if( video_st )
    {
#if LIBAVFORMAT_BUILD > 4628
        avcodec_close( video_st->codec );
285

286
#else
287 288
        avcodec_close( &(video_st->codec) );

289 290 291 292 293 294
#endif
        video_st = NULL;
    }

    if( ic )
    {
295
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
296
        av_close_input_file(ic);
297
#else
298
        avformat_close_input(&ic);
299 300
#endif

301 302 303 304 305 306 307 308 309 310 311 312
        ic = NULL;
    }

    if( rgb_picture.data[0] )
    {
        free( rgb_picture.data[0] );
        rgb_picture.data[0] = 0;
    }

    // free last packet if exist
    if (packet.data) {
        av_free_packet (&packet);
313
        packet.data = NULL;
314 315 316 317 318 319 320
    }

    init();
}


#ifndef AVSEEK_FLAG_FRAME
321
#define AVSEEK_FLAG_FRAME 0
322
#endif
A
Andrey Morozov 已提交
323
#ifndef AVSEEK_FLAG_ANY
324
#define AVSEEK_FLAG_ANY 1
325
#endif
326 327 328 329 330 331 332 333 334 335 336 337 338 339

static void icvInitFFMPEG_internal()
{
    static volatile bool initialized = false;
    if( !initialized )
    {
    #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
        avformat_network_init();
    #endif

        /* register all codecs, demux and protocols */
        av_register_all();

        av_log_set_level(AV_LOG_ERROR);
340

341 342 343
        initialized = true;
    }
}
344 345 346

bool CvCapture_FFMPEG::open( const char* _filename )
{
347
    icvInitFFMPEG_internal();
348

349 350 351 352
    unsigned i;
    bool valid = false;

    close();
353

354 355 356
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
    int err = avformat_open_input(&ic, _filename, NULL, NULL);
#else
357
    int err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
358 359
#endif

360
    if (err < 0) {
361 362
        CV_WARN("Error opening file");
        goto exit_func;
363
    }
364 365 366 367 368 369
    err =
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 3, 0)
    avformat_find_stream_info(ic, NULL);
#else
    av_find_stream_info(ic);
#endif
370
    if (err < 0) {
371 372
        CV_WARN("Could not find codec parameters");
        goto exit_func;
373
    }
374 375
    for(i = 0; i < ic->nb_streams; i++)
    {
376 377 378 379 380 381
#if LIBAVFORMAT_BUILD > 4628
        AVCodecContext *enc = ic->streams[i]->codec;
#else
        AVCodecContext *enc = &ic->streams[i]->codec;
#endif

382
#ifdef FF_API_THREAD_INIT
383
        avcodec_thread_init(enc, get_number_of_cpus());
384 385 386
#else
        enc->thread_count = get_number_of_cpus();
#endif
387

388 389 390
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#endif
391

392
        if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0) {
A
Andrey Morozov 已提交
393
            AVCodec *codec = avcodec_find_decoder(enc->codec_id);
394
            if (!codec ||
395 396 397 398 399 400 401
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
                avcodec_open2(enc, codec, NULL)
#else
                avcodec_open(enc, codec)
#endif
                < 0) goto exit_func;

402 403 404 405 406
            video_stream = i;
            video_st = ic->streams[i];
            picture = avcodec_alloc_frame();

            rgb_picture.data[0] = (uint8_t*)malloc(
407 408
                    avpicture_get_size( PIX_FMT_BGR24,
                                        enc->width, enc->height ));
409
            avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0],
410
                            PIX_FMT_BGR24, enc->width, enc->height );
411 412 413 414 415 416 417 418 419 420 421 422

            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(video_stream >= 0) valid = true;

423
exit_func:
424 425 426 427 428 429 430 431 432 433 434 435 436

    if( !valid )
        close();

    return valid;
}


bool CvCapture_FFMPEG::grabFrame()
{
    bool valid = false;
    int got_picture;

437 438
    int count_errs = 0;
    const int max_number_of_attempts = 1 << 16;
439

440
    if( !ic || !video_st )  return false;
441

A
Andrey Kamaev 已提交
442 443 444
    if( ic->streams[video_stream]->nb_frames > 0 &&
        frame_number > ic->streams[video_stream]->nb_frames )
        return false;
445

446
    av_free_packet (&packet);
447

448
    picture_pts = AV_NOPTS_VALUE_;
449 450

    // get the next frame
451 452
    while (!valid)
    {
453
        int ret = av_read_frame(ic, &packet);
454 455 456 457 458 459
        if (ret == AVERROR(EAGAIN)) continue;

        /* else if (ret < 0) break; */

        if( packet.stream_index != video_stream )
        {
460
            av_free_packet (&packet);
461 462 463
            count_errs++;
            if (count_errs > max_number_of_attempts)
                break;
464 465
            continue;
        }
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        // Decode video frame
        #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
            avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);
        #elif LIBAVFORMAT_BUILD > 4628
                avcodec_decode_video(video_st->codec,
                                     picture, &got_picture,
                                     packet.data, packet.size);
        #else
                avcodec_decode_video(&video_st->codec,
                                     picture, &got_picture,
                                     packet.data, packet.size);
        #endif

        // Did we get a video frame?
        if(got_picture)
        {
            //picture_pts = picture->best_effort_timestamp;
            if( picture_pts == AV_NOPTS_VALUE_ )
                picture_pts = packet.pts != AV_NOPTS_VALUE_ && packet.pts != 0 ? packet.pts : packet.dts;
            frame_number++;
            valid = true;
488
        }
489
        else
490
        {
491 492 493
            count_errs++;
            if (count_errs > max_number_of_attempts)
                break;
494
        }
495 496

        av_free_packet (&packet);
497 498
    }

499 500
    if( valid && first_frame_number < 0 )
        first_frame_number = dts_to_frame_number(picture_pts);
501

502 503 504 505 506 507 508 509 510 511
    // return if we have a new picture or not
    return valid;
}


bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn)
{
    if( !video_st || !picture->data[0] )
        return false;

512 513 514 515 516 517 518 519 520
    avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], PIX_FMT_RGB24,
                   video_st->codec->width, video_st->codec->height);

    if( img_convert_ctx == NULL ||
        frame.width != video_st->codec->width ||
        frame.height != video_st->codec->height )
    {
        if( img_convert_ctx )
            sws_freeContext(img_convert_ctx);
521

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
        frame.width = video_st->codec->width;
        frame.height = video_st->codec->height;

        img_convert_ctx = sws_getCachedContext(
                NULL,
                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 (img_convert_ctx == NULL)
            return false;//CV_Error(0, "Cannot initialize the conversion context!");
    }

    sws_scale(
            img_convert_ctx,
            picture->data,
            picture->linesize,
            0, video_st->codec->height,
            rgb_picture.data,
            rgb_picture.linesize
            );

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
    *data = frame.data;
    *step = frame.step;
    *width = frame.width;
    *height = frame.height;
    *cn = frame.cn;

    return true;
}


double CvCapture_FFMPEG::getProperty( int property_id )
{
    if( !video_st ) return 0;

    switch( property_id )
    {
564 565
    case CV_FFMPEG_CAP_PROP_POS_MSEC:
        return 1000.0*(double)frame_number/get_fps();
566
    case CV_FFMPEG_CAP_PROP_POS_FRAMES:
567
        return (double)frame_number;
568
    case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
569
        return r2d(ic->streams[video_stream]->time_base);
570
    case CV_FFMPEG_CAP_PROP_FRAME_COUNT:
571
        return (double)get_total_frames();
572 573 574 575 576 577
    case CV_FFMPEG_CAP_PROP_FRAME_WIDTH:
        return (double)frame.width;
    case CV_FFMPEG_CAP_PROP_FRAME_HEIGHT:
        return (double)frame.height;
    case CV_FFMPEG_CAP_PROP_FPS:
#if LIBAVCODEC_BUILD > 4753
578
        return av_q2d(video_st->r_frame_rate);
579 580
#else
        return (double)video_st->codec.frame_rate
581
                / (double)video_st->codec.frame_rate_base;
582 583 584 585 586 587 588
#endif
    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
589
    default:
590
        break;
591
    }
592

593 594 595
    return 0;
}

596
double CvCapture_FFMPEG::r2d(AVRational r)
597
{
598 599 600 601 602 603 604 605
    return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;
}

double CvCapture_FFMPEG::get_duration_sec()
{
    double sec = (double)ic->duration / (double)AV_TIME_BASE;

    if (sec < eps_zero)
606
    {
607
        sec = (double)ic->streams[video_stream]->duration * r2d(ic->streams[video_stream]->time_base);
608
    }
609 610

    if (sec < eps_zero)
611
    {
612
        sec = (double)ic->streams[video_stream]->duration * r2d(ic->streams[video_stream]->time_base);
613
    }
614 615

    return sec;
616 617
}

618
int CvCapture_FFMPEG::get_bitrate()
619
{
620 621 622 623 624 625 626 627 628 629 630
    return ic->bit_rate;
}

double CvCapture_FFMPEG::get_fps()
{
    double fps = r2d(ic->streams[video_stream]->r_frame_rate);

#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
    if (fps < eps_zero)
    {
        fps = r2d(ic->streams[video_stream]->avg_frame_rate);
631
    }
632
#endif
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668

    if (fps < eps_zero)
    {
        fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base);
    }

    return fps;
}

int64_t CvCapture_FFMPEG::get_total_frames()
{
    int64_t nbf = ic->streams[video_stream]->nb_frames;

    if (nbf == 0)
    {
        nbf = (int64_t)floor(get_duration_sec() * get_fps() + 0.5);
    }
    return nbf;
}

int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts)
{
    double sec = dts_to_sec(dts);
    return (int64_t)(get_fps() * sec + 0.5);
}

double CvCapture_FFMPEG::dts_to_sec(int64_t dts)
{
    return (double)(dts - ic->streams[video_stream]->start_time) *
        r2d(ic->streams[video_stream]->time_base);
}

void CvCapture_FFMPEG::seek(int64_t _frame_number)
{
    _frame_number = std::min(_frame_number, get_total_frames());
    int delta = 16;
669

670 671
    // if we have not grabbed a single frame before first seek, let's read the first frame
    // and get some valuable information during the process
672
    if( first_frame_number < 0 && get_total_frames() > 1 )
673
        grabFrame();
674

675 676 677 678 679 680 681
    for(;;)
    {
        int64_t _frame_number_temp = std::max(_frame_number-delta, (int64_t)0);
        double sec = (double)_frame_number_temp / get_fps();
        int64_t time_stamp = ic->streams[video_stream]->start_time;
        double  time_base  = r2d(ic->streams[video_stream]->time_base);
        time_stamp += (int64_t)(sec / time_base + 0.5);
682
        if (get_total_frames() > 1) av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD);
683 684 685 686
        avcodec_flush_buffers(ic->streams[video_stream]->codec);
        if( _frame_number > 0 )
        {
            grabFrame();
687

688 689 690 691 692
            if( _frame_number > 1 )
            {
                frame_number = dts_to_frame_number(picture_pts) - first_frame_number;
                //printf("_frame_number = %d, frame_number = %d, delta = %d\n",
                //       (int)_frame_number, (int)frame_number, delta);
693

694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
                if( frame_number < 0 || frame_number > _frame_number-1 )
                {
                    if( _frame_number_temp == 0 || delta >= INT_MAX/4 )
                        break;
                    delta = delta < 16 ? delta*2 : delta*3/2;
                    continue;
                }
                while( frame_number < _frame_number-1 )
                {
                    if(!grabFrame())
                        break;
                }
                frame_number++;
                break;
            }
            else
            {
                frame_number = 1;
                break;
            }
        }
        else
        {
            frame_number = 0;
            break;
        }
720
    }
721 722 723 724 725
}

void CvCapture_FFMPEG::seek(double sec)
{
    seek((int64_t)(sec * get_fps() + 0.5));
726
}
727 728 729 730 731 732 733 734 735 736 737 738 739 740

bool CvCapture_FFMPEG::setProperty( int property_id, double value )
{
    if( !video_st ) return false;

    switch( property_id )
    {
    case CV_FFMPEG_CAP_PROP_POS_MSEC:
    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:
741
                seek((int64_t)value);
742 743 744
                break;

            case CV_FFMPEG_CAP_PROP_POS_MSEC:
745
                seek(value/1000.0);
746 747 748
                break;

            case CV_FFMPEG_CAP_PROP_POS_AVI_RATIO:
749
                seek((int64_t)(value*ic->duration));
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
                break;
            }

            picture_pts=(int64_t)value;
        }
        break;
    default:
        return false;
    }

    return true;
}


///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
struct CvVideoWriter_FFMPEG
{
    bool open( const char* filename, int fourcc,
768
               double fps, int width, int height, bool isColor );
769 770 771 772 773
    void close();
    bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin );

    void init();

774
    AVOutputFormat  * fmt;
775
    AVFormatContext * oc;
776 777 778 779 780 781 782 783 784
    uint8_t         * outbuf;
    uint32_t          outbuf_size;
    FILE            * outfile;
    AVFrame         * picture;
    AVFrame         * input_picture;
    uint8_t         * picbuf;
    AVStream        * video_st;
    int               input_pix_fmt;
    Image_FFMPEG      temp_image;
785 786
    int               frame_width, frame_height;
    bool              ok;
787 788 789 790 791
    struct SwsContext *img_convert_ctx;
};

static const char * icvFFMPEGErrStr(int err)
{
792
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
793
    switch(err) {
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
    case AVERROR_BSF_NOT_FOUND:
        return "Bitstream filter not found";
    case AVERROR_DECODER_NOT_FOUND:
        return "Decoder not found";
    case AVERROR_DEMUXER_NOT_FOUND:
        return "Demuxer not found";
    case AVERROR_ENCODER_NOT_FOUND:
        return "Encoder not found";
    case AVERROR_EOF:
        return "End of file";
    case AVERROR_EXIT:
        return "Immediate exit was requested; the called function should not be restarted";
    case AVERROR_FILTER_NOT_FOUND:
        return "Filter not found";
    case AVERROR_INVALIDDATA:
        return "Invalid data found when processing input";
    case AVERROR_MUXER_NOT_FOUND:
        return "Muxer not found";
    case AVERROR_OPTION_NOT_FOUND:
        return "Option not found";
    case AVERROR_PATCHWELCOME:
        return "Not yet implemented in FFmpeg, patches welcome";
    case AVERROR_PROTOCOL_NOT_FOUND:
        return "Protocol not found";
    case AVERROR_STREAM_NOT_FOUND:
        return "Stream not found";
    default:
        break;
822
    }
823
#else
824 825
    switch(err) {
    case AVERROR_NUMEXPECTED:
826
        return "Incorrect filename syntax";
827
    case AVERROR_INVALIDDATA:
828
        return "Invalid data in header";
829
    case AVERROR_NOFMT:
830
        return "Unknown format";
831
    case AVERROR_IO:
832
        return "I/O error occurred";
833
    case AVERROR_NOMEM:
834
        return "Memory allocation error";
835
    default:
836
        break;
837
    }
838 839
#endif

840
    return "Unspecified error";
841 842 843 844
}

/* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/
extern "C" {
845
    enum CodecID codec_get_bmp_id(unsigned int tag);
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
}

void CvVideoWriter_FFMPEG::init()
{
    fmt = 0;
    oc = 0;
    outbuf = 0;
    outbuf_size = 0;
    outfile = 0;
    picture = 0;
    input_picture = 0;
    picbuf = 0;
    video_st = 0;
    input_pix_fmt = 0;
    memset(&temp_image, 0, sizeof(temp_image));
    img_convert_ctx = 0;
862 863
    frame_width = frame_height = 0;
    ok = false;
864 865 866 867 868 869 870 871
}

/**
 * the following function is a modified version of code
 * found in ffmpeg-0.4.9-pre1/output_example.c
 */
static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc)
{
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
    AVFrame * picture;
    uint8_t * picture_buf;
    int size;

    picture = avcodec_alloc_frame();
    if (!picture)
        return NULL;
    size = avpicture_get_size( (PixelFormat) pix_fmt, width, height);
    if(alloc){
        picture_buf = (uint8_t *) malloc(size);
        if (!picture_buf)
        {
            av_free(picture);
            return NULL;
        }
        avpicture_fill((AVPicture *)picture, picture_buf,
888
                       (PixelFormat) pix_fmt, width, height);
889 890 891 892
    }
    else {
    }
    return picture;
893 894 895 896
}

/* add a video output stream to the container */
static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
897 898 899
                                             CodecID codec_id,
                                             int w, int h, int bitrate,
                                             double fps, int pixel_format)
900
{
901 902 903 904
    AVCodecContext *c;
    AVStream *st;
    int frame_rate, frame_rate_base;
    AVCodec *codec;
905

906 907 908 909 910
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
    st = avformat_new_stream(oc, 0);
#else
    st = av_new_stream(oc, 0);
#endif
911

912 913 914 915
    if (!st) {
        CV_WARN("Could not allocate stream");
        return NULL;
    }
916 917

#if LIBAVFORMAT_BUILD > 4628
918
    c = st->codec;
919
#else
920
    c = &(st->codec);
921 922 923
#endif

#if LIBAVFORMAT_BUILD > 4621
924
    c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
925
#else
926
    c->codec_id = oc->oformat->video_codec;
927 928
#endif

929 930 931
    if(codec_id != CODEC_ID_NONE){
        c->codec_id = codec_id;
    }
932 933

    //if(codec_tag) c->codec_tag=codec_tag;
934 935 936
    codec = avcodec_find_encoder(c->codec_id);

    c->codec_type = AVMEDIA_TYPE_VIDEO;
937

938 939 940 941 942
    /* put sample parameters */
    int64_t lbit_rate = (int64_t)bitrate;
    lbit_rate += (bitrate / 2);
    lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX);
    c->bit_rate = lbit_rate;
943

944 945 946
    // took advice from
    // http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html
    c->qmin = 3;
947

948 949 950
    /* resolution must be a multiple of two */
    c->width = w;
    c->height = h;
951

952
    /* time base: this is the fundamental unit of time (in seconds) in terms
953 954 955
       of which frame timestamps are represented. for fixed-fps content,
       timebase should be 1/framerate and timestamp increments should be
       identically 1. */
956 957 958 959 960 961
    frame_rate=(int)(fps+0.5);
    frame_rate_base=1;
    while (fabs((double)frame_rate/frame_rate_base) - fps > 0.001){
        frame_rate_base*=10;
        frame_rate=(int)(fps*frame_rate_base + 0.5);
    }
962 963 964
#if LIBAVFORMAT_BUILD > 4752
    c->time_base.den = frame_rate;
    c->time_base.num = frame_rate_base;
965 966 967
    /* adjust time base for supported framerates */
    if(codec && codec->supported_framerates){
        const AVRational *p= codec->supported_framerates;
968
        AVRational req = {frame_rate, frame_rate_base};
969 970 971 972 973 974 975 976 977 978 979 980 981
        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;
    }
982
#else
983 984
    c->frame_rate = frame_rate;
    c->frame_rate_base = frame_rate_base;
985 986
#endif

987 988
    c->gop_size = 12; /* emit one intra frame every twelve frames at most */
    c->pix_fmt = (PixelFormat) pixel_format;
989

990
    if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
991 992 993 994 995 996
        c->max_b_frames = 2;
    }
    if (c->codec_id == CODEC_ID_MPEG1VIDEO || c->codec_id == CODEC_ID_MSMPEG4V3){
        /* needed to avoid using macroblocks in which some coeffs overflow
           this doesnt happen with normal video, it just happens here as the
           motion of the chroma plane doesnt match the luma plane */
997
        /* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
        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

    return st;
}

1011 1012
static const int OPENCV_NO_FRAMES_WRITTEN_CODE = 1000;

1013
static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st, uint8_t * outbuf, uint32_t outbuf_size, AVFrame * picture )
1014 1015
{
#if LIBAVFORMAT_BUILD > 4628
1016
    AVCodecContext * c = video_st->codec;
1017
#else
1018
    AVCodecContext * c = &(video_st->codec);
1019
#endif
1020 1021
    int out_size;
    int ret = 0;
1022 1023 1024 1025 1026 1027 1028

    if (oc->oformat->flags & AVFMT_RAWPICTURE) {
        /* raw video case. The API will change slightly in the near
           futur for that */
        AVPacket pkt;
        av_init_packet(&pkt);

1029 1030 1031
#ifndef PKT_FLAG_KEY
#define PKT_FLAG_KEY AV_PKT_FLAG_KEY
#endif
1032 1033

        pkt.flags |= PKT_FLAG_KEY;
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
        pkt.stream_index= video_st->index;
        pkt.data= (uint8_t *)picture;
        pkt.size= sizeof(AVPicture);

        ret = av_write_frame(oc, &pkt);
    } else {
        /* encode the image */
        out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
        /* if zero size, it means the image was buffered */
        if (out_size > 0) {
            AVPacket pkt;
            av_init_packet(&pkt);

#if LIBAVFORMAT_BUILD > 4752
1048
            if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
1049
                pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
1050
#else
1051
            pkt.pts = c->coded_frame->pts;
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
#endif
            if(c->coded_frame->key_frame)
                pkt.flags |= PKT_FLAG_KEY;
            pkt.stream_index= video_st->index;
            pkt.data= outbuf;
            pkt.size= out_size;

            /* write the compressed frame in the media file */
            ret = av_write_frame(oc, &pkt);
        } else {
1062
            ret = OPENCV_NO_FRAMES_WRITTEN_CODE;
1063 1064
        }
    }
1065
    return ret;
1066 1067 1068 1069 1070
}

/// write a frame with FFMPEG
bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin )
{
1071
    bool ret = false;
1072

1073 1074 1075 1076
    if( (width & -2) != frame_width || (height & -2) != frame_height || !data )
        return false;
    width = frame_width;
    height = frame_height;
1077

1078
    // typecast from opaque data type to implemented struct
1079 1080 1081
#if LIBAVFORMAT_BUILD > 4628
    AVCodecContext *c = video_st->codec;
#else
A
Alexander Shishkov 已提交
1082
    AVCodecContext *c = &(video_st->codec);
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
#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;
A
Alexander Shishkov 已提交
1095
            temp_image.data = (unsigned char*)malloc(temp_image.step*temp_image.height);
1096 1097 1098 1099 1100 1101
        }
        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;
    }
A
Alexander Shishkov 已提交
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
#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;
    }
1122 1123 1124 1125 1126 1127 1128 1129
#endif

    // check parameters
    if (input_pix_fmt == PIX_FMT_BGR24) {
        if (cn != 3) {
            return false;
        }
    }
1130
    else if (input_pix_fmt == PIX_FMT_GRAY8) {
1131 1132 1133 1134
        if (cn != 1) {
            return false;
        }
    }
1135
    else {
1136 1137 1138
        assert(false);
    }

1139 1140 1141 1142
    if ( c->pix_fmt != input_pix_fmt ) {
        assert( input_picture );
        // let input_picture point to the raw data buffer of 'image'
        avpicture_fill((AVPicture *)input_picture, (uint8_t *) data,
1143
                       (PixelFormat)input_pix_fmt, width, height);
1144

1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
        if( !img_convert_ctx )
        {
            img_convert_ctx = sws_getContext(width,
                                             height,
                                             (PixelFormat)input_pix_fmt,
                                             c->width,
                                             c->height,
                                             c->pix_fmt,
                                             SWS_BICUBIC,
                                             NULL, NULL, NULL);
            if( !img_convert_ctx )
                return false;
        }
1158 1159 1160 1161 1162 1163

        if ( sws_scale(img_convert_ctx, input_picture->data,
                       input_picture->linesize, 0,
                       height,
                       picture->data, picture->linesize) < 0 )
            return false;
1164 1165 1166
    }
    else{
        avpicture_fill((AVPicture *)picture, (uint8_t *) data,
1167
                       (PixelFormat)input_pix_fmt, width, height);
1168
    }
1169

1170
    ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
1171

1172
    return ret;
1173 1174 1175 1176 1177
}

/// close video output stream and free associated memory
void CvVideoWriter_FFMPEG::close()
{
1178
    unsigned i;
1179

1180 1181 1182
    // nothing to do if already released
    if ( !picture )
        return;
1183

1184 1185 1186 1187
    /* no more frame to compress. The codec has a latency of a few
       frames if using B frames, so we get the last frames by
       passing the same picture again */
    // TODO -- do we need to account for latency here?
1188

1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
    /* write the trailer, if any */
    if(ok && oc)
    {
        if( (oc->oformat->flags & AVFMT_RAWPICTURE) == 0 )
        {
            for(;;)
            {
                int ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, NULL);
                if( ret == OPENCV_NO_FRAMES_WRITTEN_CODE || ret < 0 )
                    break;
            }
        }
        av_write_trailer(oc);
    }
1203

1204 1205 1206 1207 1208
    if( img_convert_ctx )
    {
        sws_freeContext(img_convert_ctx);
        img_convert_ctx = 0;
    }
1209

1210
    // free pictures
1211
#if LIBAVFORMAT_BUILD > 4628
1212
    if( video_st->codec->pix_fmt != input_pix_fmt)
1213
#else
1214
    if( video_st->codec.pix_fmt != input_pix_fmt)
1215
#endif
1216 1217 1218 1219 1220 1221
    {
        if(picture->data[0])
            free(picture->data[0]);
        picture->data[0] = 0;
    }
    av_free(picture);
1222

1223 1224
    if (input_picture)
        av_free(input_picture);
1225

1226
    /* close codec */
1227
#if LIBAVFORMAT_BUILD > 4628
1228
    avcodec_close(video_st->codec);
1229
#else
1230
    avcodec_close(&(video_st->codec));
1231 1232
#endif

1233
    av_free(outbuf);
1234

1235 1236 1237 1238 1239 1240
    /* free the streams */
    for(i = 0; i < oc->nb_streams; i++)
    {
        av_freep(&oc->streams[i]->codec);
        av_freep(&oc->streams[i]);
    }
1241

1242 1243 1244
    if (!(fmt->flags & AVFMT_NOFILE))
    {
        /* close the output file */
1245

1246
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
1247
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
1248
        url_fclose(oc->pb);
1249
#else
1250 1251 1252 1253
        url_fclose(&oc->pb);
#endif
#else
        avio_close(oc->pb);
1254 1255
#endif

1256
    }
1257

1258 1259
    /* free the stream */
    av_free(oc);
1260

1261 1262 1263 1264
    if( temp_image.data )
    {
        free(temp_image.data);
        temp_image.data = 0;
1265
    }
1266

1267 1268
    init();
}
1269

1270 1271 1272 1273 1274
/// Create a video writer object that uses FFMPEG
bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
                                 double fps, int width, int height, bool is_color )
{
    icvInitFFMPEG_internal();
1275

1276 1277 1278
    CodecID codec_id = CODEC_ID_NONE;
    int err, codec_pix_fmt;
    double bitrate_scale = 1;
1279

1280
    close();
1281

1282 1283 1284 1285 1286
    // check arguments
    if( !filename )
        return false;
    if(fps <= 0)
        return false;
1287

1288 1289 1290 1291 1292 1293 1294
    // we allow frames of odd width or height, but in this case we truncate
    // the rightmost column/the bottom row. Probably, this should be handled more elegantly,
    // but some internal functions inside FFMPEG swscale require even width/height.
    width &= -2;
    height &= -2;
    if( width <= 0 || height <= 0 )
        return false;
1295

1296
    /* auto detect the output format from the name and fourcc code. */
1297

1298
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
1299
    fmt = av_guess_format(NULL, filename, NULL);
1300
#else
1301
    fmt = guess_format(NULL, filename, NULL);
1302
#endif
1303

1304 1305
    if (!fmt)
        return false;
1306

1307 1308 1309 1310 1311 1312 1313
    /* determine optimal pixel format */
    if (is_color) {
        input_pix_fmt = PIX_FMT_BGR24;
    }
    else {
        input_pix_fmt = PIX_FMT_GRAY8;
    }
1314

1315
    /* Lookup codec_id for given fourcc */
1316
#if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
1317 1318
    if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE )
        return false;
1319
#else
1320 1321 1322
    const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL};
    if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE )
        return false;
1323 1324
#endif

1325
    // alloc memory for context
1326
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
1327
    oc = avformat_alloc_context();
1328
#else
1329
    oc = av_alloc_format_context();
1330
#endif
1331
    assert (oc);
1332

1333 1334 1335
    /* set file name */
    oc->oformat = fmt;
    snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
1336

1337 1338
    /* set some options */
    oc->max_delay = (int)(0.7*AV_TIME_BASE);  /* This reduces buffer underrun warnings with MPEG */
1339

1340 1341
    // set a few optimal pixel formats for lossless codecs of interest..
    switch (codec_id) {
1342
#if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
1343 1344 1345 1346
    case CODEC_ID_JPEGLS:
        // BGR24 or GRAY8 depending on is_color...
        codec_pix_fmt = input_pix_fmt;
        break;
1347
#endif
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
    case CODEC_ID_HUFFYUV:
        codec_pix_fmt = PIX_FMT_YUV422P;
        break;
    case CODEC_ID_MJPEG:
    case CODEC_ID_LJPEG:
        codec_pix_fmt = PIX_FMT_YUVJ420P;
        bitrate_scale = 3;
        break;
    case CODEC_ID_RAWVIDEO:
        codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 ||
                        input_pix_fmt == PIX_FMT_GRAY16LE ||
                        input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P;
        break;
    default:
        // good for lossy formats, MPEG, etc.
        codec_pix_fmt = PIX_FMT_YUV420P;
        break;
    }
1366

1367
    double bitrate = MIN(bitrate_scale*fps*width*height, (double)INT_MAX/2);
1368

1369 1370 1371 1372
    // TODO -- safe to ignore output audio stream?
    video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
                                           width, height, (int)(bitrate + 0.5),
                                           fps, codec_pix_fmt);
1373

1374 1375 1376 1377 1378 1379 1380
    /* 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) {
        return false;
    }
#endif
1381

1382 1383 1384 1385 1386 1387 1388
#if 0
#if FF_API_DUMP_FORMAT
    dump_format(oc, 0, filename, 1);
#else
    av_dump_format(oc, 0, filename, 1);
#endif
#endif
1389

1390 1391 1392 1393 1394
    /* now that all the parameters are set, we can open the audio and
     video codecs and allocate the necessary encode buffers */
    if (!video_st){
        return false;
    }
1395

1396 1397
    AVCodec *codec;
    AVCodecContext *c;
1398 1399

#if LIBAVFORMAT_BUILD > 4628
1400
    c = (video_st->codec);
1401
#else
1402
    c = &(video_st->codec);
1403 1404
#endif

1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
    c->codec_tag = fourcc;
    /* find the video encoder */
    codec = avcodec_find_encoder(c->codec_id);
    if (!codec) {
        fprintf(stderr, "Could not find encoder for codec id %d: %s", c->codec_id, icvFFMPEGErrStr(
        #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
                AVERROR_ENCODER_NOT_FOUND
        #else
                -1
        #endif
                ));
        return false;
    }
1418

1419 1420 1421 1422 1423
    int64_t lbit_rate = (int64_t)c->bit_rate;
    lbit_rate += (bitrate / 2);
    lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX);
    c->bit_rate_tolerance = (int)lbit_rate;
    c->bit_rate = (int)lbit_rate;
1424

1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435
    /* open the codec */
    if ((err=
#if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
         avcodec_open2(c, codec, NULL)
#else
         avcodec_open(c, codec)
#endif
         ) < 0) {
        fprintf(stderr, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err));
        return false;
    }
1436

1437
    outbuf = NULL;
1438

1439 1440 1441 1442 1443 1444
    if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
        /* allocate output buffer */
        /* assume we will never get codec output with more than 4 bytes per pixel... */
        outbuf_size = width*height*4;
        outbuf = (uint8_t *) av_malloc(outbuf_size);
    }
1445

1446 1447
    bool need_color_convert;
    need_color_convert = (c->pix_fmt != input_pix_fmt);
1448

1449 1450 1451 1452 1453
    /* allocate the encoded raw picture */
    picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
    if (!picture) {
        return false;
    }
1454

1455 1456 1457 1458 1459 1460 1461 1462
    /* if the output format is not our input format, then a temporary
   picture of the input format is needed too. It is then converted
   to the required output format */
    input_picture = NULL;
    if ( need_color_convert ) {
        input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
        if (!input_picture) {
            return false;
1463
        }
1464
    }
1465

1466 1467 1468 1469 1470 1471 1472 1473 1474
    /* open the output file, if needed */
    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, AVIO_FLAG_WRITE) < 0)
#endif
            {
            return false;
1475
        }
1476
    }
1477

1478 1479 1480 1481 1482
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
    /* write the stream header, if any */
    err=avformat_write_header(oc, NULL);
#else
    err=av_write_header( oc );
1483 1484
#endif

1485
    if(err < 0)
1486
    {
1487 1488 1489
        close();
        remove(filename);
        return false;
1490
    }
1491 1492 1493 1494 1495
    frame_width = width;
    frame_height = height;
    ok = true;
    return true;
}
1496 1497 1498



1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
{
    CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
    capture->init();
    if( capture->open( filename ))
        return capture;
    capture->close();
    free(capture);
    return 0;
}
1509 1510


1511 1512 1513
void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
{
    if( capture && *capture )
1514
    {
1515 1516 1517
        (*capture)->close();
        free(*capture);
        *capture = 0;
1518
    }
1519
}
1520

1521 1522 1523 1524
int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value)
{
    return capture->setProperty(prop_id, value);
}
1525

1526 1527 1528 1529
double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id)
{
    return capture->getProperty(prop_id);
}
1530

1531 1532 1533 1534
int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)
{
    return capture->grabFrame();
}
1535

1536 1537 1538 1539
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);
}
1540

1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
                                                  int width, int height, int isColor )
{
    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;
}
1552

1553 1554 1555 1556

void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
{
    if( writer && *writer )
1557
    {
1558 1559 1560
        (*writer)->close();
        free(*writer);
        *writer = 0;
1561
    }
1562
}
1563 1564


1565 1566 1567 1568 1569 1570
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);
}
1571