1 // Copyright 2013 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 "chrome/utility/media_galleries/media_metadata_parser.h"
10 #include "base/location.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/strings/string_util.h"
13 #include "base/task_runner_util.h"
14 #include "base/threading/thread.h"
15 #include "chrome/utility/media_galleries/image_metadata_extractor.h"
16 #include "media/base/audio_video_metadata_extractor.h"
17 #include "media/base/data_source.h"
18 #include "net/base/mime_sniffer.h"
20 namespace MediaGalleries
= extensions::api::media_galleries
;
26 void SetStringScopedPtr(const std::string
& value
,
27 scoped_ptr
<std::string
>* destination
) {
30 destination
->reset(new std::string(value
));
33 void SetIntScopedPtr(int value
, scoped_ptr
<int>* destination
) {
36 destination
->reset(new int(value
));
39 void SetDoubleScopedPtr(double value
, scoped_ptr
<double>* destination
) {
42 destination
->reset(new double(value
));
45 void SetBoolScopedPtr(bool value
, scoped_ptr
<bool>* destination
) {
47 destination
->reset(new bool(value
));
50 // This runs on |media_thread_|, as the underlying FFmpeg operation is
51 // blocking, and the utility thread must not be blocked, so the media file
52 // bytes can be sent from the browser process to the utility process.
53 void ParseAudioVideoMetadata(
54 media::DataSource
* source
, bool get_attached_images
,
55 MediaMetadataParser::MediaMetadata
* metadata
,
56 std::vector
<AttachedImage
>* attached_images
) {
59 media::AudioVideoMetadataExtractor extractor
;
61 if (!extractor
.Extract(source
, get_attached_images
))
64 if (extractor
.duration() >= 0)
65 metadata
->duration
.reset(new double(extractor
.duration()));
67 if (extractor
.height() >= 0 && extractor
.width() >= 0) {
68 metadata
->height
.reset(new int(extractor
.height()));
69 metadata
->width
.reset(new int(extractor
.width()));
72 SetStringScopedPtr(extractor
.artist(), &metadata
->artist
);
73 SetStringScopedPtr(extractor
.album(), &metadata
->album
);
74 SetStringScopedPtr(extractor
.artist(), &metadata
->artist
);
75 SetStringScopedPtr(extractor
.comment(), &metadata
->comment
);
76 SetStringScopedPtr(extractor
.copyright(), &metadata
->copyright
);
77 SetIntScopedPtr(extractor
.disc(), &metadata
->disc
);
78 SetStringScopedPtr(extractor
.genre(), &metadata
->genre
);
79 SetStringScopedPtr(extractor
.language(), &metadata
->language
);
80 SetIntScopedPtr(extractor
.rotation(), &metadata
->rotation
);
81 SetStringScopedPtr(extractor
.title(), &metadata
->title
);
82 SetIntScopedPtr(extractor
.track(), &metadata
->track
);
84 for (media::AudioVideoMetadataExtractor::StreamInfoVector::const_iterator it
=
85 extractor
.stream_infos().begin();
86 it
!= extractor
.stream_infos().end(); ++it
) {
87 linked_ptr
<MediaGalleries::StreamInfo
> stream_info(
88 new MediaGalleries::StreamInfo
);
89 stream_info
->type
= it
->type
;
91 for (std::map
<std::string
, std::string
>::const_iterator tag_it
=
93 tag_it
!= it
->tags
.end(); ++tag_it
) {
94 stream_info
->tags
.additional_properties
.SetString(tag_it
->first
,
98 metadata
->raw_tags
.push_back(stream_info
);
101 if (get_attached_images
) {
102 for (std::vector
<std::string
>::const_iterator it
=
103 extractor
.attached_images_bytes().begin();
104 it
!= extractor
.attached_images_bytes().end(); ++it
) {
105 attached_images
->push_back(AttachedImage());
106 attached_images
->back().data
= *it
;
107 net::SniffMimeTypeFromLocalData(it
->c_str(), it
->length(),
108 &attached_images
->back().type
);
113 void FinishParseAudioVideoMetadata(
114 MediaMetadataParser::MetadataCallback callback
,
115 MediaMetadataParser::MediaMetadata
* metadata
,
116 std::vector
<AttachedImage
>* attached_images
) {
117 DCHECK(!callback
.is_null());
119 DCHECK(attached_images
);
121 callback
.Run(*metadata
, *attached_images
);
124 void FinishParseImageMetadata(
125 ImageMetadataExtractor
* extractor
, const std::string
& mime_type
,
126 MediaMetadataParser::MetadataCallback callback
, bool extract_success
) {
128 MediaMetadataParser::MediaMetadata metadata
;
129 metadata
.mime_type
= mime_type
;
131 if (!extract_success
) {
132 callback
.Run(metadata
, std::vector
<AttachedImage
>());
136 SetIntScopedPtr(extractor
->height(), &metadata
.height
);
137 SetIntScopedPtr(extractor
->width(), &metadata
.width
);
139 SetIntScopedPtr(extractor
->rotation(), &metadata
.rotation
);
141 SetDoubleScopedPtr(extractor
->x_resolution(), &metadata
.x_resolution
);
142 SetDoubleScopedPtr(extractor
->y_resolution(), &metadata
.y_resolution
);
143 SetBoolScopedPtr(extractor
->flash_fired(), &metadata
.flash_fired
);
144 SetStringScopedPtr(extractor
->camera_make(), &metadata
.camera_make
);
145 SetStringScopedPtr(extractor
->camera_model(), &metadata
.camera_model
);
146 SetDoubleScopedPtr(extractor
->exposure_time_sec(),
147 &metadata
.exposure_time_seconds
);
149 SetDoubleScopedPtr(extractor
->f_number(), &metadata
.f_number
);
150 SetDoubleScopedPtr(extractor
->focal_length_mm(), &metadata
.focal_length_mm
);
151 SetDoubleScopedPtr(extractor
->iso_equivalent(), &metadata
.iso_equivalent
);
153 callback
.Run(metadata
, std::vector
<AttachedImage
>());
158 MediaMetadataParser::MediaMetadataParser(media::DataSource
* source
,
159 const std::string
& mime_type
,
160 bool get_attached_images
)
162 mime_type_(mime_type
),
163 get_attached_images_(get_attached_images
) {
166 MediaMetadataParser::~MediaMetadataParser() {}
168 void MediaMetadataParser::Start(const MetadataCallback
& callback
) {
169 if (base::StartsWith(mime_type_
, "audio/", base::CompareCase::SENSITIVE
) ||
170 base::StartsWith(mime_type_
, "video/", base::CompareCase::SENSITIVE
)) {
171 MediaMetadata
* metadata
= new MediaMetadata
;
172 metadata
->mime_type
= mime_type_
;
173 std::vector
<AttachedImage
>* attached_images
=
174 new std::vector
<AttachedImage
>;
176 media_thread_
.reset(new base::Thread("media_thread"));
177 CHECK(media_thread_
->Start());
178 media_thread_
->task_runner()->PostTaskAndReply(
179 FROM_HERE
, base::Bind(&ParseAudioVideoMetadata
, source_
,
180 get_attached_images_
, metadata
, attached_images
),
181 base::Bind(&FinishParseAudioVideoMetadata
, callback
,
182 base::Owned(metadata
), base::Owned(attached_images
)));
186 if (base::StartsWith(mime_type_
, "image/", base::CompareCase::SENSITIVE
)) {
187 ImageMetadataExtractor
* extractor
= new ImageMetadataExtractor
;
190 base::Bind(&FinishParseImageMetadata
, base::Owned(extractor
),
191 mime_type_
, callback
));
195 callback
.Run(MediaMetadata(), std::vector
<AttachedImage
>());
198 } // namespace metadata