OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <map> | 5 #include <map> |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "services/media/framework/safe_clone.h" | 8 #include "services/media/framework/safe_clone.h" |
9 #include "services/media/framework_ffmpeg/av_codec_context.h" | 9 #include "services/media/framework_ffmpeg/av_codec_context.h" |
10 #include "services/media/framework_ffmpeg/av_format_context.h" | 10 #include "services/media/framework_ffmpeg/av_format_context.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 std::unique_ptr<StreamType> stream_type_; | 53 std::unique_ptr<StreamType> stream_type_; |
54 }; | 54 }; |
55 | 55 |
56 // Specialized packet implementation. | 56 // Specialized packet implementation. |
57 class DemuxPacket : public Packet { | 57 class DemuxPacket : public Packet { |
58 public: | 58 public: |
59 static PacketPtr Create(ffmpeg::AvPacketPtr av_packet) { | 59 static PacketPtr Create(ffmpeg::AvPacketPtr av_packet) { |
60 return PacketPtr(new DemuxPacket(std::move(av_packet))); | 60 return PacketPtr(new DemuxPacket(std::move(av_packet))); |
61 } | 61 } |
62 | 62 |
63 AVPacket& av_packet() { | 63 AVPacket& av_packet() { return *av_packet_; } |
64 return *av_packet_; | |
65 } | |
66 | 64 |
67 protected: | 65 protected: |
68 ~DemuxPacket() override {} | 66 ~DemuxPacket() override {} |
69 | 67 |
70 void Release() override { delete this; } | 68 void Release() override { delete this; } |
71 | 69 |
72 private: | 70 private: |
73 DemuxPacket(ffmpeg::AvPacketPtr av_packet) : | 71 DemuxPacket(ffmpeg::AvPacketPtr av_packet) |
74 Packet( | 72 : Packet( |
75 (av_packet->pts == AV_NOPTS_VALUE) ? kUnknownPts : av_packet->pts, | 73 (av_packet->pts == AV_NOPTS_VALUE) ? kUnknownPts : av_packet->pts, |
76 false, | 74 false, |
77 static_cast<size_t>(av_packet->size), | 75 static_cast<size_t>(av_packet->size), |
78 av_packet->data), | 76 av_packet->data), |
79 av_packet_(std::move(av_packet)) { | 77 av_packet_(std::move(av_packet)) { |
80 DCHECK(av_packet_->size >= 0); | 78 DCHECK(av_packet_->size >= 0); |
81 } | 79 } |
82 | 80 |
83 ffmpeg::AvPacketPtr av_packet_; | 81 ffmpeg::AvPacketPtr av_packet_; |
84 }; | 82 }; |
85 | 83 |
86 struct AVFormatContextDeleter { | 84 struct AVFormatContextDeleter { |
87 inline void operator()(AVFormatContext* ptr) const { | 85 inline void operator()(AVFormatContext* ptr) const { |
88 avformat_free_context(ptr); | 86 avformat_free_context(ptr); |
89 } | 87 } |
90 }; | 88 }; |
91 | 89 |
92 // Produces an end-of-stream packet for next_stream_to_end_. | 90 // Produces an end-of-stream packet for next_stream_to_end_. |
93 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out); | 91 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out); |
94 | 92 |
95 // Copies metadata from the specified source into map. | 93 // Copies metadata from the specified source into map. |
96 void CopyMetadata( | 94 void CopyMetadata(AVDictionary* source, |
97 AVDictionary* source, | 95 std::map<std::string, std::string>& map); |
98 std::map<std::string, std::string>& map); | |
99 | 96 |
100 std::shared_ptr<Reader> reader_; | 97 std::shared_ptr<Reader> reader_; |
101 AvFormatContextPtr format_context_; | 98 AvFormatContextPtr format_context_; |
102 AvIoContextPtr io_context_; | 99 AvIoContextPtr io_context_; |
103 std::vector<DemuxStream*> streams_; | 100 std::vector<DemuxStream*> streams_; |
104 std::unique_ptr<Metadata> metadata_; | 101 std::unique_ptr<Metadata> metadata_; |
105 int64_t next_pts_; | 102 int64_t next_pts_; |
106 int next_stream_to_end_ = -1; // -1: don't end, streams_.size(): stop. | 103 int next_stream_to_end_ = -1; // -1: don't end, streams_.size(): stop. |
107 }; | 104 }; |
108 | 105 |
109 // static | 106 // static |
110 std::shared_ptr<Demux> FfmpegDemux::Create() { | 107 std::shared_ptr<Demux> FfmpegDemux::Create() { |
111 return std::shared_ptr<Demux>(new FfmpegDemuxImpl()); | 108 return std::shared_ptr<Demux>(new FfmpegDemuxImpl()); |
112 } | 109 } |
113 | 110 |
114 FfmpegDemuxImpl::FfmpegDemuxImpl() {} | 111 FfmpegDemuxImpl::FfmpegDemuxImpl() {} |
115 | 112 |
116 FfmpegDemuxImpl::~FfmpegDemuxImpl() {} | 113 FfmpegDemuxImpl::~FfmpegDemuxImpl() {} |
(...skipping 23 matching lines...) Expand all Loading... |
140 } | 137 } |
141 | 138 |
142 std::map<std::string, std::string> metadata_map; | 139 std::map<std::string, std::string> metadata_map; |
143 | 140 |
144 CopyMetadata(format_context_->metadata, metadata_map); | 141 CopyMetadata(format_context_->metadata, metadata_map); |
145 for (uint i = 0; i < format_context_->nb_streams; i++) { | 142 for (uint i = 0; i < format_context_->nb_streams; i++) { |
146 streams_.push_back(new FfmpegDemuxStream(*format_context_, i)); | 143 streams_.push_back(new FfmpegDemuxStream(*format_context_, i)); |
147 CopyMetadata(format_context_->streams[i]->metadata, metadata_map); | 144 CopyMetadata(format_context_->streams[i]->metadata, metadata_map); |
148 } | 145 } |
149 | 146 |
150 metadata_ = Metadata::Create( | 147 metadata_ = |
151 format_context_->duration * kNanosecondsPerMicrosecond, | 148 Metadata::Create(format_context_->duration * kNanosecondsPerMicrosecond, |
152 metadata_map["TITLE"], | 149 metadata_map["TITLE"], metadata_map["ARTIST"], |
153 metadata_map["ARTIST"], | 150 metadata_map["ALBUM"], metadata_map["PUBLISHER"], |
154 metadata_map["ALBUM"], | 151 metadata_map["GENRE"], metadata_map["COMPOSER"]); |
155 metadata_map["PUBLISHER"], | |
156 metadata_map["GENRE"], | |
157 metadata_map["COMPOSER"]); | |
158 | 152 |
159 return Result::kOk; | 153 return Result::kOk; |
160 } | 154 } |
161 | 155 |
162 std::unique_ptr<Metadata> FfmpegDemuxImpl::metadata() const { | 156 std::unique_ptr<Metadata> FfmpegDemuxImpl::metadata() const { |
163 return SafeClone(metadata_); | 157 return SafeClone(metadata_); |
164 } | 158 } |
165 | 159 |
166 const std::vector<Demux::DemuxStream*>& FfmpegDemuxImpl::streams() const { | 160 const std::vector<Demux::DemuxStream*>& FfmpegDemuxImpl::streams() const { |
167 return streams_; | 161 return streams_; |
(...skipping 26 matching lines...) Expand all Loading... |
194 | 188 |
195 av_packet->data = nullptr; | 189 av_packet->data = nullptr; |
196 av_packet->size = 0; | 190 av_packet->size = 0; |
197 | 191 |
198 if (av_read_frame(format_context_.get(), av_packet.get()) < 0) { | 192 if (av_read_frame(format_context_.get(), av_packet.get()) < 0) { |
199 // End of stream. Start producing end-of-stream packets for all the streams. | 193 // End of stream. Start producing end-of-stream packets for all the streams. |
200 next_stream_to_end_ = 0; | 194 next_stream_to_end_ = 0; |
201 return PullEndOfStreamPacket(stream_index_out); | 195 return PullEndOfStreamPacket(stream_index_out); |
202 } | 196 } |
203 | 197 |
204 *stream_index_out = | 198 *stream_index_out = static_cast<size_t>(av_packet->stream_index); |
205 static_cast<size_t>(av_packet->stream_index); | |
206 // TODO(dalesat): What if the packet has no PTS or duration? | 199 // TODO(dalesat): What if the packet has no PTS or duration? |
207 next_pts_ = av_packet->pts + av_packet->duration; | 200 next_pts_ = av_packet->pts + av_packet->duration; |
208 | 201 |
209 return DemuxPacket::Create(std::move(av_packet)); | 202 return DemuxPacket::Create(std::move(av_packet)); |
210 } | 203 } |
211 | 204 |
212 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) { | 205 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) { |
213 DCHECK(next_stream_to_end_ >= 0); | 206 DCHECK(next_stream_to_end_ >= 0); |
214 | 207 |
215 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) { | 208 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) { |
216 NOTREACHED() << "PullPacket called after all streams have ended"; | 209 NOTREACHED() << "PullPacket called after all streams have ended"; |
217 return nullptr; | 210 return nullptr; |
218 } | 211 } |
219 | 212 |
220 *stream_index_out = next_stream_to_end_++; | 213 *stream_index_out = next_stream_to_end_++; |
221 return Packet::CreateEndOfStream(next_pts_); | 214 return Packet::CreateEndOfStream(next_pts_); |
222 } | 215 } |
223 | 216 |
224 void FfmpegDemuxImpl::CopyMetadata( | 217 void FfmpegDemuxImpl::CopyMetadata(AVDictionary* source, |
225 AVDictionary* source, | 218 std::map<std::string, std::string>& map) { |
226 std::map<std::string, std::string>& map) { | |
227 if (source == nullptr) { | 219 if (source == nullptr) { |
228 return; | 220 return; |
229 } | 221 } |
230 | 222 |
231 for (AVDictionaryEntry *entry = | 223 for (AVDictionaryEntry* entry = |
232 av_dict_get(source, "", nullptr, AV_DICT_IGNORE_SUFFIX); | 224 av_dict_get(source, "", nullptr, AV_DICT_IGNORE_SUFFIX); |
233 entry != nullptr; | 225 entry != nullptr; |
234 entry = av_dict_get(source, "", entry, AV_DICT_IGNORE_SUFFIX)) { | 226 entry = av_dict_get(source, "", entry, AV_DICT_IGNORE_SUFFIX)) { |
235 if (map.find(entry->key) == map.end()) { | 227 if (map.find(entry->key) == map.end()) { |
236 map.emplace(entry->key, entry->value); | 228 map.emplace(entry->key, entry->value); |
237 } | 229 } |
238 } | 230 } |
239 } | 231 } |
240 | 232 |
241 FfmpegDemuxImpl::FfmpegDemuxStream::FfmpegDemuxStream( | 233 FfmpegDemuxImpl::FfmpegDemuxStream::FfmpegDemuxStream( |
242 const AVFormatContext& format_context, | 234 const AVFormatContext& format_context, |
243 size_t index) : | 235 size_t index) |
244 stream_(format_context.streams[index]), index_(index) { | 236 : stream_(format_context.streams[index]), index_(index) { |
245 stream_type_ = AvCodecContext::GetStreamType(*stream_->codec); | 237 stream_type_ = AvCodecContext::GetStreamType(*stream_->codec); |
246 } | 238 } |
247 | 239 |
248 FfmpegDemuxImpl::FfmpegDemuxStream::~FfmpegDemuxStream() {} | 240 FfmpegDemuxImpl::FfmpegDemuxStream::~FfmpegDemuxStream() {} |
249 | 241 |
250 size_t FfmpegDemuxImpl::FfmpegDemuxStream::index() const { | 242 size_t FfmpegDemuxImpl::FfmpegDemuxStream::index() const { |
251 return index_; | 243 return index_; |
252 } | 244 } |
253 | 245 |
254 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type() | 246 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type() |
255 const { | 247 const { |
256 return SafeClone(stream_type_); | 248 return SafeClone(stream_type_); |
257 } | 249 } |
258 | 250 |
259 } // namespace media | 251 } // namespace media |
260 } // namespace mojo | 252 } // namespace mojo |
OLD | NEW |