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

Unified Diff: media/base/audio_video_metadata_extractor.cc

Issue 121383002: Media Galleries API Metadata: Add audio video metadata extractor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: media/base/audio_video_metadata_extractor.cc
diff --git a/media/base/audio_video_metadata_extractor.cc b/media/base/audio_video_metadata_extractor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f97cc99de093777c990b4a800f26eb0ed5bcb254
--- /dev/null
+++ b/media/base/audio_video_metadata_extractor.cc
@@ -0,0 +1,219 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/audio_video_metadata_extractor.h"
+
+#include <map>
Lei Zhang 2014/01/07 21:44:25 nit: remove
tommycli 2014/01/07 23:12:36 Done.
+
+#include "base/bind.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/filters/blocking_url_protocol.h"
+#include "media/filters/ffmpeg_glue.h"
+
+namespace media {
+
+namespace {
+
+static void OnError(bool* called) {
Lei Zhang 2014/01/07 21:44:25 nit: no need for static
Lei Zhang 2014/01/07 21:44:25 Isn't |succeeded| more clear than |called| ?
tommycli 2014/01/07 23:12:36 Done.
tommycli 2014/01/07 23:12:36 Done.
+ *called = false;
+}
+
+// Returns true if the |expected_key| matches |key_lower|.
+bool ExtractString(AVDictionaryEntry* tag, const std::string& key_lower,
+ const std::string& expected_key, std::string* destination) {
+ if (key_lower != expected_key)
+ return false;
+
+ if (destination->empty())
+ *destination = tag->value;
+
+ return true;
+}
+
+// Returns true if the |expected_key| matches |key_lower|.
+bool ExtractInt(AVDictionaryEntry* tag, const std::string& key_lower,
+ const std::string& expected_key, int* destination) {
+ if (key_lower != expected_key)
+ return false;
+
+ int temporary = -1;
+ if (base::StringToInt(tag->value, &temporary) && temporary >= 0 &&
+ *destination < 0) {
Lei Zhang 2014/01/07 21:44:25 it's cheaper to check *dest first before doing the
tommycli 2014/01/07 23:12:36 Done.
+ *destination = temporary;
+ }
+
+ return true;
+}
+
+} // namespace
+
+AudioVideoMetadataExtractor::AudioVideoMetadataExtractor()
+ : extracted_(false),
+ duration_(-1),
+ width_(-1),
+ height_(-1),
+ disc_(-1),
+ track_(-1) {
+}
+
+AudioVideoMetadataExtractor::~AudioVideoMetadataExtractor() {
+}
+
+bool AudioVideoMetadataExtractor::Extract(media::DataSource* source) {
+ DCHECK(!extracted_);
+
+ bool read_ok = true;
+ media::BlockingUrlProtocol protocol(source, base::Bind(&OnError, &read_ok));
+ media::FFmpegGlue glue(&protocol);
+ AVFormatContext* format_context = glue.format_context();
+
+ if (!glue.OpenContext())
+ return false;
+
+ if (!read_ok)
+ return false;
+
+ if (!format_context->iformat)
+ return false;
+
+ if (avformat_find_stream_info(format_context, NULL) < 0)
+ return false;
+
+ if (format_context->duration != AV_NOPTS_VALUE)
+ duration_ = static_cast<double>(format_context->duration) / AV_TIME_BASE;
+
+ ExtractDictionary(format_context->metadata);
+
+ for (unsigned int i = 0; i < format_context->nb_streams; ++i) {
Lei Zhang 2014/01/07 21:44:25 Isn't |format_context->nb_streams| an int, and the
tommycli 2014/01/07 23:12:36 I believe nb_streams is an unsigned int.
+ AVStream* stream = format_context->streams[i];
+ if (!stream)
+ continue;
+
+ // Ignore attached pictures for metadata extraction.
+ if ((stream->disposition & AV_DISPOSITION_ATTACHED_PIC) != 0)
+ continue;
+
+ // Extract dictionary from streams also. Needed for containers that attach
+ // metadata to contained streams instead the container itself, like OGG.
+ ExtractDictionary(stream->metadata);
+
+ if (!stream->codec)
+ continue;
+
+ // Extract dimensions of largest stream that's not an attached picture.
+ if (stream->codec->width > 0 && stream->codec->width > width_ &&
+ stream->codec->height > 0 && stream->codec->height > height_) {
+ width_ = stream->codec->width;
+ height_ = stream->codec->height;
+ }
+ }
+
+ extracted_ = true;
+ return true;
+}
+
+double AudioVideoMetadataExtractor::duration() const {
+ DCHECK(extracted_);
+ return duration_;
+}
+
+int AudioVideoMetadataExtractor::width() const {
+ DCHECK(extracted_);
+ return width_;
+}
+
+int AudioVideoMetadataExtractor::height() const {
+ DCHECK(extracted_);
+ return height_;
+}
+
+const std::string& AudioVideoMetadataExtractor::album() const {
+ DCHECK(extracted_);
+ return album_;
+}
+
+const std::string& AudioVideoMetadataExtractor::artist() const {
+ DCHECK(extracted_);
+ return artist_;
+}
+
+const std::string& AudioVideoMetadataExtractor::comment() const {
+ DCHECK(extracted_);
+ return comment_;
+}
+
+const std::string& AudioVideoMetadataExtractor::copyright() const {
+ DCHECK(extracted_);
+ return copyright_;
+}
+
+const std::string& AudioVideoMetadataExtractor::date() const {
+ DCHECK(extracted_);
+ return date_;
+}
+
+int AudioVideoMetadataExtractor::disc() const {
+ DCHECK(extracted_);
+ return disc_;
+}
+
+const std::string& AudioVideoMetadataExtractor::encoder() const {
+ DCHECK(extracted_);
+ return encoder_;
+}
+
+const std::string& AudioVideoMetadataExtractor::encoded_by() const {
+ DCHECK(extracted_);
+ return encoded_by_;
+}
+
+const std::string& AudioVideoMetadataExtractor::genre() const {
+ DCHECK(extracted_);
+ return genre_;
+}
+
+const std::string& AudioVideoMetadataExtractor::language() const {
+ DCHECK(extracted_);
+ return language_;
+}
+
+const std::string& AudioVideoMetadataExtractor::title() const {
+ DCHECK(extracted_);
+ return title_;
+}
+
+int AudioVideoMetadataExtractor::track() const {
+ DCHECK(extracted_);
+ return track_;
+}
+
+void AudioVideoMetadataExtractor::ExtractDictionary(AVDictionary* metadata) {
+ if (!metadata)
+ return;
+
+ AVDictionaryEntry* tag = NULL;
+ while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
+ std::string key = tag->key;
+ StringToLowerASCII(&key);
Lei Zhang 2014/01/07 21:44:25 Probably better to do this in ExtractString(), rat
tommycli 2014/01/07 23:12:36 Done.
+
+ // Try extracting all the defined keys.
+ if (ExtractString(tag, key, "album", &album_)) continue;
+ if (ExtractString(tag, key, "artist", &artist_)) continue;
+ if (ExtractString(tag, key, "comment", &comment_)) continue;
+ if (ExtractString(tag, key, "copyright", &copyright_)) continue;
+ if (ExtractString(tag, key, "date", &date_)) continue;
+ if (ExtractInt(tag, key, "disc", &disc_)) continue;
+ if (ExtractString(tag, key, "encoder", &encoder_)) continue;
+ if (ExtractString(tag, key, "encoded_by", &encoded_by_)) continue;
+ if (ExtractString(tag, key, "genre", &genre_)) continue;
+ if (ExtractString(tag, key, "language", &language_)) continue;
+ if (ExtractString(tag, key, "title", &title_)) continue;
+ if (ExtractInt(tag, key, "track", &track_)) continue;
+ }
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698