/src/mozilla-central/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include "FFmpegVideoDecoder.h" |
8 | | #include "FFmpegLog.h" |
9 | | #include "ImageContainer.h" |
10 | | #include "MediaInfo.h" |
11 | | #include "MP4Decoder.h" |
12 | | #include "VPXDecoder.h" |
13 | | #include "mozilla/layers/KnowsCompositor.h" |
14 | | |
15 | | #include "libavutil/pixfmt.h" |
16 | | #if LIBAVCODEC_VERSION_MAJOR < 54 |
17 | | #define AVPixelFormat PixelFormat |
18 | 0 | #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P |
19 | 0 | #define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P |
20 | 0 | #define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P |
21 | 0 | #define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P |
22 | 0 | #define AV_PIX_FMT_YUV420P10LE PIX_FMT_YUV420P10LE |
23 | 0 | #define AV_PIX_FMT_YUV444P10LE PIX_FMT_YUV444P10LE |
24 | 0 | #define AV_PIX_FMT_NONE PIX_FMT_NONE |
25 | | #endif |
26 | | #include "mozilla/PodOperations.h" |
27 | | #include "mozilla/TaskQueue.h" |
28 | | #include "nsThreadUtils.h" |
29 | | #include "prsystem.h" |
30 | | |
31 | | |
32 | | typedef mozilla::layers::Image Image; |
33 | | typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage; |
34 | | |
35 | | namespace mozilla { |
36 | | |
37 | | using media::TimeUnit; |
38 | | |
39 | | /** |
40 | | * FFmpeg calls back to this function with a list of pixel formats it supports. |
41 | | * We choose a pixel format that we support and return it. |
42 | | * For now, we just look for YUV420P, YUVJ420P and YUV444 as those are the only |
43 | | * only non-HW accelerated format supported by FFmpeg's H264 and VP9 decoder. |
44 | | */ |
45 | | static AVPixelFormat |
46 | | ChoosePixelFormat(AVCodecContext* aCodecContext, const AVPixelFormat* aFormats) |
47 | 0 | { |
48 | 0 | FFMPEG_LOG("Choosing FFmpeg pixel format for video decoding."); |
49 | 0 | for (; *aFormats > -1; aFormats++) { |
50 | 0 | switch (*aFormats) { |
51 | 0 | case AV_PIX_FMT_YUV444P: |
52 | 0 | FFMPEG_LOG("Requesting pixel format YUV444P."); |
53 | 0 | return AV_PIX_FMT_YUV444P; |
54 | 0 | case AV_PIX_FMT_YUV422P: |
55 | 0 | FFMPEG_LOG("Requesting pixel format YUV422P."); |
56 | 0 | return AV_PIX_FMT_YUV422P; |
57 | 0 | case AV_PIX_FMT_YUV420P: |
58 | 0 | FFMPEG_LOG("Requesting pixel format YUV420P."); |
59 | 0 | return AV_PIX_FMT_YUV420P; |
60 | 0 | case AV_PIX_FMT_YUVJ420P: |
61 | 0 | FFMPEG_LOG("Requesting pixel format YUVJ420P."); |
62 | 0 | return AV_PIX_FMT_YUVJ420P; |
63 | 0 | case AV_PIX_FMT_YUV420P10LE: |
64 | 0 | FFMPEG_LOG("Requesting pixel format YUV420P10LE."); |
65 | 0 | return AV_PIX_FMT_YUV420P10LE; |
66 | 0 | case AV_PIX_FMT_YUV444P10LE: |
67 | 0 | FFMPEG_LOG("Requesting pixel format YUV444P10LE."); |
68 | 0 | return AV_PIX_FMT_YUV444P10LE; |
69 | | #if LIBAVCODEC_VERSION_MAJOR >= 57 |
70 | 0 | case AV_PIX_FMT_YUV444P12LE: |
71 | 0 | FFMPEG_LOG("Requesting pixel format YUV444P12LE."); |
72 | 0 | return AV_PIX_FMT_YUV444P12LE; |
73 | | #endif |
74 | 0 | default: |
75 | 0 | break; |
76 | 0 | } |
77 | 0 | } |
78 | 0 |
|
79 | 0 | NS_WARNING("FFmpeg does not share any supported pixel formats."); |
80 | 0 | return AV_PIX_FMT_NONE; |
81 | 0 | } Unexecuted instantiation: Unified_cpp_ffmpeg_ffvpx0.cpp:mozilla::ChoosePixelFormat(AVCodecContext*, AVPixelFormat const*) Unexecuted instantiation: Unified_cpp_ffmpeg_libav530.cpp:mozilla::ChoosePixelFormat(AVCodecContext*, PixelFormat const*) Unexecuted instantiation: Unified_cpp_ffmpeg_libav540.cpp:mozilla::ChoosePixelFormat(AVCodecContext*, AVPixelFormat const*) Unexecuted instantiation: Unified_cpp_ffmpeg_libav550.cpp:mozilla::ChoosePixelFormat(AVCodecContext*, AVPixelFormat const*) Unexecuted instantiation: Unified_cpp_ffmpeg_ffmpeg570.cpp:mozilla::ChoosePixelFormat(AVCodecContext*, AVPixelFormat const*) Unexecuted instantiation: Unified_cpp_ffmpeg_ffmpeg580.cpp:mozilla::ChoosePixelFormat(AVCodecContext*, AVPixelFormat const*) |
82 | | |
83 | | FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext() |
84 | | : mNumFaultyPts(0) |
85 | | , mNumFaultyDts(0) |
86 | | , mLastPts(INT64_MIN) |
87 | | , mLastDts(INT64_MIN) |
88 | 0 | { |
89 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::PtsCorrectionContext::PtsCorrectionContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::PtsCorrectionContext::PtsCorrectionContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::PtsCorrectionContext::PtsCorrectionContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::PtsCorrectionContext::PtsCorrectionContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::PtsCorrectionContext::PtsCorrectionContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::PtsCorrectionContext::PtsCorrectionContext() |
90 | | |
91 | | int64_t |
92 | | FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::GuessCorrectPts( |
93 | | int64_t aPts, int64_t aDts) |
94 | 0 | { |
95 | 0 | int64_t pts = AV_NOPTS_VALUE; |
96 | 0 |
|
97 | 0 | if (aDts != int64_t(AV_NOPTS_VALUE)) { |
98 | 0 | mNumFaultyDts += aDts <= mLastDts; |
99 | 0 | mLastDts = aDts; |
100 | 0 | } |
101 | 0 | if (aPts != int64_t(AV_NOPTS_VALUE)) { |
102 | 0 | mNumFaultyPts += aPts <= mLastPts; |
103 | 0 | mLastPts = aPts; |
104 | 0 | } |
105 | 0 | if ((mNumFaultyPts <= mNumFaultyDts || aDts == int64_t(AV_NOPTS_VALUE)) && |
106 | 0 | aPts != int64_t(AV_NOPTS_VALUE)) { |
107 | 0 | pts = aPts; |
108 | 0 | } else { |
109 | 0 | pts = aDts; |
110 | 0 | } |
111 | 0 | return pts; |
112 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::PtsCorrectionContext::GuessCorrectPts(long, long) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::PtsCorrectionContext::GuessCorrectPts(long, long) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::PtsCorrectionContext::GuessCorrectPts(long, long) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::PtsCorrectionContext::GuessCorrectPts(long, long) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::PtsCorrectionContext::GuessCorrectPts(long, long) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::PtsCorrectionContext::GuessCorrectPts(long, long) |
113 | | |
114 | | void |
115 | | FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::Reset() |
116 | 0 | { |
117 | 0 | mNumFaultyPts = 0; |
118 | 0 | mNumFaultyDts = 0; |
119 | 0 | mLastPts = INT64_MIN; |
120 | 0 | mLastDts = INT64_MIN; |
121 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::PtsCorrectionContext::Reset() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::PtsCorrectionContext::Reset() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::PtsCorrectionContext::Reset() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::PtsCorrectionContext::Reset() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::PtsCorrectionContext::Reset() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::PtsCorrectionContext::Reset() |
122 | | |
123 | | FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder( |
124 | | FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue, const VideoInfo& aConfig, |
125 | | KnowsCompositor* aAllocator, ImageContainer* aImageContainer, |
126 | | bool aLowLatency) |
127 | | : FFmpegDataDecoder(aLib, aTaskQueue, GetCodecId(aConfig.mMimeType)) |
128 | | , mImageAllocator(aAllocator) |
129 | | , mImageContainer(aImageContainer) |
130 | | , mInfo(aConfig) |
131 | | , mLowLatency(aLowLatency) |
132 | 0 | { |
133 | 0 | // Use a new MediaByteBuffer as the object will be modified during |
134 | 0 | // initialization. |
135 | 0 | mExtraData = new MediaByteBuffer; |
136 | 0 | mExtraData->AppendElements(*aConfig.mExtraData); |
137 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::FFmpegVideoDecoder(mozilla::FFmpegLibWrapper*, mozilla::TaskQueue*, mozilla::VideoInfo const&, mozilla::layers::KnowsCompositor*, mozilla::layers::ImageContainer*, bool) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::FFmpegVideoDecoder(mozilla::FFmpegLibWrapper*, mozilla::TaskQueue*, mozilla::VideoInfo const&, mozilla::layers::KnowsCompositor*, mozilla::layers::ImageContainer*, bool) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::FFmpegVideoDecoder(mozilla::FFmpegLibWrapper*, mozilla::TaskQueue*, mozilla::VideoInfo const&, mozilla::layers::KnowsCompositor*, mozilla::layers::ImageContainer*, bool) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::FFmpegVideoDecoder(mozilla::FFmpegLibWrapper*, mozilla::TaskQueue*, mozilla::VideoInfo const&, mozilla::layers::KnowsCompositor*, mozilla::layers::ImageContainer*, bool) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::FFmpegVideoDecoder(mozilla::FFmpegLibWrapper*, mozilla::TaskQueue*, mozilla::VideoInfo const&, mozilla::layers::KnowsCompositor*, mozilla::layers::ImageContainer*, bool) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::FFmpegVideoDecoder(mozilla::FFmpegLibWrapper*, mozilla::TaskQueue*, mozilla::VideoInfo const&, mozilla::layers::KnowsCompositor*, mozilla::layers::ImageContainer*, bool) |
138 | | |
139 | | RefPtr<MediaDataDecoder::InitPromise> |
140 | | FFmpegVideoDecoder<LIBAV_VER>::Init() |
141 | 0 | { |
142 | 0 | MediaResult rv = InitDecoder(); |
143 | 0 | if (NS_FAILED(rv)) { |
144 | 0 | return InitPromise::CreateAndReject(rv, __func__); |
145 | 0 | } |
146 | 0 | |
147 | 0 | return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__); |
148 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::Init() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::Init() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::Init() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::Init() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::Init() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::Init() |
149 | | |
150 | | void |
151 | | FFmpegVideoDecoder<LIBAV_VER>::InitCodecContext() |
152 | 0 | { |
153 | 0 | mCodecContext->width = mInfo.mImage.width; |
154 | 0 | mCodecContext->height = mInfo.mImage.height; |
155 | 0 |
|
156 | 0 | // We use the same logic as libvpx in determining the number of threads to use |
157 | 0 | // so that we end up behaving in the same fashion when using ffmpeg as |
158 | 0 | // we would otherwise cause various crashes (see bug 1236167) |
159 | 0 | int decode_threads = 1; |
160 | 0 | if (mInfo.mDisplay.width >= 2048) { |
161 | 0 | decode_threads = 8; |
162 | 0 | } else if (mInfo.mDisplay.width >= 1024) { |
163 | 0 | decode_threads = 4; |
164 | 0 | } else if (mInfo.mDisplay.width >= 320) { |
165 | 0 | decode_threads = 2; |
166 | 0 | } |
167 | 0 |
|
168 | 0 | if (mLowLatency) { |
169 | 0 | mCodecContext->flags |= AV_CODEC_FLAG_LOW_DELAY; |
170 | 0 | // ffvp9 and ffvp8 at this stage do not support slice threading, but it may |
171 | 0 | // help with the h264 decoder if there's ever one. |
172 | 0 | mCodecContext->thread_type = FF_THREAD_SLICE; |
173 | 0 | } else { |
174 | 0 | decode_threads = std::min(decode_threads, PR_GetNumberOfProcessors() - 1); |
175 | 0 | decode_threads = std::max(decode_threads, 1); |
176 | 0 | mCodecContext->thread_count = decode_threads; |
177 | 0 | if (decode_threads > 1) { |
178 | 0 | mCodecContext->thread_type = FF_THREAD_SLICE | FF_THREAD_FRAME; |
179 | 0 | } |
180 | 0 | } |
181 | 0 |
|
182 | 0 | // FFmpeg will call back to this to negotiate a video pixel format. |
183 | 0 | mCodecContext->get_format = ChoosePixelFormat; |
184 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::InitCodecContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::InitCodecContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::InitCodecContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::InitCodecContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::InitCodecContext() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::InitCodecContext() |
185 | | |
186 | | MediaResult |
187 | | FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample, |
188 | | uint8_t* aData, int aSize, |
189 | | bool* aGotFrame, |
190 | | MediaDataDecoder::DecodedData& aResults) |
191 | 0 | { |
192 | 0 | AVPacket packet; |
193 | 0 | mLib->av_init_packet(&packet); |
194 | 0 |
|
195 | 0 | packet.data = aData; |
196 | 0 | packet.size = aSize; |
197 | 0 | packet.dts = aSample->mTimecode.ToMicroseconds(); |
198 | 0 | packet.pts = aSample->mTime.ToMicroseconds(); |
199 | 0 | packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0; |
200 | 0 | packet.pos = aSample->mOffset; |
201 | 0 |
|
202 | 0 | // LibAV provides no API to retrieve the decoded sample's duration. |
203 | 0 | // (FFmpeg >= 1.0 provides av_frame_get_pkt_duration) |
204 | 0 | // As such we instead use a map using the dts as key that we will retrieve |
205 | 0 | // later. |
206 | 0 | // The map will have a typical size of 16 entry. |
207 | 0 | mDurationMap.Insert( |
208 | 0 | aSample->mTimecode.ToMicroseconds(), aSample->mDuration.ToMicroseconds()); |
209 | 0 |
|
210 | 0 | if (!PrepareFrame()) { |
211 | 0 | NS_WARNING("FFmpeg h264 decoder failed to allocate frame."); |
212 | 0 | return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__); |
213 | 0 | } |
214 | 0 |
|
215 | 0 | // Required with old version of FFmpeg/LibAV |
216 | 0 | mFrame->reordered_opaque = AV_NOPTS_VALUE; |
217 | 0 |
|
218 | 0 | int decoded; |
219 | 0 | int bytesConsumed = |
220 | 0 | mLib->avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet); |
221 | 0 |
|
222 | 0 | FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d " |
223 | 0 | "(Input: pts(%" PRId64 ") dts(%" PRId64 ") Output: pts(%" PRId64 ") " |
224 | 0 | "opaque(%" PRId64 ") pkt_pts(%" PRId64 ") pkt_dts(%" PRId64 "))", |
225 | 0 | bytesConsumed, decoded, packet.pts, packet.dts, mFrame->pts, |
226 | 0 | mFrame->reordered_opaque, mFrame->pkt_pts, mFrame->pkt_dts); |
227 | 0 |
|
228 | 0 | if (bytesConsumed < 0) { |
229 | 0 | return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, |
230 | 0 | RESULT_DETAIL("FFmpeg video error:%d", bytesConsumed)); |
231 | 0 | } |
232 | 0 |
|
233 | 0 | if (!decoded) { |
234 | 0 | if (aGotFrame) { |
235 | 0 | *aGotFrame = false; |
236 | 0 | } |
237 | 0 | return NS_OK; |
238 | 0 | } |
239 | 0 |
|
240 | 0 | if ((mCodecContext->pix_fmt == AV_PIX_FMT_YUV420P10LE || |
241 | 0 | mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P10LE |
242 | | #if LIBAVCODEC_VERSION_MAJOR >= 57 |
243 | 0 | || mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P12LE |
244 | | #endif |
245 | | ) && |
246 | 0 | (!mImageAllocator || (mImageAllocator->GetCompositorBackendType() |
247 | 0 | != layers::LayersBackend::LAYERS_BASIC && |
248 | 0 | mImageAllocator->GetCompositorBackendType() |
249 | 0 | != layers::LayersBackend::LAYERS_OPENGL))) { |
250 | 0 | return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, |
251 | 0 | RESULT_DETAIL("unsupported format type (hdr)")); |
252 | 0 | } |
253 | 0 |
|
254 | 0 | // If we've decoded a frame then we need to output it |
255 | 0 | int64_t pts = mPtsContext.GuessCorrectPts(mFrame->pkt_pts, mFrame->pkt_dts); |
256 | 0 | // Retrieve duration from dts. |
257 | 0 | // We use the first entry found matching this dts (this is done to |
258 | 0 | // handle damaged file with multiple frames with the same dts) |
259 | 0 |
|
260 | 0 | int64_t duration; |
261 | 0 | if (!mDurationMap.Find(mFrame->pkt_dts, duration)) { |
262 | 0 | NS_WARNING("Unable to retrieve duration from map"); |
263 | 0 | duration = aSample->mDuration.ToMicroseconds(); |
264 | 0 | // dts are probably incorrectly reported ; so clear the map as we're |
265 | 0 | // unlikely to find them in the future anyway. This also guards |
266 | 0 | // against the map becoming extremely big. |
267 | 0 | mDurationMap.Clear(); |
268 | 0 | } |
269 | 0 | FFMPEG_LOG( |
270 | 0 | "Got one frame output with pts=%" PRId64 " dts=%" PRId64 |
271 | 0 | " duration=%" PRId64 " opaque=%" PRId64, |
272 | 0 | pts, mFrame->pkt_dts, duration, mCodecContext->reordered_opaque); |
273 | 0 |
|
274 | 0 | VideoData::YCbCrBuffer b; |
275 | 0 | b.mPlanes[0].mData = mFrame->data[0]; |
276 | 0 | b.mPlanes[1].mData = mFrame->data[1]; |
277 | 0 | b.mPlanes[2].mData = mFrame->data[2]; |
278 | 0 |
|
279 | 0 | b.mPlanes[0].mStride = mFrame->linesize[0]; |
280 | 0 | b.mPlanes[1].mStride = mFrame->linesize[1]; |
281 | 0 | b.mPlanes[2].mStride = mFrame->linesize[2]; |
282 | 0 |
|
283 | 0 | b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0; |
284 | 0 | b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0; |
285 | 0 | b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0; |
286 | 0 |
|
287 | 0 | b.mPlanes[0].mWidth = mFrame->width; |
288 | 0 | b.mPlanes[0].mHeight = mFrame->height; |
289 | 0 | if (mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P || |
290 | 0 | mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P10LE |
291 | | #if LIBAVCODEC_VERSION_MAJOR >= 57 |
292 | | || |
293 | 0 | mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P12LE |
294 | 0 | #endif |
295 | 0 | ) { |
296 | 0 | b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = mFrame->width; |
297 | 0 | b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = mFrame->height; |
298 | 0 | if (mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P10LE) { |
299 | 0 | b.mBitDepth = 10; |
300 | 0 | } |
301 | | #if LIBAVCODEC_VERSION_MAJOR >= 57 |
302 | 0 | else if (mCodecContext->pix_fmt == AV_PIX_FMT_YUV444P12LE) { |
303 | 0 | b.mBitDepth = 12; |
304 | 0 | } |
305 | | #endif |
306 | 0 | } else if (mCodecContext->pix_fmt == AV_PIX_FMT_YUV422P) { |
307 | 0 | b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1; |
308 | 0 | b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = mFrame->height; |
309 | 0 | } else { |
310 | 0 | b.mPlanes[1].mWidth = b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1; |
311 | 0 | b.mPlanes[1].mHeight = b.mPlanes[2].mHeight = (mFrame->height + 1) >> 1; |
312 | 0 | if (mCodecContext->pix_fmt == AV_PIX_FMT_YUV420P10LE) { |
313 | 0 | b.mBitDepth = 10; |
314 | 0 | } |
315 | 0 | } |
316 | 0 | if (mLib->av_frame_get_colorspace) { |
317 | 0 | switch (mLib->av_frame_get_colorspace(mFrame)) { |
318 | 0 | case AVCOL_SPC_BT709: |
319 | 0 | b.mYUVColorSpace = YUVColorSpace::BT709; |
320 | 0 | break; |
321 | 0 | case AVCOL_SPC_SMPTE170M: |
322 | 0 | case AVCOL_SPC_BT470BG: |
323 | 0 | b.mYUVColorSpace = YUVColorSpace::BT601; |
324 | 0 | break; |
325 | 0 | case AVCOL_SPC_UNSPECIFIED: |
326 | | #if LIBAVCODEC_VERSION_MAJOR >= 55 |
327 | 0 | if (mCodecContext->codec_id == AV_CODEC_ID_VP9) { |
328 | 0 | b.mYUVColorSpace = YUVColorSpace::BT709; |
329 | 0 | } |
330 | | #endif |
331 | | break; |
332 | 0 | default: |
333 | 0 | break; |
334 | 0 | } |
335 | 0 | } |
336 | 0 | RefPtr<VideoData> v = |
337 | 0 | VideoData::CreateAndCopyData(mInfo, |
338 | 0 | mImageContainer, |
339 | 0 | aSample->mOffset, |
340 | 0 | TimeUnit::FromMicroseconds(pts), |
341 | 0 | TimeUnit::FromMicroseconds(duration), |
342 | 0 | b, |
343 | 0 | !!mFrame->key_frame, |
344 | 0 | TimeUnit::FromMicroseconds(-1), |
345 | 0 | mInfo.ScaledImageRect(mFrame->width, |
346 | 0 | mFrame->height), |
347 | 0 | mImageAllocator); |
348 | 0 |
|
349 | 0 | if (!v) { |
350 | 0 | return MediaResult(NS_ERROR_OUT_OF_MEMORY, |
351 | 0 | RESULT_DETAIL("image allocation error")); |
352 | 0 | } |
353 | 0 | aResults.AppendElement(std::move(v)); |
354 | 0 | if (aGotFrame) { |
355 | 0 | *aGotFrame = true; |
356 | 0 | } |
357 | 0 | return NS_OK; |
358 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::DoDecode(mozilla::MediaRawData*, unsigned char*, int, bool*, nsTArray<RefPtr<mozilla::MediaData> >&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::DoDecode(mozilla::MediaRawData*, unsigned char*, int, bool*, nsTArray<RefPtr<mozilla::MediaData> >&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::DoDecode(mozilla::MediaRawData*, unsigned char*, int, bool*, nsTArray<RefPtr<mozilla::MediaData> >&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::DoDecode(mozilla::MediaRawData*, unsigned char*, int, bool*, nsTArray<RefPtr<mozilla::MediaData> >&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::DoDecode(mozilla::MediaRawData*, unsigned char*, int, bool*, nsTArray<RefPtr<mozilla::MediaData> >&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::DoDecode(mozilla::MediaRawData*, unsigned char*, int, bool*, nsTArray<RefPtr<mozilla::MediaData> >&) |
359 | | |
360 | | RefPtr<MediaDataDecoder::FlushPromise> |
361 | | FFmpegVideoDecoder<LIBAV_VER>::ProcessFlush() |
362 | 0 | { |
363 | 0 | mPtsContext.Reset(); |
364 | 0 | mDurationMap.Clear(); |
365 | 0 | return FFmpegDataDecoder::ProcessFlush(); |
366 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::ProcessFlush() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::ProcessFlush() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::ProcessFlush() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::ProcessFlush() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::ProcessFlush() Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::ProcessFlush() |
367 | | |
368 | | AVCodecID |
369 | | FFmpegVideoDecoder<LIBAV_VER>::GetCodecId(const nsACString& aMimeType) |
370 | 0 | { |
371 | 0 | if (MP4Decoder::IsH264(aMimeType)) { |
372 | 0 | return AV_CODEC_ID_H264; |
373 | 0 | } |
374 | 0 |
|
375 | 0 | if (aMimeType.EqualsLiteral("video/x-vnd.on2.vp6")) { |
376 | 0 | return AV_CODEC_ID_VP6F; |
377 | 0 | } |
378 | 0 |
|
379 | | #if LIBAVCODEC_VERSION_MAJOR >= 54 |
380 | 0 | if (VPXDecoder::IsVP8(aMimeType)) { |
381 | 0 | return AV_CODEC_ID_VP8; |
382 | 0 | } |
383 | 0 | #endif |
384 | 0 |
|
385 | | #if LIBAVCODEC_VERSION_MAJOR >= 55 |
386 | 0 | if (VPXDecoder::IsVP9(aMimeType)) { |
387 | 0 | return AV_CODEC_ID_VP9; |
388 | 0 | } |
389 | 0 | #endif |
390 | 0 | |
391 | 0 | return AV_CODEC_ID_NONE; |
392 | 0 | } Unexecuted instantiation: mozilla::FFmpegVideoDecoder<46465650>::GetCodecId(nsTSubstring<char> const&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<53>::GetCodecId(nsTSubstring<char> const&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<54>::GetCodecId(nsTSubstring<char> const&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<55>::GetCodecId(nsTSubstring<char> const&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<57>::GetCodecId(nsTSubstring<char> const&) Unexecuted instantiation: mozilla::FFmpegVideoDecoder<58>::GetCodecId(nsTSubstring<char> const&) |
393 | | |
394 | | } // namespace mozilla |