Index: media/formats/webm/webm_cluster_parser.h |
diff --git a/media/formats/webm/webm_cluster_parser.h b/media/formats/webm/webm_cluster_parser.h |
index 2af102eaa0ce58b28909a6aa15fffd1bdbe4ed00..759fba9d6341800a6e58d1793435fdc03b11ef91 100644 |
--- a/media/formats/webm/webm_cluster_parser.h |
+++ b/media/formats/webm/webm_cluster_parser.h |
@@ -11,6 +11,7 @@ |
#include <string> |
#include "base/memory/scoped_ptr.h" |
+#include "media/base/audio_decoder_config.h" |
#include "media/base/media_export.h" |
#include "media/base/media_log.h" |
#include "media/base/stream_parser.h" |
@@ -28,13 +29,17 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { |
// Arbitrarily-chosen numbers to estimate the duration of a buffer if none is |
// set and there is not enough information to get a better estimate. |
- // TODO(wolenetz/acolwell): Parse audio codebook to determine missing audio |
- // frame durations. See http://crbug.com/351166. |
enum { |
kDefaultAudioBufferDurationInMs = 23, // Common 1k samples @44.1kHz |
kDefaultVideoBufferDurationInMs = 42 // Low 24fps to reduce stalls |
}; |
+ // Opus packets encode the duration and other parameters in the 5 most |
+ // significant bits of the first byte. The index in this array corresponds |
+ // to the duration of each frame of the packet in microseconds. See |
+ // https://tools.ietf.org/html/rfc6716#page-14 |
+ static const uint16_t kOpusFrameDurationsMu[]; |
+ |
private: |
// Helper class that manages per-track state. |
class Track { |
@@ -87,7 +92,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { |
// block is a keyframe. |
// |data| contains the bytes in the block. |
// |size| indicates the number of bytes in |data|. |
- bool IsKeyframe(const uint8* data, int size) const; |
+ bool IsKeyframe(const uint8_t* data, int size) const; |
base::TimeDelta default_duration() const { return default_duration_; } |
@@ -143,6 +148,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { |
const std::set<int64>& ignored_tracks, |
const std::string& audio_encryption_key_id, |
const std::string& video_encryption_key_id, |
+ const AudioCodec audio_codec_, |
const LogCB& log_cb); |
~WebMClusterParser() override; |
@@ -154,7 +160,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { |
// Returns -1 if the parse fails. |
// Returns 0 if more data is needed. |
// Returns the number of bytes parsed on success. |
- int Parse(const uint8* buf, int size); |
+ int Parse(const uint8_t* buf, int size); |
base::TimeDelta cluster_start_time() const { return cluster_start_time_; } |
@@ -194,14 +200,24 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { |
WebMParserClient* OnListStart(int id) override; |
bool OnListEnd(int id) override; |
bool OnUInt(int id, int64 val) override; |
- bool OnBinary(int id, const uint8* data, int size) override; |
- |
- bool ParseBlock(bool is_simple_block, const uint8* buf, int size, |
- const uint8* additional, int additional_size, int duration, |
+ bool OnBinary(int id, const uint8_t* data, int size) override; |
+ |
+ bool ParseBlock(bool is_simple_block, |
+ const uint8_t* buf, |
+ int size, |
+ const uint8_t* additional, |
+ int additional_size, |
+ int duration, |
int64 discard_padding); |
- bool OnBlock(bool is_simple_block, int track_num, int timecode, int duration, |
- int flags, const uint8* data, int size, |
- const uint8* additional, int additional_size, |
+ bool OnBlock(bool is_simple_block, |
+ int track_num, |
+ int timecode, |
+ int duration, |
+ int flags, |
+ const uint8_t* data, |
+ int size, |
+ const uint8_t* additional, |
+ int additional_size, |
int64 discard_padding); |
// Resets the Track objects associated with each text track. |
@@ -227,21 +243,40 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient { |
// if that track num is not a text track. |
Track* FindTextTrack(int track_num); |
+ // Attempts to read the duration from the encoded audio data, returning as |
+ // TimeDelta or kNoTimestamp() if duration cannot be retrieved. This obviously |
+ // violates layering rules, but is useful for MSE to know duration in cases |
+ // where it isn't explicitly given and cannot be calculated for Blocks at the |
+ // end of a Cluster (the next Cluster in playback-order may not be the next |
+ // Cluster we parse, so we can't simply use the delta of the first Block in |
+ // the next Cluster). Avoid calling if encrypted; may produce unexpected |
+ // output. See implementation for supported codecs. |
+ base::TimeDelta TryGetEncodedAudioDuration(const uint8_t* data, int size); |
+ |
+ // Reads Opus packet header to determine packet duration. Duration returned |
+ // as TimeDelta or kNoTimestamp() upon failure to read duration from packet. |
+ base::TimeDelta ReadOpusDuration(const uint8_t* data, int size); |
+ |
+ // Tracks the number of MEDIA_LOGs made in process of reading encoded |
+ // duration. Useful to prevent log spam. |
+ int num_duration_errors_; |
+ |
double timecode_multiplier_; // Multiplier used to convert timecodes into |
// microseconds. |
std::set<int64> ignored_tracks_; |
std::string audio_encryption_key_id_; |
std::string video_encryption_key_id_; |
+ const AudioCodec audio_codec_; |
WebMListParser parser_; |
int64 last_block_timecode_; |
- scoped_ptr<uint8[]> block_data_; |
+ scoped_ptr<uint8_t[]> block_data_; |
int block_data_size_; |
int64 block_duration_; |
int64 block_add_id_; |
- scoped_ptr<uint8[]> block_additional_data_; |
+ scoped_ptr<uint8_t[]> block_additional_data_; |
// Must be 0 if |block_additional_data_| is null. Must be > 0 if |
// |block_additional_data_| is NOT null. |
int block_additional_data_size_; |