Chromium Code Reviews| 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..517cc7a2f2189e3a6a3c98556bcda911e7877fa4 |
| --- /dev/null |
| +++ b/services/media/framework_ffmpeg/ffmpeg_decoder_base.cc |
| @@ -0,0 +1,106 @@ |
| +// 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(AVCodecContext *av_codec_context) : |
| + av_codec_context_(av_codec_context), |
| + av_frame_(av_frame_alloc()), |
| + next_presentation_time_(0) { |
| + DCHECK(av_codec_context); |
| +} |
| + |
| +FfmpegDecoderBase::~FfmpegDecoderBase() {} |
| + |
| +Result FfmpegDecoderBase::Init(const StreamType& stream_type) { |
| + return Result::kOk; |
|
johngro
2016/03/01 01:31:38
Since this class is already abstract, why provide
dalesat
2016/03/01 20:43:01
AVCodecContext is established in the constructor a
|
| +} |
| + |
| +std::unique_ptr<StreamType> FfmpegDecoderBase::output_stream_type() { |
| + return StreamTypeFromAVCodecContext(av_codec_context_.get()); |
| +} |
| + |
| +void FfmpegDecoderBase::Flush() { |
| + avcodec_flush_buffers(av_codec_context_.get()); |
|
johngro
2016/03/01 01:31:38
avcodec_flush_buffers is not safe against being ca
dalesat
2016/03/01 20:43:01
Done.
|
| +} |
| + |
| +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); |
|
johngro
2016/03/01 01:31:38
ssize_t instead of int?
dalesat
2016/03/01 20:43:01
Decode wraps one of two avcodec_decode_* functions
|
| + if (input_bytes_used < 0) { |
| + // Decode failed. |
| + return UnprepareInputPacket(input, output); |
| + } |
| + |
| + if (frame_decoded) { |
| + *output = PacketFromAvFrame(allocator); |
| + } |
| + |
| + av_packet_.size -= input_bytes_used; |
| + av_packet_.data += input_bytes_used; |
|
johngro
2016/03/01 01:31:38
DCHECK(av_packet_.size >= input_bytes_used) and ru
dalesat
2016/03/01 20:43:01
Added a CHECK
|
| + |
| + 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 = Packet::CreateEndOfStream(next_presentation_time_); |
|
johngro
2016/03/01 01:31:38
what is the purpose of putting a PTS on an empty E
dalesat
2016/03/01 20:43:01
Design discussion.
|
| + } |
| + |
| + av_packet_.size = 0; |
| + av_packet_.data = nullptr; |
| + |
| + return true; |
| +} |
| + |
| +PacketPtr FfmpegDecoderBase::PacketFromAvFrame(PayloadAllocator* allocator) { |
| + DCHECK(allocator); |
| + |
| + PacketPtr packet = CreateOutputPacket(allocator); |
| + av_frame_unref(av_frame_.get()); |
| + next_presentation_time_ = packet->presentation_time() + packet->duration(); |
|
johngro
2016/03/01 01:31:38
either presentation_time or duration may be undefi
dalesat
2016/03/01 20:43:01
I've moved the next_presentation_time_ into the su
|
| + return packet; |
| +} |
| + |
| +} // namespace media |
| +} // namespace mojo |