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 |