| Index: services/media/framework_ffmpeg/ffmpeg_decoder_base.cc
|
| diff --git a/services/media/framework_ffmpeg/ffmpeg_decoder_base.cc b/services/media/framework_ffmpeg/ffmpeg_decoder_base.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c0cb980906c7ed8f2d50034181e73c62b93b19bc
|
| --- /dev/null
|
| +++ b/services/media/framework_ffmpeg/ffmpeg_decoder_base.cc
|
| @@ -0,0 +1,97 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/logging.h"
|
| +#include "services/media/framework_ffmpeg/ffmpeg_decoder_base.h"
|
| +#include "services/media/framework_ffmpeg/ffmpeg_type_converters.h"
|
| +
|
| +namespace mojo {
|
| +namespace media {
|
| +
|
| +FfmpegDecoderBase::FfmpegDecoderBase(AvCodecContextPtr av_codec_context) :
|
| + av_codec_context_(std::move(av_codec_context)),
|
| + av_frame_(av_frame_alloc()) {
|
| + DCHECK(av_codec_context);
|
| +}
|
| +
|
| +FfmpegDecoderBase::~FfmpegDecoderBase() {}
|
| +
|
| +std::unique_ptr<StreamType> FfmpegDecoderBase::output_stream_type() {
|
| + return StreamTypeFromAVCodecContext(*av_codec_context_);
|
| +}
|
| +
|
| +void FfmpegDecoderBase::Flush() {
|
| + DCHECK(av_codec_context_);
|
| + avcodec_flush_buffers(av_codec_context_.get());
|
| +}
|
| +
|
| +bool FfmpegDecoderBase::TransformPacket(
|
| + const PacketPtr& input,
|
| + bool new_input,
|
| + PayloadAllocator* allocator,
|
| + PacketPtr* output) {
|
| + DCHECK(input);
|
| + DCHECK(allocator);
|
| + DCHECK(output);
|
| +
|
| + *output = nullptr;
|
| +
|
| + if (new_input) {
|
| + PrepareInputPacket(input);
|
| + }
|
| +
|
| + bool frame_decoded = false;
|
| + int input_bytes_used = Decode(allocator, &frame_decoded);
|
| + if (input_bytes_used < 0) {
|
| + // Decode failed.
|
| + return UnprepareInputPacket(input, output);
|
| + }
|
| +
|
| + if (frame_decoded) {
|
| + DCHECK(allocator);
|
| + *output = CreateOutputPacket(allocator);
|
| + av_frame_unref(av_frame_.get());
|
| + }
|
| +
|
| + CHECK(input_bytes_used <= av_packet_.size)
|
| + << "Ffmpeg decoder read beyond end of packet";
|
| + av_packet_.size -= input_bytes_used;
|
| + av_packet_.data += input_bytes_used;
|
| +
|
| + if (av_packet_.size != 0 || (input->end_of_stream() && frame_decoded)) {
|
| + // The input packet is only partially decoded, or it's an end-of-stream
|
| + // packet and we're still draining. Let the caller know we want to see the
|
| + // input packet again.
|
| + return false;
|
| + }
|
| +
|
| + // Used up the whole input packet, and, if we were draining, we're done with
|
| + // that too.
|
| + return UnprepareInputPacket(input, output);
|
| +}
|
| +
|
| +void FfmpegDecoderBase::PrepareInputPacket(const PacketPtr& input) {
|
| + av_init_packet(&av_packet_);
|
| + av_packet_.data = reinterpret_cast<uint8_t*>(input->payload());
|
| + av_packet_.size = input->size();
|
| +}
|
| +
|
| +bool FfmpegDecoderBase::UnprepareInputPacket(
|
| + const PacketPtr& input,
|
| + PacketPtr* output) {
|
| + if (input->end_of_stream()) {
|
| + // Indicate end of stream. This happens when we're draining for the last
|
| + // time, so there should be no output packet yet.
|
| + DCHECK(*output == nullptr);
|
| + *output = CreateOutputEndOfStreamPacket();
|
| + }
|
| +
|
| + av_packet_.size = 0;
|
| + av_packet_.data = nullptr;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace media
|
| +} // namespace mojo
|
|
|