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

Side by Side Diff: media/filters/audio_file_reader.cc

Issue 10912080: Switch to AVIO instead of a custom FFmpeg URLProtocol handler. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase. Created 8 years, 1 month 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 unified diff | Download patch
« no previous file with comments | « media/filters/audio_file_reader.h ('k') | media/filters/ffmpeg_audio_decoder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/audio_file_reader.h" 5 #include "media/filters/audio_file_reader.h"
6 6
7 #include <string> 7 #include "base/logging.h"
8 #include "base/basictypes.h"
9 #include "base/string_util.h"
10 #include "base/time.h" 8 #include "base/time.h"
11 #include "media/base/audio_bus.h" 9 #include "media/base/audio_bus.h"
12 #include "media/ffmpeg/ffmpeg_common.h" 10 #include "media/ffmpeg/ffmpeg_common.h"
13 #include "media/filters/ffmpeg_glue.h" 11 #include "media/filters/ffmpeg_glue.h"
14 12
15 namespace media { 13 namespace media {
16 14
17 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) 15 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol)
18 : protocol_(protocol), 16 : codec_context_(NULL),
19 format_context_(NULL), 17 stream_index_(0),
20 codec_context_(NULL), 18 protocol_(protocol) {
21 stream_index_(0) {
22 } 19 }
23 20
24 AudioFileReader::~AudioFileReader() { 21 AudioFileReader::~AudioFileReader() {
25 Close(); 22 Close();
26 } 23 }
27 24
28 int AudioFileReader::channels() const { 25 int AudioFileReader::channels() const {
29 return codec_context_->channels; 26 return codec_context_->channels;
30 } 27 }
31 28
32 int AudioFileReader::sample_rate() const { 29 int AudioFileReader::sample_rate() const {
33 return codec_context_->sample_rate; 30 return codec_context_->sample_rate;
34 } 31 }
35 32
36 base::TimeDelta AudioFileReader::duration() const { 33 base::TimeDelta AudioFileReader::duration() const {
37 const AVRational av_time_base = {1, AV_TIME_BASE}; 34 const AVRational av_time_base = {1, AV_TIME_BASE};
38 35
39 // Add one microsecond to avoid rounding-down errors which can occur when 36 // Add one microsecond to avoid rounding-down errors which can occur when
40 // |duration| has been calculated from an exact number of sample-frames. 37 // |duration| has been calculated from an exact number of sample-frames.
41 // One microsecond is much less than the time of a single sample-frame 38 // One microsecond is much less than the time of a single sample-frame
42 // at any real-world sample-rate. 39 // at any real-world sample-rate.
43 return ConvertFromTimeBase(av_time_base, format_context_->duration + 1); 40 return ConvertFromTimeBase(
41 av_time_base, glue_->format_context()->duration + 1);
44 } 42 }
45 43
46 int64 AudioFileReader::number_of_frames() const { 44 int64 AudioFileReader::number_of_frames() const {
47 return static_cast<int64>(duration().InSecondsF() * sample_rate()); 45 return static_cast<int64>(duration().InSecondsF() * sample_rate());
48 } 46 }
49 47
50 bool AudioFileReader::Open() { 48 bool AudioFileReader::Open() {
51 // Add our data reader to the protocol list and get our unique key. 49 glue_.reset(new FFmpegGlue(protocol_));
52 std::string key = FFmpegGlue::GetInstance()->AddProtocol(protocol_); 50 AVFormatContext* format_context = glue_->format_context();
53 51
54 // Open FFmpeg AVFormatContext. 52 // Open FFmpeg AVFormatContext.
55 DCHECK(!format_context_); 53 if (!glue_->OpenContext()) {
56 AVFormatContext* context = NULL; 54 DLOG(WARNING) << "AudioFileReader::Open() : error in avformat_open_input()";
57
58 int result = avformat_open_input(&context, key.c_str(), NULL, NULL);
59
60 // Remove our data reader from protocol list since avformat_open_input() setup
61 // the AVFormatContext with the data reader.
62 FFmpegGlue::GetInstance()->RemoveProtocol(protocol_);
63
64 if (result) {
65 DLOG(WARNING)
66 << "AudioFileReader::Open() : error in avformat_open_input() -"
67 << " result: " << result;
68 return false; 55 return false;
69 } 56 }
70 57
71 DCHECK(context);
72 format_context_ = context;
73
74 // Get the codec context. 58 // Get the codec context.
75 codec_context_ = NULL; 59 codec_context_ = NULL;
76 for (size_t i = 0; i < format_context_->nb_streams; ++i) { 60 for (size_t i = 0; i < format_context->nb_streams; ++i) {
77 AVCodecContext* c = format_context_->streams[i]->codec; 61 AVCodecContext* c = format_context->streams[i]->codec;
78 if (c->codec_type == AVMEDIA_TYPE_AUDIO) { 62 if (c->codec_type == AVMEDIA_TYPE_AUDIO) {
79 codec_context_ = c; 63 codec_context_ = c;
80 stream_index_ = i; 64 stream_index_ = i;
81 break; 65 break;
82 } 66 }
83 } 67 }
84 68
85 // Get the codec. 69 // Get the codec.
86 if (!codec_context_) 70 if (!codec_context_)
87 return false; 71 return false;
88 72
89 avformat_find_stream_info(format_context_, NULL); 73 int result = avformat_find_stream_info(format_context, NULL);
74 if (result < 0) {
75 DLOG(WARNING)
76 << "AudioFileReader::Open() : error in avformat_find_stream_info()";
77 return false;
78 }
79
90 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); 80 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
91 if (codec) { 81 if (codec) {
92 if ((result = avcodec_open2(codec_context_, codec, NULL)) < 0) { 82 if ((result = avcodec_open2(codec_context_, codec, NULL)) < 0) {
93 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -" 83 DLOG(WARNING) << "AudioFileReader::Open() : could not open codec -"
94 << " result: " << result; 84 << " result: " << result;
95 return false; 85 return false;
96 } 86 }
97 } else { 87 } else {
98 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec -" 88 DLOG(WARNING) << "AudioFileReader::Open() : could not find codec -"
99 << " result: " << result; 89 << " result: " << result;
100 return false; 90 return false;
101 } 91 }
102 92
103 return true; 93 return true;
104 } 94 }
105 95
106 void AudioFileReader::Close() { 96 void AudioFileReader::Close() {
107 if (codec_context_) { 97 if (codec_context_) {
108 avcodec_close(codec_context_); 98 avcodec_close(codec_context_);
109 codec_context_ = NULL; 99 codec_context_ = NULL;
110 } 100 }
111
112 if (format_context_) {
113 avformat_close_input(&format_context_);
114 format_context_ = NULL;
115 }
116 } 101 }
117 102
118 int AudioFileReader::Read(AudioBus* audio_bus) { 103 int AudioFileReader::Read(AudioBus* audio_bus) {
119 DCHECK(format_context_ && codec_context_) << 104 DCHECK(glue_.get() && codec_context_) <<
120 "AudioFileReader::Read() : reader is not opened!"; 105 "AudioFileReader::Read() : reader is not opened!";
121 106
122 DCHECK_EQ(audio_bus->channels(), channels()); 107 DCHECK_EQ(audio_bus->channels(), channels());
123 if (audio_bus->channels() != channels()) 108 if (audio_bus->channels() != channels())
124 return 0; 109 return 0;
125 110
126 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); 111 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt);
127 112
128 // Holds decoded audio. 113 // Holds decoded audio.
129 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> av_frame(avcodec_alloc_frame()); 114 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> av_frame(avcodec_alloc_frame());
130 115
131 // Read until we hit EOF or we've read the requested number of frames. 116 // Read until we hit EOF or we've read the requested number of frames.
132 AVPacket packet; 117 AVPacket packet;
133 int current_frame = 0; 118 int current_frame = 0;
134 bool continue_decoding = true; 119 bool continue_decoding = true;
135 120
136 while (current_frame < audio_bus->frames() && continue_decoding && 121 while (current_frame < audio_bus->frames() && continue_decoding &&
137 av_read_frame(format_context_, &packet) >= 0 && 122 av_read_frame(glue_->format_context(), &packet) >= 0 &&
138 av_dup_packet(&packet) >= 0) { 123 av_dup_packet(&packet) >= 0) {
139 // Skip packets from other streams. 124 // Skip packets from other streams.
140 if (packet.stream_index != stream_index_) { 125 if (packet.stream_index != stream_index_) {
141 av_free_packet(&packet); 126 av_free_packet(&packet);
142 continue; 127 continue;
143 } 128 }
144 129
145 // Make a shallow copy of packet so we can slide packet.data as frames are 130 // Make a shallow copy of packet so we can slide packet.data as frames are
146 // decoded from the packet; otherwise av_free_packet() will corrupt memory. 131 // decoded from the packet; otherwise av_free_packet() will corrupt memory.
147 AVPacket packet_temp = packet; 132 AVPacket packet_temp = packet;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 // Zero any remaining frames. 176 // Zero any remaining frames.
192 audio_bus->ZeroFramesPartial( 177 audio_bus->ZeroFramesPartial(
193 current_frame, audio_bus->frames() - current_frame); 178 current_frame, audio_bus->frames() - current_frame);
194 179
195 // Returns the actual number of sample-frames decoded. 180 // Returns the actual number of sample-frames decoded.
196 // Ideally this represents the "true" exact length of the file. 181 // Ideally this represents the "true" exact length of the file.
197 return current_frame; 182 return current_frame;
198 } 183 }
199 184
200 } // namespace media 185 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/audio_file_reader.h ('k') | media/filters/ffmpeg_audio_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698