|
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 |