1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
@@ -106,10 +106,11 @@
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
bool IsHardwareAccelerated() const {
nsAutoCString dummy;
return IsHardwareAccelerated(dummy);
}
+ void UpdateDecodeTimes(TimeStamp aDecodeStart);
#if LIBAVCODEC_VERSION_MAJOR >= 57 && LIBAVUTIL_VERSION_MAJOR >= 56
layers::TextureClient* AllocateTextureClientForImage(
struct AVCodecContext* aCodecContext, layers::PlanarYCbCrImage* aImage);
@@ -142,10 +143,15 @@
static nsTArray<AVCodecID> mAcceleratedFormats;
#endif
RefPtr<KnowsCompositor> mImageAllocator;
RefPtr<ImageContainer> mImageContainer;
VideoInfo mInfo;
+ int mDecodedFrames;
+#if LIBAVCODEC_VERSION_MAJOR >= 58
+ int mDecodedFramesLate;
+#endif
+ float mAverangeDecodeTime;
class PtsCorrectionContext {
public:
PtsCorrectionContext();
int64_t GuessCorrectPts(int64_t aPts, int64_t aDts);
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
@@ -383,10 +383,15 @@
mDisplay(nullptr),
#endif
mImageAllocator(aAllocator),
mImageContainer(aImageContainer),
mInfo(aConfig),
+ mDecodedFrames(0),
+#if LIBAVCODEC_VERSION_MAJOR >= 58
+ mDecodedFramesLate(0),
+#endif
+ mAverangeDecodeTime(0),
mLowLatency(aLowLatency) {
FFMPEG_LOG("FFmpegVideoDecoder::FFmpegVideoDecoder MIME %s Codec ID %d",
aConfig.mMimeType.get(), mCodecID);
// Use a new MediaByteBuffer as the object will be modified during
// initialization.
@@ -769,17 +774,41 @@
#else
return aFrame->pkt_pts;
#endif
}
+void FFmpegVideoDecoder<LIBAV_VER>::UpdateDecodeTimes(TimeStamp aDecodeStart) {
+ mDecodedFrames++;
+ float decodeTime = (TimeStamp::Now() - aDecodeStart).ToMilliseconds();
+ mAverangeDecodeTime =
+ (mAverangeDecodeTime * (mDecodedFrames - 1) + decodeTime) /
+ mDecodedFrames;
+ FFMPEG_LOG(" averange frame decode time %.2f ms decoded frames %d\n",
+ mAverangeDecodeTime, mDecodedFrames);
+#if LIBAVCODEC_VERSION_MAJOR >= 58
+ int frameDuration = mFrame->pkt_duration;
+ if (frameDuration > 0 && frameDuration / 1000.0 < decodeTime) {
+ mDecodedFramesLate++;
+ FFMPEG_LOG(
+ " slow decode: failed to decode in time, frame duration %.2f ms, "
+ "decode time %.2f\n",
+ frameDuration / 1000.0, decodeTime);
+ FFMPEG_LOG(" all decoded frames / late decoded frames %d/%d\n",
+ mDecodedFrames, mDecodedFramesLate);
+ }
+#endif
+}
+
MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
MediaRawData* aSample, uint8_t* aData, int aSize, bool* aGotFrame,
MediaDataDecoder::DecodedData& aResults) {
MOZ_ASSERT(mTaskQueue->IsOnCurrentThread());
AVPacket packet;
mLib->av_init_packet(&packet);
+ TimeStamp decodeStart = TimeStamp::Now();
+
packet.data = aData;
packet.size = aSize;
packet.dts = aSample->mTimecode.ToMicroseconds();
packet.pts = aSample->mTime.ToMicroseconds();
packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0;
@@ -794,11 +823,10 @@
// at a time, and we immediately call avcodec_receive_frame right after.
FFMPEG_LOG("avcodec_send_packet error: %d", res);
return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
RESULT_DETAIL("avcodec_send_packet error: %d", res));
}
-
if (aGotFrame) {
*aGotFrame = false;
}
do {
if (!PrepareFrame()) {
@@ -831,10 +859,13 @@
FFMPEG_LOG(" avcodec_receive_frame error: %d", res);
return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
RESULT_DETAIL("avcodec_receive_frame error: %d", res));
}
+ UpdateDecodeTimes(decodeStart);
+ decodeStart = TimeStamp::Now();
+
MediaResult rv;
# ifdef MOZ_WAYLAND_USE_VAAPI
if (IsHardwareAccelerated()) {
rv = CreateImageVAAPI(mFrame->pkt_pos, GetFramePts(mFrame),
mFrame->pkt_duration, aResults);
@@ -898,10 +929,12 @@
*aGotFrame = false;
}
return NS_OK;
}
+ UpdateDecodeTimes(decodeStart);
+
// If we've decoded a frame then we need to output it
int64_t pts =
mPtsContext.GuessCorrectPts(GetFramePts(mFrame), mFrame->pkt_dts);
// Retrieve duration from dts.
// We use the first entry found matching this dts (this is done to
|