Chromium Code Reviews| Index: media/filters/ffmpeg_text_decoder.cc |
| diff --git a/media/filters/ffmpeg_text_decoder.cc b/media/filters/ffmpeg_text_decoder.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..370abdf322f8fb30a12594101f8afe4af54cffa6 |
| --- /dev/null |
| +++ b/media/filters/ffmpeg_text_decoder.cc |
| @@ -0,0 +1,126 @@ |
| +// Copyright (c) 2013 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 "media/filters/ffmpeg_text_decoder.h" |
| + |
| +#include "base/callback_helpers.h" |
| +#include "media/base/bind_to_loop.h" |
| +#include "media/base/decoder_buffer.h" |
| +#include "media/base/demuxer.h" |
| +#include "media/base/text_buffer.h" |
| +#include "media/filters/ffmpeg_glue.h" |
| + |
| +namespace media { |
| + |
| +FFmpegTextDecoder::FFmpegTextDecoder( |
| + const scoped_refptr<base::MessageLoopProxy>& message_loop) |
| + : message_loop_(message_loop), |
| + weak_factory_(this) { |
| +} |
| + |
| +FFmpegTextDecoder::~FFmpegTextDecoder() { |
| +} |
| + |
| +void FFmpegTextDecoder::Initialize(Demuxer* demuxer) { |
| + DCHECK(message_loop_->BelongsToCurrentThread()); |
| + DCHECK_NE(demuxer, static_cast<Demuxer*>(NULL)); |
| + |
| + FFmpegGlue::InitializeFFmpeg(); |
| + |
| + if (!demuxer_streams_.empty()) { |
| + // TODO(scherkus): initialization currently happens more than once in |
| + // PipelineIntegrationTest.BasicPlayback. |
|
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
Do we really need this? I don't think we should be
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
|
| + LOG(ERROR) << "Initialize has already been called."; |
| + CHECK(false); |
| + } |
| + |
| + weak_this_ = weak_factory_.GetWeakPtr(); |
| + |
| + int stream_count = demuxer->GetStreamCount(); |
| + demuxer_streams_.reserve(stream_count); |
| + |
| + for (int idx = 0; idx < stream_count; ++idx) { |
| + DemuxerStream* stream = demuxer->GetStreamByIndex(idx); |
| + if (stream == NULL || stream->type() != DemuxerStream::TEXT) { |
| + demuxer_streams_.push_back(NULL); |
| + } else { |
| + demuxer_streams_.push_back(stream); |
| + } |
| + } |
| + |
| + read_callbacks_.resize(stream_count); |
| +} |
| + |
| +void FFmpegTextDecoder::Read(int index, const ReadCB& read_cb) { |
| + DCHECK(message_loop_->BelongsToCurrentThread()); |
| + DCHECK(!read_cb.is_null()); |
| + |
| + ReadCB& cb = read_callbacks_[index]; |
| + CHECK(cb.is_null()) << "Overlapping decodes are not supported."; |
| + |
| + cb = BindToCurrentLoop(read_cb); |
| + |
| + DemuxerStream* stream = demuxer_streams_[index]; |
| + CHECK(stream); |
| + |
| + stream->Read(base::Bind( |
| + &FFmpegTextDecoder::BufferReady, weak_this_, index)); |
| +} |
| + |
| +void FFmpegTextDecoder::BufferReady( |
|
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
nit:There doesn't appear to be anything FFmpeg spe
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
|
| + int index, |
| + DemuxerStream::Status status, |
| + const scoped_refptr<DecoderBuffer>& input) { |
| + DCHECK(message_loop_->BelongsToCurrentThread()); |
| + |
| + ReadCB& read_cb = read_callbacks_[index]; |
| + DCHECK(!read_cb.is_null()); |
| + |
| + if (status == DemuxerStream::kAborted) { |
| + DCHECK(!input.get()); |
| + base::ResetAndReturn(&read_cb).Run(index, NULL); |
| + return; |
| + } |
| + |
| + if (input->end_of_stream()) { |
| + base::ResetAndReturn(&read_cb).Run(index, NULL); |
| + return; |
| + } |
| + |
| + DCHECK_EQ(status, DemuxerStream::kOk); |
| + DCHECK(input.get()); |
| + |
| + scoped_refptr<TextBuffer> text_buffer( |
| + new TextBuffer(input->timestamp(), |
| + input->duration())); |
| + |
| + // The side data here contains both the cue id and cue settings, |
| + // separated using a 0xFF marker. |
| + const uint8* side_data = input->side_data(); |
| + DCHECK_NE(side_data, static_cast<const uint8*>(NULL)); |
| + |
| + int side_data_size = input->side_data_size(); |
| + DCHECK_GE(side_data_size, 1); |
| + |
| + const uint8* side_data_end = side_data + side_data_size; |
| + |
| + const uint8* id_end = std::find(side_data, side_data_end, 0xFF); |
| + DCHECK_NE(id_end, side_data_end); |
| + DCHECK_EQ(*id_end, 0xFF); |
| + |
| + int id_size = id_end - side_data; |
| + DCHECK_GE(id_size, 0); |
| + |
| + text_buffer->set_id(side_data, id_size); |
| + |
| + int settings_size = side_data_size - id_size - 1; |
| + DCHECK_GE(settings_size, 0); |
| + |
| + text_buffer->set_settings(id_end + 1, settings_size); |
| + text_buffer->set_text(input->data(), input->data_size()); |
| + |
| + base::ResetAndReturn(&read_cb).Run(index, text_buffer); |
| +} |
| + |
| +} // namespace media |