1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef __FFmpegVideoDecoder_h__
8 #define __FFmpegVideoDecoder_h__
9 
10 #include "FFmpegLibWrapper.h"
11 #include "FFmpegDataDecoder.h"
12 #include "mozilla/Pair.h"
13 #include "nsTArray.h"
14 
15 namespace mozilla
16 {
17 
18 template <int V>
19 class FFmpegVideoDecoder : public FFmpegDataDecoder<V>
20 {
21 };
22 
23 template <>
24 class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
25 {
26   typedef mozilla::layers::Image Image;
27   typedef mozilla::layers::ImageContainer ImageContainer;
28 
29 public:
30   FFmpegVideoDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue,
31                      MediaDataDecoderCallback* aCallback,
32                      const VideoInfo& aConfig,
33                      ImageContainer* aImageContainer);
34   virtual ~FFmpegVideoDecoder();
35 
36   RefPtr<InitPromise> Init() override;
37   void InitCodecContext() override;
GetDescriptionName()38   const char* GetDescriptionName() const override
39   {
40 #ifdef USING_MOZFFVPX
41     return "ffvpx video decoder";
42 #else
43     return "ffmpeg video decoder";
44 #endif
45   }
46   static AVCodecID GetCodecId(const nsACString& aMimeType);
47 
48 private:
49   MediaResult DoDecode(MediaRawData* aSample) override;
50   MediaResult DoDecode(MediaRawData* aSample, bool* aGotFrame);
51   MediaResult DoDecode(MediaRawData* aSample, uint8_t* aData, int aSize, bool* aGotFrame);
52   void ProcessDrain() override;
53   void ProcessFlush() override;
54   void OutputDelayedFrames();
55 
56   /**
57    * This method allocates a buffer for FFmpeg's decoder, wrapped in an Image.
58    * Currently it only supports Planar YUV420, which appears to be the only
59    * non-hardware accelerated image format that FFmpeg's H264 decoder is
60    * capable of outputting.
61    */
62   int AllocateYUV420PVideoBuffer(AVCodecContext* aCodecContext,
63                                  AVFrame* aFrame);
64 
65   RefPtr<ImageContainer> mImageContainer;
66   VideoInfo mInfo;
67 
68   // Parser used for VP8 and VP9 decoding.
69   AVCodecParserContext* mCodecParser;
70 
71   class PtsCorrectionContext {
72   public:
73     PtsCorrectionContext();
74     int64_t GuessCorrectPts(int64_t aPts, int64_t aDts);
75     void Reset();
LastDts()76     int64_t LastDts() const { return mLastDts; }
77 
78   private:
79     int64_t mNumFaultyPts; /// Number of incorrect PTS values so far
80     int64_t mNumFaultyDts; /// Number of incorrect DTS values so far
81     int64_t mLastPts;       /// PTS of the last frame
82     int64_t mLastDts;       /// DTS of the last frame
83   };
84 
85   PtsCorrectionContext mPtsContext;
86   int64_t mLastInputDts;
87 
88   class DurationMap {
89   public:
90     typedef Pair<int64_t, int64_t> DurationElement;
91 
92     // Insert Key and Duration pair at the end of our map.
Insert(int64_t aKey,int64_t aDuration)93     void Insert(int64_t aKey, int64_t aDuration)
94     {
95       mMap.AppendElement(MakePair(aKey, aDuration));
96     }
97     // Sets aDuration matching aKey and remove it from the map if found.
98     // The element returned is the first one found.
99     // Returns true if found, false otherwise.
Find(int64_t aKey,int64_t & aDuration)100     bool Find(int64_t aKey, int64_t& aDuration)
101     {
102       for (uint32_t i = 0; i < mMap.Length(); i++) {
103         DurationElement& element = mMap[i];
104         if (element.first() == aKey) {
105           aDuration = element.second();
106           mMap.RemoveElementAt(i);
107           return true;
108         }
109       }
110       return false;
111     }
112     // Remove all elements of the map.
Clear()113     void Clear()
114     {
115       mMap.Clear();
116     }
117 
118   private:
119     AutoTArray<DurationElement, 16> mMap;
120   };
121 
122   DurationMap mDurationMap;
123 };
124 
125 } // namespace mozilla
126 
127 #endif // __FFmpegVideoDecoder_h__
128