Chromium Code Reviews| 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..268a5e157aa538b2916f7e35ce725d77650b86ec |
| --- /dev/null |
| +++ b/media/base/audio_video_metadata_extractor.cc |
| @@ -0,0 +1,139 @@ |
| +// Copyright 2013 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> |
| + |
| +#include "base/bind.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) { |
| + *called = false; |
| +} |
| + |
| +std::map<std::string, std::string> ExtractAVMetadata(AVDictionary* metadata) { |
| + DCHECK(metadata); |
| + |
| + std::map<std::string, std::string> tags; |
| + |
| + AVDictionaryEntry *tag = NULL; |
| + while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { |
| + std::string key = tag->key; |
| + StringToLowerASCII(&key); |
| + tags[key] = std::string(tag->value); |
| + } |
| + |
| + return tags; |
| +} |
| + |
| +} // namespace |
| + |
| +AudioVideoMetadataExtractor::AudioVideoMetadataExtractor(DataSource* source) |
| + : source_(source), |
| + extracted_(false), |
| + duration_(-1), |
| + width_(0), |
| + height_(0) { |
| +} |
| + |
| +AudioVideoMetadataExtractor::~AudioVideoMetadataExtractor() { |
| +} |
| + |
| +bool AudioVideoMetadataExtractor::Extract() { |
| + 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; |
| + |
| + format_ = format_context->iformat->name; |
| + |
| + if (format_context->duration != AV_NOPTS_VALUE) |
| + duration_ = format_context->duration / AV_TIME_BASE; |
| + |
| + if (format_context->metadata) |
| + tags_ = ExtractAVMetadata(format_context->metadata); |
| + |
| + bool container_has_metadata = !tags_.empty(); |
| + |
| + for (unsigned int i = 0; i < format_context->nb_streams; ++i) { |
| + AVStream* stream = format_context->streams[i]; |
| + if (!stream) |
| + continue; |
| + |
| + // Ignore attached pictures for metadata extraction. |
| + if ((stream->disposition & AV_DISPOSITION_ATTACHED_PIC) != 0) |
| + continue; |
| + |
| + // If the container does not have metadata, take the metadata from the |
| + // stream with the most tags. This is needed for containers that attach |
| + // metadata to contained streams instead the container itself, like OGG. |
|
acolwell GONE FROM CHROMIUM
2014/01/03 19:14:04
This seems brittle. How about just taking the firs
tommycli
2014/01/03 23:08:36
Done.
|
| + if (!container_has_metadata && stream->metadata) { |
| + std::map<std::string, std::string> stream_tags = |
| + ExtractAVMetadata(stream->metadata); |
| + if (stream_tags.size() > tags_.size()) |
| + tags_ = stream_tags; |
| + } |
| + |
| + if (!stream->codec) |
| + continue; |
| + |
| + // Extract dimensions of largest stream that's not an attached picture. |
| + if (stream->codec->width > width_ && stream->codec->height > height_) { |
| + width_ = stream->codec->width; |
| + height_ = stream->codec->height; |
| + } |
| + } |
| + |
| + extracted_ = true; |
| + return true; |
| +} |
| + |
| +const std::map<std::string, std::string>& |
| +AudioVideoMetadataExtractor::GetTags() { |
| + DCHECK(extracted_); |
| + return tags_; |
| +} |
| + |
| +const std::string& AudioVideoMetadataExtractor::GetFormat() { |
| + DCHECK(extracted_); |
| + return format_; |
| +} |
| + |
| +int AudioVideoMetadataExtractor::GetDurationSeconds() { |
| + DCHECK(extracted_); |
| + return duration_; |
| +} |
| + |
| +int AudioVideoMetadataExtractor::GetWidth() { |
| + DCHECK(extracted_); |
| + return width_; |
| +} |
| + |
| +int AudioVideoMetadataExtractor::GetHeight() { |
| + DCHECK(extracted_); |
| + return height_; |
| +} |
| + |
| +} // namespace media |