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(ffmpeg::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(ffmpeg::AvPacketPtr av_packet) : |
| 73 Packet( |
| 74 (av_packet->pts == AV_NOPTS_VALUE) ? kUnknownPts : av_packet->pts, |
| 75 false, |
| 76 static_cast<size_t>(av_packet->size), |
| 77 av_packet->data), |
| 78 av_packet_(std::move(av_packet)) { |
| 79 DCHECK(av_packet->size >= 0); |
| 80 } |
| 81 |
| 82 ffmpeg::AvPacketPtr av_packet_; |
87 }; | 83 }; |
88 | 84 |
89 struct AVFormatContextDeleter { | 85 struct AVFormatContextDeleter { |
90 inline void operator()(AVFormatContext* ptr) const { | 86 inline void operator()(AVFormatContext* ptr) const { |
91 avformat_free_context(ptr); | 87 avformat_free_context(ptr); |
92 } | 88 } |
93 }; | 89 }; |
94 | 90 |
95 // Produces an end-of-stream packet for next_stream_to_end_. | 91 // Produces an end-of-stream packet for next_stream_to_end_. |
96 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out); | 92 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out); |
97 | 93 |
98 // Copies metadata from the specified source into map. | 94 // Copies metadata from the specified source into map. |
99 void CopyMetadata( | 95 void CopyMetadata( |
100 AVDictionary* source, | 96 AVDictionary* source, |
101 std::map<std::string, std::string>& map); | 97 std::map<std::string, std::string>& map); |
102 | 98 |
103 std::shared_ptr<Reader> reader_; | 99 std::shared_ptr<Reader> reader_; |
104 std::unique_ptr<AVFormatContext, AVFormatContextDeleter> format_context_; | 100 std::unique_ptr<AVFormatContext, AVFormatContextDeleter> format_context_; |
105 AvioContextPtr io_context_; | 101 AvioContextPtr io_context_; |
106 std::vector<DemuxStream*> streams_; | 102 std::vector<DemuxStream*> streams_; |
107 std::unique_ptr<Metadata> metadata_; | 103 std::unique_ptr<Metadata> metadata_; |
108 int64_t next_presentation_time_; | 104 int64_t next_pts_; |
109 int next_stream_to_end_ = -1; // -1: don't end, streams_.size(): stop. | 105 int next_stream_to_end_ = -1; // -1: don't end, streams_.size(): stop. |
110 }; | 106 }; |
111 | 107 |
112 // static | 108 // static |
113 std::shared_ptr<Demux> FfmpegDemux::Create() { | 109 std::shared_ptr<Demux> FfmpegDemux::Create() { |
114 return std::shared_ptr<Demux>(new FfmpegDemuxImpl()); | 110 return std::shared_ptr<Demux>(new FfmpegDemuxImpl()); |
115 } | 111 } |
116 | 112 |
117 FfmpegDemuxImpl::FfmpegDemuxImpl() {} | 113 FfmpegDemuxImpl::FfmpegDemuxImpl() {} |
118 | 114 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 188 } |
193 | 189 |
194 PacketPtr FfmpegDemuxImpl::PullPacket(size_t* stream_index_out) { | 190 PacketPtr FfmpegDemuxImpl::PullPacket(size_t* stream_index_out) { |
195 DCHECK(stream_index_out); | 191 DCHECK(stream_index_out); |
196 | 192 |
197 if (next_stream_to_end_ != -1) { | 193 if (next_stream_to_end_ != -1) { |
198 // We're producing end-of-stream packets for all the streams. | 194 // We're producing end-of-stream packets for all the streams. |
199 return PullEndOfStreamPacket(stream_index_out); | 195 return PullEndOfStreamPacket(stream_index_out); |
200 } | 196 } |
201 | 197 |
202 FfmpegDemuxImpl::DemuxPacket* demux_packet = | 198 ffmpeg::AvPacketPtr av_packet = ffmpeg::AvPacket::Create(); |
203 new FfmpegDemuxImpl::DemuxPacket(); | |
204 | 199 |
205 demux_packet->av_packet().data = nullptr; | 200 av_packet->data = nullptr; |
206 demux_packet->av_packet().size = 0; | 201 av_packet->size = 0; |
207 | 202 |
208 if (av_read_frame(format_context_.get(), &demux_packet->av_packet()) < 0) { | 203 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. | 204 // 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; | 205 next_stream_to_end_ = 0; |
212 return PullEndOfStreamPacket(stream_index_out); | 206 return PullEndOfStreamPacket(stream_index_out); |
213 } | 207 } |
214 | 208 |
215 *stream_index_out = | 209 *stream_index_out = |
216 static_cast<size_t>(demux_packet->av_packet().stream_index); | 210 static_cast<size_t>(av_packet->stream_index); |
217 // TODO(dalesat): What if the packet has no PTS or duration? | 211 // TODO(dalesat): What if the packet has no PTS or duration? |
218 next_presentation_time_ = | 212 next_pts_ = av_packet->pts + av_packet->duration; |
219 demux_packet->presentation_time() + demux_packet->duration(); | |
220 | 213 |
221 return PacketPtr(demux_packet); | 214 return DemuxPacket::Create(std::move(av_packet)); |
222 } | 215 } |
223 | 216 |
224 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) { | 217 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) { |
225 DCHECK(next_stream_to_end_ >= 0); | 218 DCHECK(next_stream_to_end_ >= 0); |
226 | 219 |
227 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) { | 220 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) { |
228 NOTREACHED() << "PullPacket called after all streams have ended"; | 221 NOTREACHED() << "PullPacket called after all streams have ended"; |
229 return nullptr; | 222 return nullptr; |
230 } | 223 } |
231 | 224 |
232 *stream_index_out = next_stream_to_end_++; | 225 *stream_index_out = next_stream_to_end_++; |
233 return Packet::CreateEndOfStream(next_presentation_time_); | 226 return Packet::CreateEndOfStream(next_pts_); |
234 } | 227 } |
235 | 228 |
236 void FfmpegDemuxImpl::CopyMetadata( | 229 void FfmpegDemuxImpl::CopyMetadata( |
237 AVDictionary* source, | 230 AVDictionary* source, |
238 std::map<std::string, std::string>& map) { | 231 std::map<std::string, std::string>& map) { |
239 if (source == nullptr) { | 232 if (source == nullptr) { |
240 return; | 233 return; |
241 } | 234 } |
242 | 235 |
243 for (AVDictionaryEntry *entry = | 236 for (AVDictionaryEntry *entry = |
(...skipping 19 matching lines...) Expand all Loading... |
263 return index_; | 256 return index_; |
264 } | 257 } |
265 | 258 |
266 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type() | 259 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type() |
267 const { | 260 const { |
268 return SafeClone(stream_type_); | 261 return SafeClone(stream_type_); |
269 } | 262 } |
270 | 263 |
271 } // namespace media | 264 } // namespace media |
272 } // namespace mojo | 265 } // namespace mojo |
OLD | NEW |