Handle multiple audio streams in a single piece of content
[dcpomatic.git] / src / lib / ffmpeg.cc
index 4fe1c04484ab38527db8bf67a051904e8fb60eee..741716b0400acc818c23d965b02eb97071d8278e 100644 (file)
@@ -22,20 +22,19 @@ extern "C" {
 #include <libavformat/avformat.h>
 #include <libswscale/swscale.h>
 }
-#include <dcp/raw_convert.h>
 #include "ffmpeg.h"
 #include "ffmpeg_content.h"
 #include "ffmpeg_audio_stream.h"
 #include "ffmpeg_subtitle_stream.h"
 #include "exceptions.h"
 #include "util.h"
+#include "raw_convert.h"
 
 #include "i18n.h"
 
 using std::string;
 using std::cout;
 using boost::shared_ptr;
-using dcp::raw_convert;
 
 boost::mutex FFmpeg::_mutex;
 
@@ -104,16 +103,31 @@ FFmpeg::setup_general ()
 
        /* Find video stream */
 
+       int video_stream_undefined_frame_rate = -1;
+
        for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
                AVStream* s = _format_context->streams[i];
                /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
                   to zero.  Ignore these streams.
                */
-               if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO && s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
-                       _video_stream = i;
+               if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+                       if (s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
+                               /* This is definitely our video stream */
+                               _video_stream = i;
+                       } else {
+                               /* This is our video stream if we don't get a better offer */
+                               video_stream_undefined_frame_rate = i;
+                       }
                }
        }
 
+       /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
+          to zero.  Only use such a stream if there is no alternative.
+       */
+       if (_video_stream == -1 && video_stream_undefined_frame_rate != -1) {
+               _video_stream = video_stream_undefined_frame_rate;
+       }       
+       
        if (_video_stream < 0) {
                throw DecodeError (N_("could not find video stream"));
        }
@@ -152,7 +166,15 @@ FFmpeg::setup_decoders ()
                
                AVCodec* codec = avcodec_find_decoder (context->codec_id);
                if (codec) {
-                       if (avcodec_open2 (context, codec, 0) < 0) {
+
+                       /* This option disables decoding of DCA frame footers in our patched version
+                          of FFmpeg.  I believe these footers are of no use to us, and they can cause
+                          problems when FFmpeg fails to decode them (mantis #352).
+                       */
+                       AVDictionary* options = 0;
+                       av_dict_set (&options, "disable_footer", "1", 0);
+                       
+                       if (avcodec_open2 (context, codec, &options) < 0) {
                                throw DecodeError (N_("could not open decoder"));
                        }
                }
@@ -167,16 +189,6 @@ FFmpeg::video_codec_context () const
        return _format_context->streams[_video_stream]->codec;
 }
 
-AVCodecContext *
-FFmpeg::audio_codec_context () const
-{
-       if (!_ffmpeg_content->audio_stream ()) {
-               return 0;
-       }
-       
-       return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
-}
-
 AVCodecContext *
 FFmpeg::subtitle_codec_context () const
 {