summaryrefslogtreecommitdiff
path: root/chromium/media/formats
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/formats')
-rw-r--r--chromium/media/formats/BUILD.gn2
-rw-r--r--chromium/media/formats/mp4/h264_annex_b_fuzz_corpus/pps_neq_sps_config_idr.binbin0 -> 461 bytes
-rw-r--r--chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter.cc4
-rw-r--r--chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter_unittest.cc9
-rw-r--r--chromium/media/formats/mpeg/mpeg1_audio_stream_parser.cc33
-rw-r--r--chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.cc178
-rw-r--r--chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h79
7 files changed, 268 insertions, 37 deletions
diff --git a/chromium/media/formats/BUILD.gn b/chromium/media/formats/BUILD.gn
index fbb2170607d..1a9089f2b1a 100644
--- a/chromium/media/formats/BUILD.gn
+++ b/chromium/media/formats/BUILD.gn
@@ -45,6 +45,8 @@ source_set("formats") {
"mpeg/mpeg1_audio_stream_parser.h",
"mpeg/mpeg_audio_stream_parser_base.cc",
"mpeg/mpeg_audio_stream_parser_base.h",
+ "webcodecs/webcodecs_encoded_chunk_stream_parser.cc",
+ "webcodecs/webcodecs_encoded_chunk_stream_parser.h",
"webm/webm_audio_client.cc",
"webm/webm_audio_client.h",
"webm/webm_cluster_parser.cc",
diff --git a/chromium/media/formats/mp4/h264_annex_b_fuzz_corpus/pps_neq_sps_config_idr.bin b/chromium/media/formats/mp4/h264_annex_b_fuzz_corpus/pps_neq_sps_config_idr.bin
new file mode 100644
index 00000000000..77706919f14
--- /dev/null
+++ b/chromium/media/formats/mp4/h264_annex_b_fuzz_corpus/pps_neq_sps_config_idr.bin
Binary files differ
diff --git a/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter.cc b/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter.cc
index f3c4e8ef0e8..621bd8b7e49 100644
--- a/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter.cc
+++ b/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter.cc
@@ -78,7 +78,7 @@ Status H264AnnexBToAvcBitstreamConverter::ConvertChunk(
}
case H264NALU::kSPSExt: {
- NOTREACHED() << "SPS extensions are not supported yet.";
+ // SPS extensions are not supported yet.
break;
}
@@ -95,7 +95,7 @@ Status H264AnnexBToAvcBitstreamConverter::ConvertChunk(
blob(nalu.data, nalu.data + nalu.size));
pps_to_include.insert(pps_id);
if (auto* pps = parser_.GetPPS(pps_id))
- pps_to_include.insert(pps->seq_parameter_set_id);
+ sps_to_include.insert(pps->seq_parameter_set_id);
config_changed = true;
break;
}
diff --git a/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter_unittest.cc b/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter_unittest.cc
index 8fadf60e6f2..176dc31063f 100644
--- a/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter_unittest.cc
+++ b/chromium/media/formats/mp4/h264_annex_b_to_avc_bitstream_converter_unittest.cc
@@ -37,10 +37,11 @@ std::vector<uint8_t> ReadTestFile(std::string name) {
namespace media {
TEST(H264AnnexBToAvcBitstreamConverterTest, Success) {
- std::string chunks[] = {"chunk1-config-idr.bin", "chunk2-non-idr.bin",
- "chunk3-non-idr.bin", "chunk4-non-idr.bin",
- "chunk5-non-idr.bin", "chunk6-config-idr.bin",
- "chunk7-non-idr.bin"};
+ std::string chunks[] = {
+ "chunk1-config-idr.bin", "chunk2-non-idr.bin",
+ "chunk3-non-idr.bin", "chunk4-non-idr.bin",
+ "chunk5-non-idr.bin", "chunk6-config-idr.bin",
+ "chunk7-non-idr.bin", "pps_neq_sps_config_idr.bin"};
H264AnnexBToAvcBitstreamConverter converter;
for (std::string& name : chunks) {
diff --git a/chromium/media/formats/mpeg/mpeg1_audio_stream_parser.cc b/chromium/media/formats/mpeg/mpeg1_audio_stream_parser.cc
index 05a84624583..d12f7cacee4 100644
--- a/chromium/media/formats/mpeg/mpeg1_audio_stream_parser.cc
+++ b/chromium/media/formats/mpeg/mpeg1_audio_stream_parser.cc
@@ -12,28 +12,6 @@ namespace {
constexpr uint32_t kMPEG1StartCodeMask = 0xffe00000;
-// Map that determines which bitrate_index & channel_mode combinations
-// are allowed.
-// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html
-constexpr bool kIsAllowed[17][4] = {
- {true, true, true, true}, // free
- {true, false, false, false}, // 32
- {true, false, false, false}, // 48
- {true, false, false, false}, // 56
- {true, true, true, true}, // 64
- {true, false, false, false}, // 80
- {true, true, true, true}, // 96
- {true, true, true, true}, // 112
- {true, true, true, true}, // 128
- {true, true, true, true}, // 160
- {true, true, true, true}, // 192
- {false, true, true, true}, // 224
- {false, true, true, true}, // 256
- {false, true, true, true}, // 320
- {false, true, true, true}, // 384
- {false, false, false, false} // bad
-};
-
// Maps version and layer information in the frame header
// into an index for the |kBitrateMap|.
// Derived from: http://mpgedit.org/mpgedit/mpeg_format/MP3Format.html
@@ -125,15 +103,8 @@ bool MPEG1AudioStreamParser::ParseHeader(MediaLog* media_log,
return false;
}
- if (layer == kLayer2 && !kIsAllowed[bitrate_index][channel_mode]) {
- if (media_log) {
- LIMITED_MEDIA_LOG(DEBUG, media_log, *media_log_limit, 5)
- << "Invalid MP3 (bitrate_index, channel_mode)"
- << " combination :" << std::hex << " bitrate_index " << bitrate_index
- << " channel_mode " << channel_mode;
- }
- return false;
- }
+ // Note: For MPEG2 we don't check if a given bitrate or channel layout is
+ // allowed per spec since all tested decoders don't seem to care.
int bitrate = kBitrateMap[bitrate_index][kVersionLayerMap[version][layer]];
diff --git a/chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.cc b/chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.cc
new file mode 100644
index 00000000000..cb09be7e0bf
--- /dev/null
+++ b/chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.cc
@@ -0,0 +1,178 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h"
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "media/base/media_log.h"
+#include "media/base/media_track.h"
+#include "media/base/media_tracks.h"
+#include "media/base/stream_parser_buffer.h"
+#include "media/base/text_track_config.h"
+#include "media/base/timestamp_constants.h"
+
+namespace {
+
+// TODO(crbug.com/1144908): Since these must be identical to those generated
+// in the SourceBuffer, consider moving these to possibly stream_parser.h.
+// Meanwhile, must be kept in sync with similar constexpr in SourceBuffer
+// manually.
+constexpr media::StreamParser::TrackId kWebCodecsAudioTrackId = 1;
+constexpr media::StreamParser::TrackId kWebCodecsVideoTrackId = 2;
+
+} // namespace
+
+namespace media {
+
+WebCodecsEncodedChunkStreamParser::WebCodecsEncodedChunkStreamParser(
+ std::unique_ptr<AudioDecoderConfig> audio_config)
+ : state_(kWaitingForInit), audio_config_(std::move(audio_config)) {
+ DCHECK(audio_config_ && !video_config_);
+}
+
+WebCodecsEncodedChunkStreamParser::WebCodecsEncodedChunkStreamParser(
+ std::unique_ptr<VideoDecoderConfig> video_config)
+ : state_(kWaitingForInit), video_config_(std::move(video_config)) {
+ DCHECK(video_config_ && !audio_config_);
+}
+
+WebCodecsEncodedChunkStreamParser::~WebCodecsEncodedChunkStreamParser() =
+ default;
+
+void WebCodecsEncodedChunkStreamParser::Init(
+ InitCB init_cb,
+ const NewConfigCB& config_cb,
+ const NewBuffersCB& new_buffers_cb,
+ bool /* ignore_text_tracks */,
+ const EncryptedMediaInitDataCB& /* ignored */,
+ const NewMediaSegmentCB& new_segment_cb,
+ const EndMediaSegmentCB& end_of_segment_cb,
+ MediaLog* media_log) {
+ DCHECK_EQ(state_, kWaitingForInit);
+ DCHECK(!init_cb_);
+ DCHECK(init_cb);
+ DCHECK(config_cb);
+ DCHECK(new_buffers_cb);
+ DCHECK(new_segment_cb);
+ DCHECK(end_of_segment_cb);
+
+ ChangeState(kWaitingForConfigEmission);
+ init_cb_ = std::move(init_cb);
+ config_cb_ = config_cb;
+ new_buffers_cb_ = new_buffers_cb;
+ new_segment_cb_ = new_segment_cb;
+ end_of_segment_cb_ = end_of_segment_cb;
+ media_log_ = media_log;
+}
+
+void WebCodecsEncodedChunkStreamParser::Flush() {
+ DCHECK_NE(state_, kWaitingForInit);
+ if (state_ == kWaitingForEncodedChunks)
+ ChangeState(kWaitingForConfigEmission);
+}
+
+bool WebCodecsEncodedChunkStreamParser::GetGenerateTimestampsFlag() const {
+ return false;
+}
+
+bool WebCodecsEncodedChunkStreamParser::Parse(const uint8_t* /* buf */,
+ int /* size */) {
+ // TODO(crbug.com/1144908): Protect against app reaching this (and similer
+ // inverse case in other parsers) simply by using the wrong append method on
+ // the SourceBuffer. Maybe a better MEDIA_LOG here would be sufficient? Or
+ // instead have the top-level SourceBuffer throw synchronous exception when
+ // attempting the wrong append method, without causing parse/decode error?
+ NOTREACHED(); // ProcessChunks() is the method to use instead for this
+ // parser.
+ return false;
+}
+
+bool WebCodecsEncodedChunkStreamParser::ProcessChunks(
+ std::unique_ptr<BufferQueue> buffer_queue) {
+ DCHECK_NE(state_, kWaitingForInit);
+
+ if (state_ == kError)
+ return false;
+
+ if (state_ == kWaitingForConfigEmission) {
+ // Must (still) have only one config. We'll retain ownership.
+ // MediaTracks::AddAudio/VideoTrack copies the config.
+ DCHECK((audio_config_ && !video_config_) ||
+ (video_config_ && !audio_config_));
+ auto media_tracks = std::make_unique<MediaTracks>();
+ if (audio_config_) {
+ media_tracks->AddAudioTrack(
+ *audio_config_, kWebCodecsAudioTrackId, MediaTrack::Kind("main"),
+ MediaTrack::Label(""), MediaTrack::Language(""));
+ } else if (video_config_) {
+ media_tracks->AddVideoTrack(
+ *video_config_, kWebCodecsVideoTrackId, MediaTrack::Kind("main"),
+ MediaTrack::Label(""), MediaTrack::Language(""));
+ }
+
+ if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap())) {
+ ChangeState(kError);
+ return false;
+ }
+
+ if (init_cb_) {
+ InitParameters params(kInfiniteDuration);
+ params.liveness = DemuxerStream::LIVENESS_UNKNOWN;
+ if (audio_config_)
+ params.detected_audio_track_count = 1;
+ if (video_config_)
+ params.detected_video_track_count = 1;
+ params.detected_text_track_count = 0;
+ std::move(init_cb_).Run(params);
+ }
+
+ ChangeState(kWaitingForEncodedChunks);
+ }
+
+ DCHECK_EQ(state_, kWaitingForEncodedChunks);
+
+ // All of |buffer_queue| must be of the media type (audio or video)
+ // corresponding to the exactly one type of decoder config we have. Otherwise,
+ // the caller has provided encoded chunks for the wrong kind of config.
+ DemuxerStream::Type expected_type =
+ audio_config_ ? DemuxerStream::AUDIO : DemuxerStream::VIDEO;
+ for (const auto& it : *buffer_queue) {
+ if (it->type() != expected_type) {
+ MEDIA_LOG(ERROR, media_log_)
+ << "Incorrect EncodedChunk type (audio vs video) appended";
+ ChangeState(kError);
+ return false;
+ }
+ }
+
+ // TODO(crbug.com/1144908): Add a different new_buffers_cb type for us to use
+ // so that we can just std::move the buffer_queue, and avoid potential issues
+ // with out-of-order timestamps in the caller-provided queue that would
+ // otherwise cause parse failure in MergeBufferQueues with the current, legacy
+ // style of new_buffers_cb that depends on parsers to emit sanely time-ordered
+ // groups of frames from *muxed* multi-track bytestreams. FrameProcessor is
+ // capable of handling our buffer_queue verbatim.
+ BufferQueueMap buffers;
+ if (audio_config_)
+ buffers.insert(std::make_pair(kWebCodecsAudioTrackId, *buffer_queue));
+ else
+ buffers.insert(std::make_pair(kWebCodecsVideoTrackId, *buffer_queue));
+ new_segment_cb_.Run();
+ if (!new_buffers_cb_.Run(buffers))
+ return false;
+ end_of_segment_cb_.Run();
+
+ return true;
+}
+
+void WebCodecsEncodedChunkStreamParser::ChangeState(State new_state) {
+ DVLOG(1) << __func__ << ": " << state_ << " -> " << new_state;
+ state_ = new_state;
+}
+
+} // namespace media
diff --git a/chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h b/chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h
new file mode 100644
index 00000000000..c5dafee217a
--- /dev/null
+++ b/chromium/media/formats/webcodecs/webcodecs_encoded_chunk_stream_parser.h
@@ -0,0 +1,79 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_FORMATS_WEBCODECS_WEBCODECS_ENCODED_CHUNK_STREAM_PARSER_H_
+#define MEDIA_FORMATS_WEBCODECS_WEBCODECS_ENCODED_CHUNK_STREAM_PARSER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/media_export.h"
+#include "media/base/stream_parser.h"
+#include "media/base/video_decoder_config.h"
+
+namespace media {
+
+class MEDIA_EXPORT WebCodecsEncodedChunkStreamParser : public StreamParser {
+ public:
+ explicit WebCodecsEncodedChunkStreamParser(
+ std::unique_ptr<AudioDecoderConfig> audio_config);
+ explicit WebCodecsEncodedChunkStreamParser(
+ std::unique_ptr<VideoDecoderConfig> video_config);
+ ~WebCodecsEncodedChunkStreamParser() override;
+
+ // StreamParser implementation.
+ void Init(InitCB init_cb,
+ const NewConfigCB& config_cb,
+ const NewBuffersCB& new_buffers_cb,
+ bool ignore_text_tracks /* must be true */,
+ const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
+ const NewMediaSegmentCB& new_segment_cb,
+ const EndMediaSegmentCB& end_of_segment_cb,
+ MediaLog* media_log) override;
+ void Flush() override;
+ bool GetGenerateTimestampsFlag() const override;
+ bool Parse(const uint8_t* buf, int size) override;
+
+ // Processes and emits buffers from |buffer_queue|. If state is
+ // kWaitingForConfigEmission, first emit the config.
+ bool ProcessChunks(std::unique_ptr<BufferQueue> buffer_queue) override;
+
+ private:
+ enum State {
+ kWaitingForInit,
+ kWaitingForConfigEmission,
+ kWaitingForEncodedChunks,
+ kError
+ };
+
+ void ChangeState(State new_state);
+
+ State state_;
+
+ // These configs are populated during ctor. A copy of the appropriate config
+ // is emitted on demand when "parsing" newly appended encoded chunks if that
+ // append occurs when state is kWaitingForConfigEmission. Note, only one type
+ // of config can be emitted (not both), for an instance of this parser.
+ std::unique_ptr<AudioDecoderConfig> audio_config_;
+ std::unique_ptr<VideoDecoderConfig> video_config_;
+
+ InitCB init_cb_;
+ NewConfigCB config_cb_;
+ NewBuffersCB new_buffers_cb_;
+
+ NewMediaSegmentCB new_segment_cb_;
+ EndMediaSegmentCB end_of_segment_cb_;
+ MediaLog* media_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebCodecsEncodedChunkStreamParser);
+};
+
+} // namespace media
+
+#endif // MEDIA_FORMATS_WEBCODECS_WEBCODECS_ENCODED_CHUNK_STREAM_PARSER_H_