Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "media/filters/audio_file_reader.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include "base/basictypes.h" | |
| 9 #include "base/string_util.h" | |
| 10 #include "base/time.h" | |
| 11 #include "media/audio/audio_util.h" | |
| 12 #include "media/base/filters.h" | |
| 13 #include "media/ffmpeg/ffmpeg_common.h" | |
| 14 #include "media/ffmpeg/ffmpeg_util.h" | |
| 15 #include "media/filters/ffmpeg_glue.h" | |
| 16 | |
| 17 namespace media { | |
| 18 | |
| 19 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) | |
| 20 : 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.
| |
| 21 format_context_(NULL), | |
| 22 codec_context_(NULL), | |
| 23 codec_(NULL) { | |
| 24 } | |
| 25 | |
| 26 AudioFileReader::~AudioFileReader() { | |
| 27 Close(); | |
| 28 } | |
| 29 | |
| 30 int AudioFileReader::channels() const { | |
| 31 return codec_context_->channels; | |
| 32 } | |
| 33 | |
| 34 int AudioFileReader::sample_rate() const { | |
| 35 return codec_context_->sample_rate; | |
| 36 } | |
| 37 | |
| 38 base::TimeDelta AudioFileReader::duration() const { | |
| 39 const AVRational av_time_base = {1, AV_TIME_BASE}; | |
| 40 return ConvertTimestamp(av_time_base, format_context_->duration); | |
| 41 } | |
| 42 | |
| 43 int64 AudioFileReader::number_of_frames() const { | |
| 44 return duration().InSecondsF() * sample_rate(); | |
| 45 } | |
| 46 | |
| 47 bool AudioFileReader::Open() { | |
| 48 // Add our data reader to the protocol list and get our unique key. | |
| 49 std::string key = FFmpegGlue::get()->AddProtocol(protocol_); | |
| 50 | |
| 51 // Open FFmpeg AVFormatContext. | |
| 52 DCHECK(!format_context_); | |
| 53 AVFormatContext* context = NULL; | |
| 54 | |
| 55 int result = av_open_input_file(&context, key.c_str(), NULL, 0, NULL); | |
| 56 | |
| 57 // Remove our data reader from protocol list since av_open_input_file() setup | |
| 58 // the AVFormatContext with the data reader. | |
| 59 FFmpegGlue::get()->RemoveProtocol(protocol_); | |
| 60 | |
| 61 if (result) { | |
| 62 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.
| |
| 63 << "AudioFileReader::Open() : error in av_open_input_file() -" | |
| 64 << " result: " << result; | |
| 65 return false; | |
| 66 } | |
| 67 | |
| 68 DCHECK(context); | |
| 69 format_context_ = context; | |
| 70 | |
| 71 // Get the codec context. | |
| 72 codec_context_ = NULL; | |
| 73 for (unsigned i = 0; i < format_context_->nb_streams; ++i) { | |
| 74 AVCodecContext* c = format_context_->streams[i]->codec; | |
| 75 if (c->codec_type == CODEC_TYPE_AUDIO) { | |
| 76 codec_context_ = c; | |
| 77 break; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 // Get the codec. | |
| 82 if (codec_context_) { | |
| 83 av_find_stream_info(format_context_); | |
| 84 codec_ = avcodec_find_decoder(codec_context_->codec_id); | |
| 85 if (codec_) { | |
| 86 if ((result = avcodec_open(codec_context_, codec_)) < 0) { | |
| 87 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -" | |
| 88 << " result: " << result; | |
| 89 return false; | |
| 90 } | |
| 91 | |
| 92 result = av_seek_frame(format_context_, 0, 0, 0); | |
| 93 } | |
| 94 } else { | |
| 95 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.
| |
| 96 } | |
| 97 | |
| 98 return true; | |
| 99 } | |
| 100 | |
| 101 void AudioFileReader::Close() { | |
| 102 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.
| |
| 103 avcodec_close(codec_context_); | |
| 104 } | |
| 105 codec_context_ = NULL; | |
| 106 codec_ = NULL; | |
| 107 | |
| 108 if (format_context_) { | |
| 109 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.
| |
| 110 format_context_ = NULL; | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 bool AudioFileReader::Read(const std::vector<float*>& audio_data, | |
| 115 size_t number_of_frames) { | |
| 116 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.
| |
| 117 DCHECK_EQ(audio_data.size(), number_of_channels); | |
| 118 if (audio_data.size() != number_of_channels) | |
| 119 return false; | |
| 120 | |
| 121 DCHECK(format_context_ && codec_context_); | |
| 122 if (!format_context_ || !codec_context_) { | |
| 123 DLOG(WARNING) << "AudioFileReader::Read() : reader is not opened!"; | |
| 124 return false; | |
| 125 } | |
| 126 | |
| 127 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.
| |
| 128 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.
| |
| 129 | |
| 130 // Read until we hit EOF or we've read the requested number of frames. | |
| 131 AVPacket avpkt; | |
| 132 av_init_packet(&avpkt); | |
| 133 | |
| 134 int result = 0; | |
| 135 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.
| |
| 136 | |
| 137 while (current_frame < number_of_frames | |
| 138 && (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.
| |
| 139 int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; | |
| 140 result = avcodec_decode_audio3(codec_context_, | |
| 141 output_buffer, | |
| 142 &out_size, | |
| 143 &avpkt); | |
| 144 | |
| 145 if (result < 0) { | |
| 146 DLOG(WARNING) | |
| 147 << "AudioFileReader::Read() : error in avcodec_decode_audio3() -" | |
| 148 << result; | |
| 149 free(output_buffer); | |
| 150 return false; | |
| 151 } | |
| 152 | |
| 153 // Determine the number of sample-frames we just decoded. | |
| 154 size_t sample_byte_size = | |
| 155 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.
| |
| 156 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.
| |
| 157 | |
| 158 // Truncate, if necessary, if the destination isn't big enough. | |
| 159 if (current_frame + frames_read > number_of_frames) { | |
| 160 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.
| |
| 161 } | |
| 162 | |
| 163 // Deinterleave each channel and convert to 32bit floating-point | |
| 164 // with nominal range -1.0 -> +1.0. | |
| 165 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.
| |
| 166 ++channel_index) { | |
| 167 if (!DeinterleaveAudioChannel(output_buffer, | |
| 168 audio_data[channel_index] + current_frame, | |
| 169 codec_context_->sample_fmt, | |
| 170 number_of_channels, | |
| 171 channel_index, | |
| 172 frames_read)) { | |
| 173 DLOG(WARNING) | |
| 174 << "AudioFileReader::Read() : Unsupported sample format : " | |
| 175 << codec_context_->sample_fmt | |
| 176 << " codec_->id : " << codec_->id; | |
| 177 return false; | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 current_frame += frames_read; | |
| 182 } | |
| 183 | |
| 184 free(output_buffer); | |
| 185 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.
| |
| 186 } | |
| 187 | |
| 188 InMemoryDataReader::InMemoryDataReader(const char* data, int64 size) | |
| 189 : 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.
| |
| 190 size_(size), | |
| 191 position_(0) { | |
| 192 } | |
| 193 | |
| 194 int InMemoryDataReader::Read(int size, uint8* data) { | |
| 195 if (size < 0) | |
| 196 return -1; | |
| 197 | |
| 198 int64 available_bytes = size_ - position_; | |
| 199 if (size > available_bytes) | |
| 200 size = available_bytes; | |
| 201 | |
| 202 memcpy(data, data_ + position_, size); | |
| 203 position_ += size; | |
| 204 return size; | |
| 205 } | |
| 206 | |
| 207 bool InMemoryDataReader::GetPosition(int64* position_out) { | |
| 208 if (position_out) | |
| 209 *position_out = position_; | |
| 210 return true; | |
| 211 } | |
| 212 | |
| 213 bool InMemoryDataReader::SetPosition(int64 position) { | |
| 214 if (position >= size_) | |
| 215 return false; | |
| 216 position_ = position; | |
| 217 return true; | |
| 218 } | |
| 219 | |
| 220 bool InMemoryDataReader::GetSize(int64* size_out) { | |
| 221 if (size_out) | |
| 222 *size_out = size_; | |
| 223 return true; | |
| 224 } | |
| 225 | |
| 226 bool InMemoryDataReader::IsStreaming() { | |
| 227 return false; | |
| 228 } | |
| 229 | |
| 230 } // namespace media | |
| OLD | NEW |