Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / media / base / audio_video_metadata_extractor.cc
bloba18cc7d3d97c2286f85b1d2cabaf8ac75f995f45
1 // Copyright 2014 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.
5 #include "media/base/audio_video_metadata_extractor.h"
7 #include "base/bind.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "base/time/time.h"
11 #include "media/ffmpeg/ffmpeg_common.h"
12 #include "media/filters/blocking_url_protocol.h"
13 #include "media/filters/ffmpeg_glue.h"
15 namespace media {
17 namespace {
19 void OnError(bool* succeeded) {
20 *succeeded = false;
23 // Returns true if the |tag| matches |expected_key|.
24 bool ExtractString(AVDictionaryEntry* tag, const char* expected_key,
25 std::string* destination) {
26 if (!LowerCaseEqualsASCII(std::string(tag->key), expected_key))
27 return false;
29 if (destination->empty())
30 *destination = tag->value;
32 return true;
35 // Returns true if the |tag| matches |expected_key|.
36 bool ExtractInt(AVDictionaryEntry* tag, const char* expected_key,
37 int* destination) {
38 if (!LowerCaseEqualsASCII(std::string(tag->key), expected_key))
39 return false;
41 int temporary = -1;
42 if (*destination < 0 && base::StringToInt(tag->value, &temporary) &&
43 temporary >= 0) {
44 *destination = temporary;
47 return true;
50 } // namespace
52 AudioVideoMetadataExtractor::StreamInfo::StreamInfo() {}
54 AudioVideoMetadataExtractor::StreamInfo::~StreamInfo() {}
56 AudioVideoMetadataExtractor::AudioVideoMetadataExtractor()
57 : extracted_(false),
58 duration_(-1),
59 width_(-1),
60 height_(-1),
61 disc_(-1),
62 rotation_(-1),
63 track_(-1) {
66 AudioVideoMetadataExtractor::~AudioVideoMetadataExtractor() {
69 bool AudioVideoMetadataExtractor::Extract(DataSource* source) {
70 DCHECK(!extracted_);
72 bool read_ok = true;
73 media::BlockingUrlProtocol protocol(source, base::Bind(&OnError, &read_ok));
74 media::FFmpegGlue glue(&protocol);
75 AVFormatContext* format_context = glue.format_context();
77 if (!glue.OpenContext())
78 return false;
80 if (!read_ok)
81 return false;
83 if (!format_context->iformat)
84 return false;
86 if (avformat_find_stream_info(format_context, NULL) < 0)
87 return false;
89 if (format_context->duration != AV_NOPTS_VALUE)
90 duration_ = static_cast<double>(format_context->duration) / AV_TIME_BASE;
92 stream_infos_.push_back(StreamInfo());
93 StreamInfo& container_info = stream_infos_.back();
94 container_info.type = format_context->iformat->name;
95 ExtractDictionary(format_context->metadata, &container_info.tags);
97 for (unsigned int i = 0; i < format_context->nb_streams; ++i) {
98 stream_infos_.push_back(StreamInfo());
99 StreamInfo& info = stream_infos_.back();
101 AVStream* stream = format_context->streams[i];
102 if (!stream)
103 continue;
105 // Extract dictionary from streams also. Needed for containers that attach
106 // metadata to contained streams instead the container itself, like OGG.
107 ExtractDictionary(stream->metadata, &info.tags);
109 if (!stream->codec)
110 continue;
112 info.type = avcodec_get_name(stream->codec->codec_id);
114 // Extract dimensions of largest stream that's not an attached picture.
115 if (stream->codec->width > 0 && stream->codec->width > width_ &&
116 stream->codec->height > 0 && stream->codec->height > height_) {
117 width_ = stream->codec->width;
118 height_ = stream->codec->height;
122 extracted_ = true;
123 return true;
126 double AudioVideoMetadataExtractor::duration() const {
127 DCHECK(extracted_);
128 return duration_;
131 int AudioVideoMetadataExtractor::width() const {
132 DCHECK(extracted_);
133 return width_;
136 int AudioVideoMetadataExtractor::height() const {
137 DCHECK(extracted_);
138 return height_;
141 int AudioVideoMetadataExtractor::rotation() const {
142 DCHECK(extracted_);
143 return rotation_;
146 const std::string& AudioVideoMetadataExtractor::album() const {
147 DCHECK(extracted_);
148 return album_;
151 const std::string& AudioVideoMetadataExtractor::artist() const {
152 DCHECK(extracted_);
153 return artist_;
156 const std::string& AudioVideoMetadataExtractor::comment() const {
157 DCHECK(extracted_);
158 return comment_;
161 const std::string& AudioVideoMetadataExtractor::copyright() const {
162 DCHECK(extracted_);
163 return copyright_;
166 const std::string& AudioVideoMetadataExtractor::date() const {
167 DCHECK(extracted_);
168 return date_;
171 int AudioVideoMetadataExtractor::disc() const {
172 DCHECK(extracted_);
173 return disc_;
176 const std::string& AudioVideoMetadataExtractor::encoder() const {
177 DCHECK(extracted_);
178 return encoder_;
181 const std::string& AudioVideoMetadataExtractor::encoded_by() const {
182 DCHECK(extracted_);
183 return encoded_by_;
186 const std::string& AudioVideoMetadataExtractor::genre() const {
187 DCHECK(extracted_);
188 return genre_;
191 const std::string& AudioVideoMetadataExtractor::language() const {
192 DCHECK(extracted_);
193 return language_;
196 const std::string& AudioVideoMetadataExtractor::title() const {
197 DCHECK(extracted_);
198 return title_;
201 int AudioVideoMetadataExtractor::track() const {
202 DCHECK(extracted_);
203 return track_;
206 const std::vector<AudioVideoMetadataExtractor::StreamInfo>&
207 AudioVideoMetadataExtractor::stream_infos() const {
208 DCHECK(extracted_);
209 return stream_infos_;
212 void AudioVideoMetadataExtractor::ExtractDictionary(
213 AVDictionary* metadata, TagDictionary* raw_tags) {
214 if (!metadata)
215 return;
217 AVDictionaryEntry* tag = NULL;
218 while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
219 if (raw_tags->find(tag->key) == raw_tags->end())
220 (*raw_tags)[tag->key] = tag->value;
222 if (ExtractInt(tag, "rotate", &rotation_)) continue;
223 if (ExtractString(tag, "album", &album_)) continue;
224 if (ExtractString(tag, "artist", &artist_)) continue;
225 if (ExtractString(tag, "comment", &comment_)) continue;
226 if (ExtractString(tag, "copyright", &copyright_)) continue;
227 if (ExtractString(tag, "date", &date_)) continue;
228 if (ExtractInt(tag, "disc", &disc_)) continue;
229 if (ExtractString(tag, "encoder", &encoder_)) continue;
230 if (ExtractString(tag, "encoded_by", &encoded_by_)) continue;
231 if (ExtractString(tag, "genre", &genre_)) continue;
232 if (ExtractString(tag, "language", &language_)) continue;
233 if (ExtractString(tag, "title", &title_)) continue;
234 if (ExtractInt(tag, "track", &track_)) continue;
238 } // namespace media