Various markup and tweaks.
[dcpomatic.git] / src / lib / ffmpeg_decoder.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file  src/ffmpeg_decoder.cc
21  *  @brief A decoder using FFmpeg to decode content.
22  */
23
24 #include <stdexcept>
25 #include <vector>
26 #include <sstream>
27 #include <iomanip>
28 #include <iostream>
29 #include <stdint.h>
30 #include <boost/lexical_cast.hpp>
31 extern "C" {
32 #include <tiffio.h>
33 #include <libavcodec/avcodec.h>
34 #include <libavformat/avformat.h>
35 #include <libswscale/swscale.h>
36 #include <libpostproc/postprocess.h>
37 }
38 #include <sndfile.h>
39 #include "film.h"
40 #include "format.h"
41 #include "transcoder.h"
42 #include "job.h"
43 #include "filter.h"
44 #include "options.h"
45 #include "exceptions.h"
46 #include "image.h"
47 #include "util.h"
48 #include "log.h"
49 #include "ffmpeg_decoder.h"
50 #include "filter_graph.h"
51 #include "subtitle.h"
52
53 #include "i18n.h"
54
55 using std::cout;
56 using std::string;
57 using std::vector;
58 using std::stringstream;
59 using std::list;
60 using boost::shared_ptr;
61 using boost::optional;
62 using boost::dynamic_pointer_cast;
63 using libdcp::Size;
64
65 FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, DecodeOptions o)
66         : Decoder (f, o)
67         , VideoDecoder (f, o)
68         , AudioDecoder (f, o)
69         , _format_context (0)
70         , _video_stream (-1)
71         , _frame (0)
72         , _video_codec_context (0)
73         , _video_codec (0)
74         , _audio_codec_context (0)
75         , _audio_codec (0)
76         , _subtitle_codec_context (0)
77         , _subtitle_codec (0)
78 {
79         setup_general ();
80         setup_video ();
81         setup_audio ();
82         setup_subtitle ();
83
84         if (!o.video_sync) {
85                 _first_video = 0;
86         }
87 }
88
89 FFmpegDecoder::~FFmpegDecoder ()
90 {
91         if (_audio_codec_context) {
92                 avcodec_close (_audio_codec_context);
93         }
94         
95         if (_video_codec_context) {
96                 avcodec_close (_video_codec_context);
97         }
98
99         if (_subtitle_codec_context) {
100                 avcodec_close (_subtitle_codec_context);
101         }
102
103         av_free (_frame);
104         
105         avformat_close_input (&_format_context);
106 }       
107
108 void
109 FFmpegDecoder::setup_general ()
110 {
111         av_register_all ();
112
113         if (avformat_open_input (&_format_context, _film->content_path().c_str(), 0, 0) < 0) {
114                 throw OpenFileError (_film->content_path ());
115         }
116
117         if (avformat_find_stream_info (_format_context, 0) < 0) {
118                 throw DecodeError (_("could not find stream information"));
119         }
120
121         /* Find video, audio and subtitle streams and choose the first of each */
122
123         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
124                 AVStream* s = _format_context->streams[i];
125                 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
126                         _video_stream = i;
127                 } else if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
128
129                         /* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
130                            so bodge it here.  No idea why we should have to do this.
131                         */
132
133                         if (s->codec->channel_layout == 0) {
134                                 s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
135                         }
136                         
137                         _audio_streams.push_back (
138                                 shared_ptr<AudioStream> (
139                                         new FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channel_layout)
140                                         )
141                                 );
142                         
143                 } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
144                         _subtitle_streams.push_back (
145                                 shared_ptr<SubtitleStream> (
146                                         new SubtitleStream (stream_name (s), i)
147                                         )
148                                 );
149                 }
150         }
151
152         if (_video_stream < 0) {
153                 throw DecodeError (N_("could not find video stream"));
154         }
155
156         _frame = avcodec_alloc_frame ();
157         if (_frame == 0) {
158                 throw DecodeError (N_("could not allocate frame"));
159         }
160 }
161
162 void
163 FFmpegDecoder::setup_video ()
164 {
165         _video_codec_context = _format_context->streams[_video_stream]->codec;
166         _video_codec = avcodec_find_decoder (_video_codec_context->codec_id);
167
168         if (_video_codec == 0) {
169                 throw DecodeError (_("could not find video decoder"));
170         }
171
172         if (avcodec_open2 (_video_codec_context, _video_codec, 0) < 0) {
173                 throw DecodeError (N_("could not open video decoder"));
174         }
175 }
176
177 void
178 FFmpegDecoder::setup_audio ()
179 {
180         if (!_audio_stream) {
181                 return;
182         }
183
184         shared_ptr<FFmpegAudioStream> ffa = dynamic_pointer_cast<FFmpegAudioStream> (_audio_stream);
185         assert (ffa);
186         
187         _audio_codec_context = _format_context->streams[ffa->id()]->codec;
188         _audio_codec = avcodec_find_decoder (_audio_codec_context->codec_id);
189
190         if (_audio_codec == 0) {
191                 throw DecodeError (_("could not find audio decoder"));
192         }
193
194         if (avcodec_open2 (_audio_codec_context, _audio_codec, 0) < 0) {
195                 throw DecodeError (N_("could not open audio decoder"));
196         }
197 }
198
199 void
200 FFmpegDecoder::setup_subtitle ()
201 {
202         if (!_subtitle_stream) {
203                 return;
204         }
205
206         _subtitle_codec_context = _format_context->streams[_subtitle_stream->id()]->codec;
207         _subtitle_codec = avcodec_find_decoder (_subtitle_codec_context->codec_id);
208
209         if (_subtitle_codec == 0) {
210                 throw DecodeError (_("could not find subtitle decoder"));
211         }
212         
213         if (avcodec_open2 (_subtitle_codec_context, _subtitle_codec, 0) < 0) {
214                 throw DecodeError (N_("could not open subtitle decoder"));
215         }
216 }
217
218
219 bool
220 FFmpegDecoder::pass ()
221 {
222         int r = av_read_frame (_format_context, &_packet);
223         
224         if (r < 0) {
225                 if (r != AVERROR_EOF) {
226                         /* Maybe we should fail here, but for now we'll just finish off instead */
227                         char buf[256];
228                         av_strerror (r, buf, sizeof(buf));
229                         _film->log()->log (String::compose (N_("error on av_read_frame (%1) (%2)"), buf, r));
230                 }
231                 
232                 /* Get any remaining frames */
233                 
234                 _packet.data = 0;
235                 _packet.size = 0;
236
237                 /* XXX: should we reset _packet.data and size after each *_decode_* call? */
238
239                 int frame_finished;
240
241                 while (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
242                         filter_and_emit_video (_frame);
243                 }
244
245                 if (_audio_stream && _opt.decode_audio) {
246                         while (avcodec_decode_audio4 (_audio_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
247                                 int const data_size = av_samples_get_buffer_size (
248                                         0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1
249                                         );
250
251                                 assert (_audio_codec_context->channels == _film->audio_channels());
252                                 Audio (deinterleave_audio (_frame->data, data_size));
253                         }
254                 }
255
256                 return true;
257         }
258
259         avcodec_get_frame_defaults (_frame);
260
261         shared_ptr<FFmpegAudioStream> ffa = dynamic_pointer_cast<FFmpegAudioStream> (_audio_stream);
262
263         if (_packet.stream_index == _video_stream) {
264
265                 int frame_finished;
266                 int const r = avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet);
267                 if (r >= 0 && frame_finished) {
268
269                         if (r != _packet.size) {
270                                 _film->log()->log (String::compose (N_("Used only %1 bytes of %2 in packet"), r, _packet.size));
271                         }
272
273                         if (_opt.video_sync) {
274                                 out_with_sync ();
275                         } else {
276                                 filter_and_emit_video (_frame);
277                         }
278                 }
279
280         } else if (ffa && _packet.stream_index == ffa->id() && _opt.decode_audio) {
281
282                 int frame_finished;
283                 if (avcodec_decode_audio4 (_audio_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
284
285                         /* Where we are in the source, in seconds */
286                         double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
287                                 * av_frame_get_best_effort_timestamp(_frame);
288
289                         /* We only decode audio if we've had our first video packet through, and if it
290                            was before this packet.  Until then audio is thrown away.
291                         */
292                                 
293                         if (_first_video && _first_video.get() <= source_pts_seconds) {
294
295                                 if (!_first_audio) {
296                                         _first_audio = source_pts_seconds;
297                                         
298                                         /* This is our first audio frame, and if we've arrived here we must have had our
299                                            first video frame.  Push some silence to make up any gap between our first
300                                            video frame and our first audio.
301                                         */
302                         
303                                         /* frames of silence that we must push */
304                                         int const s = rint ((_first_audio.get() - _first_video.get()) * ffa->sample_rate ());
305                                         
306                                         _film->log()->log (
307                                                 String::compose (
308                                                         N_("First video at %1, first audio at %2, pushing %3 audio frames of silence for %4 channels (%5 bytes per sample)"),
309                                                         _first_video.get(), _first_audio.get(), s, ffa->channels(), bytes_per_audio_sample()
310                                                         )
311                                                 );
312                                         
313                                         if (s) {
314                                                 shared_ptr<AudioBuffers> audio (new AudioBuffers (ffa->channels(), s));
315                                                 audio->make_silent ();
316                                                 Audio (audio);
317                                         }
318                                 }
319
320                                 int const data_size = av_samples_get_buffer_size (
321                                         0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1
322                                         );
323                                 
324                                 assert (_audio_codec_context->channels == _film->audio_channels());
325                                 Audio (deinterleave_audio (_frame->data, data_size));
326                         }
327                 }
328                         
329         } else if (_subtitle_stream && _packet.stream_index == _subtitle_stream->id() && _opt.decode_subtitles && _first_video) {
330
331                 int got_subtitle;
332                 AVSubtitle sub;
333                 if (avcodec_decode_subtitle2 (_subtitle_codec_context, &sub, &got_subtitle, &_packet) && got_subtitle) {
334                         /* Sometimes we get an empty AVSubtitle, which is used by some codecs to
335                            indicate that the previous subtitle should stop.
336                         */
337                         if (sub.num_rects > 0) {
338                                 shared_ptr<TimedSubtitle> ts;
339                                 try {
340                                         emit_subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub)));
341                                 } catch (...) {
342                                         /* some problem with the subtitle; we probably didn't understand it */
343                                 }
344                         } else {
345                                 emit_subtitle (shared_ptr<TimedSubtitle> ());
346                         }
347                         avsubtitle_free (&sub);
348                 }
349         }
350         
351         av_free_packet (&_packet);
352         return false;
353 }
354
355 /** @param data pointer to array of pointers to buffers.
356  *  Only the first buffer will be used for non-planar data, otherwise there will be one per channel.
357  */
358 shared_ptr<AudioBuffers>
359 FFmpegDecoder::deinterleave_audio (uint8_t** data, int size)
360 {
361         assert (_film->audio_channels());
362         assert (bytes_per_audio_sample());
363
364         shared_ptr<FFmpegAudioStream> ffa = dynamic_pointer_cast<FFmpegAudioStream> (_audio_stream);
365         assert (ffa);
366         
367         /* Deinterleave and convert to float */
368
369         assert ((size % (bytes_per_audio_sample() * ffa->channels())) == 0);
370
371         int const total_samples = size / bytes_per_audio_sample();
372         int const frames = total_samples / _film->audio_channels();
373         shared_ptr<AudioBuffers> audio (new AudioBuffers (ffa->channels(), frames));
374
375         switch (audio_sample_format()) {
376         case AV_SAMPLE_FMT_S16:
377         {
378                 int16_t* p = reinterpret_cast<int16_t *> (data[0]);
379                 int sample = 0;
380                 int channel = 0;
381                 for (int i = 0; i < total_samples; ++i) {
382                         audio->data(channel)[sample] = float(*p++) / (1 << 15);
383
384                         ++channel;
385                         if (channel == _film->audio_channels()) {
386                                 channel = 0;
387                                 ++sample;
388                         }
389                 }
390         }
391         break;
392
393         case AV_SAMPLE_FMT_S16P:
394         {
395                 int16_t** p = reinterpret_cast<int16_t **> (data);
396                 for (int i = 0; i < _film->audio_channels(); ++i) {
397                         for (int j = 0; j < frames; ++j) {
398                                 audio->data(i)[j] = static_cast<float>(p[i][j]) / (1 << 15);
399                         }
400                 }
401         }
402         break;
403         
404         case AV_SAMPLE_FMT_S32:
405         {
406                 int32_t* p = reinterpret_cast<int32_t *> (data[0]);
407                 int sample = 0;
408                 int channel = 0;
409                 for (int i = 0; i < total_samples; ++i) {
410                         audio->data(channel)[sample] = static_cast<float>(*p++) / (1 << 31);
411
412                         ++channel;
413                         if (channel == _film->audio_channels()) {
414                                 channel = 0;
415                                 ++sample;
416                         }
417                 }
418         }
419         break;
420
421         case AV_SAMPLE_FMT_FLT:
422         {
423                 float* p = reinterpret_cast<float*> (data[0]);
424                 int sample = 0;
425                 int channel = 0;
426                 for (int i = 0; i < total_samples; ++i) {
427                         audio->data(channel)[sample] = *p++;
428
429                         ++channel;
430                         if (channel == _film->audio_channels()) {
431                                 channel = 0;
432                                 ++sample;
433                         }
434                 }
435         }
436         break;
437                 
438         case AV_SAMPLE_FMT_FLTP:
439         {
440                 float** p = reinterpret_cast<float**> (data);
441                 for (int i = 0; i < _film->audio_channels(); ++i) {
442                         memcpy (audio->data(i), p[i], frames * sizeof(float));
443                 }
444         }
445         break;
446
447         default:
448                 throw DecodeError (String::compose (_("Unrecognised audio sample format (%1)"), static_cast<int> (audio_sample_format())));
449         }
450
451         return audio;
452 }
453
454 float
455 FFmpegDecoder::frames_per_second () const
456 {
457         AVStream* s = _format_context->streams[_video_stream];
458
459         if (s->avg_frame_rate.num && s->avg_frame_rate.den) {
460                 return av_q2d (s->avg_frame_rate);
461         }
462
463         return av_q2d (s->r_frame_rate);
464 }
465
466 AVSampleFormat
467 FFmpegDecoder::audio_sample_format () const
468 {
469         if (_audio_codec_context == 0) {
470                 return (AVSampleFormat) 0;
471         }
472         
473         return _audio_codec_context->sample_fmt;
474 }
475
476 libdcp::Size
477 FFmpegDecoder::native_size () const
478 {
479         return libdcp::Size (_video_codec_context->width, _video_codec_context->height);
480 }
481
482 PixelFormat
483 FFmpegDecoder::pixel_format () const
484 {
485         return _video_codec_context->pix_fmt;
486 }
487
488 int
489 FFmpegDecoder::time_base_numerator () const
490 {
491         return _video_codec_context->time_base.num;
492 }
493
494 int
495 FFmpegDecoder::time_base_denominator () const
496 {
497         return _video_codec_context->time_base.den;
498 }
499
500 int
501 FFmpegDecoder::sample_aspect_ratio_numerator () const
502 {
503         return _video_codec_context->sample_aspect_ratio.num;
504 }
505
506 int
507 FFmpegDecoder::sample_aspect_ratio_denominator () const
508 {
509         return _video_codec_context->sample_aspect_ratio.den;
510 }
511
512 string
513 FFmpegDecoder::stream_name (AVStream* s) const
514 {
515         stringstream n;
516         
517         AVDictionaryEntry const * lang = av_dict_get (s->metadata, N_("language"), 0, 0);
518         if (lang) {
519                 n << lang->value;
520         }
521         
522         AVDictionaryEntry const * title = av_dict_get (s->metadata, N_("title"), 0, 0);
523         if (title) {
524                 if (!n.str().empty()) {
525                         n << N_(" ");
526                 }
527                 n << title->value;
528         }
529
530         if (n.str().empty()) {
531                 n << N_("unknown");
532         }
533
534         return n.str ();
535 }
536
537 int
538 FFmpegDecoder::bytes_per_audio_sample () const
539 {
540         return av_get_bytes_per_sample (audio_sample_format ());
541 }
542
543 void
544 FFmpegDecoder::set_audio_stream (shared_ptr<AudioStream> s)
545 {
546         AudioDecoder::set_audio_stream (s);
547         setup_audio ();
548 }
549
550 void
551 FFmpegDecoder::set_subtitle_stream (shared_ptr<SubtitleStream> s)
552 {
553         VideoDecoder::set_subtitle_stream (s);
554         setup_subtitle ();
555         OutputChanged ();
556 }
557
558 void
559 FFmpegDecoder::filter_and_emit_video (AVFrame* frame)
560 {
561         boost::mutex::scoped_lock lm (_filter_graphs_mutex);
562         
563         shared_ptr<FilterGraph> graph;
564
565         list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
566         while (i != _filter_graphs.end() && !(*i)->can_process (libdcp::Size (frame->width, frame->height), (AVPixelFormat) frame->format)) {
567                 ++i;
568         }
569
570         if (i == _filter_graphs.end ()) {
571                 graph.reset (new FilterGraph (_film, this, libdcp::Size (frame->width, frame->height), (AVPixelFormat) frame->format));
572                 _filter_graphs.push_back (graph);
573                 _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), frame->width, frame->height, frame->format));
574         } else {
575                 graph = *i;
576         }
577
578         list<shared_ptr<Image> > images = graph->process (frame);
579
580         for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
581                 emit_video (*i, frame_time ());
582         }
583 }
584
585 bool
586 FFmpegDecoder::seek (double p)
587 {
588         return do_seek (p, false);
589 }
590
591 bool
592 FFmpegDecoder::seek_to_last ()
593 {
594         /* This AVSEEK_FLAG_BACKWARD in do_seek is a bit of a hack; without it, if we ask for a seek to the same place as last time
595            (used when we change decoder parameters and want to re-fetch the frame) we end up going forwards rather than
596            staying in the same place.
597         */
598         return do_seek (last_source_time(), true);
599 }
600
601 bool
602 FFmpegDecoder::do_seek (double p, bool backwards)
603 {
604         int64_t const vt = p / av_q2d (_format_context->streams[_video_stream]->time_base);
605
606         int const r = av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
607         
608         avcodec_flush_buffers (_video_codec_context);
609         if (_subtitle_codec_context) {
610                 avcodec_flush_buffers (_subtitle_codec_context);
611         }
612         
613         return r < 0;
614 }
615
616 shared_ptr<FFmpegAudioStream>
617 FFmpegAudioStream::create (string t, optional<int> v)
618 {
619         if (!v) {
620                 /* version < 1; no type in the string, and there's only FFmpeg streams anyway */
621                 return shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream (t, v));
622         }
623
624         stringstream s (t);
625         string type;
626         s >> type;
627         if (type != N_("ffmpeg")) {
628                 return shared_ptr<FFmpegAudioStream> ();
629         }
630
631         return shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream (t, v));
632 }
633
634 FFmpegAudioStream::FFmpegAudioStream (string t, optional<int> version)
635 {
636         stringstream n (t);
637         
638         int name_index = 4;
639         if (!version) {
640                 name_index = 2;
641                 int channels;
642                 n >> _id >> channels;
643                 _channel_layout = av_get_default_channel_layout (channels);
644                 _sample_rate = 0;
645         } else {
646                 string type;
647                 /* Current (marked version 1) */
648                 n >> type >> _id >> _sample_rate >> _channel_layout;
649                 assert (type == N_("ffmpeg"));
650         }
651
652         for (int i = 0; i < name_index; ++i) {
653                 size_t const s = t.find (' ');
654                 if (s != string::npos) {
655                         t = t.substr (s + 1);
656                 }
657         }
658
659         _name = t;
660 }
661
662 string
663 FFmpegAudioStream::to_string () const
664 {
665         return String::compose (N_("ffmpeg %1 %2 %3 %4"), _id, _sample_rate, _channel_layout, _name);
666 }
667
668 void
669 FFmpegDecoder::out_with_sync ()
670 {
671         /* Where we are in the output, in seconds */
672         double const out_pts_seconds = video_frame() / frames_per_second();
673         
674         /* Where we are in the source, in seconds */
675         double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
676                 * av_frame_get_best_effort_timestamp(_frame);
677         
678         _film->log()->log (
679                 String::compose (N_("Source video frame ready; source at %1, output at %2"), source_pts_seconds, out_pts_seconds),
680                 Log::VERBOSE
681                 );
682         
683         if (!_first_video) {
684                 _first_video = source_pts_seconds;
685         }
686         
687         /* Difference between where we are and where we should be */
688         double const delta = source_pts_seconds - _first_video.get() - out_pts_seconds;
689         double const one_frame = 1 / frames_per_second();
690         
691         /* Insert frames if required to get out_pts_seconds up to pts_seconds */
692         if (delta > one_frame) {
693                 int const extra = rint (delta / one_frame);
694                 for (int i = 0; i < extra; ++i) {
695                         repeat_last_video ();
696                         _film->log()->log (
697                                 String::compose (
698                                         N_("Extra video frame inserted at %1s; source frame %2, source PTS %3 (at %4 fps)"),
699                                         out_pts_seconds, video_frame(), source_pts_seconds, frames_per_second()
700                                         )
701                                 );
702                 }
703         }
704         
705         if (delta > -one_frame) {
706                 /* Process this frame */
707                 filter_and_emit_video (_frame);
708         } else {
709                 /* Otherwise we are omitting a frame to keep things right */
710                 _film->log()->log (String::compose (N_("Frame removed at %1s"), out_pts_seconds));
711         }
712 }
713
714 void
715 FFmpegDecoder::film_changed (Film::Property p)
716 {
717         switch (p) {
718         case Film::CROP:
719         case Film::FILTERS:
720         {
721                 boost::mutex::scoped_lock lm (_filter_graphs_mutex);
722                 _filter_graphs.clear ();
723         }
724         OutputChanged ();
725         break;
726
727         default:
728                 break;
729         }
730 }
731
732 /** @return Length (in video frames) according to our content's header */
733 SourceFrame
734 FFmpegDecoder::length () const
735 {
736         return (double(_format_context->duration) / AV_TIME_BASE) * frames_per_second();
737 }
738
739 double
740 FFmpegDecoder::frame_time () const
741 {
742         return av_frame_get_best_effort_timestamp(_frame) * av_q2d (_format_context->streams[_video_stream]->time_base);
743 }
744