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_packet.h" | |
9 #include "services/media/framework_ffmpeg/ffmpeg_demux.h" | 10 #include "services/media/framework_ffmpeg/ffmpeg_demux.h" |
10 #include "services/media/framework_ffmpeg/ffmpeg_io.h" | 11 #include "services/media/framework_ffmpeg/ffmpeg_io.h" |
11 #include "services/media/framework_ffmpeg/ffmpeg_type_converters.h" | 12 #include "services/media/framework_ffmpeg/ffmpeg_type_converters.h" |
12 | 13 |
13 namespace mojo { | 14 namespace mojo { |
14 namespace media { | 15 namespace media { |
15 | 16 |
16 class FfmpegDemuxImpl : public FfmpegDemux { | 17 class FfmpegDemuxImpl : public FfmpegDemux { |
17 public: | 18 public: |
18 FfmpegDemuxImpl(); | 19 FfmpegDemuxImpl(); |
(...skipping 28 matching lines...) Expand all Loading... | |
47 | 48 |
48 private: | 49 private: |
49 AVStream* stream_; | 50 AVStream* stream_; |
50 size_t index_; | 51 size_t index_; |
51 std::unique_ptr<StreamType> stream_type_; | 52 std::unique_ptr<StreamType> stream_type_; |
52 }; | 53 }; |
53 | 54 |
54 // Specialized packet implementation. | 55 // Specialized packet implementation. |
55 class DemuxPacket : public Packet { | 56 class DemuxPacket : public Packet { |
56 public: | 57 public: |
57 DemuxPacket() { | 58 static PacketPtr Create(AvPacketPtr av_packet) { |
58 av_init_packet(&av_packet_); | 59 return PacketPtr(new DemuxPacket(std::move(av_packet))); |
59 } | |
60 | |
61 // Packet implementation. | |
62 int64_t presentation_time() const override { return av_packet_.pts; }; | |
63 | |
64 uint64_t duration() const override { return av_packet_.duration; }; | |
65 | |
66 bool end_of_stream() const override { return false; } | |
67 | |
68 size_t size() const override { return size_t(av_packet_.size); } | |
69 | |
70 void* payload() const override { | |
71 return reinterpret_cast<void*>(av_packet_.data); | |
72 } | 60 } |
73 | 61 |
74 AVPacket& av_packet() { | 62 AVPacket& av_packet() { |
75 return av_packet_; | 63 return *av_packet_; |
76 } | 64 } |
77 | 65 |
78 protected: | 66 protected: |
79 ~DemuxPacket() override { | 67 ~DemuxPacket() override {} |
80 av_free_packet(&av_packet_); | |
81 } | |
82 | 68 |
83 void Release() override { delete this; } | 69 void Release() override { delete this; } |
84 | 70 |
85 private: | 71 private: |
86 AVPacket av_packet_; | 72 DemuxPacket(AvPacketPtr av_packet) : |
73 Packet( | |
74 av_packet->pts, | |
johngro
2016/03/21 19:47:56
Since this is a place where we we are coming from
dalesat
2016/03/21 22:30:59
Done.
| |
75 false, | |
76 static_cast<size_t>(av_packet->size), | |
johngro
2016/03/21 19:47:56
If this cast is required because av_packet->size i
dalesat
2016/03/21 22:30:59
Done.
| |
77 av_packet->data), | |
78 av_packet_(std::move(av_packet)) {} | |
79 | |
80 AvPacketPtr av_packet_; | |
87 }; | 81 }; |
88 | 82 |
89 struct AVFormatContextDeleter { | 83 struct AVFormatContextDeleter { |
90 inline void operator()(AVFormatContext* ptr) const { | 84 inline void operator()(AVFormatContext* ptr) const { |
91 avformat_free_context(ptr); | 85 avformat_free_context(ptr); |
92 } | 86 } |
93 }; | 87 }; |
94 | 88 |
95 // Produces an end-of-stream packet for next_stream_to_end_. | 89 // Produces an end-of-stream packet for next_stream_to_end_. |
96 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out); | 90 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out); |
97 | 91 |
98 // Copies metadata from the specified source into map. | 92 // Copies metadata from the specified source into map. |
99 void CopyMetadata( | 93 void CopyMetadata( |
100 AVDictionary* source, | 94 AVDictionary* source, |
101 std::map<std::string, std::string>& map); | 95 std::map<std::string, std::string>& map); |
102 | 96 |
103 std::shared_ptr<Reader> reader_; | 97 std::shared_ptr<Reader> reader_; |
104 std::unique_ptr<AVFormatContext, AVFormatContextDeleter> format_context_; | 98 std::unique_ptr<AVFormatContext, AVFormatContextDeleter> format_context_; |
105 AvioContextPtr io_context_; | 99 AvioContextPtr io_context_; |
106 std::vector<DemuxStream*> streams_; | 100 std::vector<DemuxStream*> streams_; |
107 std::unique_ptr<Metadata> metadata_; | 101 std::unique_ptr<Metadata> metadata_; |
108 int64_t next_presentation_time_; | 102 int64_t next_pts_; |
109 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. |
110 }; | 104 }; |
111 | 105 |
112 // static | 106 // static |
113 std::shared_ptr<Demux> FfmpegDemux::Create() { | 107 std::shared_ptr<Demux> FfmpegDemux::Create() { |
114 return std::shared_ptr<Demux>(new FfmpegDemuxImpl()); | 108 return std::shared_ptr<Demux>(new FfmpegDemuxImpl()); |
115 } | 109 } |
116 | 110 |
117 FfmpegDemuxImpl::FfmpegDemuxImpl() {} | 111 FfmpegDemuxImpl::FfmpegDemuxImpl() {} |
118 | 112 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 } | 186 } |
193 | 187 |
194 PacketPtr FfmpegDemuxImpl::PullPacket(size_t* stream_index_out) { | 188 PacketPtr FfmpegDemuxImpl::PullPacket(size_t* stream_index_out) { |
195 DCHECK(stream_index_out); | 189 DCHECK(stream_index_out); |
196 | 190 |
197 if (next_stream_to_end_ != -1) { | 191 if (next_stream_to_end_ != -1) { |
198 // We're producing end-of-stream packets for all the streams. | 192 // We're producing end-of-stream packets for all the streams. |
199 return PullEndOfStreamPacket(stream_index_out); | 193 return PullEndOfStreamPacket(stream_index_out); |
200 } | 194 } |
201 | 195 |
202 FfmpegDemuxImpl::DemuxPacket* demux_packet = | 196 AvPacketPtr av_packet = AvPacket::Create(); |
203 new FfmpegDemuxImpl::DemuxPacket(); | |
204 | 197 |
205 demux_packet->av_packet().data = nullptr; | 198 av_packet->data = nullptr; |
206 demux_packet->av_packet().size = 0; | 199 av_packet->size = 0; |
207 | 200 |
208 if (av_read_frame(format_context_.get(), &demux_packet->av_packet()) < 0) { | 201 if (av_read_frame(format_context_.get(), av_packet.get()) < 0) { |
209 // End of stream. Start producing end-of-stream packets for all the streams. | 202 // End of stream. Start producing end-of-stream packets for all the streams. |
210 PacketPtr(demux_packet); // Deletes demux_packet. | |
211 next_stream_to_end_ = 0; | 203 next_stream_to_end_ = 0; |
212 return PullEndOfStreamPacket(stream_index_out); | 204 return PullEndOfStreamPacket(stream_index_out); |
213 } | 205 } |
214 | 206 |
215 *stream_index_out = | 207 *stream_index_out = |
216 static_cast<size_t>(demux_packet->av_packet().stream_index); | 208 static_cast<size_t>(av_packet->stream_index); |
217 // TODO(dalesat): What if the packet has no PTS or duration? | 209 // TODO(dalesat): What if the packet has no PTS or duration? |
218 next_presentation_time_ = | 210 next_pts_ = av_packet->pts + av_packet->duration; |
219 demux_packet->presentation_time() + demux_packet->duration(); | |
220 | 211 |
221 return PacketPtr(demux_packet); | 212 return DemuxPacket::Create(std::move(av_packet)); |
222 } | 213 } |
223 | 214 |
224 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) { | 215 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) { |
225 DCHECK(next_stream_to_end_ >= 0); | 216 DCHECK(next_stream_to_end_ >= 0); |
226 | 217 |
227 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) { | 218 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) { |
228 NOTREACHED() << "PullPacket called after all streams have ended"; | 219 NOTREACHED() << "PullPacket called after all streams have ended"; |
229 return nullptr; | 220 return nullptr; |
230 } | 221 } |
231 | 222 |
232 *stream_index_out = next_stream_to_end_++; | 223 *stream_index_out = next_stream_to_end_++; |
233 return Packet::CreateEndOfStream(next_presentation_time_); | 224 return Packet::CreateEndOfStream(next_pts_); |
234 } | 225 } |
235 | 226 |
236 void FfmpegDemuxImpl::CopyMetadata( | 227 void FfmpegDemuxImpl::CopyMetadata( |
237 AVDictionary* source, | 228 AVDictionary* source, |
238 std::map<std::string, std::string>& map) { | 229 std::map<std::string, std::string>& map) { |
239 if (source == nullptr) { | 230 if (source == nullptr) { |
240 return; | 231 return; |
241 } | 232 } |
242 | 233 |
243 for (AVDictionaryEntry *entry = | 234 for (AVDictionaryEntry *entry = |
(...skipping 19 matching lines...) Expand all Loading... | |
263 return index_; | 254 return index_; |
264 } | 255 } |
265 | 256 |
266 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type() | 257 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type() |
267 const { | 258 const { |
268 return SafeClone(stream_type_); | 259 return SafeClone(stream_type_); |
269 } | 260 } |
270 | 261 |
271 } // namespace media | 262 } // namespace media |
272 } // namespace mojo | 263 } // namespace mojo |
OLD | NEW |