Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: services/media/framework_ffmpeg/ffmpeg_demux.cc

Issue 1686363002: Motown: ffmpeg implementations of framework 'parts' (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Retype some const unique_ptr<T>& parameters to const T&. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <map>
6
7 #include "base/logging.h"
8 #include "services/media/framework/safe_clone.h"
9 #include "services/media/framework_ffmpeg/ffmpeg_demux.h"
10 #include "services/media/framework_ffmpeg/ffmpeg_io.h"
11 #include "services/media/framework_ffmpeg/ffmpeg_type_converters.h"
12
13 namespace mojo {
14 namespace media {
15
16 class FfmpegDemuxImpl : public FfmpegDemux {
17 public:
18 FfmpegDemuxImpl();
19
20 ~FfmpegDemuxImpl() override;
21
22 // Demux implementation.
23 Result Init(std::shared_ptr<Reader> reader) override;
24
25 std::unique_ptr<Metadata> metadata() const override;
26
27 const std::vector<DemuxStream*>& streams() const override;
28
29 // MultistreamSource implementation.
30 size_t stream_count() const override;
31
32 PacketPtr PullPacket(size_t* stream_index_out) override;
33
34 private:
35 class FfmpegDemuxStream : public DemuxStream {
36 public:
37 FfmpegDemuxStream(AVFormatContext* format_context, size_t index);
38
39 ~FfmpegDemuxStream() override;
40
41 // Demux::DemuxStream implementation.
42 size_t index() const override;
43
44 std::unique_ptr<StreamType> stream_type() const override;
45
46 private:
47 AVStream* stream_;
48 size_t index_;
49 std::unique_ptr<StreamType> stream_type_;
50 };
51
52 // Specialized packet implementation.
53 class DemuxPacket : public Packet {
54 public:
55 ~DemuxPacket() override {
johngro 2016/03/01 01:31:38 Packet's destructor is protected, DemuxPacket's sh
dalesat 2016/03/01 20:43:02 Made the destructor protected. Packet::Create crea
56 av_free_packet(&av_packet);
johngro 2016/03/01 01:31:39 what happens if the av_packet was never allocated
dalesat 2016/03/01 20:43:02 Not sure what you mean. This packet implementation
johngro 2016/03/01 22:07:26 yes, but nothing in this class made certain that a
dalesat 2016/03/02 18:35:36 Acknowledged.
57 }
58
59 // Packet implementation.
60 int64_t presentation_time() const override { return av_packet.pts; };
61
62 uint64_t duration() const override { return av_packet.duration; };
63
64 bool end_of_stream() const override { return false; }
johngro 2016/03/01 01:31:39 if PTS, duration and EOS are core pieces of metada
dalesat 2016/03/01 20:43:02 We already have TODOs to revisit the packet defini
65
66 size_t size() const override { return size_t(av_packet.size); }
67
68 void* payload() const override {
69 return reinterpret_cast<void*>(av_packet.data);
70 }
71
72 AVPacket av_packet;
johngro 2016/03/01 01:31:39 this should be private and named av_packet_
dalesat 2016/03/01 20:43:02 Done.
73
74 protected:
75 void Release() override { delete this; }
johngro 2016/03/01 01:31:39 so, Packet instances seem to be managed using a st
dalesat 2016/03/01 20:43:01 We already have TODOs to revisit this. I took this
76 };
77
78 struct AVFormatContextDeleter {
79 inline void operator()(AVFormatContext* ptr) const {
80 avformat_free_context(ptr);
81 }
82 };
83
84 struct AVIOContextDeleter {
85 inline void operator()(AVIOContext* ptr) const {
86 FreeAvioContext(ptr);
87 }
88 };
89
90 // Produces an end-of-stream packet for next_stream_to_end_.
91 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out);
92
93 // Copies metadata from the specified source into map.
94 void CopyMetadata(
95 AVDictionary* source,
96 std::map<std::string, std::string>& map);
97
98 std::shared_ptr<Reader> reader_;
99 std::unique_ptr<AVFormatContext, AVFormatContextDeleter> format_context_;
100 std::unique_ptr<AVIOContext, AVIOContextDeleter> io_context_;
101 std::vector<DemuxStream*> streams_;
102 std::unique_ptr<Metadata> metadata_;
103 int64_t next_presentation_time_;
104 int next_stream_to_end_; // -1 means don't end. streams_.size() means stop.
105 };
106
107 // static
108 std::shared_ptr<Demux> FfmpegDemux::Create() {
109 return std::shared_ptr<Demux>(new FfmpegDemuxImpl());
110 }
111
112 FfmpegDemuxImpl::FfmpegDemuxImpl() : next_stream_to_end_(-1) {}
113
114 FfmpegDemuxImpl::~FfmpegDemuxImpl() {}
115
116 Result FfmpegDemuxImpl::Init(std::shared_ptr<Reader> reader) {
117 static const uint64_t kNanosecondsPerMicrosecond = 1000;
johngro 2016/03/01 01:31:39 constexpr
dalesat 2016/03/01 20:43:02 Done.
118
119 reader_ = reader;
120
121 AVFormatContext* format_context = avformat_alloc_context();
122
123 io_context_.reset(CreateAvioContext(reader.get()));
124 if (!io_context_) {
125 LOG(ERROR) << "CreateAvioContext failed (allocation failure)";
johngro 2016/03/01 01:31:38 this leaks format_context I made a similar commen
dalesat 2016/03/01 20:43:01 Moved this allocation down to where it belongs. Ad
126 return Result::kInternalError;
127 }
128
129 format_context->flags |= AVFMT_FLAG_CUSTOM_IO | AVFMT_FLAG_FAST_SEEK;
130 format_context->pb = io_context_.get();
131
132 int r = avformat_open_input(&format_context, nullptr, nullptr, nullptr);
johngro 2016/03/01 01:31:39 These two operations (open_input and find_stream_i
dalesat 2016/03/01 20:43:02 Done.
dalesat 2016/03/01 20:43:02 Done.
133 format_context_.reset(format_context);
134 if (r < 0) {
135 return Result::kInternalError;
136 }
137
138 r = avformat_find_stream_info(format_context_.get(), nullptr);
139 if (r < 0) {
140 LOG(ERROR) << "avformat_find_stream_info failed, result " << r;
141 return Result::kInternalError;
142 }
143
144 std::map<std::string, std::string> metadata_map;
145
146 CopyMetadata(format_context_->metadata, metadata_map);
147 for (uint i = 0; i < format_context_->nb_streams; i++) {
148 streams_.push_back(new FfmpegDemuxStream(format_context_.get(), i));
149 CopyMetadata(format_context_->streams[i]->metadata, metadata_map);
150 }
151
152 metadata_ = Metadata::Create(
153 format_context_->duration * kNanosecondsPerMicrosecond,
154 metadata_map["TITLE"],
155 metadata_map["ARTIST"],
156 metadata_map["ALBUM"],
157 metadata_map["PUBLISHER"],
158 metadata_map["GENRE"],
159 metadata_map["COMPOSER"]);
160
161 return Result::kOk;
162 }
163
164 std::unique_ptr<Metadata> FfmpegDemuxImpl::metadata() const {
165 return SafeClone(metadata_);
166 }
167
168 const std::vector<Demux::DemuxStream*>& FfmpegDemuxImpl::streams() const {
169 return streams_;
170 }
171
172 size_t FfmpegDemuxImpl::stream_count() const {
173 if (!format_context_) {
174 return 0;
175 }
176 return format_context_->nb_streams;
177 }
178
179 PacketPtr FfmpegDemuxImpl::PullPacket(size_t* stream_index_out) {
180 DCHECK(stream_index_out);
181
182 if (next_stream_to_end_ != -1) {
183 // We're producing end-of-stream packets for all the streams.
184 return PullEndOfStreamPacket(stream_index_out);
185 }
186
187 FfmpegDemuxImpl::DemuxPacket* demux_packet =
188 new FfmpegDemuxImpl::DemuxPacket();
189
190 av_init_packet(&demux_packet->av_packet);
johngro 2016/03/01 01:31:39 FfmpegDemuxImpl::DemuxPacket owns the call to av_f
dalesat 2016/03/01 20:43:02 Done.
191 demux_packet->av_packet.data = nullptr;
192 demux_packet->av_packet.size = 0;
johngro 2016/03/01 01:31:39 access to av_packet should exposed using an access
dalesat 2016/03/01 20:43:02 Done.
193
194 if (av_read_frame(format_context_.get(), &demux_packet->av_packet) < 0) {
195 // End of stream. Start producing end-of-stream packets for all the streams.
196 delete demux_packet;
197 next_stream_to_end_ = 0;
198 return PullEndOfStreamPacket(stream_index_out);
199 }
200
201 *stream_index_out =
202 static_cast<size_t>(demux_packet->av_packet.stream_index);
203 next_presentation_time_ =
204 demux_packet->presentation_time() + demux_packet->duration();
johngro 2016/03/01 01:31:39 either PTS or duration may be AV_NOPTS_VALUE and n
dalesat 2016/03/01 20:43:01 Acknowledged.
johngro 2016/03/01 22:07:26 Great, if you agree that this can be an issue, but
dalesat 2016/03/02 18:35:36 Done.
205
206 return PacketPtr(demux_packet);
207 }
208
209 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) {
210 DCHECK(next_stream_to_end_ >= 0);
211
212 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) {
213 NOTREACHED() << "PullPacket called after all streams have ended";
214 return nullptr;
215 }
216
217 *stream_index_out = next_stream_to_end_++;
218 return Packet::CreateEndOfStream(next_presentation_time_);
219 }
220
221 void FfmpegDemuxImpl::CopyMetadata(
222 AVDictionary* source,
223 std::map<std::string, std::string>& map) {
224 if (source == nullptr) {
225 return;
226 }
227
228 for (AVDictionaryEntry *entry =
229 av_dict_get(source, "", nullptr, AV_DICT_IGNORE_SUFFIX);
230 entry != nullptr;
231 entry = av_dict_get(source, "", entry, AV_DICT_IGNORE_SUFFIX)) {
232 if (map.find(entry->key) == map.end()) {
233 map.emplace(entry->key, entry->value);
234 }
235 }
236 }
237
238 FfmpegDemuxImpl::FfmpegDemuxStream::FfmpegDemuxStream(
239 AVFormatContext* format_context,
johngro 2016/03/01 01:31:39 Ownership of format_context is not being transferr
dalesat 2016/03/01 20:43:02 Done.
240 size_t index) :
241 stream_(format_context->streams[index]), index_(index) {
242 stream_type_ = StreamTypeFromAVCodecContext(stream_->codec);
243 }
244
245 FfmpegDemuxImpl::FfmpegDemuxStream::~FfmpegDemuxStream() {}
246
247 size_t FfmpegDemuxImpl::FfmpegDemuxStream::index() const {
248 return index_;
249 }
250
251 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type()
252 const {
253 return SafeClone(stream_type_);
254 }
255
256 } // namespace media
257 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698