1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42 
43 /* ATTENTION:
44 *
45 * This file was generated from
46 *
47 * https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap_ffmpeg_impl.hpp
48 * commit 2ad0487cec35b08a1dbf49e98c27b05153aaa23a
49 *
50 * and applying the patches in cap_ffmpeg_impl_ov.patch
51 */
52 
53 #include <assert.h>
54 #include <algorithm>
55 #include <limits>
56 
57 #include <string>
58 #include <octave/oct.h>
59 #undef USE_AV_INTERRUPT_CALLBACK
60 
61 #ifndef __OPENCV_BUILD
62 #define CV_FOURCC(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))
63 #endif
64 
65 #define CALC_FFMPEG_VERSION(a,b,c) ( a<<16 | b<<8 | c )
66 
67 #if defined _MSC_VER && _MSC_VER >= 1200
68 #pragma warning( disable: 4244 4510 4610 )
69 #endif
70 
71 #ifdef __GNUC__
72 #  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
73 #endif
74 
75 #ifndef CV_UNUSED  // Required for standalone compilation mode (OpenCV defines this in base.hpp)
76 #define CV_UNUSED(name) (void)name
77 #endif
78 
79 #ifdef __cplusplus
80 extern "C" {
81 #endif
82 
83 #include "ffmpeg_codecs.hpp"
84 
85 #include <libavutil/mathematics.h>
86 
87 #if LIBAVUTIL_BUILD > CALC_FFMPEG_VERSION(51,11,0)
88   #include <libavutil/opt.h>
89 #endif
90 
91 #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \
92     ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0))
93 #include <libavutil/imgutils.h>
94 #endif
95 
96 #include <libavcodec/avcodec.h>
97 #include <libswscale/swscale.h>
98 
99 #ifdef __cplusplus
100 }
101 #endif
102 
103 #if defined _MSC_VER && _MSC_VER >= 1200
104 #pragma warning( default: 4244 4510 4610 )
105 #endif
106 
107 #ifdef NDEBUG
108 #define CV_WARN(message)
109 #else
110 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
111 #endif
112 
113 static int global_err;
114 
get_last_err_msg()115 std::string get_last_err_msg ()
116 {
117   char err_buf[80];
118   av_strerror (global_err, err_buf, 80);
119   return err_buf;
120 }
121 
122 #if defined _WIN32
123     #include <windows.h>
124     #if defined _MSC_VER && _MSC_VER < 1900
125     struct timespec
126     {
127         time_t tv_sec;
128         long   tv_nsec;
129     };
130   #endif
131 #elif defined __linux__ || defined __APPLE__ || defined __HAIKU__
132     #include <unistd.h>
133     #include <stdio.h>
134     #include <sys/types.h>
135     #include <sys/time.h>
136 #if defined __APPLE__
137     #include <sys/sysctl.h>
138     #include <mach/clock.h>
139     #include <mach/mach_host.h>
140     #include <mach/mach_init.h>
141     #include <mach/mach_traps.h>
142     #include <mach/mach_port.h>
143 #endif
144 #endif
145 
146 #ifndef MIN
147 #define MIN(a, b) ((a) < (b) ? (a) : (b))
148 #endif
149 
150 #if defined(__APPLE__)
151 #define AV_NOPTS_VALUE_ ((int64_t)0x8000000000000000LL)
152 #else
153 #define AV_NOPTS_VALUE_ ((int64_t)AV_NOPTS_VALUE)
154 #endif
155 
156 #ifndef AVERROR_EOF
157 #define AVERROR_EOF (-MKTAG( 'E','O','F',' '))
158 #endif
159 
160 #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54,25,0)
161 #  define CV_CODEC_ID AVCodecID
162 #  define CV_CODEC(name) AV_##name
163 #else
164 #  define CV_CODEC_ID CodecID
165 #  define CV_CODEC(name) name
166 #endif
167 
168 #if LIBAVUTIL_BUILD < (LIBAVUTIL_VERSION_MICRO >= 100 \
169     ? CALC_FFMPEG_VERSION(51, 74, 100) : CALC_FFMPEG_VERSION(51, 42, 0))
170 #define AVPixelFormat PixelFormat
171 #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
172 #define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
173 #define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8
174 #define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P
175 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
176 #define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P
177 #define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P
178 #define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE
179 #define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE
180 #endif
181 
182 #ifndef PKT_FLAG_KEY
183 #define PKT_FLAG_KEY AV_PKT_FLAG_KEY
184 #endif
185 
186 #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \
187     ? CALC_FFMPEG_VERSION(52, 38, 100) : CALC_FFMPEG_VERSION(52, 13, 0))
188 #define USE_AV_FRAME_GET_BUFFER 1
189 #else
190 #define USE_AV_FRAME_GET_BUFFER 0
191 #ifndef AV_NUM_DATA_POINTERS // required for 0.7.x/0.8.x ffmpeg releases
192 #define AV_NUM_DATA_POINTERS 4
193 #endif
194 #endif
195 
196 
197 #ifndef USE_AV_INTERRUPT_CALLBACK
198 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 21, 0)
199 #define USE_AV_INTERRUPT_CALLBACK 1
200 #else
201 #define USE_AV_INTERRUPT_CALLBACK 0
202 #endif
203 #endif
204 
205 #if USE_AV_INTERRUPT_CALLBACK
206 #define LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS 30000
207 #define LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS 30000
208 
209 #ifdef _WIN32
210 // http://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows
211 
212 static
get_filetime_offset()213 inline LARGE_INTEGER get_filetime_offset()
214 {
215     SYSTEMTIME s;
216     FILETIME f;
217     LARGE_INTEGER t;
218 
219     s.wYear = 1970;
220     s.wMonth = 1;
221     s.wDay = 1;
222     s.wHour = 0;
223     s.wMinute = 0;
224     s.wSecond = 0;
225     s.wMilliseconds = 0;
226     SystemTimeToFileTime(&s, &f);
227     t.QuadPart = f.dwHighDateTime;
228     t.QuadPart <<= 32;
229     t.QuadPart |= f.dwLowDateTime;
230     return t;
231 }
232 
233 static
get_monotonic_time(timespec * tv)234 inline void get_monotonic_time(timespec *tv)
235 {
236     LARGE_INTEGER           t;
237     FILETIME				f;
238     double                  microseconds;
239     static LARGE_INTEGER    offset;
240     static double           frequencyToMicroseconds;
241     static int              initialized = 0;
242     static BOOL             usePerformanceCounter = 0;
243 
244     if (!initialized)
245     {
246         LARGE_INTEGER performanceFrequency;
247         initialized = 1;
248         usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
249         if (usePerformanceCounter)
250         {
251             QueryPerformanceCounter(&offset);
252             frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
253         }
254         else
255         {
256             offset = get_filetime_offset();
257             frequencyToMicroseconds = 10.;
258         }
259     }
260 
261     if (usePerformanceCounter)
262     {
263         QueryPerformanceCounter(&t);
264     } else {
265         GetSystemTimeAsFileTime(&f);
266         t.QuadPart = f.dwHighDateTime;
267         t.QuadPart <<= 32;
268         t.QuadPart |= f.dwLowDateTime;
269     }
270 
271     t.QuadPart -= offset.QuadPart;
272     microseconds = (double)t.QuadPart / frequencyToMicroseconds;
273     t.QuadPart = microseconds;
274     tv->tv_sec = t.QuadPart / 1000000;
275     tv->tv_nsec = (t.QuadPart % 1000000) * 1000;
276 }
277 #else
278 static
get_monotonic_time(timespec * time)279 inline void get_monotonic_time(timespec *time)
280 {
281 #if defined(__APPLE__) && defined(__MACH__)
282     clock_serv_t cclock;
283     mach_timespec_t mts;
284     host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
285     clock_get_time(cclock, &mts);
286     mach_port_deallocate(mach_task_self(), cclock);
287     time->tv_sec = mts.tv_sec;
288     time->tv_nsec = mts.tv_nsec;
289 #else
290     clock_gettime(CLOCK_MONOTONIC, time);
291 #endif
292 }
293 #endif
294 
295 static
get_monotonic_time_diff(timespec start,timespec end)296 inline timespec get_monotonic_time_diff(timespec start, timespec end)
297 {
298     timespec temp;
299     if (end.tv_nsec - start.tv_nsec < 0)
300     {
301         temp.tv_sec = end.tv_sec - start.tv_sec - 1;
302         temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
303     }
304     else
305     {
306         temp.tv_sec = end.tv_sec - start.tv_sec;
307         temp.tv_nsec = end.tv_nsec - start.tv_nsec;
308     }
309     return temp;
310 }
311 
312 static
get_monotonic_time_diff_ms(timespec time1,timespec time2)313 inline double get_monotonic_time_diff_ms(timespec time1, timespec time2)
314 {
315     timespec delta = get_monotonic_time_diff(time1, time2);
316     double milliseconds = delta.tv_sec * 1000 + (double)delta.tv_nsec / 1000000.0;
317 
318     return milliseconds;
319 }
320 #endif // USE_AV_INTERRUPT_CALLBACK
321 
get_number_of_cpus(void)322 static int get_number_of_cpus(void)
323 {
324 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0)
325     return 1;
326 #elif defined _WIN32
327     SYSTEM_INFO sysinfo;
328     GetSystemInfo( &sysinfo );
329 
330     return (int)sysinfo.dwNumberOfProcessors;
331 #elif defined __linux__ || defined __HAIKU__
332     return (int)sysconf( _SC_NPROCESSORS_ONLN );
333 #elif defined __APPLE__
334     int numCPU=0;
335     int mib[4];
336     size_t len = sizeof(numCPU);
337 
338     // set the mib for hw.ncpu
339     mib[0] = CTL_HW;
340     mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
341 
342     // get the number of CPUs from the system
343     sysctl(mib, 2, &numCPU, &len, NULL, 0);
344 
345     if( numCPU < 1 )
346     {
347         mib[1] = HW_NCPU;
348         sysctl( mib, 2, &numCPU, &len, NULL, 0 );
349 
350         if( numCPU < 1 )
351             numCPU = 1;
352     }
353 
354     return (int)numCPU;
355 #else
356     return 1;
357 #endif
358 }
359 
360 
361 struct Image_FFMPEG
362 {
363     unsigned char* data;
364     int step;
365     int width;
366     int height;
367     int cn;
368 };
369 
370 
371 #if USE_AV_INTERRUPT_CALLBACK
372 struct AVInterruptCallbackMetadata
373 {
374     timespec value;
375     unsigned int timeout_after_ms;
376     int timeout;
377 };
378 
379 // https://github.com/opencv/opencv/pull/12693#issuecomment-426236731
380 static
_opencv_avcodec_get_name(AVCodecID id)381 inline const char* _opencv_avcodec_get_name(AVCodecID id)
382 {
383 #if LIBAVCODEC_VERSION_MICRO >= 100 \
384     && LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(53, 47, 100)
385     return avcodec_get_name(id);
386 #else
387     const AVCodecDescriptor *cd;
388     AVCodec *codec;
389 
390     if (id == AV_CODEC_ID_NONE)
391     {
392         return "none";
393     }
394     cd = avcodec_descriptor_get(id);
395     if (cd)
396     {
397         return cd->name;
398     }
399     codec = avcodec_find_decoder(id);
400     if (codec)
401     {
402         return codec->name;
403     }
404     codec = avcodec_find_encoder(id);
405     if (codec)
406     {
407         return codec->name;
408     }
409 
410     return "unknown_codec";
411 #endif
412 }
413 
414 static
_opencv_ffmpeg_free(void ** ptr)415 inline void _opencv_ffmpeg_free(void** ptr)
416 {
417     if(*ptr) free(*ptr);
418     *ptr = 0;
419 }
420 
421 static
_opencv_ffmpeg_interrupt_callback(void * ptr)422 inline int _opencv_ffmpeg_interrupt_callback(void *ptr)
423 {
424     AVInterruptCallbackMetadata* metadata = (AVInterruptCallbackMetadata*)ptr;
425     assert(metadata);
426 
427     if (metadata->timeout_after_ms == 0)
428     {
429         return 0; // timeout is disabled
430     }
431 
432     timespec now;
433     get_monotonic_time(&now);
434 
435     metadata->timeout = get_monotonic_time_diff_ms(metadata->value, now) > metadata->timeout_after_ms;
436 
437     return metadata->timeout ? -1 : 0;
438 }
439 #endif
440 
441 static
_opencv_ffmpeg_av_packet_unref(AVPacket * pkt)442 inline void _opencv_ffmpeg_av_packet_unref(AVPacket *pkt)
443 {
444 #if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
445     ? CALC_FFMPEG_VERSION(55, 25, 100) : CALC_FFMPEG_VERSION(55, 16, 0))
446     av_packet_unref(pkt);
447 #else
448     av_free_packet(pkt);
449 #endif
450 };
451 
452 static
_opencv_ffmpeg_av_image_fill_arrays(void * frame,uint8_t * ptr,enum AVPixelFormat pix_fmt,int width,int height)453 inline void _opencv_ffmpeg_av_image_fill_arrays(void *frame, uint8_t *ptr, enum AVPixelFormat pix_fmt, int width, int height)
454 {
455 #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \
456     ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0))
457     av_image_fill_arrays(((AVFrame*)frame)->data, ((AVFrame*)frame)->linesize, ptr, pix_fmt, width, height, 1);
458 #else
459     avpicture_fill((AVPicture*)frame, ptr, pix_fmt, width, height);
460 #endif
461 };
462 
463 static
_opencv_ffmpeg_av_image_get_buffer_size(enum AVPixelFormat pix_fmt,int width,int height)464 inline int _opencv_ffmpeg_av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height)
465 {
466 #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \
467     ? CALC_FFMPEG_VERSION(51, 63, 100) : CALC_FFMPEG_VERSION(54, 6, 0))
468     return av_image_get_buffer_size(pix_fmt, width, height, 1);
469 #else
470     return avpicture_get_size(pix_fmt, width, height);
471 #endif
472 };
473 
_opencv_ffmpeg_get_sample_aspect_ratio(AVStream * stream)474 static AVRational _opencv_ffmpeg_get_sample_aspect_ratio(AVStream *stream)
475 {
476 #if LIBAVUTIL_VERSION_MICRO >= 100 && LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(54, 5, 100)
477     return av_guess_sample_aspect_ratio(NULL, stream, NULL);
478 #else
479     AVRational undef = {0, 1};
480 
481     // stream
482     AVRational ratio = stream ? stream->sample_aspect_ratio : undef;
483     av_reduce(&ratio.num, &ratio.den, ratio.num, ratio.den, INT_MAX);
484     if (ratio.num > 0 && ratio.den > 0)
485         return ratio;
486 
487     // codec
488     ratio  = stream && stream->codec ? stream->codec->sample_aspect_ratio : undef;
489     av_reduce(&ratio.num, &ratio.den, ratio.num, ratio.den, INT_MAX);
490     if (ratio.num > 0 && ratio.den > 0)
491         return ratio;
492 
493     return undef;
494 #endif
495 }
496 
497 static bool capture_type_loaded = false;
498 
499 class CvCapture_FFMPEG: public octave_base_value
500 {
501   public:
502     CvCapture_FFMPEG ();
503 
504     bool open( const char* filename );
505     void close();
506 
507     //double getProperty(int) const;
508     bool setProperty(int, double);
509     bool grabFrame();
510     bool retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn);
511 
512     void init();
513 
514     void    seek(int64_t frame_number);
515     void    seek(double sec);
516     bool    slowSeek( int framenumber );
517 
518     int64_t get_total_frames() const;
519     double  get_duration_sec() const;
520     double  get_fps() const;
521     int     get_bitrate() const;
522 
get_sample_aspect_ratio() const523     AVRational get_sample_aspect_ratio () const
524       { return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]); }
525 
get_video_codec_name() const526     const char* get_video_codec_name () const
527       {
528 #if LIBAVFORMAT_BUILD > 4628
529         return _opencv_avcodec_get_name(video_st->codec->codec_id);
530 #else
531         return _opencv_avcodec_get_name(video_st->codec.codec_id);
532 #endif
533       }
534 
535     double  r2d(AVRational r) const;
536     int64_t dts_to_frame_number(int64_t dts);
537     double  dts_to_sec(int64_t dts) const;
538 
539     AVFormatContext * ic;
540     AVCodec         * avcodec;
541     int               video_stream;
542     AVStream        * video_st;
543     AVFrame         * picture;
544     AVFrame           rgb_picture;
545     int64_t           picture_pts;
546 
547     AVPacket          packet;
548     Image_FFMPEG      frame;
549     struct SwsContext *img_convert_ctx;
550 
551     int64_t frame_number, first_frame_number;
552 
553     double eps_zero;
554 /*
555    'filename' contains the filename of the videosource,
556    'filename==NULL' indicates that ffmpeg's seek support works
557    for the particular file.
558    'filename!=NULL' indicates that the slow fallback function is used for seeking,
559    and so the filename is needed to reopen the file on backward seeking.
560 */
561     char              * filename;
562 
563 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
564     AVDictionary *dict;
565 #endif
566 #if USE_AV_INTERRUPT_CALLBACK
567     AVInterruptCallbackMetadata interrupt_metadata;
568 #endif
569 
is_constant(void) const570   bool is_constant (void) const
571   {
572     return true;
573   }
is_defined(void) const574   bool is_defined (void) const
575   {
576     return true;
577   }
578 
579   DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
580 
print(std::ostream & os,bool pr_as_read_syntax=false)581   void print (std::ostream & os, bool pr_as_read_syntax = false)
582   {
583     os << "CvCapture_FFMPEG:" << std::endl;
584     if (filename)
585       os << "  filename           = " << filename << std::endl;
586     os << "  get_total_frames() = " << get_total_frames() << std::endl;
587     os << "  get_duration_sec() = " << get_duration_sec() << std::endl;
588     os << "  get_fps()          = " << get_fps() << std::endl;
589     os << "  get_bitrate()      = " << get_bitrate() << std::endl;
590     os << "  width              = " << frame.width << std::endl;
591     os << "  height             = " << frame.height << std::endl;
592     os << "  frame_number       = " << frame_number << std::endl;
593     os << "  video_codec_name   = " << get_video_codec_name () << std::endl;
594     AVRational s = get_sample_aspect_ratio ();
595     os << "  aspect_ration_num  = " << s.num << std::endl;
596     os << "  aspect_ration_den  = " << s.den << std::endl;
597   }
598 };
599 
600 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(CvCapture_FFMPEG, "CvCapture_FFMPEG", "CvCapture_FFMPEG");
601 
CvCapture_FFMPEG()602 CvCapture_FFMPEG::CvCapture_FFMPEG ()
603   : octave_base_value () { init (); };
604 
init()605 void CvCapture_FFMPEG::init()
606 {
607     av_register_all();
608     ic = 0;
609     video_stream = -1;
610     video_st = 0;
611     picture = 0;
612     picture_pts = AV_NOPTS_VALUE_;
613     first_frame_number = -1;
614     memset( &rgb_picture, 0, sizeof(rgb_picture) );
615     memset( &frame, 0, sizeof(frame) );
616     filename = 0;
617     memset(&packet, 0, sizeof(packet));
618     av_init_packet(&packet);
619     img_convert_ctx = 0;
620 
621     avcodec = 0;
622     frame_number = 0;
623     eps_zero = 0.000025;
624 
625 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
626     dict = NULL;
627 #endif
628 }
629 
630 
close()631 void CvCapture_FFMPEG::close()
632 {
633     if( img_convert_ctx )
634     {
635         sws_freeContext(img_convert_ctx);
636         img_convert_ctx = 0;
637     }
638 
639     if( picture )
640     {
641 #if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
642     ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))
643         av_frame_free(&picture);
644 #elif LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
645     ? CALC_FFMPEG_VERSION(54, 59, 100) : CALC_FFMPEG_VERSION(54, 28, 0))
646         avcodec_free_frame(&picture);
647 #else
648         av_free(picture);
649 #endif
650     }
651 
652     if( video_st )
653     {
654 #if LIBAVFORMAT_BUILD > 4628
655         avcodec_close( video_st->codec );
656 
657 #else
658         avcodec_close( &(video_st->codec) );
659 
660 #endif
661         video_st = NULL;
662     }
663 
664     if( ic )
665     {
666 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 24, 2)
667         av_close_input_file(ic);
668 #else
669         avformat_close_input(&ic);
670 #endif
671 
672         ic = NULL;
673     }
674 
675 #if USE_AV_FRAME_GET_BUFFER
676     av_frame_unref(&rgb_picture);
677 #else
678     if( rgb_picture.data[0] )
679     {
680         free( rgb_picture.data[0] );
681         rgb_picture.data[0] = 0;
682     }
683 #endif
684 
685     // free last packet if exist
686     if (packet.data) {
687         _opencv_ffmpeg_av_packet_unref (&packet);
688         packet.data = NULL;
689     }
690 
691 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
692     if (dict != NULL)
693        av_dict_free(&dict);
694 #endif
695 
696     init();
697 }
698 
699 
700 #ifndef AVSEEK_FLAG_FRAME
701 #define AVSEEK_FLAG_FRAME 0
702 #endif
703 #ifndef AVSEEK_FLAG_ANY
704 #define AVSEEK_FLAG_ANY 1
705 #endif
706 
707 #if defined(__OPENCV_BUILD) || defined(BUILD_PLUGIN)
708 typedef cv::Mutex ImplMutex;
709 #else
710 class ImplMutex
711 {
712 public:
ImplMutex()713     ImplMutex() { init(); }
~ImplMutex()714     ~ImplMutex() { destroy(); }
715 
716     void init();
717     void destroy();
718 
719     void lock();
720     bool trylock();
721     void unlock();
722 
723     struct Impl;
724 protected:
725     Impl* impl;
726 
727 private:
728     ImplMutex(const ImplMutex&);
729     ImplMutex& operator = (const ImplMutex& m);
730 };
731 
732 #if defined _WIN32 || defined WINCE
733 
734 struct ImplMutex::Impl
735 {
initImplMutex::Impl736     void init()
737     {
738 #if (_WIN32_WINNT >= 0x0600)
739         ::InitializeCriticalSectionEx(&cs, 1000, 0);
740 #else
741         ::InitializeCriticalSection(&cs);
742 #endif
743         refcount = 1;
744     }
destroyImplMutex::Impl745     void destroy() { DeleteCriticalSection(&cs); }
746 
lockImplMutex::Impl747     void lock() { EnterCriticalSection(&cs); }
trylockImplMutex::Impl748     bool trylock() { return TryEnterCriticalSection(&cs) != 0; }
unlockImplMutex::Impl749     void unlock() { LeaveCriticalSection(&cs); }
750 
751     CRITICAL_SECTION cs;
752     int refcount;
753 };
754 
755 #ifndef __GNUC__
_interlockedExchangeAdd(int * addr,int delta)756 static int _interlockedExchangeAdd(int* addr, int delta)
757 {
758 #if defined _MSC_VER && _MSC_VER >= 1500
759     return (int)_InterlockedExchangeAdd((long volatile*)addr, delta);
760 #else
761     return (int)InterlockedExchangeAdd((long volatile*)addr, delta);
762 #endif
763 }
764 #endif // __GNUC__
765 
766 #elif defined __APPLE__
767 
768 #include <libkern/OSAtomic.h>
769 
770 struct ImplMutex::Impl
771 {
initImplMutex::Impl772     void init() { sl = OS_SPINLOCK_INIT; refcount = 1; }
destroyImplMutex::Impl773     void destroy() { }
774 
lockImplMutex::Impl775     void lock() { OSSpinLockLock(&sl); }
trylockImplMutex::Impl776     bool trylock() { return OSSpinLockTry(&sl); }
unlockImplMutex::Impl777     void unlock() { OSSpinLockUnlock(&sl); }
778 
779     OSSpinLock sl;
780     int refcount;
781 };
782 
783 #elif defined __linux__ && !defined __ANDROID__
784 
785 struct ImplMutex::Impl
786 {
initImplMutex::Impl787     void init() { pthread_spin_init(&sl, 0); refcount = 1; }
destroyImplMutex::Impl788     void destroy() { pthread_spin_destroy(&sl); }
789 
lockImplMutex::Impl790     void lock() { pthread_spin_lock(&sl); }
trylockImplMutex::Impl791     bool trylock() { return pthread_spin_trylock(&sl) == 0; }
unlockImplMutex::Impl792     void unlock() { pthread_spin_unlock(&sl); }
793 
794     pthread_spinlock_t sl;
795     int refcount;
796 };
797 
798 #else
799 
800 struct ImplMutex::Impl
801 {
initImplMutex::Impl802     void init() { pthread_mutex_init(&sl, 0); refcount = 1; }
destroyImplMutex::Impl803     void destroy() { pthread_mutex_destroy(&sl); }
804 
lockImplMutex::Impl805     void lock() { pthread_mutex_lock(&sl); }
trylockImplMutex::Impl806     bool trylock() { return pthread_mutex_trylock(&sl) == 0; }
unlockImplMutex::Impl807     void unlock() { pthread_mutex_unlock(&sl); }
808 
809     pthread_mutex_t sl;
810     int refcount;
811 };
812 
813 #endif
814 
init()815 void ImplMutex::init()
816 {
817     impl = new Impl();
818     impl->init();
819 }
destroy()820 void ImplMutex::destroy()
821 {
822     impl->destroy();
823     delete(impl);
824     impl = NULL;
825 }
lock()826 void ImplMutex::lock() { impl->lock(); }
unlock()827 void ImplMutex::unlock() { impl->unlock(); }
trylock()828 bool ImplMutex::trylock() { return impl->trylock(); }
829 
830 class AutoLock
831 {
832 public:
AutoLock(ImplMutex & m)833     AutoLock(ImplMutex& m) : mutex(&m) { mutex->lock(); }
~AutoLock()834     ~AutoLock() { mutex->unlock(); }
835 protected:
836     ImplMutex* mutex;
837 private:
838     AutoLock(const AutoLock&); // disabled
839     AutoLock& operator = (const AutoLock&); // disabled
840 };
841 #endif
842 
843 static ImplMutex _mutex;
844 
LockCallBack(void ** mutex,AVLockOp op)845 static int LockCallBack(void **mutex, AVLockOp op)
846 {
847     ImplMutex* localMutex = reinterpret_cast<ImplMutex*>(*mutex);
848     switch (op)
849     {
850         case AV_LOCK_CREATE:
851             localMutex = new ImplMutex();
852             if (!localMutex)
853                 return 1;
854             *mutex = localMutex;
855             if (!*mutex)
856                 return 1;
857         break;
858 
859         case AV_LOCK_OBTAIN:
860             localMutex->lock();
861         break;
862 
863         case AV_LOCK_RELEASE:
864             localMutex->unlock();
865         break;
866 
867         case AV_LOCK_DESTROY:
868             delete localMutex;
869             localMutex = NULL;
870             *mutex = NULL;
871         break;
872     }
873     return 0;
874 }
875 
876 
ffmpeg_log_callback(void * ptr,int level,const char * fmt,va_list vargs)877 static void ffmpeg_log_callback(void *ptr, int level, const char *fmt, va_list vargs)
878 {
879     static bool skip_header = false;
880     static int prev_level = -1;
881     CV_UNUSED(ptr);
882     if (!skip_header || level != prev_level) printf("[OPENCV:FFMPEG:%02d] ", level);
883     vprintf(fmt, vargs);
884     size_t fmt_len = strlen(fmt);
885     skip_header = fmt_len > 0 && fmt[fmt_len - 1] != '\n';
886     prev_level = level;
887 }
888 
889 class InternalFFMpegRegister
890 {
891 public:
init()892     static void init()
893     {
894         AutoLock lock(_mutex);
895         static InternalFFMpegRegister instance;
896     }
InternalFFMpegRegister()897     InternalFFMpegRegister()
898     {
899 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 13, 0)
900         avformat_network_init();
901 #endif
902 
903         /* register all codecs, demux and protocols */
904         av_register_all();
905 
906         /* register a callback function for synchronization */
907         av_lockmgr_register(&LockCallBack);
908 
909 #ifndef NO_GETENV
910         char* debug_option = getenv("OPENCV_FFMPEG_DEBUG");
911         if (debug_option != NULL)
912         {
913             av_log_set_level(AV_LOG_VERBOSE);
914             av_log_set_callback(ffmpeg_log_callback);
915         }
916         else
917 #endif
918         {
919             av_log_set_level(AV_LOG_ERROR);
920         }
921     }
~InternalFFMpegRegister()922     ~InternalFFMpegRegister()
923     {
924         av_lockmgr_register(NULL);
925     }
926 };
927 
open(const char * _filename)928 bool CvCapture_FFMPEG::open( const char* _filename )
929 {
930     InternalFFMpegRegister::init();
931     AutoLock lock(_mutex);
932     unsigned i;
933     bool valid = false;
934 
935     close();
936 
937 #if USE_AV_INTERRUPT_CALLBACK
938     /* interrupt callback */
939     interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_OPEN_TIMEOUT_MS;
940     get_monotonic_time(&interrupt_metadata.value);
941 
942     ic = avformat_alloc_context();
943     ic->interrupt_callback.callback = _opencv_ffmpeg_interrupt_callback;
944     ic->interrupt_callback.opaque = &interrupt_metadata;
945 #endif
946 
947 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
948 #ifndef NO_GETENV
949     char* options = getenv("OPENCV_FFMPEG_CAPTURE_OPTIONS");
950     if(options == NULL)
951     {
952         av_dict_set(&dict, "rtsp_transport", "tcp", 0);
953     }
954     else
955     {
956 #if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 ? CALC_FFMPEG_VERSION(52, 17, 100) : CALC_FFMPEG_VERSION(52, 7, 0))
957         av_dict_parse_string(&dict, options, ";", "|", 0);
958 #else
959         av_dict_set(&dict, "rtsp_transport", "tcp", 0);
960 #endif
961     }
962 #else
963     av_dict_set(&dict, "rtsp_transport", "tcp", 0);
964 #endif
965     AVInputFormat* input_format = NULL;
966     AVDictionaryEntry* entry = av_dict_get(dict, "input_format", NULL, 0);
967     if (entry != 0)
968     {
969       input_format = av_find_input_format(entry->value);
970     }
971 
972     global_err = avformat_open_input(&ic, _filename, input_format, &dict);
973 #else
974     global_err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
975 #endif
976 
977     if (global_err < 0)
978     {
979         CV_WARN("Error opening file");
980         CV_WARN(_filename);
981         goto exit_func;
982     }
983     global_err =
984 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 6, 0)
985     avformat_find_stream_info(ic, NULL);
986 #else
987     av_find_stream_info(ic);
988 #endif
989     if (global_err < 0)
990     {
991         CV_WARN("Could not find codec parameters");
992         goto exit_func;
993     }
994     for(i = 0; i < ic->nb_streams; i++)
995     {
996 #if LIBAVFORMAT_BUILD > 4628
997         AVCodecContext *enc = ic->streams[i]->codec;
998 #else
999         AVCodecContext *enc = &ic->streams[i]->codec;
1000 #endif
1001 
1002 //#ifdef FF_API_THREAD_INIT
1003 //        avcodec_thread_init(enc, get_number_of_cpus());
1004 //#else
1005         enc->thread_count = get_number_of_cpus();
1006 //#endif
1007 
1008 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
1009 #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
1010 #endif
1011 
1012         if( AVMEDIA_TYPE_VIDEO == enc->codec_type && video_stream < 0)
1013         {
1014             // backup encoder' width/height
1015             int enc_width = enc->width;
1016             int enc_height = enc->height;
1017 
1018             AVCodec *codec;
1019             if(av_dict_get(dict, "video_codec", NULL, 0) == NULL) {
1020                 codec = avcodec_find_decoder(enc->codec_id);
1021             } else {
1022                 codec = avcodec_find_decoder_by_name(av_dict_get(dict, "video_codec", NULL, 0)->value);
1023             }
1024             if (!codec ||
1025 #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
1026                 avcodec_open2(enc, codec, NULL)
1027 #else
1028                 avcodec_open(enc, codec)
1029 #endif
1030                 < 0)
1031                 goto exit_func;
1032 
1033             // checking width/height (since decoder can sometimes alter it, eg. vp6f)
1034             if (enc_width && (enc->width != enc_width)) { enc->width = enc_width; }
1035             if (enc_height && (enc->height != enc_height)) { enc->height = enc_height; }
1036 
1037             video_stream = i;
1038             video_st = ic->streams[i];
1039 #if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
1040     ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))
1041             picture = av_frame_alloc();
1042 #else
1043             picture = avcodec_alloc_frame();
1044 #endif
1045 
1046             frame.width = enc->width;
1047             frame.height = enc->height;
1048             frame.cn = 3;
1049             frame.step = 0;
1050             frame.data = NULL;
1051             break;
1052         }
1053     }
1054 
1055     if(video_stream >= 0) valid = true;
1056 
1057 exit_func:
1058 
1059 #if USE_AV_INTERRUPT_CALLBACK
1060     // deactivate interrupt callback
1061     interrupt_metadata.timeout_after_ms = 0;
1062 #endif
1063 
1064     if( !valid )
1065         close();
1066 
1067     return valid;
1068 }
1069 
1070 
grabFrame()1071 bool CvCapture_FFMPEG::grabFrame()
1072 {
1073     bool valid = false;
1074     int got_picture;
1075 
1076     int count_errs = 0;
1077     const int max_number_of_attempts = 1 << 9;
1078 
1079     if( !ic || !video_st )  return false;
1080 
1081     if( ic->streams[video_stream]->nb_frames > 0 &&
1082         frame_number > ic->streams[video_stream]->nb_frames )
1083         return false;
1084 
1085     picture_pts = AV_NOPTS_VALUE_;
1086 
1087 #if USE_AV_INTERRUPT_CALLBACK
1088     // activate interrupt callback
1089     get_monotonic_time(&interrupt_metadata.value);
1090     interrupt_metadata.timeout_after_ms = LIBAVFORMAT_INTERRUPT_READ_TIMEOUT_MS;
1091 #endif
1092 
1093     // get the next frame
1094     while (!valid)
1095     {
1096 
1097         _opencv_ffmpeg_av_packet_unref (&packet);
1098 
1099 #if USE_AV_INTERRUPT_CALLBACK
1100         if (interrupt_metadata.timeout)
1101         {
1102             valid = false;
1103             break;
1104         }
1105 #endif
1106 
1107         int ret = av_read_frame(ic, &packet);
1108         if (ret == AVERROR(EAGAIN)) continue;
1109 
1110         /* else if (ret < 0) break; */
1111 
1112         if( packet.stream_index != video_stream )
1113         {
1114             _opencv_ffmpeg_av_packet_unref (&packet);
1115             count_errs++;
1116             if (count_errs > max_number_of_attempts)
1117                 break;
1118             continue;
1119         }
1120 
1121         // Decode video frame
1122         #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
1123             avcodec_decode_video2(video_st->codec, picture, &got_picture, &packet);
1124         #elif LIBAVFORMAT_BUILD > 4628
1125                 avcodec_decode_video(video_st->codec,
1126                                      picture, &got_picture,
1127                                      packet.data, packet.size);
1128         #else
1129                 avcodec_decode_video(&video_st->codec,
1130                                      picture, &got_picture,
1131                                      packet.data, packet.size);
1132         #endif
1133 
1134         // Did we get a video frame?
1135         if(got_picture)
1136         {
1137             //picture_pts = picture->best_effort_timestamp;
1138             if( picture_pts == AV_NOPTS_VALUE_ )
1139                 picture_pts = picture->pkt_pts != AV_NOPTS_VALUE_ && picture->pkt_pts != 0 ? picture->pkt_pts : picture->pkt_dts;
1140 
1141             frame_number++;
1142             valid = true;
1143         }
1144         else
1145         {
1146             count_errs++;
1147             if (count_errs > max_number_of_attempts)
1148                 break;
1149         }
1150     }
1151 
1152     if( valid && first_frame_number < 0 )
1153         first_frame_number = dts_to_frame_number(picture_pts);
1154 
1155 #if USE_AV_INTERRUPT_CALLBACK
1156     // deactivate interrupt callback
1157     interrupt_metadata.timeout_after_ms = 0;
1158 #endif
1159 
1160     // return if we have a new picture or not
1161     return valid;
1162 }
1163 
1164 
retrieveFrame(int,unsigned char ** data,int * step,int * width,int * height,int * cn)1165 bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* width, int* height, int* cn)
1166 {
1167     if( !video_st || !picture->data[0] )
1168         return false;
1169 
1170     if( img_convert_ctx == NULL ||
1171         frame.width != video_st->codec->width ||
1172         frame.height != video_st->codec->height ||
1173         frame.data == NULL )
1174     {
1175         // Some sws_scale optimizations have some assumptions about alignment of data/step/width/height
1176         // Also we use coded_width/height to workaround problem with legacy ffmpeg versions (like n0.8)
1177         int buffer_width = video_st->codec->coded_width, buffer_height = video_st->codec->coded_height;
1178 
1179         img_convert_ctx = sws_getCachedContext(
1180                 img_convert_ctx,
1181                 buffer_width, buffer_height,
1182                 video_st->codec->pix_fmt,
1183                 buffer_width, buffer_height,
1184                 AV_PIX_FMT_BGR24,
1185                 SWS_BICUBIC,
1186                 NULL, NULL, NULL
1187                 );
1188 
1189         if (img_convert_ctx == NULL)
1190             return false;//CV_Error(0, "Cannot initialize the conversion context!");
1191 
1192 #if USE_AV_FRAME_GET_BUFFER
1193         av_frame_unref(&rgb_picture);
1194         rgb_picture.format = AV_PIX_FMT_BGR24;
1195         rgb_picture.width = buffer_width;
1196         rgb_picture.height = buffer_height;
1197         if (0 != av_frame_get_buffer(&rgb_picture, 32))
1198         {
1199             CV_WARN("OutOfMemory");
1200             return false;
1201         }
1202 #else
1203         int aligns[AV_NUM_DATA_POINTERS];
1204         avcodec_align_dimensions2(video_st->codec, &buffer_width, &buffer_height, aligns);
1205         rgb_picture.data[0] = (uint8_t*)realloc(rgb_picture.data[0],
1206                 _opencv_ffmpeg_av_image_get_buffer_size( AV_PIX_FMT_BGR24,
1207                                     buffer_width, buffer_height ));
1208         _opencv_ffmpeg_av_image_fill_arrays(&rgb_picture, rgb_picture.data[0],
1209                         AV_PIX_FMT_BGR24, buffer_width, buffer_height );
1210 #endif
1211         frame.width = video_st->codec->width;
1212         frame.height = video_st->codec->height;
1213         frame.cn = 3;
1214         frame.data = rgb_picture.data[0];
1215         frame.step = rgb_picture.linesize[0];
1216     }
1217 
1218     sws_scale(
1219             img_convert_ctx,
1220             picture->data,
1221             picture->linesize,
1222             0, video_st->codec->coded_height,
1223             rgb_picture.data,
1224             rgb_picture.linesize
1225             );
1226 
1227     *data = frame.data;
1228     *step = frame.step;
1229     *width = frame.width;
1230     *height = frame.height;
1231     *cn = frame.cn;
1232 
1233     return true;
1234 }
1235 
1236 #if 0
1237 double CvCapture_FFMPEG::getProperty( int property_id ) const
1238 {
1239     if( !video_st ) return 0;
1240 
1241     double codec_tag = 0;
1242     AVCodecID codec_id = AV_CODEC_ID_NONE;
1243     const char* codec_fourcc = NULL;
1244 
1245     switch( property_id )
1246     {
1247     case CAP_PROP_POS_MSEC:
1248         if (picture_pts == AV_NOPTS_VALUE_)
1249         {
1250             return 0;
1251         }
1252         return (dts_to_sec(picture_pts) * 1000);
1253     case CAP_PROP_POS_FRAMES:
1254         return (double)frame_number;
1255     case CAP_PROP_POS_AVI_RATIO:
1256         return r2d(ic->streams[video_stream]->time_base);
1257     case CAP_PROP_FRAME_COUNT:
1258         return (double)get_total_frames();
1259     case CAP_PROP_FRAME_WIDTH:
1260         return (double)frame.width;
1261     case CAP_PROP_FRAME_HEIGHT:
1262         return (double)frame.height;
1263     case CAP_PROP_FPS:
1264         return get_fps();
1265     case CAP_PROP_FOURCC:
1266 #if LIBAVFORMAT_BUILD > 4628
1267         codec_id = video_st->codec->codec_id;
1268         codec_tag = (double) video_st->codec->codec_tag;
1269 #else
1270         codec_id = video_st->codec.codec_id;
1271         codec_tag = (double)video_st->codec.codec_tag;
1272 #endif
1273 
1274         if(codec_tag || codec_id == AV_CODEC_ID_NONE)
1275         {
1276             return codec_tag;
1277         }
1278 
1279         codec_fourcc = _opencv_avcodec_get_name(codec_id);
1280         if(!codec_fourcc || strlen(codec_fourcc) < 4 || strcmp(codec_fourcc, "unknown_codec") == 0)
1281         {
1282             return codec_tag;
1283         }
1284 
1285         return (double) CV_FOURCC(codec_fourcc[0], codec_fourcc[1], codec_fourcc[2], codec_fourcc[3]);
1286     case CAP_PROP_SAR_NUM:
1287         return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).num;
1288     case CAP_PROP_SAR_DEN:
1289         return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).den;
1290     default:
1291         break;
1292     }
1293     return 0;
1294 }
1295 #endif
1296 
r2d(AVRational r) const1297 double CvCapture_FFMPEG::r2d(AVRational r) const
1298 {
1299     return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;
1300 }
1301 
get_duration_sec() const1302 double CvCapture_FFMPEG::get_duration_sec() const
1303 {
1304     double sec = (double)ic->duration / (double)AV_TIME_BASE;
1305 
1306     if (sec < eps_zero)
1307     {
1308         sec = (double)ic->streams[video_stream]->duration * r2d(ic->streams[video_stream]->time_base);
1309     }
1310 
1311     return sec;
1312 }
1313 
get_bitrate() const1314 int CvCapture_FFMPEG::get_bitrate() const
1315 {
1316     return ic->bit_rate;
1317 }
1318 
get_fps() const1319 double CvCapture_FFMPEG::get_fps() const
1320 {
1321 #if 0 && LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 1, 100) && LIBAVFORMAT_VERSION_MICRO >= 100
1322     double fps = r2d(av_guess_frame_rate(ic, ic->streams[video_stream], NULL));
1323 #else
1324 #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)
1325     double fps = r2d(ic->streams[video_stream]->avg_frame_rate);
1326 #else
1327     double fps = r2d(ic->streams[video_stream]->r_frame_rate);
1328 #endif
1329 
1330 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
1331     if (fps < eps_zero)
1332     {
1333         fps = r2d(ic->streams[video_stream]->avg_frame_rate);
1334     }
1335 #endif
1336 
1337     if (fps < eps_zero)
1338     {
1339         fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base);
1340     }
1341 #endif
1342     return fps;
1343 }
1344 
get_total_frames() const1345 int64_t CvCapture_FFMPEG::get_total_frames() const
1346 {
1347     int64_t nbf = ic->streams[video_stream]->nb_frames;
1348 
1349     if (nbf == 0)
1350     {
1351         nbf = (int64_t)floor(get_duration_sec() * get_fps() + 0.5);
1352     }
1353     return nbf;
1354 }
1355 
dts_to_frame_number(int64_t dts)1356 int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts)
1357 {
1358     double sec = dts_to_sec(dts);
1359     return (int64_t)(get_fps() * sec + 0.5);
1360 }
1361 
dts_to_sec(int64_t dts) const1362 double CvCapture_FFMPEG::dts_to_sec(int64_t dts) const
1363 {
1364     return (double)(dts - ic->streams[video_stream]->start_time) *
1365         r2d(ic->streams[video_stream]->time_base);
1366 }
1367 
seek(int64_t _frame_number)1368 void CvCapture_FFMPEG::seek(int64_t _frame_number)
1369 {
1370     _frame_number = std::min(_frame_number, get_total_frames());
1371     int delta = 16;
1372 
1373     // if we have not grabbed a single frame before first seek, let's read the first frame
1374     // and get some valuable information during the process
1375     if( first_frame_number < 0 && get_total_frames() > 1 )
1376         grabFrame();
1377 
1378     for(;;)
1379     {
1380         int64_t _frame_number_temp = std::max(_frame_number-delta, (int64_t)0);
1381         double sec = (double)_frame_number_temp / get_fps();
1382         int64_t time_stamp = ic->streams[video_stream]->start_time;
1383         double  time_base  = r2d(ic->streams[video_stream]->time_base);
1384         time_stamp += (int64_t)(sec / time_base + 0.5);
1385         if (get_total_frames() > 1) av_seek_frame(ic, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD);
1386         avcodec_flush_buffers(ic->streams[video_stream]->codec);
1387         if( _frame_number > 0 )
1388         {
1389             grabFrame();
1390 
1391             if( _frame_number > 1 )
1392             {
1393                 frame_number = dts_to_frame_number(picture_pts) - first_frame_number;
1394                 //printf("_frame_number = %d, frame_number = %d, delta = %d\n",
1395                 //       (int)_frame_number, (int)frame_number, delta);
1396 
1397                 if( frame_number < 0 || frame_number > _frame_number-1 )
1398                 {
1399                     if( _frame_number_temp == 0 || delta >= INT_MAX/4 )
1400                         break;
1401                     delta = delta < 16 ? delta*2 : delta*3/2;
1402                     continue;
1403                 }
1404                 while( frame_number < _frame_number-1 )
1405                 {
1406                     if(!grabFrame())
1407                         break;
1408                 }
1409                 frame_number++;
1410                 break;
1411             }
1412             else
1413             {
1414                 frame_number = 1;
1415                 break;
1416             }
1417         }
1418         else
1419         {
1420             frame_number = 0;
1421             break;
1422         }
1423     }
1424 }
1425 
seek(double sec)1426 void CvCapture_FFMPEG::seek(double sec)
1427 {
1428     seek((int64_t)(sec * get_fps() + 0.5));
1429 }
1430 
setProperty(int property_id,double value)1431 bool CvCapture_FFMPEG::setProperty( int property_id, double value )
1432 {
1433     if( !video_st ) return false;
1434 #if 0
1435     switch( property_id )
1436     {
1437     case CAP_PROP_POS_MSEC:
1438     case CAP_PROP_POS_FRAMES:
1439     case CAP_PROP_POS_AVI_RATIO:
1440         {
1441             switch( property_id )
1442             {
1443             case CAP_PROP_POS_FRAMES:
1444                 seek((int64_t)value);
1445                 break;
1446 
1447             case CAP_PROP_POS_MSEC:
1448                 seek(value/1000.0);
1449                 break;
1450 
1451             case CAP_PROP_POS_AVI_RATIO:
1452                 seek((int64_t)(value*ic->duration));
1453                 break;
1454             }
1455 
1456             picture_pts=(int64_t)value;
1457         }
1458         break;
1459     default:
1460         return false;
1461     }
1462 #endif
1463     return true;
1464 }
1465 
1466 
1467 ///////////////// FFMPEG CvVideoWriter implementation //////////////////////////
1468 static bool writer_type_loaded = false;
1469 
1470 class CvVideoWriter_FFMPEG: public octave_base_value
1471 {
1472   public:
1473     CvVideoWriter_FFMPEG ();
1474 
1475     bool open( const char* filename, int fourcc,
1476                double fps, int width, int height, bool isColor );
1477     void close();
1478     bool writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin );
1479 
1480     void init();
1481 
1482     AVOutputFormat  * fmt;
1483     AVFormatContext * oc;
1484     uint8_t         * outbuf;
1485     uint32_t          outbuf_size;
1486     FILE            * outfile;
1487     AVFrame         * picture;
1488     AVFrame         * input_picture;
1489     uint8_t         * picbuf;
1490     AVStream        * video_st;
1491     int               input_pix_fmt;
1492     unsigned char   * aligned_input;
1493     size_t            aligned_input_size;
1494     int               frame_width, frame_height;
1495     int               frame_idx;
1496     bool              ok;
1497     struct SwsContext *img_convert_ctx;
1498 
get_video_codec_name() const1499     const char* get_video_codec_name () const
1500       {
1501 #if LIBAVFORMAT_BUILD > 4628
1502         return _opencv_avcodec_get_name(video_st->codec->codec_id);
1503 #else
1504         return _opencv_avcodec_get_name(video_st->codec.codec_id);
1505 #endif
1506       }
1507 
is_constant(void) const1508     bool is_constant (void) const
1509     {
1510       return true;
1511     }
is_defined(void) const1512     bool is_defined (void) const
1513     {
1514       return true;
1515     }
1516 
1517     DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
1518 
print(std::ostream & os,bool pr_as_read_syntax=false)1519     void print (std::ostream & os, bool pr_as_read_syntax = false)
1520     {
1521       os << "CvVideoWriter_FFMPEG:" << std::endl;
1522       os << "  ok                      = " << ok << std::endl;
1523       os << "  frame_width             = " << frame_width << std::endl;
1524       os << "  frame_height            = " << frame_height << std::endl;
1525       os << "  frame_idx               = " << frame_idx << std::endl;
1526 
1527     // FIXME: add more properies
1528     }
1529 };
1530 
1531 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(CvVideoWriter_FFMPEG, "CvVideoWriter_FFMPEG", "CvVideoWriter_FFMPEG");
1532 
CvVideoWriter_FFMPEG()1533 CvVideoWriter_FFMPEG::CvVideoWriter_FFMPEG ()
1534   : octave_base_value () { init (); };
1535 
icvFFMPEGErrStr(int err)1536 static const char * icvFFMPEGErrStr(int err)
1537 {
1538 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
1539     switch(err) {
1540     case AVERROR_BSF_NOT_FOUND:
1541         return "Bitstream filter not found";
1542     case AVERROR_DECODER_NOT_FOUND:
1543         return "Decoder not found";
1544     case AVERROR_DEMUXER_NOT_FOUND:
1545         return "Demuxer not found";
1546     case AVERROR_ENCODER_NOT_FOUND:
1547         return "Encoder not found";
1548     case AVERROR_EOF:
1549         return "End of file";
1550     case AVERROR_EXIT:
1551         return "Immediate exit was requested; the called function should not be restarted";
1552     case AVERROR_FILTER_NOT_FOUND:
1553         return "Filter not found";
1554     case AVERROR_INVALIDDATA:
1555         return "Invalid data found when processing input";
1556     case AVERROR_MUXER_NOT_FOUND:
1557         return "Muxer not found";
1558     case AVERROR_OPTION_NOT_FOUND:
1559         return "Option not found";
1560     case AVERROR_PATCHWELCOME:
1561         return "Not yet implemented in FFmpeg, patches welcome";
1562     case AVERROR_PROTOCOL_NOT_FOUND:
1563         return "Protocol not found";
1564     case AVERROR_STREAM_NOT_FOUND:
1565         return "Stream not found";
1566     default:
1567         break;
1568     }
1569 #else
1570     switch(err) {
1571     case AVERROR_NUMEXPECTED:
1572         return "Incorrect filename syntax";
1573     case AVERROR_INVALIDDATA:
1574         return "Invalid data in header";
1575     case AVERROR_NOFMT:
1576         return "Unknown format";
1577     case AVERROR_IO:
1578         return "I/O error occurred";
1579     case AVERROR_NOMEM:
1580         return "Memory allocation error";
1581     default:
1582         break;
1583     }
1584 #endif
1585 
1586     return "Unspecified error";
1587 }
1588 
1589 /* function internal to FFMPEG (libavformat/riff.c) to lookup codec id by fourcc tag*/
1590 extern "C" {
1591     enum CV_CODEC_ID codec_get_bmp_id(unsigned int tag);
1592 }
1593 
init()1594 void CvVideoWriter_FFMPEG::init()
1595 {
1596     av_register_all();
1597     fmt = 0;
1598     oc = 0;
1599     outbuf = 0;
1600     outbuf_size = 0;
1601     outfile = 0;
1602     picture = 0;
1603     input_picture = 0;
1604     picbuf = 0;
1605     video_st = 0;
1606     input_pix_fmt = 0;
1607     aligned_input = NULL;
1608     aligned_input_size = 0;
1609     img_convert_ctx = 0;
1610     frame_width = frame_height = 0;
1611     frame_idx = 0;
1612     ok = false;
1613 }
1614 
1615 /**
1616  * the following function is a modified version of code
1617  * found in ffmpeg-0.4.9-pre1/output_example.c
1618  */
icv_alloc_picture_FFMPEG(int pix_fmt,int width,int height,bool alloc)1619 static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bool alloc)
1620 {
1621     AVFrame * picture;
1622     uint8_t * picture_buf = 0;
1623     int size;
1624 
1625 #if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \
1626     ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1))
1627     picture = av_frame_alloc();
1628 #else
1629     picture = avcodec_alloc_frame();
1630 #endif
1631     if (!picture)
1632         return NULL;
1633 
1634     picture->format = pix_fmt;
1635     picture->width = width;
1636     picture->height = height;
1637 
1638     size = _opencv_ffmpeg_av_image_get_buffer_size( (AVPixelFormat) pix_fmt, width, height);
1639     if(alloc){
1640         picture_buf = (uint8_t *) malloc(size);
1641         if (!picture_buf)
1642         {
1643             av_free(picture);
1644             return NULL;
1645         }
1646         _opencv_ffmpeg_av_image_fill_arrays(picture, picture_buf,
1647                        (AVPixelFormat) pix_fmt, width, height);
1648     }
1649 
1650     return picture;
1651 }
1652 
1653 /* add a video output stream to the container */
icv_add_video_stream_FFMPEG(AVFormatContext * oc,CV_CODEC_ID codec_id,int w,int h,int bitrate,double fps,int pixel_format)1654 static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
1655                                              CV_CODEC_ID codec_id,
1656                                              int w, int h, int bitrate,
1657                                              double fps, int pixel_format)
1658 {
1659     AVCodecContext *c;
1660     AVStream *st;
1661     int frame_rate, frame_rate_base;
1662     AVCodec *codec;
1663 
1664 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 10, 0)
1665     st = avformat_new_stream(oc, 0);
1666 #else
1667     st = av_new_stream(oc, 0);
1668 #endif
1669 
1670     if (!st) {
1671         CV_WARN("Could not allocate stream");
1672         return NULL;
1673     }
1674 
1675 #if LIBAVFORMAT_BUILD > 4628
1676     c = st->codec;
1677 #else
1678     c = &(st->codec);
1679 #endif
1680 
1681 #if LIBAVFORMAT_BUILD > 4621
1682     c->codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
1683 #else
1684     c->codec_id = oc->oformat->video_codec;
1685 #endif
1686 
1687     if(codec_id != CV_CODEC(CODEC_ID_NONE)){
1688         c->codec_id = codec_id;
1689     }
1690 
1691     //if(codec_tag) c->codec_tag=codec_tag;
1692     codec = avcodec_find_encoder(c->codec_id);
1693 
1694     c->codec_type = AVMEDIA_TYPE_VIDEO;
1695 
1696 #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54,25,0)
1697     // Set per-codec defaults
1698     AVCodecID c_id = c->codec_id;
1699     avcodec_get_context_defaults3(c, codec);
1700     // avcodec_get_context_defaults3 erases codec_id for some reason
1701     c->codec_id = c_id;
1702 #endif
1703 
1704     /* put sample parameters */
1705     int64_t lbit_rate = (int64_t)bitrate;
1706     lbit_rate += (bitrate / 2);
1707     lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX);
1708     c->bit_rate = lbit_rate;
1709 
1710     // took advice from
1711     // http://ffmpeg-users.933282.n4.nabble.com/warning-clipping-1-dct-coefficients-to-127-127-td934297.html
1712     c->qmin = 3;
1713 
1714     /* resolution must be a multiple of two */
1715     c->width = w;
1716     c->height = h;
1717 
1718     /* time base: this is the fundamental unit of time (in seconds) in terms
1719        of which frame timestamps are represented. for fixed-fps content,
1720        timebase should be 1/framerate and timestamp increments should be
1721        identically 1. */
1722     frame_rate=(int)(fps+0.5);
1723     frame_rate_base=1;
1724     while (fabs(((double)frame_rate/frame_rate_base) - fps) > 0.001){
1725         frame_rate_base*=10;
1726         frame_rate=(int)(fps*frame_rate_base + 0.5);
1727     }
1728 #if LIBAVFORMAT_BUILD > 4752
1729     c->time_base.den = frame_rate;
1730     c->time_base.num = frame_rate_base;
1731     /* adjust time base for supported framerates */
1732     if(codec && codec->supported_framerates){
1733         const AVRational *p= codec->supported_framerates;
1734         AVRational req = {frame_rate, frame_rate_base};
1735         const AVRational *best=NULL;
1736         AVRational best_error= {INT_MAX, 1};
1737         for(; p->den!=0; p++){
1738             AVRational error= av_sub_q(req, *p);
1739             if(error.num <0) error.num *= -1;
1740             if(av_cmp_q(error, best_error) < 0){
1741                 best_error= error;
1742                 best= p;
1743             }
1744         }
1745         if (best == NULL)
1746             return NULL;
1747         c->time_base.den= best->num;
1748         c->time_base.num= best->den;
1749     }
1750 #else
1751     c->frame_rate = frame_rate;
1752     c->frame_rate_base = frame_rate_base;
1753 #endif
1754 
1755     c->gop_size = 12; /* emit one intra frame every twelve frames at most */
1756     c->pix_fmt = (AVPixelFormat) pixel_format;
1757 
1758     if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO)) {
1759         c->max_b_frames = 2;
1760     }
1761     if (c->codec_id == CV_CODEC(CODEC_ID_MPEG1VIDEO) || c->codec_id == CV_CODEC(CODEC_ID_MSMPEG4V3)){
1762         /* needed to avoid using macroblocks in which some coeffs overflow
1763            this doesn't happen with normal video, it just happens here as the
1764            motion of the chroma plane doesn't match the luma plane */
1765         /* avoid FFMPEG warning 'clipping 1 dct coefficients...' */
1766         c->mb_decision=2;
1767     }
1768 
1769 #if LIBAVUTIL_BUILD > CALC_FFMPEG_VERSION(51,11,0)
1770     /* Some settings for libx264 encoding, restore dummy values for gop_size
1771      and qmin since they will be set to reasonable defaults by the libx264
1772      preset system. Also, use a crf encode with the default quality rating,
1773      this seems easier than finding an appropriate default bitrate. */
1774     if (c->codec_id == AV_CODEC_ID_H264) {
1775       c->gop_size = -1;
1776       c->qmin = -1;
1777       c->bit_rate = 0;
1778       if (c->priv_data)
1779           av_opt_set(c->priv_data,"crf","23", 0);
1780     }
1781 #endif
1782 
1783 #if LIBAVCODEC_VERSION_INT>0x000409
1784     // some formats want stream headers to be separate
1785     if(oc->oformat->flags & AVFMT_GLOBALHEADER)
1786     {
1787 #if LIBAVCODEC_BUILD > CALC_FFMPEG_VERSION(56, 35, 0)
1788         c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1789 #else
1790         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
1791 #endif
1792     }
1793 #endif
1794 
1795 #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(52, 42, 0)
1796 #if defined(_MSC_VER)
1797     AVRational avg_frame_rate = {frame_rate, frame_rate_base};
1798     st->avg_frame_rate = avg_frame_rate;
1799 #else
1800     st->avg_frame_rate = (AVRational){frame_rate, frame_rate_base};
1801 #endif
1802 #endif
1803 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 20, 0)
1804     st->time_base = c->time_base;
1805 #endif
1806 
1807     return st;
1808 }
1809 
1810 static const int OPENCV_NO_FRAMES_WRITTEN_CODE = 1000;
1811 
icv_av_write_frame_FFMPEG(AVFormatContext * oc,AVStream * video_st,uint8_t *,uint32_t,AVFrame * picture)1812 static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st,
1813 #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)
1814                                       uint8_t *, uint32_t,
1815 #else
1816                                       uint8_t * outbuf, uint32_t outbuf_size,
1817 #endif
1818                                       AVFrame * picture )
1819 {
1820 #if LIBAVFORMAT_BUILD > 4628
1821     AVCodecContext * c = video_st->codec;
1822 #else
1823     AVCodecContext * c = &(video_st->codec);
1824 #endif
1825     int ret = OPENCV_NO_FRAMES_WRITTEN_CODE;
1826 
1827 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)
1828     if (oc->oformat->flags & AVFMT_RAWPICTURE)
1829     {
1830         /* raw video case. The API will change slightly in the near
1831            futur for that */
1832         AVPacket pkt;
1833         av_init_packet(&pkt);
1834 
1835         pkt.flags |= PKT_FLAG_KEY;
1836         pkt.stream_index= video_st->index;
1837         pkt.data= (uint8_t *)picture;
1838         pkt.size= sizeof(AVPicture);
1839 
1840         ret = av_write_frame(oc, &pkt);
1841     }
1842     else
1843 #endif
1844     {
1845         /* encode the image */
1846         AVPacket pkt;
1847         av_init_packet(&pkt);
1848 #if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)
1849         int got_output = 0;
1850         pkt.data = NULL;
1851         pkt.size = 0;
1852         ret = avcodec_encode_video2(c, &pkt, picture, &got_output);
1853         if (ret < 0)
1854             ;
1855         else if (got_output) {
1856             if (pkt.pts != (int64_t)AV_NOPTS_VALUE)
1857                 pkt.pts = av_rescale_q(pkt.pts, c->time_base, video_st->time_base);
1858             if (pkt.dts != (int64_t)AV_NOPTS_VALUE)
1859                 pkt.dts = av_rescale_q(pkt.dts, c->time_base, video_st->time_base);
1860             if (pkt.duration)
1861                 pkt.duration = av_rescale_q(pkt.duration, c->time_base, video_st->time_base);
1862             pkt.stream_index= video_st->index;
1863             ret = av_write_frame(oc, &pkt);
1864             _opencv_ffmpeg_av_packet_unref(&pkt);
1865         }
1866         else
1867             ret = OPENCV_NO_FRAMES_WRITTEN_CODE;
1868 #else
1869         int out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
1870         /* if zero size, it means the image was buffered */
1871         if (out_size > 0) {
1872 #if LIBAVFORMAT_BUILD > 4752
1873             if(c->coded_frame->pts != (int64_t)AV_NOPTS_VALUE)
1874                 pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_st->time_base);
1875 #else
1876             pkt.pts = c->coded_frame->pts;
1877 #endif
1878             if(c->coded_frame->key_frame)
1879                 pkt.flags |= PKT_FLAG_KEY;
1880             pkt.stream_index= video_st->index;
1881             pkt.data= outbuf;
1882             pkt.size= out_size;
1883 
1884             /* write the compressed frame in the media file */
1885             ret = av_write_frame(oc, &pkt);
1886         }
1887 #endif
1888     }
1889     return ret;
1890 }
1891 
1892 /// write a frame with FFMPEG
writeFrame(const unsigned char * data,int step,int width,int height,int cn,int origin)1893 bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin )
1894 {
1895     // check parameters
1896     if (input_pix_fmt == AV_PIX_FMT_BGR24) {
1897         if (cn != 3) {
1898             return false;
1899         }
1900     }
1901     else if (input_pix_fmt == AV_PIX_FMT_GRAY8) {
1902         if (cn != 1) {
1903             return false;
1904         }
1905     }
1906     else {
1907         assert(false);
1908     }
1909 
1910     if( (width & -2) != frame_width || (height & -2) != frame_height || !data )
1911         return false;
1912     width = frame_width;
1913     height = frame_height;
1914 
1915     // typecast from opaque data type to implemented struct
1916 #if LIBAVFORMAT_BUILD > 4628
1917     AVCodecContext *c = video_st->codec;
1918 #else
1919     AVCodecContext *c = &(video_st->codec);
1920 #endif
1921 
1922     // FFmpeg contains SIMD optimizations which can sometimes read data past
1923     // the supplied input buffer.
1924     // Related info: https://trac.ffmpeg.org/ticket/6763
1925     // 1. To ensure that doesn't happen, we pad the step to a multiple of 32
1926     // (that's the minimal alignment for which Valgrind doesn't raise any warnings).
1927     // 2. (dataend - SIMD_SIZE) and (dataend + SIMD_SIZE) is from the same 4k page
1928     const int CV_STEP_ALIGNMENT = 32;
1929     const size_t CV_SIMD_SIZE = 32;
1930     const size_t CV_PAGE_MASK = ~(4096 - 1);
1931     const unsigned char* dataend = data + ((size_t)height * step);
1932     if (step % CV_STEP_ALIGNMENT != 0 ||
1933         (((size_t)dataend - CV_SIMD_SIZE) & CV_PAGE_MASK) != (((size_t)dataend + CV_SIMD_SIZE) & CV_PAGE_MASK))
1934     {
1935         int aligned_step = (step + CV_STEP_ALIGNMENT - 1) & ~(CV_STEP_ALIGNMENT - 1);
1936 
1937         size_t new_size = (aligned_step * height + CV_SIMD_SIZE);
1938 
1939         if (!aligned_input || aligned_input_size < new_size)
1940         {
1941             if (aligned_input)
1942                 av_freep(&aligned_input);
1943             aligned_input_size = new_size;
1944             aligned_input = (unsigned char*)av_mallocz(aligned_input_size);
1945         }
1946 
1947         if (origin == 1)
1948             for( int y = 0; y < height; y++ )
1949                 memcpy(aligned_input + y*aligned_step, data + (height-1-y)*step, step);
1950         else
1951             for( int y = 0; y < height; y++ )
1952                 memcpy(aligned_input + y*aligned_step, data + y*step, step);
1953 
1954         data = aligned_input;
1955         step = aligned_step;
1956     }
1957 
1958     if ( c->pix_fmt != input_pix_fmt ) {
1959         assert( input_picture );
1960         // let input_picture point to the raw data buffer of 'image'
1961         _opencv_ffmpeg_av_image_fill_arrays(input_picture, (uint8_t *) data,
1962                        (AVPixelFormat)input_pix_fmt, width, height);
1963         input_picture->linesize[0] = step;
1964 
1965         if( !img_convert_ctx )
1966         {
1967             img_convert_ctx = sws_getContext(width,
1968                                              height,
1969                                              (AVPixelFormat)input_pix_fmt,
1970                                              c->width,
1971                                              c->height,
1972                                              c->pix_fmt,
1973                                              SWS_BICUBIC,
1974                                              NULL, NULL, NULL);
1975             if( !img_convert_ctx )
1976                 return false;
1977         }
1978 
1979         if ( sws_scale(img_convert_ctx, input_picture->data,
1980                        input_picture->linesize, 0,
1981                        height,
1982                        picture->data, picture->linesize) < 0 )
1983             return false;
1984     }
1985     else{
1986         _opencv_ffmpeg_av_image_fill_arrays(picture, (uint8_t *) data,
1987                        (AVPixelFormat)input_pix_fmt, width, height);
1988         picture->linesize[0] = step;
1989     }
1990 
1991     picture->pts = frame_idx;
1992     bool ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, picture) >= 0;
1993     frame_idx++;
1994 
1995     return ret;
1996 }
1997 
1998 /// close video output stream and free associated memory
close()1999 void CvVideoWriter_FFMPEG::close()
2000 {
2001     // nothing to do if already released
2002     if ( !picture )
2003         return;
2004 
2005     /* no more frame to compress. The codec has a latency of a few
2006        frames if using B frames, so we get the last frames by
2007        passing the same picture again */
2008     // TODO -- do we need to account for latency here?
2009 
2010     /* write the trailer, if any */
2011     if(ok && oc)
2012     {
2013 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)
2014         if (!(oc->oformat->flags & AVFMT_RAWPICTURE))
2015 #endif
2016         {
2017             for(;;)
2018             {
2019                 int ret = icv_av_write_frame_FFMPEG( oc, video_st, outbuf, outbuf_size, NULL);
2020                 if( ret == OPENCV_NO_FRAMES_WRITTEN_CODE || ret < 0 )
2021                     break;
2022             }
2023         }
2024         av_write_trailer(oc);
2025     }
2026 
2027     if( img_convert_ctx )
2028     {
2029         sws_freeContext(img_convert_ctx);
2030         img_convert_ctx = 0;
2031     }
2032 
2033     // free pictures
2034 #if LIBAVFORMAT_BUILD > 4628
2035     if( video_st->codec->pix_fmt != input_pix_fmt)
2036 #else
2037     if( video_st->codec.pix_fmt != input_pix_fmt)
2038 #endif
2039     {
2040         if(picture->data[0])
2041             free(picture->data[0]);
2042         picture->data[0] = 0;
2043     }
2044     av_free(picture);
2045 
2046     if (input_picture)
2047         av_free(input_picture);
2048 
2049     /* close codec */
2050 #if LIBAVFORMAT_BUILD > 4628
2051     avcodec_close(video_st->codec);
2052 #else
2053     avcodec_close(&(video_st->codec));
2054 #endif
2055 
2056     av_free(outbuf);
2057 
2058     if (oc)
2059     {
2060         if (!(fmt->flags & AVFMT_NOFILE))
2061         {
2062             /* close the output file */
2063 
2064 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(123<<8)+0)
2065 #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0)
2066             url_fclose(oc->pb);
2067 #else
2068             url_fclose(&oc->pb);
2069 #endif
2070 #else
2071             avio_close(oc->pb);
2072 #endif
2073 
2074         }
2075 
2076         /* free the stream */
2077         avformat_free_context(oc);
2078     }
2079 
2080     av_freep(&aligned_input);
2081 
2082     init();
2083 }
2084 
2085 #define CV_PRINTABLE_CHAR(ch) ((ch) < 32 ? '?' : (ch))
2086 #define CV_TAG_TO_PRINTABLE_CHAR4(tag) CV_PRINTABLE_CHAR((tag) & 255), CV_PRINTABLE_CHAR(((tag) >> 8) & 255), CV_PRINTABLE_CHAR(((tag) >> 16) & 255), CV_PRINTABLE_CHAR(((tag) >> 24) & 255)
2087 
cv_ff_codec_tag_match(const AVCodecTag * tags,CV_CODEC_ID id,unsigned int tag)2088 static inline bool cv_ff_codec_tag_match(const AVCodecTag *tags, CV_CODEC_ID id, unsigned int tag)
2089 {
2090     while (tags->id != AV_CODEC_ID_NONE)
2091     {
2092         if (tags->id == id && tags->tag == tag)
2093             return true;
2094         tags++;
2095     }
2096     return false;
2097 }
2098 
cv_ff_codec_tag_list_match(const AVCodecTag * const * tags,CV_CODEC_ID id,unsigned int tag)2099 static inline bool cv_ff_codec_tag_list_match(const AVCodecTag *const *tags, CV_CODEC_ID id, unsigned int tag)
2100 {
2101     int i;
2102     for (i = 0; tags && tags[i]; i++) {
2103         bool res = cv_ff_codec_tag_match(tags[i], id, tag);
2104         if (res)
2105             return res;
2106     }
2107     return false;
2108 }
2109 
2110 
cv_ff_codec_tag_dump(const AVCodecTag * const * tags)2111 static inline void cv_ff_codec_tag_dump(const AVCodecTag *const *tags)
2112 {
2113     int i;
2114     for (i = 0; tags && tags[i]; i++) {
2115         const AVCodecTag * ptags = tags[i];
2116         while (ptags->id != AV_CODEC_ID_NONE)
2117         {
2118             unsigned int tag = ptags->tag;
2119             printf("fourcc tag 0x%08x/'%c%c%c%c' codec_id %04X\n", tag, CV_TAG_TO_PRINTABLE_CHAR4(tag), ptags->id);
2120             ptags++;
2121         }
2122     }
2123 }
2124 
2125 /// Create a video writer object that uses FFMPEG
open(const char * filename,int fourcc,double fps,int width,int height,bool is_color)2126 bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
2127                                  double fps, int width, int height, bool is_color )
2128 {
2129     InternalFFMpegRegister::init();
2130     CV_CODEC_ID codec_id = CV_CODEC(CODEC_ID_NONE);
2131     int codec_pix_fmt;
2132     double bitrate_scale = 1;
2133 
2134     close();
2135 
2136     // check arguments
2137     if( !filename )
2138         return false;
2139     if(fps <= 0)
2140         return false;
2141 
2142     // we allow frames of odd width or height, but in this case we truncate
2143     // the rightmost column/the bottom row. Probably, this should be handled more elegantly,
2144     // but some internal functions inside FFMPEG swscale require even width/height.
2145     width &= -2;
2146     height &= -2;
2147     if( width <= 0 || height <= 0 )
2148         return false;
2149 
2150     /* auto detect the output format from the name and fourcc code. */
2151 
2152 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
2153     fmt = av_guess_format(NULL, filename, NULL);
2154 #else
2155     fmt = guess_format(NULL, filename, NULL);
2156 #endif
2157 
2158     if (!fmt)
2159         return false;
2160 
2161     /* determine optimal pixel format */
2162     if (is_color) {
2163         input_pix_fmt = AV_PIX_FMT_BGR24;
2164     }
2165     else {
2166         input_pix_fmt = AV_PIX_FMT_GRAY8;
2167     }
2168 
2169     if (fourcc == -1)
2170     {
2171         fprintf(stderr,"OpenCV: FFMPEG: format %s / %s\n", fmt->name, fmt->long_name);
2172         cv_ff_codec_tag_dump(fmt->codec_tag);
2173         return false;
2174     }
2175 
2176     /* Lookup codec_id for given fourcc */
2177 #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0)
2178     if( (codec_id = codec_get_bmp_id( fourcc )) == CV_CODEC(CODEC_ID_NONE) )
2179         return false;
2180 #else
2181     if( (codec_id = av_codec_get_id(fmt->codec_tag, fourcc)) == CV_CODEC(CODEC_ID_NONE) )
2182     {
2183         const struct AVCodecTag * fallback_tags[] = {
2184 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(54, 1, 0)
2185 // APIchanges:
2186 // 2012-01-31 - dd6d3b0 - lavf 54.01.0
2187 //   Add avformat_get_riff_video_tags() and avformat_get_riff_audio_tags().
2188                 avformat_get_riff_video_tags(),
2189 #endif
2190 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 25, 100) && defined LIBAVFORMAT_VERSION_MICRO && LIBAVFORMAT_VERSION_MICRO >= 100
2191 // APIchanges: ffmpeg only
2192 // 2014-01-19 - 1a193c4 - lavf 55.25.100 - avformat.h
2193 //   Add avformat_get_mov_video_tags() and avformat_get_mov_audio_tags().
2194                 avformat_get_mov_video_tags(),
2195 #endif
2196                 codec_bmp_tags, // fallback for avformat < 54.1
2197                 NULL };
2198         if( (codec_id = av_codec_get_id(fallback_tags, fourcc)) == CV_CODEC(CODEC_ID_NONE) )
2199         {
2200             fflush(stdout);
2201             fprintf(stderr, "OpenCV: FFMPEG: tag 0x%08x/'%c%c%c%c' is not found (format '%s / %s')'\n",
2202                     fourcc, CV_TAG_TO_PRINTABLE_CHAR4(fourcc),
2203                     fmt->name, fmt->long_name);
2204             return false;
2205         }
2206     }
2207 
2208 
2209     // validate tag
2210     if (cv_ff_codec_tag_list_match(fmt->codec_tag, codec_id, fourcc) == false)
2211     {
2212         fflush(stdout);
2213         fprintf(stderr, "OpenCV: FFMPEG: tag 0x%08x/'%c%c%c%c' is not supported with codec id %d and format '%s / %s'\n",
2214                 fourcc, CV_TAG_TO_PRINTABLE_CHAR4(fourcc),
2215                 codec_id, fmt->name, fmt->long_name);
2216         int supported_tag;
2217         if( (supported_tag = av_codec_get_tag(fmt->codec_tag, codec_id)) != 0 )
2218         {
2219             fprintf(stderr, "OpenCV: FFMPEG: fallback to use tag 0x%08x/'%c%c%c%c'\n",
2220                     supported_tag, CV_TAG_TO_PRINTABLE_CHAR4(supported_tag));
2221             fourcc = supported_tag;
2222         }
2223     }
2224 #endif
2225 
2226     // alloc memory for context
2227 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
2228     oc = avformat_alloc_context();
2229 #else
2230     oc = av_alloc_format_context();
2231 #endif
2232     assert (oc);
2233 
2234     /* set file name */
2235     oc->oformat = fmt;
2236     snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
2237 
2238     /* set some options */
2239     oc->max_delay = (int)(0.7*AV_TIME_BASE);  /* This reduces buffer underrun warnings with MPEG */
2240 
2241     // set a few optimal pixel formats for lossless codecs of interest..
2242     switch (codec_id) {
2243 #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0)
2244     case CV_CODEC(CODEC_ID_JPEGLS):
2245         // BGR24 or GRAY8 depending on is_color...
2246         // supported: bgr24 rgb24 gray gray16le
2247         // as of version 3.4.1
2248         codec_pix_fmt = input_pix_fmt;
2249         break;
2250 #endif
2251     case CV_CODEC(CODEC_ID_HUFFYUV):
2252         // supported: yuv422p rgb24 bgra
2253         // as of version 3.4.1
2254         switch(input_pix_fmt)
2255         {
2256             case AV_PIX_FMT_RGB24:
2257             case AV_PIX_FMT_BGRA:
2258                 codec_pix_fmt = input_pix_fmt;
2259                 break;
2260             case AV_PIX_FMT_BGR24:
2261                 codec_pix_fmt = AV_PIX_FMT_RGB24;
2262                 break;
2263             default:
2264                 codec_pix_fmt = AV_PIX_FMT_YUV422P;
2265                 break;
2266         }
2267         break;
2268     case CV_CODEC(CODEC_ID_PNG):
2269         // supported: rgb24 rgba rgb48be rgba64be pal8 gray ya8 gray16be ya16be monob
2270         // as of version 3.4.1
2271         switch(input_pix_fmt)
2272         {
2273             case AV_PIX_FMT_GRAY8:
2274             case AV_PIX_FMT_GRAY16BE:
2275             case AV_PIX_FMT_RGB24:
2276             case AV_PIX_FMT_BGRA:
2277                 codec_pix_fmt = input_pix_fmt;
2278                 break;
2279             case AV_PIX_FMT_GRAY16LE:
2280                 codec_pix_fmt = AV_PIX_FMT_GRAY16BE;
2281                 break;
2282             case AV_PIX_FMT_BGR24:
2283                 codec_pix_fmt = AV_PIX_FMT_RGB24;
2284                 break;
2285             default:
2286                 codec_pix_fmt = AV_PIX_FMT_YUV422P;
2287                 break;
2288         }
2289         break;
2290     case CV_CODEC(CODEC_ID_FFV1):
2291         // supported: MANY
2292         // as of version 3.4.1
2293         switch(input_pix_fmt)
2294         {
2295             case AV_PIX_FMT_GRAY8:
2296             case AV_PIX_FMT_GRAY16LE:
2297 #ifdef AV_PIX_FMT_BGR0
2298             case AV_PIX_FMT_BGR0:
2299 #endif
2300             case AV_PIX_FMT_BGRA:
2301                 codec_pix_fmt = input_pix_fmt;
2302                 break;
2303             case AV_PIX_FMT_GRAY16BE:
2304                 codec_pix_fmt = AV_PIX_FMT_GRAY16LE;
2305                 break;
2306             case AV_PIX_FMT_BGR24:
2307             case AV_PIX_FMT_RGB24:
2308 #ifdef AV_PIX_FMT_BGR0
2309                 codec_pix_fmt = AV_PIX_FMT_BGR0;
2310 #else
2311                 codec_pix_fmt = AV_PIX_FMT_BGRA;
2312 #endif
2313                 break;
2314             default:
2315                 codec_pix_fmt = AV_PIX_FMT_YUV422P;
2316                 break;
2317         }
2318         break;
2319     case CV_CODEC(CODEC_ID_MJPEG):
2320     case CV_CODEC(CODEC_ID_LJPEG):
2321         codec_pix_fmt = AV_PIX_FMT_YUVJ420P;
2322         bitrate_scale = 3;
2323         break;
2324     case CV_CODEC(CODEC_ID_RAWVIDEO):
2325         // RGBA is the only RGB fourcc supported by AVI and MKV format
2326         if(fourcc == CV_FOURCC('R','G','B','A'))
2327         {
2328             codec_pix_fmt = AV_PIX_FMT_RGBA;
2329         }
2330         else
2331         {
2332             switch(input_pix_fmt)
2333             {
2334                 case AV_PIX_FMT_GRAY8:
2335                 case AV_PIX_FMT_GRAY16LE:
2336                 case AV_PIX_FMT_GRAY16BE:
2337                     codec_pix_fmt = input_pix_fmt;
2338                     break;
2339                 default:
2340                     codec_pix_fmt = AV_PIX_FMT_YUV420P;
2341                     break;
2342             }
2343         }
2344         break;
2345     default:
2346         // good for lossy formats, MPEG, etc.
2347         codec_pix_fmt = AV_PIX_FMT_YUV420P;
2348         break;
2349     }
2350 
2351     double bitrate = MIN(bitrate_scale*fps*width*height, (double)INT_MAX/2);
2352 
2353     // TODO -- safe to ignore output audio stream?
2354     video_st = icv_add_video_stream_FFMPEG(oc, codec_id,
2355                                            width, height, (int)(bitrate + 0.5),
2356                                            fps, codec_pix_fmt);
2357 
2358     /* set the output parameters (must be done even if no
2359    parameters). */
2360 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
2361     if (av_set_parameters(oc, NULL) < 0) {
2362         return false;
2363     }
2364 #endif
2365 
2366 #if 0
2367 #if FF_API_DUMP_FORMAT
2368     dump_format(oc, 0, filename, 1);
2369 #else
2370     av_dump_format(oc, 0, filename, 1);
2371 #endif
2372 #endif
2373 
2374     /* now that all the parameters are set, we can open the audio and
2375      video codecs and allocate the necessary encode buffers */
2376     if (!video_st){
2377         return false;
2378     }
2379 
2380     AVCodec *codec;
2381     AVCodecContext *c;
2382 
2383 #if LIBAVFORMAT_BUILD > 4628
2384     c = (video_st->codec);
2385 #else
2386     c = &(video_st->codec);
2387 #endif
2388 
2389     c->codec_tag = fourcc;
2390     /* find the video encoder */
2391     codec = avcodec_find_encoder(c->codec_id);
2392     if (!codec) {
2393         fprintf(stderr, "Could not find encoder for codec id %d: %s\n", c->codec_id, icvFFMPEGErrStr(
2394         #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
2395                 AVERROR_ENCODER_NOT_FOUND
2396         #else
2397                 -1
2398         #endif
2399                 ));
2400         return false;
2401     }
2402 
2403     int64_t lbit_rate = (int64_t)c->bit_rate;
2404     lbit_rate += (bitrate / 2);
2405     lbit_rate = std::min(lbit_rate, (int64_t)INT_MAX);
2406     c->bit_rate_tolerance = (int)lbit_rate;
2407     c->bit_rate = (int)lbit_rate;
2408 
2409     /* open the codec */
2410     if ((global_err=
2411 #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0)
2412          avcodec_open2(c, codec, NULL)
2413 #else
2414          avcodec_open(c, codec)
2415 #endif
2416          ) < 0) {
2417         fprintf(stderr, "Could not open codec '%s': %s\n", codec->name, icvFFMPEGErrStr(global_err));
2418         return false;
2419     }
2420 
2421     outbuf = NULL;
2422 
2423 
2424 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)
2425     if (!(oc->oformat->flags & AVFMT_RAWPICTURE))
2426 #endif
2427     {
2428         /* allocate output buffer */
2429         /* assume we will never get codec output with more than 4 bytes per pixel... */
2430         outbuf_size = width*height*4;
2431         outbuf = (uint8_t *) av_malloc(outbuf_size);
2432     }
2433 
2434     bool need_color_convert;
2435     need_color_convert = (c->pix_fmt != input_pix_fmt);
2436 
2437     /* allocate the encoded raw picture */
2438     picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert);
2439     if (!picture) {
2440         return false;
2441     }
2442 
2443     /* if the output format is not our input format, then a temporary
2444    picture of the input format is needed too. It is then converted
2445    to the required output format */
2446     input_picture = NULL;
2447     if ( need_color_convert ) {
2448         input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false);
2449         if (!input_picture) {
2450             return false;
2451         }
2452     }
2453 
2454     /* open the output file, if needed */
2455     if (!(fmt->flags & AVFMT_NOFILE)) {
2456 #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0)
2457         if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)
2458 #else
2459             if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0)
2460 #endif
2461             {
2462             return false;
2463         }
2464     }
2465 
2466 #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0)
2467     /* write the stream header, if any */
2468     global_err=avformat_write_header(oc, NULL);
2469 #else
2470     global_err=av_write_header( oc );
2471 #endif
2472 
2473     if(global_err < 0)
2474     {
2475         close();
2476         remove(filename);
2477         return false;
2478     }
2479     frame_width = width;
2480     frame_height = height;
2481     frame_idx = 0;
2482     ok = true;
2483 
2484     return true;
2485 }
2486 
2487 
2488 
cvCreateFileCapture_FFMPEG(const char * filename)2489 CvCapture_FFMPEG* cvCreateFileCapture_FFMPEG( const char* filename )
2490 {
2491     CvCapture_FFMPEG* capture = (CvCapture_FFMPEG*)malloc(sizeof(*capture));
2492     if (!capture)
2493         return 0;
2494     capture->init();
2495     if( capture->open( filename ))
2496         return capture;
2497 
2498     capture->close();
2499     free(capture);
2500     return 0;
2501 }
2502 
2503 
cvReleaseCapture_FFMPEG(CvCapture_FFMPEG ** capture)2504 void cvReleaseCapture_FFMPEG(CvCapture_FFMPEG** capture)
2505 {
2506     if( capture && *capture )
2507     {
2508         (*capture)->close();
2509         free(*capture);
2510         *capture = 0;
2511     }
2512 }
2513 
cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG * capture,int prop_id,double value)2514 int cvSetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id, double value)
2515 {
2516     return capture->setProperty(prop_id, value);
2517 }
2518 
2519 //~ double cvGetCaptureProperty_FFMPEG(CvCapture_FFMPEG* capture, int prop_id)
2520 //~ {
2521     //~ return capture->getProperty(prop_id);
2522 //~ }
2523 
cvGrabFrame_FFMPEG(CvCapture_FFMPEG * capture)2524 int cvGrabFrame_FFMPEG(CvCapture_FFMPEG* capture)
2525 {
2526     return capture->grabFrame();
2527 }
2528 
cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG * capture,unsigned char ** data,int * step,int * width,int * height,int * cn)2529 int cvRetrieveFrame_FFMPEG(CvCapture_FFMPEG* capture, unsigned char** data, int* step, int* width, int* height, int* cn)
2530 {
2531     return capture->retrieveFrame(0, data, step, width, height, cn);
2532 }
2533 
cvCreateVideoWriter_FFMPEG(const char * filename,int fourcc,double fps,int width,int height,int isColor)2534 CvVideoWriter_FFMPEG* cvCreateVideoWriter_FFMPEG( const char* filename, int fourcc, double fps,
2535                                                   int width, int height, int isColor )
2536 {
2537     CvVideoWriter_FFMPEG* writer = (CvVideoWriter_FFMPEG*)malloc(sizeof(*writer));
2538     if (!writer)
2539         return 0;
2540     writer->init();
2541     if( writer->open( filename, fourcc, fps, width, height, isColor != 0 ))
2542         return writer;
2543     writer->close();
2544     free(writer);
2545     return 0;
2546 }
2547 
cvReleaseVideoWriter_FFMPEG(CvVideoWriter_FFMPEG ** writer)2548 void cvReleaseVideoWriter_FFMPEG( CvVideoWriter_FFMPEG** writer )
2549 {
2550     if( writer && *writer )
2551     {
2552         (*writer)->close();
2553         free(*writer);
2554         *writer = 0;
2555     }
2556 }
2557 
2558 
cvWriteFrame_FFMPEG(CvVideoWriter_FFMPEG * writer,const unsigned char * data,int step,int width,int height,int cn,int origin)2559 int cvWriteFrame_FFMPEG( CvVideoWriter_FFMPEG* writer,
2560                          const unsigned char* data, int step,
2561                          int width, int height, int cn, int origin)
2562 {
2563     return writer->writeFrame(data, step, width, height, cn, origin);
2564 }
2565