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