| 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 |