Add explicit |forceOnlineSignin| to user pod status
[chromium-blink-merge.git] / media / base / audio_video_metadata_extractor.cc
blobfe26d84313618ee614b2e82c7391f406b5f41562
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::AudioVideoMetadataExtractor()
53 : extracted_(false),
54 duration_(-1),
55 width_(-1),
56 height_(-1),
57 disc_(-1),
58 track_(-1) {
61 AudioVideoMetadataExtractor::~AudioVideoMetadataExtractor() {
64 bool AudioVideoMetadataExtractor::Extract(DataSource* source) {
65 DCHECK(!extracted_);
67 bool read_ok = true;
68 media::BlockingUrlProtocol protocol(source, base::Bind(&OnError, &read_ok));
69 media::FFmpegGlue glue(&protocol);
70 AVFormatContext* format_context = glue.format_context();
72 if (!glue.OpenContext())
73 return false;
75 if (!read_ok)
76 return false;
78 if (!format_context->iformat)
79 return false;
81 if (avformat_find_stream_info(format_context, NULL) < 0)
82 return false;
84 if (format_context->duration != AV_NOPTS_VALUE)
85 duration_ = static_cast<double>(format_context->duration) / AV_TIME_BASE;
87 ExtractDictionary(format_context->metadata);
89 for (unsigned int i = 0; i < format_context->nb_streams; ++i) {
90 AVStream* stream = format_context->streams[i];
91 if (!stream)
92 continue;
94 // Ignore attached pictures for metadata extraction.
95 if ((stream->disposition & AV_DISPOSITION_ATTACHED_PIC) != 0)
96 continue;
98 // Extract dictionary from streams also. Needed for containers that attach
99 // metadata to contained streams instead the container itself, like OGG.
100 ExtractDictionary(stream->metadata);
102 if (!stream->codec)
103 continue;
105 // Extract dimensions of largest stream that's not an attached picture.
106 if (stream->codec->width > 0 && stream->codec->width > width_ &&
107 stream->codec->height > 0 && stream->codec->height > height_) {
108 width_ = stream->codec->width;
109 height_ = stream->codec->height;
113 extracted_ = true;
114 return true;
117 double AudioVideoMetadataExtractor::duration() const {
118 DCHECK(extracted_);
119 return duration_;
122 int AudioVideoMetadataExtractor::width() const {
123 DCHECK(extracted_);
124 return width_;
127 int AudioVideoMetadataExtractor::height() const {
128 DCHECK(extracted_);
129 return height_;
132 const std::string& AudioVideoMetadataExtractor::album() const {
133 DCHECK(extracted_);
134 return album_;
137 const std::string& AudioVideoMetadataExtractor::artist() const {
138 DCHECK(extracted_);
139 return artist_;
142 const std::string& AudioVideoMetadataExtractor::comment() const {
143 DCHECK(extracted_);
144 return comment_;
147 const std::string& AudioVideoMetadataExtractor::copyright() const {
148 DCHECK(extracted_);
149 return copyright_;
152 const std::string& AudioVideoMetadataExtractor::date() const {
153 DCHECK(extracted_);
154 return date_;
157 int AudioVideoMetadataExtractor::disc() const {
158 DCHECK(extracted_);
159 return disc_;
162 const std::string& AudioVideoMetadataExtractor::encoder() const {
163 DCHECK(extracted_);
164 return encoder_;
167 const std::string& AudioVideoMetadataExtractor::encoded_by() const {
168 DCHECK(extracted_);
169 return encoded_by_;
172 const std::string& AudioVideoMetadataExtractor::genre() const {
173 DCHECK(extracted_);
174 return genre_;
177 const std::string& AudioVideoMetadataExtractor::language() const {
178 DCHECK(extracted_);
179 return language_;
182 const std::string& AudioVideoMetadataExtractor::title() const {
183 DCHECK(extracted_);
184 return title_;
187 int AudioVideoMetadataExtractor::track() const {
188 DCHECK(extracted_);
189 return track_;
192 void AudioVideoMetadataExtractor::ExtractDictionary(AVDictionary* metadata) {
193 if (!metadata)
194 return;
196 AVDictionaryEntry* tag = NULL;
197 while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
198 if (ExtractString(tag, "album", &album_)) continue;
199 if (ExtractString(tag, "artist", &artist_)) continue;
200 if (ExtractString(tag, "comment", &comment_)) continue;
201 if (ExtractString(tag, "copyright", &copyright_)) continue;
202 if (ExtractString(tag, "date", &date_)) continue;
203 if (ExtractInt(tag, "disc", &disc_)) continue;
204 if (ExtractString(tag, "encoder", &encoder_)) continue;
205 if (ExtractString(tag, "encoded_by", &encoded_by_)) continue;
206 if (ExtractString(tag, "genre", &genre_)) continue;
207 if (ExtractString(tag, "language", &language_)) continue;
208 if (ExtractString(tag, "title", &title_)) continue;
209 if (ExtractInt(tag, "track", &track_)) continue;
213 } // namespace media