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

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: Changed the way AVBuffer allocation/deallocation is done in the ffmpeg audio decoder. Created 4 years, 9 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(const 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() {
56 av_init_packet(&av_packet_);
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; }
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() {
73 return av_packet_;
74 }
75
76 protected:
77 ~DemuxPacket() override {
78 av_free_packet(&av_packet_);
79 }
80
81 void Release() override { delete this; }
82
83 private:
84 AVPacket av_packet_;
85 };
86
87 struct AVFormatContextDeleter {
88 inline void operator()(AVFormatContext* ptr) const {
89 avformat_free_context(ptr);
90 }
91 };
92
93 // Produces an end-of-stream packet for next_stream_to_end_.
94 PacketPtr PullEndOfStreamPacket(size_t* stream_index_out);
95
96 // Copies metadata from the specified source into map.
97 void CopyMetadata(
98 AVDictionary* source,
99 std::map<std::string, std::string>& map);
100
101 std::shared_ptr<Reader> reader_;
102 std::unique_ptr<AVFormatContext, AVFormatContextDeleter> format_context_;
103 AvioContextPtr io_context_;
104 std::vector<DemuxStream*> streams_;
105 std::unique_ptr<Metadata> metadata_;
106 int64_t next_presentation_time_;
107 int next_stream_to_end_; // -1 means don't end. streams_.size() means stop.
108 };
109
110 // static
111 std::shared_ptr<Demux> FfmpegDemux::Create() {
112 return std::shared_ptr<Demux>(new FfmpegDemuxImpl());
113 }
114
115 FfmpegDemuxImpl::FfmpegDemuxImpl() : next_stream_to_end_(-1) {}
116
117 FfmpegDemuxImpl::~FfmpegDemuxImpl() {}
118
119 Result FfmpegDemuxImpl::Init(std::shared_ptr<Reader> reader) {
120 static constexpr uint64_t kNanosecondsPerMicrosecond = 1000;
121
122 reader_ = reader;
123
124 io_context_ = CreateAvioContext(reader.get());
125 if (!io_context_) {
126 LOG(ERROR) << "CreateAvioContext failed (allocation failure)";
127 return Result::kInternalError;
128 }
129
130 // TODO(dalesat): Consider ffmpeg util to centralize memory management.
131 AVFormatContext* format_context = avformat_alloc_context();
132 format_context->flags |= AVFMT_FLAG_CUSTOM_IO | AVFMT_FLAG_FAST_SEEK;
133 format_context->pb = io_context_.get();
134
135 // TODO(dalesat): This synchronous operation may take a long time.
136 int r = avformat_open_input(&format_context, nullptr, nullptr, nullptr);
137 format_context_.reset(format_context);
138 if (r < 0) {
139 return Result::kInternalError;
140 }
141
142 // TODO(dalesat): This synchronous operation may take a long time.
143 r = avformat_find_stream_info(format_context_.get(), nullptr);
144 if (r < 0) {
145 LOG(ERROR) << "avformat_find_stream_info failed, result " << r;
146 return Result::kInternalError;
147 }
148
149 std::map<std::string, std::string> metadata_map;
150
151 CopyMetadata(format_context_->metadata, metadata_map);
152 for (uint i = 0; i < format_context_->nb_streams; i++) {
153 streams_.push_back(new FfmpegDemuxStream(*format_context_, i));
154 CopyMetadata(format_context_->streams[i]->metadata, metadata_map);
155 }
156
157 metadata_ = Metadata::Create(
158 format_context_->duration * kNanosecondsPerMicrosecond,
159 metadata_map["TITLE"],
160 metadata_map["ARTIST"],
161 metadata_map["ALBUM"],
162 metadata_map["PUBLISHER"],
163 metadata_map["GENRE"],
164 metadata_map["COMPOSER"]);
165
166 return Result::kOk;
167 }
168
169 std::unique_ptr<Metadata> FfmpegDemuxImpl::metadata() const {
170 return SafeClone(metadata_);
171 }
172
173 const std::vector<Demux::DemuxStream*>& FfmpegDemuxImpl::streams() const {
174 return streams_;
175 }
176
177 size_t FfmpegDemuxImpl::stream_count() const {
178 if (!format_context_) {
179 return 0;
180 }
181 return format_context_->nb_streams;
182 }
183
184 PacketPtr FfmpegDemuxImpl::PullPacket(size_t* stream_index_out) {
185 DCHECK(stream_index_out);
186
187 if (next_stream_to_end_ != -1) {
188 // We're producing end-of-stream packets for all the streams.
189 return PullEndOfStreamPacket(stream_index_out);
190 }
191
192 FfmpegDemuxImpl::DemuxPacket* demux_packet =
193 new FfmpegDemuxImpl::DemuxPacket();
194
195 demux_packet->av_packet().data = nullptr;
196 demux_packet->av_packet().size = 0;
197
198 if (av_read_frame(format_context_.get(), &demux_packet->av_packet()) < 0) {
199 // End of stream. Start producing end-of-stream packets for all the streams.
200 PacketPtr(demux_packet); // Deletes demux_packet.
201 next_stream_to_end_ = 0;
202 return PullEndOfStreamPacket(stream_index_out);
203 }
204
205 *stream_index_out =
206 static_cast<size_t>(demux_packet->av_packet().stream_index);
207 // TODO(dalesat): What if the packet has no PTS or duration?
208 next_presentation_time_ =
209 demux_packet->presentation_time() + demux_packet->duration();
210
211 return PacketPtr(demux_packet);
212 }
213
214 PacketPtr FfmpegDemuxImpl::PullEndOfStreamPacket(size_t* stream_index_out) {
215 DCHECK(next_stream_to_end_ >= 0);
216
217 if (static_cast<std::size_t>(next_stream_to_end_) >= streams_.size()) {
218 NOTREACHED() << "PullPacket called after all streams have ended";
219 return nullptr;
220 }
221
222 *stream_index_out = next_stream_to_end_++;
223 return Packet::CreateEndOfStream(next_presentation_time_);
224 }
225
226 void FfmpegDemuxImpl::CopyMetadata(
227 AVDictionary* source,
228 std::map<std::string, std::string>& map) {
229 if (source == nullptr) {
230 return;
231 }
232
233 for (AVDictionaryEntry *entry =
234 av_dict_get(source, "", nullptr, AV_DICT_IGNORE_SUFFIX);
235 entry != nullptr;
236 entry = av_dict_get(source, "", entry, AV_DICT_IGNORE_SUFFIX)) {
237 if (map.find(entry->key) == map.end()) {
238 map.emplace(entry->key, entry->value);
239 }
240 }
241 }
242
243 FfmpegDemuxImpl::FfmpegDemuxStream::FfmpegDemuxStream(
244 const AVFormatContext& format_context,
245 size_t index) :
246 stream_(format_context.streams[index]), index_(index) {
247 stream_type_ = StreamTypeFromAVCodecContext(*stream_->codec);
248 }
249
250 FfmpegDemuxImpl::FfmpegDemuxStream::~FfmpegDemuxStream() {}
251
252 size_t FfmpegDemuxImpl::FfmpegDemuxStream::index() const {
253 return index_;
254 }
255
256 std::unique_ptr<StreamType> FfmpegDemuxImpl::FfmpegDemuxStream::stream_type()
257 const {
258 return SafeClone(stream_type_);
259 }
260
261 } // namespace media
262 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698