Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1451)

Unified Diff: media/filters/audio_file_reader.cc

Issue 5550006: Implement WebKitClientImpl::loadAudioResource() to decode in-memory audio fil... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/audio_file_reader.cc
===================================================================
--- media/filters/audio_file_reader.cc (revision 0)
+++ media/filters/audio_file_reader.cc (revision 0)
@@ -0,0 +1,230 @@
+// Copyright (c) 2010 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/audio_file_reader.h"
+
+#include <string>
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "base/time.h"
+#include "media/audio/audio_util.h"
+#include "media/base/filters.h"
+#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/ffmpeg/ffmpeg_util.h"
+#include "media/filters/ffmpeg_glue.h"
+
+namespace media {
+
+AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol)
+ : protocol_(protocol),
scherkus (not reviewing) 2010/12/11 02:31:12 indent this by extra 2 spaces
Chris Rogers 2010/12/13 20:25:27 Done.
+ format_context_(NULL),
+ codec_context_(NULL),
+ codec_(NULL) {
+}
+
+AudioFileReader::~AudioFileReader() {
+ Close();
+}
+
+int AudioFileReader::channels() const {
+ return codec_context_->channels;
+}
+
+int AudioFileReader::sample_rate() const {
+ return codec_context_->sample_rate;
+}
+
+base::TimeDelta AudioFileReader::duration() const {
+ const AVRational av_time_base = {1, AV_TIME_BASE};
+ return ConvertTimestamp(av_time_base, format_context_->duration);
+}
+
+int64 AudioFileReader::number_of_frames() const {
+ return duration().InSecondsF() * sample_rate();
+}
+
+bool AudioFileReader::Open() {
+ // Add our data reader to the protocol list and get our unique key.
+ std::string key = FFmpegGlue::get()->AddProtocol(protocol_);
+
+ // Open FFmpeg AVFormatContext.
+ DCHECK(!format_context_);
+ AVFormatContext* context = NULL;
+
+ int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL);
+
+ // Remove our data reader from protocol list since av_open_input_file() setup
+ // the AVFormatContext with the data reader.
+ FFmpegGlue::get()->RemoveProtocol(protocol_);
+
+ if (result) {
+ DLOG(WARNING)
scherkus (not reviewing) 2010/12/11 02:31:12 de-indent by 2 spaces
Chris Rogers 2010/12/13 20:25:27 Done.
+ << "AudioFileReader::Open() : error in av_open_input_file() -"
+ << " result: " << result;
+ return false;
+ }
+
+ DCHECK(context);
+ format_context_ = context;
+
+ // Get the codec context.
+ codec_context_ = NULL;
+ for (unsigned i = 0; i < format_context_->nb_streams; ++i) {
+ AVCodecContext* c = format_context_->streams[i]->codec;
+ if (c->codec_type == CODEC_TYPE_AUDIO) {
+ codec_context_ = c;
+ break;
+ }
+ }
+
+ // Get the codec.
+ if (codec_context_) {
+ av_find_stream_info(format_context_);
+ codec_ = avcodec_find_decoder(codec_context_->codec_id);
+ if (codec_) {
+ if ((result = avcodec_open(codec_context_, codec_)) < 0) {
+ DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -"
+ << " result: " << result;
+ return false;
+ }
+
+ result = av_seek_frame(format_context_, 0, 0, 0);
+ }
+ } else {
+ return false;
scherkus (not reviewing) 2010/12/11 02:31:12 I'd flip this condition around and simply exit ear
Chris Rogers 2010/12/13 20:25:27 Done.
+ }
+
+ return true;
+}
+
+void AudioFileReader::Close() {
+ if (codec_context_ && codec_) {
scherkus (not reviewing) 2010/12/11 02:31:12 nit: the rest of this file seems to not include {
Chris Rogers 2010/12/13 20:25:27 Done.
+ avcodec_close(codec_context_);
+ }
+ codec_context_ = NULL;
+ codec_ = NULL;
+
+ if (format_context_) {
+ av_close_input_file(format_context_);
scherkus (not reviewing) 2010/12/11 02:31:12 de-indent by 2 spaces
Chris Rogers 2010/12/13 20:25:27 Done.
+ format_context_ = NULL;
+ }
+}
+
+bool AudioFileReader::Read(const std::vector<float*>& audio_data,
+ size_t number_of_frames) {
+ unsigned number_of_channels = channels();
scherkus (not reviewing) 2010/12/11 02:31:12 we haven't used unsigned anywhere in the media cod
Chris Rogers 2010/12/13 20:25:27 Done.
+ DCHECK_EQ(audio_data.size(), number_of_channels);
+ if (audio_data.size() != number_of_channels)
+ return false;
+
+ DCHECK(format_context_ && codec_context_);
+ if (!format_context_ || !codec_context_) {
+ DLOG(WARNING) << "AudioFileReader::Read() : reader is not opened!";
+ return false;
+ }
+
+ int16* output_buffer =
scherkus (not reviewing) 2010/12/11 02:31:12 crazy ffmpeg stuff: you must use av_malloc()!! ot
Chris Rogers 2010/12/13 20:25:27 Done.
+ static_cast<int16*>(malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE));
scherkus (not reviewing) 2010/12/11 02:31:12 indent by extra 2 spaces
Chris Rogers 2010/12/13 20:25:27 Done.
+
+ // Read until we hit EOF or we've read the requested number of frames.
+ AVPacket avpkt;
+ av_init_packet(&avpkt);
+
+ int result = 0;
+ unsigned current_frame = 0;
scherkus (not reviewing) 2010/12/11 02:31:12 unsigned -> size_t
Chris Rogers 2010/12/13 20:25:27 Done.
+
+ while (current_frame < number_of_frames
+ && (result = av_read_frame(format_context_, &avpkt)) >= 0) {
scherkus (not reviewing) 2010/12/11 02:31:12 nit: && should be at end of last line + following
Chris Rogers 2010/12/13 20:25:27 Done.
+ int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+ result = avcodec_decode_audio3(codec_context_,
+ output_buffer,
+ &out_size,
+ &avpkt);
+
+ if (result < 0) {
+ DLOG(WARNING)
+ << "AudioFileReader::Read() : error in avcodec_decode_audio3() -"
+ << result;
+ free(output_buffer);
+ return false;
+ }
+
+ // Determine the number of sample-frames we just decoded.
+ size_t sample_byte_size =
+ av_get_bits_per_sample_fmt(codec_context_->sample_fmt) >> 3;
scherkus (not reviewing) 2010/12/11 02:31:12 indent by extra 2 spaces
Chris Rogers 2010/12/13 20:25:27 Done.
+ unsigned frames_read = out_size / (number_of_channels * sample_byte_size);
scherkus (not reviewing) 2010/12/11 02:31:12 unsigned -> size_t
Chris Rogers 2010/12/13 20:25:27 Done.
+
+ // Truncate, if necessary, if the destination isn't big enough.
+ if (current_frame + frames_read > number_of_frames) {
+ frames_read = static_cast<int>(number_of_frames) - current_frame;
scherkus (not reviewing) 2010/12/11 02:31:12 is cast needed here? it looks like frames_read, n
Chris Rogers 2010/12/13 20:25:27 Done.
+ }
+
+ // Deinterleave each channel and convert to 32bit floating-point
+ // with nominal range -1.0 -> +1.0.
+ for (unsigned channel_index = 0; channel_index < number_of_channels;
scherkus (not reviewing) 2010/12/11 02:31:12 unsigned -> size_t OR unsinged -> int, number_of_c
Chris Rogers 2010/12/13 20:25:27 Done.
+ ++channel_index) {
+ if (!DeinterleaveAudioChannel(output_buffer,
+ audio_data[channel_index] + current_frame,
+ codec_context_->sample_fmt,
+ number_of_channels,
+ channel_index,
+ frames_read)) {
+ DLOG(WARNING)
+ << "AudioFileReader::Read() : Unsupported sample format : "
+ << codec_context_->sample_fmt
+ << " codec_->id : " << codec_->id;
+ return false;
+ }
+ }
+
+ current_frame += frames_read;
+ }
+
+ free(output_buffer);
+ return true; // success
scherkus (not reviewing) 2010/12/11 02:31:12 no need for comment
Chris Rogers 2010/12/13 20:25:27 Done.
+}
+
+InMemoryDataReader::InMemoryDataReader(const char* data, int64 size)
+ : data_(data),
scherkus (not reviewing) 2010/12/11 02:31:12 indent by 2 extra spaces
Chris Rogers 2010/12/13 20:25:27 Done.
+ size_(size),
+ position_(0) {
+}
+
+int InMemoryDataReader::Read(int size, uint8* data) {
+ if (size < 0)
+ return -1;
+
+ int64 available_bytes = size_ - position_;
+ if (size > available_bytes)
+ size = available_bytes;
+
+ memcpy(data, data_ + position_, size);
+ position_ += size;
+ return size;
+}
+
+bool InMemoryDataReader::GetPosition(int64* position_out) {
+ if (position_out)
+ *position_out = position_;
+ return true;
+}
+
+bool InMemoryDataReader::SetPosition(int64 position) {
+ if (position >= size_)
+ return false;
+ position_ = position;
+ return true;
+}
+
+bool InMemoryDataReader::GetSize(int64* size_out) {
+ if (size_out)
+ *size_out = size_;
+ return true;
+}
+
+bool InMemoryDataReader::IsStreaming() {
+ return false;
+}
+
+} // namespace media
Property changes on: media/filters/audio_file_reader.cc
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698