Commit b70a0600 authored by Dan Sanders's avatar Dan Sanders Committed by Commit Bot

[media] Use FFmpegVideoDecoder for WebCodecs

Change-Id: I28a23d9ff976bdc0b655be4dd5f6a5b2c2d2d4da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2185859Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#766555}
parent 817b5607
include_rules = [
"+base",
"+media/base",
"+media/filters",
"+media/media_buildflags.h",
"+media/video",
"+third_party/libyuv",
"+ui/gfx/geometry/rect.h",
......
......@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/webcodecs/video_decoder.h"
#include <utility>
#include <vector>
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
......@@ -12,6 +13,8 @@
#include "media/base/decoder_buffer.h"
#include "media/base/media_util.h"
#include "media/base/video_decoder.h"
#include "media/filters/ffmpeg_video_decoder.h"
#include "media/media_buildflags.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
......@@ -28,6 +31,50 @@
namespace blink {
namespace {
media::VideoDecoderConfig ToVideoDecoderConfig(
const EncodedVideoConfig* config) {
std::vector<uint8_t> extra_data;
if (config->hasDescription()) {
DOMArrayBuffer* buffer;
if (config->description().IsArrayBuffer()) {
buffer = config->description().GetAsArrayBuffer();
} else {
// TODO(sandersd): Can IsNull() be true?
DCHECK(config->description().IsArrayBufferView());
buffer = config->description().GetAsArrayBufferView()->buffer();
}
// TODO(sandersd): Is it possible to not have Data()?
uint8_t* start = static_cast<uint8_t*>(buffer->Data());
size_t size = buffer->ByteLengthAsSizeT();
extra_data.assign(start, start + size);
}
// TODO(sandersd): Parse |codec| to produce a VideoCodecProfile.
media::VideoCodec codec = media::kCodecH264;
media::VideoCodecProfile profile = media::H264PROFILE_BASELINE;
// TODO(sandersd): Either remove sizes from VideoDecoderConfig (replace with
// sample aspect) or parse the AvcC here to get the actual size.
gfx::Size size = gfx::Size(1280, 720);
return media::VideoDecoderConfig(
codec, profile, media::VideoDecoderConfig::AlphaMode::kIsOpaque,
media::VideoColorSpace::REC709(), media::kNoTransformation, size,
gfx::Rect(gfx::Point(), size), size, extra_data,
media::EncryptionScheme::kUnencrypted);
}
std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
media::MediaLog* media_log) {
#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
return std::make_unique<media::FFmpegVideoDecoder>(media_log);
#else
return nullptr;
#endif // BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
}
} // namespace
// static
VideoDecoder* VideoDecoder::Create(ScriptState* script_state,
const VideoDecoderInit* init,
......@@ -104,7 +151,6 @@ ScriptPromise VideoDecoder::EnqueueRequest(Request* request) {
void VideoDecoder::ProcessRequests() {
DVLOG(3) << __func__;
// TODO(sandersd): Re-entrancy checker.
// TODO(sandersd): Requests should probably be using virtual dispatch.
while (!pending_request_ && !requests_.IsEmpty()) {
Request* request = requests_.front();
switch (request->type) {
......@@ -142,10 +188,27 @@ bool VideoDecoder::ProcessConfigureRequest(Request* request) {
// TODO(sandersd): Elide this request if the configuration is unchanged.
if (!decoder_) {
// TODO(sandersd): Create and initialize a decoder.
media_log_ = std::make_unique<media::NullMediaLog>();
decoder_ = CreateVideoDecoder(media_log_.get());
if (!decoder_) {
request->resolver.Release()->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError,
"Codec initialization failed."));
// TODO(sandersd): This is a bit awkward because |request| is still in the
// queue.
HandleError();
return false;
}
// Processing continues in OnInitializeDone().
// TODO(sandersd): OnInitializeDone() may be called reentrantly, in which
// case it must not call ProcessRequests().
pending_request_ = request;
decoder_->Initialize(
ToVideoDecoderConfig(pending_request_->config), false, nullptr,
WTF::Bind(&VideoDecoder::OnInitializeDone, WrapWeakPersistent(this)),
WTF::BindRepeating(&VideoDecoder::OnOutput, WrapWeakPersistent(this)),
media::WaitingCB());
return true;
}
......@@ -259,6 +322,24 @@ void VideoDecoder::HandleError() {
NOTIMPLEMENTED();
}
void VideoDecoder::OnConfigureFlushDone(media::DecodeStatus status) {
DVLOG(3) << __func__;
DCHECK(pending_request_);
DCHECK_EQ(pending_request_->type, Request::Type::kConfigure);
if (status != media::DecodeStatus::OK) {
HandleError();
return;
}
// Processing continues in OnInitializeDone().
decoder_->Initialize(
ToVideoDecoderConfig(pending_request_->config), false, nullptr,
WTF::Bind(&VideoDecoder::OnInitializeDone, WrapWeakPersistent(this)),
WTF::BindRepeating(&VideoDecoder::OnOutput, WrapWeakPersistent(this)),
media::WaitingCB());
}
void VideoDecoder::OnInitializeDone(media::Status status) {
DVLOG(3) << __func__;
DCHECK(pending_request_);
......@@ -308,23 +389,6 @@ void VideoDecoder::OnFlushDone(media::DecodeStatus status) {
ProcessRequests();
}
void VideoDecoder::OnConfigureFlushDone(media::DecodeStatus status) {
DVLOG(3) << __func__;
DCHECK(pending_request_);
DCHECK_EQ(pending_request_->type, Request::Type::kConfigure);
if (status != media::DecodeStatus::OK) {
HandleError();
return;
}
// TODO(sandersd): Actually reconfigure the decoder.
// Processing continues in OnInitializeDone().
NOTIMPLEMENTED();
ProcessRequests();
}
void VideoDecoder::OnResetDone() {
DVLOG(3) << __func__;
DCHECK(pending_request_);
......
......@@ -8,6 +8,7 @@
#include <stdint.h>
#include <memory>
#include "media/base/media_log.h"
#include "media/base/status.h"
#include "media/base/video_decoder.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
......@@ -96,6 +97,7 @@ class MODULES_EXPORT VideoDecoder final : public ScriptWrappable {
// Could be a configure, flush, or reset. Decodes go in |pending_decodes_|.
Member<Request> pending_request_;
std::unique_ptr<media::MediaLog> media_log_;
// TODO(sandersd): Store the last config, flush, and reset so that duplicates
// can be elided.
std::unique_ptr<media::VideoDecoder> decoder_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment