mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Bug 1197319: P2. Parse raw data to identify single frames before decoding. r=kentuckyfriedtakahe
A VP9 or VP9 packet may contains alternate frames. They need to be fed separately to the ffmpeg decoder.
This commit is contained in:
parent
bcf327201c
commit
13a129c06b
@ -42,12 +42,11 @@ protected:
|
||||
AVCodecContext* mCodecContext;
|
||||
AVFrame* mFrame;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
AVCodecID mCodecID;
|
||||
|
||||
private:
|
||||
static bool sFFmpegInitDone;
|
||||
static StaticMutex sMonitor;
|
||||
|
||||
AVCodecID mCodecID;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -20,6 +20,9 @@ AV_FUNC(avcodec_get_edge_width, 0)
|
||||
AV_FUNC(avcodec_open2, 0)
|
||||
AV_FUNC(av_init_packet, 0)
|
||||
AV_FUNC(av_dict_get, 0)
|
||||
AV_FUNC(av_parser_init, 0)
|
||||
AV_FUNC(av_parser_close, 0)
|
||||
AV_FUNC(av_parser_parse2, 0)
|
||||
|
||||
/* libavutil */
|
||||
AV_FUNC(av_image_fill_linesizes, 0)
|
||||
|
@ -33,6 +33,7 @@ FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
|
||||
, mImageContainer(aImageContainer)
|
||||
, mDisplayWidth(aConfig.mDisplay.width)
|
||||
, mDisplayHeight(aConfig.mDisplay.height)
|
||||
, mCodecParser(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegH264Decoder);
|
||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||
@ -69,12 +70,63 @@ FFmpegH264Decoder<LIBAV_VER>::GetPts(const AVPacket& packet)
|
||||
|
||||
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
|
||||
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
||||
{
|
||||
uint8_t* inputData = const_cast<uint8_t*>(aSample->Data());
|
||||
size_t inputSize = aSample->Size();
|
||||
|
||||
if (inputSize && (mCodecID == AV_CODEC_ID_VP8
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||
|| mCodecID == AV_CODEC_ID_VP9
|
||||
#endif
|
||||
)) {
|
||||
if (!mCodecParser) {
|
||||
mCodecParser = av_parser_init(mCodecID);
|
||||
if (!mCodecParser) {
|
||||
mCallback->Error();
|
||||
return DecodeResult::DECODE_ERROR;
|
||||
}
|
||||
mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
|
||||
}
|
||||
bool gotFrame = false;
|
||||
while (inputSize) {
|
||||
uint8_t* data;
|
||||
int size;
|
||||
int len = av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
||||
inputData, inputSize,
|
||||
aSample->mTime, aSample->mTimecode,
|
||||
aSample->mOffset);
|
||||
if (size_t(len) > inputSize) {
|
||||
mCallback->Error();
|
||||
return DecodeResult::DECODE_ERROR;
|
||||
}
|
||||
inputData += len;
|
||||
inputSize -= len;
|
||||
if (size) {
|
||||
switch (DoDecodeFrame(aSample, data, size)) {
|
||||
case DecodeResult::DECODE_ERROR:
|
||||
return DecodeResult::DECODE_ERROR;
|
||||
case DecodeResult::DECODE_FRAME:
|
||||
gotFrame = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return gotFrame ? DecodeResult::DECODE_FRAME : DecodeResult::DECODE_NO_FRAME;
|
||||
}
|
||||
return DoDecodeFrame(aSample, inputData, inputSize);
|
||||
}
|
||||
|
||||
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
|
||||
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||
uint8_t* aData, int aSize)
|
||||
{
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
|
||||
packet.data = const_cast<uint8_t*>(aSample->Data());
|
||||
packet.size = aSample->Size();
|
||||
packet.data = aData;
|
||||
packet.size = aSize;
|
||||
packet.dts = aSample->mTimecode;
|
||||
packet.pts = aSample->mTime;
|
||||
packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0;
|
||||
@ -316,6 +368,10 @@ FFmpegH264Decoder<LIBAV_VER>::Flush()
|
||||
FFmpegH264Decoder<LIBAV_VER>::~FFmpegH264Decoder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FFmpegH264Decoder);
|
||||
if (mCodecParser) {
|
||||
av_parser_close(mCodecParser);
|
||||
mCodecParser = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AVCodecID
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
private:
|
||||
void DecodeFrame(MediaRawData* aSample);
|
||||
DecodeResult DoDecodeFrame(MediaRawData* aSample);
|
||||
DecodeResult DoDecodeFrame(MediaRawData* aSample, uint8_t* aData, int aSize);
|
||||
void DoDrain();
|
||||
void OutputDelayedFrames();
|
||||
|
||||
@ -65,6 +66,7 @@ private:
|
||||
nsRefPtr<ImageContainer> mImageContainer;
|
||||
uint32_t mDisplayWidth;
|
||||
uint32_t mDisplayHeight;
|
||||
AVCodecParserContext* mCodecParser;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user