summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/ffmpeg
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/platforms/ffmpeg')
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp18
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp3
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegLibWrapper.h7
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp75
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h1
-rw-r--r--dom/media/platforms/ffmpeg/ffvpx/moz.build2
6 files changed, 91 insertions, 15 deletions
diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
index 8cb5c8578..8655ce25f 100644
--- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp
@@ -69,12 +69,21 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
mCodecContext->extradata_size = mExtraData->Length();
// FFmpeg may use SIMD instructions to access the data which reads the
// data in 32 bytes block. Must ensure we have enough data to read.
+ uint32_t padding_size =
#if LIBAVCODEC_VERSION_MAJOR >= 58
- mExtraData->AppendElements(AV_INPUT_BUFFER_PADDING_SIZE);
+ AV_INPUT_BUFFER_PADDING_SIZE;
#else
- mExtraData->AppendElements(FF_INPUT_BUFFER_PADDING_SIZE);
+ FF_INPUT_BUFFER_PADDING_SIZE;
#endif
- mCodecContext->extradata = mExtraData->Elements();
+ mCodecContext->extradata = static_cast<uint8_t*>(
+ mLib->av_malloc(mExtraData->Length() + padding_size));
+ if (!mCodecContext->extradata) {
+ return MediaResult(NS_ERROR_OUT_OF_MEMORY,
+ RESULT_DETAIL("Couldn't init ffmpeg extradata"));
+ }
+ memcpy(mCodecContext->extradata,
+ mExtraData->Elements(),
+ mExtraData->Length());
} else {
mCodecContext->extradata_size = 0;
}
@@ -165,6 +174,9 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown()
StaticMutexAutoLock mon(sMonitor);
if (mCodecContext) {
+ if (mCodecContext->extradata) {
+ mLib->av_freep(&mCodecContext->extradata);
+ }
mLib->avcodec_close(mCodecContext);
mLib->av_freep(&mCodecContext);
#if LIBAVCODEC_VERSION_MAJOR >= 55
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
index 6302882a6..426e9f74b 100644
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp
@@ -7,6 +7,7 @@
#include "MediaPrefs.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Types.h"
+#include "PlatformDecoderModule.h"
#include "prlink.h"
#define AV_LOG_DEBUG 48
@@ -144,6 +145,8 @@ FFmpegLibWrapper::Link()
AV_FUNC(avcodec_alloc_frame, (AV_FUNC_53 | AV_FUNC_54))
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
AV_FUNC(avcodec_free_frame, AV_FUNC_54)
+ AV_FUNC(avcodec_send_packet, AV_FUNC_58)
+ AV_FUNC(avcodec_receive_frame, AV_FUNC_58)
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
index d6944a1d8..b968edd32 100644
--- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h
@@ -5,6 +5,7 @@
#ifndef __FFmpegLibWrapper_h__
#define __FFmpegLibWrapper_h__
+#include "mozilla/Attributes.h"
#include "mozilla/Types.h"
struct AVCodec;
@@ -70,6 +71,10 @@ struct FFmpegLibWrapper
// libavcodec v54 only
void (*avcodec_free_frame)(AVFrame** frame);
+ // libavcodec v58 and later only
+ int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt);
+ int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame);
+
// libavutil
void (*av_log_set_level)(int level);
void* (*av_malloc)(size_t size);
@@ -91,4 +96,4 @@ private:
} // namespace mozilla
-#endif // FFmpegLibWrapper \ No newline at end of file
+#endif // FFmpegLibWrapper
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
index aec1e9136..f3101e44c 100644
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp
@@ -174,12 +174,15 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample, bool* aGotFrame)
uint8_t* inputData = const_cast<uint8_t*>(aSample->Data());
size_t inputSize = aSample->Size();
-#if LIBAVCODEC_VERSION_MAJOR >= 54
+#if LIBAVCODEC_VERSION_MAJOR >= 54 && LIBAVCODEC_VERSION_MAJOR < 58
if (inputSize && mCodecParser && (mCodecID == AV_CODEC_ID_VP8
-#if LIBAVCODEC_VERSION_MAJOR >= 55
+#if LIBAVCODEC_VERSION_MAJOR >= 55 && LIBAVCODEC_VERSION_MAJOR < 58
|| mCodecID == AV_CODEC_ID_VP9
#endif
- )) {
+ ))
+#endif
+#if LIBAVCODEC_VERSION_MAJOR >= 54
+ {
while (inputSize) {
uint8_t* data = inputData;
int size = inputSize;
@@ -224,6 +227,48 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0;
packet.pos = aSample->mOffset;
+#if LIBAVCODEC_VERSION_MAJOR >= 58
+ packet.duration = aSample->mDuration;
+ int res = mLib->avcodec_send_packet(mCodecContext, &packet);
+ if (res < 0) {
+ // In theory, avcodec_send_packet could sent -EAGAIN should its internal
+ // buffers be full. In practice this can't happen as we only feed one frame
+ // 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()) {
+ NS_WARNING("FFmpeg h264 decoder failed to allocate frame.");
+ return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__);
+ }
+ res = mLib->avcodec_receive_frame(mCodecContext, mFrame);
+ if (res == int(AVERROR_EOF)) {
+ return NS_ERROR_DOM_MEDIA_END_OF_STREAM;
+ }
+ if (res == AVERROR(EAGAIN)) {
+ return NS_OK;
+ }
+ if (res < 0) {
+ FFMPEG_LOG("avcodec_receive_frame error: %d", res);
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("avcodec_receive_frame error: %d", res));
+ }
+ MediaResult rv = CreateImage(mFrame->pkt_pos, mFrame->pkt_pts,
+ mFrame->pkt_duration);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ if (aGotFrame) {
+ *aGotFrame = true;
+ }
+ } while (true);
+#else
// LibAV provides no API to retrieve the decoded sample's duration.
// (FFmpeg >= 1.0 provides av_frame_get_pkt_duration)
// As such we instead use a map using the dts as key that we will retrieve
@@ -276,8 +321,21 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
// against the map becoming extremely big.
mDurationMap.Clear();
}
+
+ MediaResult rv = CreateImage(aSample->mOffset, pts, duration);
+ if (NS_SUCCEEDED(rv) && aGotFrame) {
+ *aGotFrame = true;
+ }
+ return rv;
+#endif
+}
+
+MediaResult
+FFmpegVideoDecoder<LIBAV_VER>::CreateImage(int64_t aOffset, int64_t aPts,
+ int64_t aDuration)
+{
FFMPEG_LOG("Got one frame output with pts=%lld dts=%lld duration=%lld opaque=%lld",
- pts, mFrame->pkt_dts, duration, mCodecContext->reordered_opaque);
+ aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque);
VideoData::YCbCrBuffer b;
b.mPlanes[0].mData = mFrame->data[0];
@@ -317,9 +375,9 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
RefPtr<VideoData> v =
VideoData::CreateAndCopyData(mInfo,
mImageContainer,
- aSample->mOffset,
- pts,
- duration,
+ aOffset,
+ aPts,
+ aDuration,
b,
!!mFrame->key_frame,
-1,
@@ -331,9 +389,6 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample,
RESULT_DETAIL("image allocation error"));
}
mCallback->Output(v);
- if (aGotFrame) {
- *aGotFrame = true;
- }
return NS_OK;
}
diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
index 786df0da1..49a55e8a6 100644
--- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h
@@ -49,6 +49,7 @@ private:
MediaResult DoDecode(MediaRawData* aSample) override;
MediaResult DoDecode(MediaRawData* aSample, bool* aGotFrame);
MediaResult DoDecode(MediaRawData* aSample, uint8_t* aData, int aSize, bool* aGotFrame);
+ MediaResult CreateImage(int64_t aOffset, int64_t aPts, int64_t aDuration);
void ProcessDrain() override;
void ProcessFlush() override;
void OutputDelayedFrames();
diff --git a/dom/media/platforms/ffmpeg/ffvpx/moz.build b/dom/media/platforms/ffmpeg/ffvpx/moz.build
index aee58b5b0..c0041a4d4 100644
--- a/dom/media/platforms/ffmpeg/ffvpx/moz.build
+++ b/dom/media/platforms/ffmpeg/ffvpx/moz.build
@@ -20,7 +20,7 @@ SOURCES += [
]
LOCAL_INCLUDES += [
'..',
- '../ffmpeg57/include',
+ '../ffmpeg58/include',
]
if CONFIG['OS_ARCH'] == 'WINNT':