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/memory/linked_ptr.h"
11 #include "base/message_loop/message_loop.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"
19 namespace MediaGalleries
= extensions::api::media_galleries
;
25 void SetStringScopedPtr(const std::string
& value
,
26 scoped_ptr
<std::string
>* destination
) {
29 destination
->reset(new std::string(value
));
32 void SetIntScopedPtr(int value
, scoped_ptr
<int>* destination
) {
35 destination
->reset(new int(value
));
38 void SetDoubleScopedPtr(double value
, scoped_ptr
<double>* destination
) {
41 destination
->reset(new double(value
));
44 void SetBoolScopedPtr(bool value
, scoped_ptr
<bool>* destination
) {
46 destination
->reset(new bool(value
));
49 // This runs on |media_thread_|, as the underlying FFmpeg operation is
50 // blocking, and the utility thread must not be blocked, so the media file
51 // bytes can be sent from the browser process to the utility process.
52 scoped_ptr
<MediaMetadataParser::MediaMetadata
> ParseAudioVideoMetadata(
53 media::DataSource
* source
,
54 scoped_ptr
<MediaMetadataParser::MediaMetadata
> metadata
) {
56 DCHECK(metadata
.get());
57 media::AudioVideoMetadataExtractor extractor
;
59 if (!extractor
.Extract(source
))
60 return metadata
.Pass();
62 if (extractor
.duration() >= 0)
63 metadata
->duration
.reset(new double(extractor
.duration()));
65 if (extractor
.height() >= 0 && extractor
.width() >= 0) {
66 metadata
->height
.reset(new int(extractor
.height()));
67 metadata
->width
.reset(new int(extractor
.width()));
70 SetStringScopedPtr(extractor
.artist(), &metadata
->artist
);
71 SetStringScopedPtr(extractor
.album(), &metadata
->album
);
72 SetStringScopedPtr(extractor
.artist(), &metadata
->artist
);
73 SetStringScopedPtr(extractor
.comment(), &metadata
->comment
);
74 SetStringScopedPtr(extractor
.copyright(), &metadata
->copyright
);
75 SetIntScopedPtr(extractor
.disc(), &metadata
->disc
);
76 SetStringScopedPtr(extractor
.genre(), &metadata
->genre
);
77 SetStringScopedPtr(extractor
.language(), &metadata
->language
);
78 SetIntScopedPtr(extractor
.rotation(), &metadata
->rotation
);
79 SetStringScopedPtr(extractor
.title(), &metadata
->title
);
80 SetIntScopedPtr(extractor
.track(), &metadata
->track
);
82 for (media::AudioVideoMetadataExtractor::StreamInfoVector::const_iterator it
=
83 extractor
.stream_infos().begin();
84 it
!= extractor
.stream_infos().end(); ++it
) {
85 linked_ptr
<MediaGalleries::StreamInfo
> stream_info(
86 new MediaGalleries::StreamInfo
);
87 stream_info
->type
= it
->type
;
89 for (std::map
<std::string
, std::string
>::const_iterator tag_it
=
91 tag_it
!= it
->tags
.end(); ++tag_it
) {
92 stream_info
->tags
.additional_properties
.SetString(tag_it
->first
,
96 metadata
->raw_tags
.push_back(stream_info
);
99 return metadata
.Pass();
102 void FinishParseImageMetadata(
103 ImageMetadataExtractor
* extractor
,
104 scoped_ptr
<MediaMetadataParser::MediaMetadata
> metadata
,
105 MediaMetadataParser::MetadataCallback callback
,
106 bool extract_success
) {
108 DCHECK(metadata
.get());
110 if (!extract_success
) {
111 callback
.Run(metadata
.Pass());
115 SetIntScopedPtr(extractor
->height(), &metadata
->height
);
116 SetIntScopedPtr(extractor
->width(), &metadata
->width
);
118 SetIntScopedPtr(extractor
->rotation(), &metadata
->rotation
);
120 SetDoubleScopedPtr(extractor
->x_resolution(), &metadata
->x_resolution
);
121 SetDoubleScopedPtr(extractor
->y_resolution(), &metadata
->y_resolution
);
122 SetBoolScopedPtr(extractor
->flash_fired(), &metadata
->flash_fired
);
123 SetStringScopedPtr(extractor
->camera_make(), &metadata
->camera_make
);
124 SetStringScopedPtr(extractor
->camera_model(), &metadata
->camera_model
);
125 SetDoubleScopedPtr(extractor
->exposure_time_sec(),
126 &metadata
->exposure_time_seconds
);
128 SetDoubleScopedPtr(extractor
->f_number(), &metadata
->f_number
);
129 SetDoubleScopedPtr(extractor
->focal_length_mm(), &metadata
->focal_length_mm
);
130 SetDoubleScopedPtr(extractor
->iso_equivalent(), &metadata
->iso_equivalent
);
132 callback
.Run(metadata
.Pass());
137 MediaMetadataParser::MediaMetadataParser(media::DataSource
* source
,
138 const std::string
& mime_type
)
140 mime_type_(mime_type
) {
143 MediaMetadataParser::~MediaMetadataParser() {}
145 void MediaMetadataParser::Start(const MetadataCallback
& callback
) {
146 scoped_ptr
<MediaMetadata
> metadata(new MediaMetadata
);
147 metadata
->mime_type
= mime_type_
;
149 if (StartsWithASCII(mime_type_
, "audio/", true) ||
150 StartsWithASCII(mime_type_
, "video/", true)) {
151 media_thread_
.reset(new base::Thread("media_thread"));
152 CHECK(media_thread_
->Start());
153 base::PostTaskAndReplyWithResult(
154 media_thread_
->message_loop_proxy(),
156 base::Bind(&ParseAudioVideoMetadata
, source_
, base::Passed(&metadata
)),
161 if (StartsWithASCII(mime_type_
, "image/", true)) {
162 ImageMetadataExtractor
* extractor
= new ImageMetadataExtractor
;
165 base::Bind(&FinishParseImageMetadata
, base::Owned(extractor
),
166 base::Passed(&metadata
), callback
));
170 // TODO(tommycli): Implement for image mime types.
171 callback
.Run(metadata
.Pass());
174 } // namespace metadata