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

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

Issue 2819863003: Only run container name detection upon ffmpeg parse failure. (Closed)
Patch Set: Created 3 years, 8 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
« no previous file with comments | « media/base/container_names.cc ('k') | media/filters/ffmpeg_glue_unittest.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/ffmpeg_glue.h" 5 #include "media/filters/ffmpeg_glue.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 format_context_->pb = avio_context_.get(); 130 format_context_->pb = avio_context_.get();
131 } 131 }
132 132
133 bool FFmpegGlue::OpenContext() { 133 bool FFmpegGlue::OpenContext() {
134 DCHECK(!open_called_) << "OpenContext() shouldn't be called twice."; 134 DCHECK(!open_called_) << "OpenContext() shouldn't be called twice.";
135 135
136 // If avformat_open_input() is called we have to take a slightly different 136 // If avformat_open_input() is called we have to take a slightly different
137 // destruction path to avoid double frees. 137 // destruction path to avoid double frees.
138 open_called_ = true; 138 open_called_ = true;
139 139
140 // Attempt to recognize the container by looking at the first few bytes of the 140 // By passing nullptr for the filename (second parameter) we are telling
141 // stream. The stream position is left unchanged. 141 // FFmpeg to use the AVIO context we setup from the AVFormatContext structure.
142 std::unique_ptr<std::vector<uint8_t>> buffer(new std::vector<uint8_t>(8192)); 142 const int ret =
143 avformat_open_input(&format_context_, nullptr, nullptr, nullptr);
143 144
144 int64_t pos = AVIOSeekOperation(avio_context_.get()->opaque, 0, SEEK_CUR); 145 // If FFmpeg can't identify the file, read the first 8k and attempt to guess
145 AVIOSeekOperation(avio_context_.get()->opaque, 0, SEEK_SET); 146 // at the container type ourselves. This way we can track emergent formats.
146 int numRead = AVIOReadOperation( 147 // Only try on AVERROR_INVALIDDATA to avoid running after I/O errors.
147 avio_context_.get()->opaque, buffer.get()->data(), buffer.get()->size()); 148 if (ret == AVERROR_INVALIDDATA) {
148 AVIOSeekOperation(avio_context_.get()->opaque, pos, SEEK_SET); 149 std::vector<uint8_t> buffer(8192);
149 if (numRead > 0) { 150
150 // < 0 means Read failed 151 const int64_t pos = AVIOSeekOperation(avio_context_->opaque, 0, SEEK_SET);
151 container_names::MediaContainerName container = 152 if (pos < 0)
152 container_names::DetermineContainer(buffer.get()->data(), numRead); 153 return false;
153 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedContainer", container); 154
155 const int num_read =
156 AVIOReadOperation(avio_context_->opaque, buffer.data(), buffer.size());
157 if (num_read < container_names::kMinimumContainerSize)
158 return false;
159
160 UMA_HISTOGRAM_SPARSE_SLOWLY(
161 "Media.DetectedContainer",
162 container_names::DetermineContainer(buffer.data(), num_read));
163 return false;
164 } else if (ret < 0) {
165 return false;
154 } 166 }
155 167
156 // By passing nullptr for the filename (second parameter) we are telling 168 // Rely on ffmpeg's parsing if we're able to succesfully open the file.
157 // FFmpeg to use the AVIO context we setup from the AVFormatContext structure. 169 container_names::MediaContainerName container =
158 return avformat_open_input(&format_context_, nullptr, nullptr, nullptr) == 0; 170 container_names::CONTAINER_UNKNOWN;
171 if (strcmp(format_context_->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0)
jrummell 2017/04/17 18:00:15 Too bad there isn't a better way to compute this w
DaleCurtis 2017/04/17 19:08:46 Yeah, hence all the test cases to make sure we sti
172 container = container_names::CONTAINER_MOV;
173 else if (strcmp(format_context_->iformat->name, "flac") == 0)
174 container = container_names::CONTAINER_FLAC;
175 else if (strcmp(format_context_->iformat->name, "matroska,webm") == 0)
176 container = container_names::CONTAINER_WEBM;
177 else if (strcmp(format_context_->iformat->name, "ogg") == 0)
178 container = container_names::CONTAINER_OGG;
179 else if (strcmp(format_context_->iformat->name, "wav") == 0)
180 container = container_names::CONTAINER_WAV;
181 else if (strcmp(format_context_->iformat->name, "aac") == 0)
182 container = container_names::CONTAINER_AAC;
183 else if (strcmp(format_context_->iformat->name, "mp3") == 0)
184 container = container_names::CONTAINER_MP3;
185 else if (strcmp(format_context_->iformat->name, "amr") == 0)
186 container = container_names::CONTAINER_AMR;
187 else if (strcmp(format_context_->iformat->name, "avi") == 0)
188 container = container_names::CONTAINER_AVI;
189 // TODO(jrummell): Remove GSM detection. http://crbug.com/711774
190 else if (strcmp(format_context_->iformat->name, "gsm") == 0)
191 container = container_names::CONTAINER_GSM;
192
193 DCHECK_NE(container, container_names::CONTAINER_UNKNOWN);
194 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedContainer", container);
195
196 return true;
159 } 197 }
160 198
161 FFmpegGlue::~FFmpegGlue() { 199 FFmpegGlue::~FFmpegGlue() {
162 // In the event of avformat_open_input() failure, FFmpeg may sometimes free 200 // In the event of avformat_open_input() failure, FFmpeg may sometimes free
163 // our AVFormatContext behind the scenes, but leave the buffer alive. It will 201 // our AVFormatContext behind the scenes, but leave the buffer alive. It will
164 // helpfully set |format_context_| to nullptr in this case. 202 // helpfully set |format_context_| to nullptr in this case.
165 if (!format_context_) { 203 if (!format_context_) {
166 av_free(avio_context_->buffer); 204 av_free(avio_context_->buffer);
167 return; 205 return;
168 } 206 }
169 207
170 // If avformat_open_input() hasn't been called, we should simply free the 208 // If avformat_open_input() hasn't been called, we should simply free the
171 // AVFormatContext and buffer instead of using avformat_close_input(). 209 // AVFormatContext and buffer instead of using avformat_close_input().
172 if (!open_called_) { 210 if (!open_called_) {
173 avformat_free_context(format_context_); 211 avformat_free_context(format_context_);
174 av_free(avio_context_->buffer); 212 av_free(avio_context_->buffer);
175 return; 213 return;
176 } 214 }
177 215
178 avformat_close_input(&format_context_); 216 avformat_close_input(&format_context_);
179 av_free(avio_context_->buffer); 217 av_free(avio_context_->buffer);
180 } 218 }
181 219
182 } // namespace media 220 } // namespace media
OLDNEW
« no previous file with comments | « media/base/container_names.cc ('k') | media/filters/ffmpeg_glue_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698