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

Side by Side Diff: media/webm/webm_stream_parser.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: AVIO! Created 8 years, 2 months 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
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/webm/webm_stream_parser.h" 5 #include "media/webm/webm_stream_parser.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 22 matching lines...) Expand all
33 bool Parse(const uint8* data, int size); 33 bool Parse(const uint8* data, int size);
34 34
35 const AudioDecoderConfig& audio_config() const; 35 const AudioDecoderConfig& audio_config() const;
36 const VideoDecoderConfig& video_config() const; 36 const VideoDecoderConfig& video_config() const;
37 37
38 private: 38 private:
39 static const uint8 kWebMHeader[]; 39 static const uint8 kWebMHeader[];
40 static const int kSegmentSizeOffset; 40 static const int kSegmentSizeOffset;
41 static const uint8 kEmptyCluster[]; 41 static const uint8 kEmptyCluster[];
42 42
43 AVFormatContext* CreateFormatContext(const uint8* data, int size); 43 bool OpenFormatContext(const uint8* data, int size);
44 bool SetupStreamConfigs(); 44 bool SetupStreamConfigs();
45 45
46 AudioDecoderConfig audio_config_; 46 AudioDecoderConfig audio_config_;
47 VideoDecoderConfig video_config_; 47 VideoDecoderConfig video_config_;
48 48
49 // Backing buffer for |url_protocol_|. 49 // Backing buffer for |url_protocol_|.
50 scoped_array<uint8> url_protocol_buffer_; 50 scoped_array<uint8> url_protocol_buffer_;
51 51
52 // Protocol used by |format_context_|. It must outlive the context object. 52 // Protocol used by FFmpegGlue. It must outlive the context object.
53 scoped_ptr<InMemoryUrlProtocol> url_protocol_; 53 scoped_ptr<InMemoryUrlProtocol> url_protocol_;
54 54
55 // FFmpeg format context for this demuxer. It is created by 55 // Glue for interfacing InMemoryUrlProtocol with FFmpeg.
56 // avformat_open_input() during demuxer initialization and cleaned up with 56 scoped_ptr<FFmpegGlue> glue_;
57 // DestroyAVFormatContext() in the destructor.
58 AVFormatContext* format_context_;
59 57
60 DISALLOW_COPY_AND_ASSIGN(FFmpegConfigHelper); 58 DISALLOW_COPY_AND_ASSIGN(FFmpegConfigHelper);
61 }; 59 };
62 60
63 // WebM File Header. This is prepended to the INFO & TRACKS 61 // WebM File Header. This is prepended to the INFO & TRACKS
64 // data passed to Init() before handing it to FFmpeg. Essentially 62 // data passed to Init() before handing it to FFmpeg. Essentially
65 // we are making the INFO & TRACKS data look like a small WebM 63 // we are making the INFO & TRACKS data look like a small WebM
66 // file so we can use FFmpeg to initialize the AVFormatContext. 64 // file so we can use FFmpeg to initialize the AVFormatContext.
67 const uint8 FFmpegConfigHelper::kWebMHeader[] = { 65 const uint8 FFmpegConfigHelper::kWebMHeader[] = {
68 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f) 66 0x1A, 0x45, 0xDF, 0xA3, 0x9F, // EBML (size = 0x1f)
(...skipping 11 matching lines...) Expand all
80 }; 78 };
81 79
82 // Offset of the segment size field in kWebMHeader. Used to update 80 // Offset of the segment size field in kWebMHeader. Used to update
83 // the segment size field before handing the buffer to FFmpeg. 81 // the segment size field before handing the buffer to FFmpeg.
84 const int FFmpegConfigHelper::kSegmentSizeOffset = sizeof(kWebMHeader) - 8; 82 const int FFmpegConfigHelper::kSegmentSizeOffset = sizeof(kWebMHeader) - 8;
85 83
86 const uint8 FFmpegConfigHelper::kEmptyCluster[] = { 84 const uint8 FFmpegConfigHelper::kEmptyCluster[] = {
87 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0) 85 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0)
88 }; 86 };
89 87
90 FFmpegConfigHelper::FFmpegConfigHelper() : format_context_(NULL) {} 88 FFmpegConfigHelper::FFmpegConfigHelper() {}
91 89
92 FFmpegConfigHelper::~FFmpegConfigHelper() { 90 FFmpegConfigHelper::~FFmpegConfigHelper() {
93 if (!format_context_)
94 return;
95
96 DestroyAVFormatContext(format_context_);
97 format_context_ = NULL;
98
99 if (url_protocol_.get()) { 91 if (url_protocol_.get()) {
100 FFmpegGlue::GetInstance()->RemoveProtocol(url_protocol_.get());
101 url_protocol_.reset(); 92 url_protocol_.reset();
102 url_protocol_buffer_.reset(); 93 url_protocol_buffer_.reset();
103 } 94 }
95
96 if (glue_.get())
97 glue_.reset();
104 } 98 }
105 99
106 bool FFmpegConfigHelper::Parse(const uint8* data, int size) { 100 bool FFmpegConfigHelper::Parse(const uint8* data, int size) {
107 format_context_ = CreateFormatContext(data, size); 101 return OpenFormatContext(data, size) && SetupStreamConfigs();
108 return format_context_ && SetupStreamConfigs();
109 } 102 }
110 103
111 const AudioDecoderConfig& FFmpegConfigHelper::audio_config() const { 104 const AudioDecoderConfig& FFmpegConfigHelper::audio_config() const {
112 return audio_config_; 105 return audio_config_;
113 } 106 }
114 107
115 const VideoDecoderConfig& FFmpegConfigHelper::video_config() const { 108 const VideoDecoderConfig& FFmpegConfigHelper::video_config() const {
116 return video_config_; 109 return video_config_;
117 } 110 }
118 111
119 AVFormatContext* FFmpegConfigHelper::CreateFormatContext(const uint8* data, 112 bool FFmpegConfigHelper::OpenFormatContext(const uint8* data, int size) {
120 int size) {
121 DCHECK(!url_protocol_.get()); 113 DCHECK(!url_protocol_.get());
122 DCHECK(!url_protocol_buffer_.get()); 114 DCHECK(!url_protocol_buffer_.get());
115 DCHECK(!glue_.get());
123 116
124 int segment_size = size + sizeof(kEmptyCluster); 117 int segment_size = size + sizeof(kEmptyCluster);
125 int buf_size = sizeof(kWebMHeader) + segment_size; 118 int buf_size = sizeof(kWebMHeader) + segment_size;
126 url_protocol_buffer_.reset(new uint8[buf_size]); 119 url_protocol_buffer_.reset(new uint8[buf_size]);
127 uint8* buf = url_protocol_buffer_.get(); 120 uint8* buf = url_protocol_buffer_.get();
128 memcpy(buf, kWebMHeader, sizeof(kWebMHeader)); 121 memcpy(buf, kWebMHeader, sizeof(kWebMHeader));
129 memcpy(buf + sizeof(kWebMHeader), data, size); 122 memcpy(buf + sizeof(kWebMHeader), data, size);
130 memcpy(buf + sizeof(kWebMHeader) + size, kEmptyCluster, 123 memcpy(buf + sizeof(kWebMHeader) + size, kEmptyCluster,
131 sizeof(kEmptyCluster)); 124 sizeof(kEmptyCluster));
132 125
133 // Update the segment size in the buffer. 126 // Update the segment size in the buffer.
134 int64 tmp = (segment_size & GG_LONGLONG(0x00FFFFFFFFFFFFFF)) | 127 int64 tmp = (segment_size & GG_LONGLONG(0x00FFFFFFFFFFFFFF)) |
135 GG_LONGLONG(0x0100000000000000); 128 GG_LONGLONG(0x0100000000000000);
136 for (int i = 0; i < 8; i++) { 129 for (int i = 0; i < 8; i++) {
137 buf[kSegmentSizeOffset + i] = (tmp >> (8 * (7 - i))) & 0xff; 130 buf[kSegmentSizeOffset + i] = (tmp >> (8 * (7 - i))) & 0xff;
138 } 131 }
139 132
140 url_protocol_.reset(new InMemoryUrlProtocol(buf, buf_size, true)); 133 url_protocol_.reset(new InMemoryUrlProtocol(buf, buf_size, true));
141 std::string key = FFmpegGlue::GetInstance()->AddProtocol(url_protocol_.get()); 134 glue_.reset(new FFmpegGlue(url_protocol_.get()));
142 135
143 // Open FFmpeg AVFormatContext. 136 // Open FFmpeg AVFormatContext.
144 AVFormatContext* context = NULL; 137 return glue_->OpenContext() >= 0;
145 int result = avformat_open_input(&context, key.c_str(), NULL, NULL);
146
147 if (result < 0)
148 return NULL;
149
150 return context;
151 } 138 }
152 139
153 bool FFmpegConfigHelper::SetupStreamConfigs() { 140 bool FFmpegConfigHelper::SetupStreamConfigs() {
154 int result = avformat_find_stream_info(format_context_, NULL); 141 AVFormatContext* format_context = glue_->format_context();
142 int result = avformat_find_stream_info(format_context, NULL);
155 143
156 if (result < 0) 144 if (result < 0)
157 return false; 145 return false;
158 146
159 bool no_supported_streams = true; 147 bool no_supported_streams = true;
160 for (size_t i = 0; i < format_context_->nb_streams; ++i) { 148 for (size_t i = 0; i < format_context->nb_streams; ++i) {
161 AVStream* stream = format_context_->streams[i]; 149 AVStream* stream = format_context->streams[i];
162 AVCodecContext* codec_context = stream->codec; 150 AVCodecContext* codec_context = stream->codec;
163 AVMediaType codec_type = codec_context->codec_type; 151 AVMediaType codec_type = codec_context->codec_type;
164 152
165 if (codec_type == AVMEDIA_TYPE_AUDIO && 153 if (codec_type == AVMEDIA_TYPE_AUDIO &&
166 stream->codec->codec_id == CODEC_ID_VORBIS && 154 stream->codec->codec_id == CODEC_ID_VORBIS &&
167 !audio_config_.IsValidConfig()) { 155 !audio_config_.IsValidConfig()) {
168 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); 156 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_);
169 no_supported_streams = false; 157 no_supported_streams = false;
170 continue; 158 continue;
171 } 159 }
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 if (!video_buffers.empty() && !video_cb_.Run(video_buffers)) 437 if (!video_buffers.empty() && !video_cb_.Run(video_buffers))
450 return -1; 438 return -1;
451 439
452 if (cluster_ended) 440 if (cluster_ended)
453 end_of_segment_cb_.Run(); 441 end_of_segment_cb_.Run();
454 442
455 return bytes_parsed; 443 return bytes_parsed;
456 } 444 }
457 445
458 } // namespace media 446 } // namespace media
OLDNEW
« media/filters/ffmpeg_glue_unittest.cc ('K') | « media/filters/in_memory_url_protocol.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698