summaryrefslogtreecommitdiff
path: root/chromium/media/base
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-12 11:40:13 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-12 09:52:12 +0000
commit980b784afe75be22158126ac6a639c19459d3427 (patch)
treecc9111d7faa5042ad860237f5c5ec88ce4bd987c /chromium/media/base
parent2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (diff)
downloadqtwebengine-chromium-980b784afe75be22158126ac6a639c19459d3427.tar.gz
BASELINE: Update Chromium to 51.0.2704.47
And adds in a few missing files. Change-Id: Id0d85c81f5efc1b1c8cf9cb3241da26bf7245026 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'chromium/media/base')
-rw-r--r--chromium/media/base/android/audio_decoder_job.cc71
-rw-r--r--chromium/media/base/android/audio_decoder_job.h12
-rw-r--r--chromium/media/base/android/audio_media_codec_decoder.cc47
-rw-r--r--chromium/media/base/android/audio_media_codec_decoder.h9
-rw-r--r--chromium/media/base/android/media_codec_bridge.cc15
-rw-r--r--chromium/media/base/android/media_codec_bridge.h24
-rw-r--r--chromium/media/base/android/media_codec_decoder.cc7
-rw-r--r--chromium/media/base/android/media_codec_decoder.h3
-rw-r--r--chromium/media/base/android/media_decoder_job.cc10
-rw-r--r--chromium/media/base/android/media_decoder_job.h4
-rw-r--r--chromium/media/base/android/ndk_media_codec_bridge.cc28
-rw-r--r--chromium/media/base/android/ndk_media_codec_bridge.h9
-rw-r--r--chromium/media/base/android/ndk_media_codec_wrapper.cc8
-rw-r--r--chromium/media/base/android/sdk_media_codec_bridge.cc58
-rw-r--r--chromium/media/base/android/sdk_media_codec_bridge.h24
-rw-r--r--chromium/media/base/android/video_media_codec_decoder.cc3
-rw-r--r--chromium/media/base/android/video_media_codec_decoder.h2
-rw-r--r--chromium/media/base/video_decoder.h11
18 files changed, 236 insertions, 109 deletions
diff --git a/chromium/media/base/android/audio_decoder_job.cc b/chromium/media/base/android/audio_decoder_job.cc
index f0baca4e949..9b237b8ec67 100644
--- a/chromium/media/base/android/audio_decoder_job.cc
+++ b/chromium/media/base/android/audio_decoder_job.cc
@@ -40,13 +40,12 @@ AudioDecoderJob::AudioDecoderJob(
request_data_cb,
on_demuxer_config_changed_cb),
audio_codec_(kUnknownAudioCodec),
- num_channels_(0),
+ config_num_channels_(0),
config_sampling_rate_(0),
volume_(-1.0),
- bytes_per_frame_(0),
output_sampling_rate_(0),
- frame_count_(0) {
-}
+ output_num_channels_(0),
+ frame_count_(0) {}
AudioDecoderJob::~AudioDecoderJob() {}
@@ -63,15 +62,17 @@ void AudioDecoderJob::SetDemuxerConfigs(const DemuxerConfigs& configs) {
// TODO(qinmin): split DemuxerConfig for audio and video separately so we
// can simply store the stucture here.
audio_codec_ = configs.audio_codec;
- num_channels_ = configs.audio_channels;
+ config_num_channels_ = configs.audio_channels;
config_sampling_rate_ = configs.audio_sampling_rate;
set_is_content_encrypted(configs.is_audio_encrypted);
audio_extra_data_ = configs.audio_extra_data;
audio_codec_delay_ns_ = configs.audio_codec_delay_ns;
audio_seek_preroll_ns_ = configs.audio_seek_preroll_ns;
- bytes_per_frame_ = kBytesPerAudioOutputSample * num_channels_;
- if (!media_codec_bridge_)
+
+ if (!media_codec_bridge_) {
output_sampling_rate_ = config_sampling_rate_;
+ output_num_channels_ = config_num_channels_;
+ }
}
void AudioDecoderJob::SetVolume(double volume) {
@@ -118,7 +119,8 @@ void AudioDecoderJob::ReleaseOutputBuffer(
base::TimeTicks current_time = base::TimeTicks::Now();
- size_t new_frames_count = size / bytes_per_frame_;
+ size_t bytes_per_frame = kBytesPerAudioOutputSample * output_num_channels_;
+ size_t new_frames_count = size / bytes_per_frame;
frame_count_ += new_frames_count;
audio_timestamp_helper_->AddFrames(new_frames_count);
int64_t frames_to_play = frame_count_ - head_position;
@@ -153,13 +155,12 @@ bool AudioDecoderJob::ComputeTimeToRender() const {
bool AudioDecoderJob::AreDemuxerConfigsChanged(
const DemuxerConfigs& configs) const {
return audio_codec_ != configs.audio_codec ||
- num_channels_ != configs.audio_channels ||
- config_sampling_rate_ != configs.audio_sampling_rate ||
- is_content_encrypted() != configs.is_audio_encrypted ||
- audio_extra_data_.size() != configs.audio_extra_data.size() ||
- !std::equal(audio_extra_data_.begin(),
- audio_extra_data_.end(),
- configs.audio_extra_data.begin());
+ config_num_channels_ != configs.audio_channels ||
+ config_sampling_rate_ != configs.audio_sampling_rate ||
+ is_content_encrypted() != configs.is_audio_encrypted ||
+ audio_extra_data_.size() != configs.audio_extra_data.size() ||
+ !std::equal(audio_extra_data_.begin(), audio_extra_data_.end(),
+ configs.audio_extra_data.begin());
}
MediaDecoderJob::MediaDecoderJobStatus
@@ -170,7 +171,7 @@ MediaDecoderJob::MediaDecoderJobStatus
if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))
->ConfigureAndStart(audio_codec_, config_sampling_rate_,
- num_channels_, &audio_extra_data_[0],
+ config_num_channels_, &audio_extra_data_[0],
audio_extra_data_.size(), audio_codec_delay_ns_,
audio_seek_preroll_ns_, true,
GetMediaCrypto())) {
@@ -194,18 +195,42 @@ void AudioDecoderJob::SetVolumeInternal() {
}
}
-void AudioDecoderJob::OnOutputFormatChanged() {
+bool AudioDecoderJob::OnOutputFormatChanged() {
DCHECK(media_codec_bridge_);
- int old_sampling_rate = output_sampling_rate_;
+ // Recreate AudioTrack if either sample rate or output channel count changed.
+ // If we cannot obtain these values we assume they did not change.
+ bool needs_recreate_audio_track = false;
+
+ const int old_sampling_rate = output_sampling_rate_;
MediaCodecStatus status =
media_codec_bridge_->GetOutputSamplingRate(&output_sampling_rate_);
- // TODO(timav,watk): This CHECK maintains the behavior of this call before
- // we started catching CodecException and returning it as MEDIA_CODEC_ERROR.
- // It needs to be handled some other way. http://crbug.com/585978
- CHECK_EQ(status, MEDIA_CODEC_OK);
- if (output_sampling_rate_ != old_sampling_rate)
+
+ if (status == MEDIA_CODEC_OK && old_sampling_rate != output_sampling_rate_) {
+ DCHECK_GT(output_sampling_rate_, 0);
+ DVLOG(2) << __FUNCTION__ << ": new sampling rate " << output_sampling_rate_;
+ needs_recreate_audio_track = true;
+
ResetTimestampHelper();
+ }
+
+ const int old_num_channels = output_num_channels_;
+ status = media_codec_bridge_->GetOutputChannelCount(&output_num_channels_);
+
+ if (status == MEDIA_CODEC_OK && old_num_channels != output_num_channels_) {
+ DCHECK_GT(output_sampling_rate_, 0);
+ DVLOG(2) << __FUNCTION__ << ": new channel count " << output_num_channels_;
+ needs_recreate_audio_track = true;
+ }
+
+ if (needs_recreate_audio_track &&
+ !static_cast<AudioCodecBridge*>(media_codec_bridge_.get())
+ ->CreateAudioTrack(output_sampling_rate_, output_num_channels_)) {
+ DLOG(ERROR) << __FUNCTION__ << ": cannot create AudioTrack";
+ return false;
+ }
+
+ return true;
}
} // namespace media
diff --git a/chromium/media/base/android/audio_decoder_job.h b/chromium/media/base/android/audio_decoder_job.h
index 8b1b4e9c51f..1583185e497 100644
--- a/chromium/media/base/android/audio_decoder_job.h
+++ b/chromium/media/base/android/audio_decoder_job.h
@@ -54,7 +54,7 @@ class AudioDecoderJob : public MediaDecoderJob {
bool ComputeTimeToRender() const override;
bool AreDemuxerConfigsChanged(const DemuxerConfigs& configs) const override;
MediaDecoderJobStatus CreateMediaCodecBridgeInternal() override;
- void OnOutputFormatChanged() override;
+ bool OnOutputFormatChanged() override;
// Helper method to set the audio output volume.
void SetVolumeInternal();
@@ -63,18 +63,20 @@ class AudioDecoderJob : public MediaDecoderJob {
// Audio configs from the demuxer.
AudioCodec audio_codec_;
- int num_channels_;
+ int config_num_channels_;
int config_sampling_rate_;
std::vector<uint8_t> audio_extra_data_;
int64_t audio_codec_delay_ns_;
int64_t audio_seek_preroll_ns_;
double volume_;
- int bytes_per_frame_;
- // Audio output sample rate
+ // Audio output sample rate.
int output_sampling_rate_;
- // Frame count to sync with audio codec output
+ // Number of output audio channels.
+ int output_num_channels_;
+
+ // Frame count to sync with audio codec output.
int64_t frame_count_;
// Base timestamp for the |audio_timestamp_helper_|.
diff --git a/chromium/media/base/android/audio_media_codec_decoder.cc b/chromium/media/base/android/audio_media_codec_decoder.cc
index 5654e7ca4a0..bf9939de1e5 100644
--- a/chromium/media/base/android/audio_media_codec_decoder.cc
+++ b/chromium/media/base/android/audio_media_codec_decoder.cc
@@ -40,8 +40,8 @@ AudioMediaCodecDecoder::AudioMediaCodecDecoder(
waiting_for_decryption_key_cb,
error_cb),
volume_(-1.0),
- bytes_per_frame_(0),
output_sampling_rate_(0),
+ output_num_channels_(0),
frame_count_(0),
update_current_time_cb_(update_current_time_cb) {}
@@ -65,8 +65,10 @@ void AudioMediaCodecDecoder::SetDemuxerConfigs(const DemuxerConfigs& configs) {
DVLOG(1) << class_name() << "::" << __FUNCTION__ << " " << configs;
configs_ = configs;
- if (!media_codec_bridge_)
+ if (!media_codec_bridge_) {
output_sampling_rate_ = configs.audio_sampling_rate;
+ output_num_channels_ = configs.audio_channels;
+ }
}
bool AudioMediaCodecDecoder::IsContentEncrypted() const {
@@ -159,7 +161,6 @@ MediaCodecDecoder::ConfigStatus AudioMediaCodecDecoder::ConfigureInternal(
SetVolumeInternal();
- bytes_per_frame_ = kBytesPerAudioOutputSample * configs_.audio_channels;
frame_count_ = 0;
ResetTimestampHelper();
@@ -169,16 +170,44 @@ MediaCodecDecoder::ConfigStatus AudioMediaCodecDecoder::ConfigureInternal(
return kConfigOk;
}
-void AudioMediaCodecDecoder::OnOutputFormatChanged() {
+bool AudioMediaCodecDecoder::OnOutputFormatChanged() {
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
DCHECK(media_codec_bridge_);
- int old_sampling_rate = output_sampling_rate_;
+ // Recreate AudioTrack if either sample rate or output channel count changed.
+ // If we cannot obtain these values we assume they did not change.
+ bool needs_recreate_audio_track = false;
+
+ const int old_sampling_rate = output_sampling_rate_;
MediaCodecStatus status =
media_codec_bridge_->GetOutputSamplingRate(&output_sampling_rate_);
- if (status != MEDIA_CODEC_OK || output_sampling_rate_ != old_sampling_rate)
+
+ if (status == MEDIA_CODEC_OK && old_sampling_rate != output_sampling_rate_) {
+ DCHECK_GT(output_sampling_rate_, 0);
+ DVLOG(2) << __FUNCTION__ << ": new sampling rate " << output_sampling_rate_;
+ needs_recreate_audio_track = true;
+
ResetTimestampHelper();
+ }
+
+ const int old_num_channels = output_num_channels_;
+ status = media_codec_bridge_->GetOutputChannelCount(&output_num_channels_);
+
+ if (status == MEDIA_CODEC_OK && old_num_channels != output_num_channels_) {
+ DCHECK_GT(output_sampling_rate_, 0);
+ DVLOG(2) << __FUNCTION__ << ": new channel count " << output_num_channels_;
+ needs_recreate_audio_track = true;
+ }
+
+ if (needs_recreate_audio_track &&
+ !static_cast<AudioCodecBridge*>(media_codec_bridge_.get())
+ ->CreateAudioTrack(output_sampling_rate_, output_num_channels_)) {
+ DLOG(ERROR) << __FUNCTION__ << ": cannot create AudioTrack";
+ return false;
+ }
+
+ return true;
}
void AudioMediaCodecDecoder::Render(int buffer_index,
@@ -220,7 +249,9 @@ void AudioMediaCodecDecoder::Render(int buffer_index,
if (postpone && !frame_count_)
SetBaseTimestamp(pts);
- size_t new_frames_count = size / bytes_per_frame_;
+ const size_t bytes_per_frame =
+ kBytesPerAudioOutputSample * output_num_channels_;
+ const size_t new_frames_count = size / bytes_per_frame;
frame_count_ += new_frames_count;
audio_timestamp_helper_->AddFrames(new_frames_count);
@@ -286,7 +317,7 @@ void AudioMediaCodecDecoder::ResetTimestampHelper() {
base_timestamp_ = audio_timestamp_helper_->GetTimestamp();
audio_timestamp_helper_.reset(
- new AudioTimestampHelper(configs_.audio_sampling_rate));
+ new AudioTimestampHelper(output_sampling_rate_));
audio_timestamp_helper_->SetBaseTimestamp(base_timestamp_);
}
diff --git a/chromium/media/base/android/audio_media_codec_decoder.h b/chromium/media/base/android/audio_media_codec_decoder.h
index ce264b60ee6..d82322c96f9 100644
--- a/chromium/media/base/android/audio_media_codec_decoder.h
+++ b/chromium/media/base/android/audio_media_codec_decoder.h
@@ -50,7 +50,7 @@ class AudioMediaCodecDecoder : public MediaCodecDecoder {
protected:
bool IsCodecReconfigureNeeded(const DemuxerConfigs& next) const override;
ConfigStatus ConfigureInternal(jobject media_crypto) override;
- void OnOutputFormatChanged() override;
+ bool OnOutputFormatChanged() override;
void Render(int buffer_index,
size_t offset,
size_t size,
@@ -73,13 +73,12 @@ class AudioMediaCodecDecoder : public MediaCodecDecoder {
// Requested volume
double volume_;
- // Number of bytes per audio frame. Depends on the output format and the
- // number of channels.
- int bytes_per_frame_;
-
// The sampling rate received from decoder.
int output_sampling_rate_;
+ // The number of audio channels received from decoder.
+ int output_num_channels_;
+
// Frame count to sync with audio codec output.
int64_t frame_count_;
diff --git a/chromium/media/base/android/media_codec_bridge.cc b/chromium/media/base/android/media_codec_bridge.cc
index 833d51ef890..8beb1a2c803 100644
--- a/chromium/media/base/android/media_codec_bridge.cc
+++ b/chromium/media/base/android/media_codec_bridge.cc
@@ -42,6 +42,21 @@ MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer(
subsamples.size(), presentation_time);
}
+MediaCodecStatus MediaCodecBridge::CopyFromOutputBuffer(int index,
+ size_t offset,
+ void* dst,
+ size_t num) {
+ const uint8_t* src_data = nullptr;
+ size_t src_capacity = 0;
+ MediaCodecStatus status =
+ GetOutputBufferAddress(index, offset, &src_data, &src_capacity);
+ if (status == MEDIA_CODEC_OK) {
+ CHECK_GE(src_capacity, num);
+ memcpy(dst, src_data, num);
+ }
+ return status;
+}
+
bool MediaCodecBridge::FillInputBuffer(int index,
const uint8_t* data,
size_t size) {
diff --git a/chromium/media/base/android/media_codec_bridge.h b/chromium/media/base/android/media_codec_bridge.h
index 25d61f97cc3..434f1806761 100644
--- a/chromium/media/base/android/media_codec_bridge.h
+++ b/chromium/media/base/android/media_codec_bridge.h
@@ -75,6 +75,11 @@ class MEDIA_EXPORT MediaCodecBridge {
// Returns MEDIA_CODEC_ERROR if an error occurs, or MEDIA_CODEC_OK otherwise.
virtual MediaCodecStatus GetOutputSamplingRate(int* sampling_rate) = 0;
+ // Fills |channel_count| with the number of audio channels. Useful after
+ // INFO_OUTPUT_FORMAT_CHANGED.
+ // Returns MEDIA_CODEC_ERROR if an error occurs, or MEDIA_CODEC_OK otherwise.
+ virtual MediaCodecStatus GetOutputChannelCount(int* channel_count) = 0;
+
// Submits a byte array to the given input buffer. Call this after getting an
// available buffer from DequeueInputBuffer(). If |data| is NULL, assume the
// input buffer has already been populated (but still obey |size|).
@@ -151,14 +156,23 @@ class MEDIA_EXPORT MediaCodecBridge {
uint8_t** data,
size_t* capacity) = 0;
- // Copy |num| bytes from output buffer |index|'s |offset| into the memory
+ // Gives the access to buffer's data which is referenced by |index| and
+ // |offset|. The size of available data for reading is written to |*capacity|
+ // and the address is written to |*addr|.
+ // Returns MEDIA_CODEC_ERROR if a error occurs, or MEDIA_CODEC_OK otherwise.
+ virtual MediaCodecStatus GetOutputBufferAddress(int index,
+ size_t offset,
+ const uint8_t** addr,
+ size_t* capacity) = 0;
+
+ // Copies |num| bytes from output buffer |index|'s |offset| into the memory
// region pointed to by |dst|. To avoid overflows, the size of both source
// and destination must be at least |num| bytes, and should not overlap.
// Returns MEDIA_CODEC_ERROR if an error occurs, or MEDIA_CODEC_OK otherwise.
- virtual MediaCodecStatus CopyFromOutputBuffer(int index,
- size_t offset,
- void* dst,
- size_t num) = 0;
+ MediaCodecStatus CopyFromOutputBuffer(int index,
+ size_t offset,
+ void* dst,
+ size_t num);
protected:
MediaCodecBridge();
diff --git a/chromium/media/base/android/media_codec_decoder.cc b/chromium/media/base/android/media_codec_decoder.cc
index bf3c8a31591..942cd6351c3 100644
--- a/chromium/media/base/android/media_codec_decoder.cc
+++ b/chromium/media/base/android/media_codec_decoder.cc
@@ -891,7 +891,12 @@ bool MediaCodecDecoder::DepleteOutputBufferQueue() {
case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
DVLOG(2) << class_name() << "::" << __FUNCTION__
<< " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
- OnOutputFormatChanged();
+ if (!OnOutputFormatChanged()) {
+ DVLOG(0) << class_name() << "::" << __FUNCTION__
+ << ": OnOutputFormatChanged failed";
+ status = MEDIA_CODEC_ERROR;
+ media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
+ }
break;
case MEDIA_CODEC_OK:
diff --git a/chromium/media/base/android/media_codec_decoder.h b/chromium/media/base/android/media_codec_decoder.h
index 4135d27fb01..e9d281ff58b 100644
--- a/chromium/media/base/android/media_codec_decoder.h
+++ b/chromium/media/base/android/media_codec_decoder.h
@@ -281,7 +281,8 @@ class MediaCodecDecoder {
virtual void DissociatePTSFromTime() {}
// Processes the change of the output format, varies by stream.
- virtual void OnOutputFormatChanged() = 0;
+ // Returns true if this processing succeeded.
+ virtual bool OnOutputFormatChanged() = 0;
// Renders the decoded frame and releases output buffer, or posts
// a delayed task to do it at a later time,
diff --git a/chromium/media/base/android/media_decoder_job.cc b/chromium/media/base/android/media_decoder_job.cc
index 9e0a2168adb..0e036870bb9 100644
--- a/chromium/media/base/android/media_decoder_job.cc
+++ b/chromium/media/base/android/media_decoder_job.cc
@@ -457,8 +457,10 @@ void MediaDecoderJob::DecodeInternal(
if (status == MEDIA_CODEC_OUTPUT_FORMAT_CHANGED) {
// TODO(qinmin): instead of waiting for the next output buffer to be
// dequeued, post a task on the UI thread to signal the format change.
- OnOutputFormatChanged();
- has_format_change = true;
+ if (OnOutputFormatChanged())
+ has_format_change = true;
+ else
+ status = MEDIA_CODEC_ERROR;
}
} while (status != MEDIA_CODEC_OK && status != MEDIA_CODEC_ERROR &&
status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER);
@@ -675,7 +677,9 @@ bool MediaDecoderJob::IsCodecReconfigureNeeded(
return true;
}
-void MediaDecoderJob::OnOutputFormatChanged() {}
+bool MediaDecoderJob::OnOutputFormatChanged() {
+ return true;
+}
bool MediaDecoderJob::UpdateOutputFormat() {
return false;
diff --git a/chromium/media/base/android/media_decoder_job.h b/chromium/media/base/android/media_decoder_job.h
index b0136aa8191..ce3cd767120 100644
--- a/chromium/media/base/android/media_decoder_job.h
+++ b/chromium/media/base/android/media_decoder_job.h
@@ -253,8 +253,8 @@ class MediaDecoderJob {
// Signals to decoder job that decoder has updated output format. Decoder job
// may need to do internal reconfiguration in order to correctly interpret
- // incoming buffers
- virtual void OnOutputFormatChanged();
+ // incoming buffers. Returns true if this internal configuration succeeded.
+ virtual bool OnOutputFormatChanged();
// Update the output format from the decoder, returns true if the output
// format changes, or false otherwise.
diff --git a/chromium/media/base/android/ndk_media_codec_bridge.cc b/chromium/media/base/android/ndk_media_codec_bridge.cc
index 3a66db675c9..c39e0f9ca3e 100644
--- a/chromium/media/base/android/ndk_media_codec_bridge.cc
+++ b/chromium/media/base/android/ndk_media_codec_bridge.cc
@@ -85,6 +85,7 @@ MediaCodecStatus NdkMediaCodecBridge::GetOutputSize(gfx::Size* size) {
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
}
+ AMediaFormat_delete(format);
size->SetSize(width, height);
return MEDIA_CODEC_OK;
}
@@ -94,10 +95,21 @@ MediaCodecStatus NdkMediaCodecBridge::GetOutputSamplingRate(
AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
*sampling_rate = 0;
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampling_rate);
+ AMediaFormat_delete(format);
DCHECK_NE(*sampling_rate, 0);
return MEDIA_CODEC_OK;
}
+MediaCodecStatus NdkMediaCodecBridge::GetOutputChannelCount(
+ int* channel_count) {
+ AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get());
+ *channel_count = 0;
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channel_count);
+ AMediaFormat_delete(format);
+ DCHECK_NE(*channel_count, 0);
+ return MEDIA_CODEC_OK;
+}
+
MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer(
int index,
const uint8_t* data,
@@ -225,15 +237,15 @@ MediaCodecStatus NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
return MEDIA_CODEC_OK;
}
-MediaCodecStatus NdkMediaCodecBridge::CopyFromOutputBuffer(int index,
- size_t offset,
- void* dst,
- size_t num) {
- size_t capacity;
+MediaCodecStatus NdkMediaCodecBridge::GetOutputBufferAddress(
+ int index,
+ size_t offset,
+ const uint8_t** addr,
+ size_t* capacity) {
const uint8_t* src_data =
- AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity);
- CHECK_GE(capacity, offset + num);
- memcpy(dst, src_data + offset, num);
+ AMediaCodec_getOutputBuffer(media_codec_.get(), index, capacity);
+ *addr = src_data + offset;
+ *capacity -= offset;
return MEDIA_CODEC_OK;
}
diff --git a/chromium/media/base/android/ndk_media_codec_bridge.h b/chromium/media/base/android/ndk_media_codec_bridge.h
index d7f2b108a1a..d247d9f1e12 100644
--- a/chromium/media/base/android/ndk_media_codec_bridge.h
+++ b/chromium/media/base/android/ndk_media_codec_bridge.h
@@ -28,6 +28,7 @@ class MEDIA_EXPORT NdkMediaCodecBridge : public MediaCodecBridge {
void Stop() override;
MediaCodecStatus GetOutputSize(gfx::Size* size) override;
MediaCodecStatus GetOutputSamplingRate(int* sampling_rate) override;
+ MediaCodecStatus GetOutputChannelCount(int* channel_count) override;
MediaCodecStatus QueueInputBuffer(
int index,
const uint8_t* data,
@@ -57,10 +58,10 @@ class MEDIA_EXPORT NdkMediaCodecBridge : public MediaCodecBridge {
MediaCodecStatus GetInputBuffer(int input_buffer_index,
uint8_t** data,
size_t* capacity) override;
- MediaCodecStatus CopyFromOutputBuffer(int index,
- size_t offset,
- void* dst,
- size_t num) override;
+ MediaCodecStatus GetOutputBufferAddress(int index,
+ size_t offset,
+ const uint8_t** addr,
+ size_t* capacity) override;
protected:
NdkMediaCodecBridge(const std::string& mime,
diff --git a/chromium/media/base/android/ndk_media_codec_wrapper.cc b/chromium/media/base/android/ndk_media_codec_wrapper.cc
index e4709a63a52..ba8a250c9ee 100644
--- a/chromium/media/base/android/ndk_media_codec_wrapper.cc
+++ b/chromium/media/base/android/ndk_media_codec_wrapper.cc
@@ -26,6 +26,7 @@
// The constants used in chromium. Those symbols are defined as extern symbols
// in the NdkMediaFormat headers. They will be initialized to their correct
// values when the library is loaded.
+const char* AMEDIAFORMAT_KEY_CHANNEL_COUNT;
const char* AMEDIAFORMAT_KEY_HEIGHT;
const char* AMEDIAFORMAT_KEY_SAMPLE_RATE;
const char* AMEDIAFORMAT_KEY_WIDTH;
@@ -50,9 +51,10 @@ base::NativeLibrary IntializeLibraryHandle() {
// The list of defined symbols.
const SymbolDefinition kSymbols[] = {
+ {"AMEDIAFORMAT_KEY_CHANNEL_COUNT", &AMEDIAFORMAT_KEY_CHANNEL_COUNT},
{"AMEDIAFORMAT_KEY_HEIGHT", &AMEDIAFORMAT_KEY_HEIGHT},
{"AMEDIAFORMAT_KEY_SAMPLE_RATE", &AMEDIAFORMAT_KEY_SAMPLE_RATE},
- {"AMEDIAFORMAT_KEY_SAMPLE_RATE", &AMEDIAFORMAT_KEY_SAMPLE_RATE},
+ {"AMEDIAFORMAT_KEY_WIDTH", &AMEDIAFORMAT_KEY_WIDTH},
};
for (size_t i = 0; i < sizeof(kSymbols) / sizeof(kSymbols[0]); ++i) {
@@ -158,6 +160,10 @@ LOOKUP_FUNC(AMediaCodecCryptoInfo_delete,
media_status_t,
(AMediaCodecCryptoInfo * info),
(info));
+LOOKUP_FUNC(AMediaFormat_delete,
+ media_status_t,
+ (AMediaFormat * format),
+ (format));
LOOKUP_FUNC(AMediaFormat_getInt32,
bool,
(AMediaFormat * format, const char* name, int32_t* out),
diff --git a/chromium/media/base/android/sdk_media_codec_bridge.cc b/chromium/media/base/android/sdk_media_codec_bridge.cc
index 226a90a6cbf..e35fd4b7a8d 100644
--- a/chromium/media/base/android/sdk_media_codec_bridge.cc
+++ b/chromium/media/base/android/sdk_media_codec_bridge.cc
@@ -137,6 +137,18 @@ MediaCodecStatus SdkMediaCodecBridge::GetOutputSamplingRate(
return status;
}
+MediaCodecStatus SdkMediaCodecBridge::GetOutputChannelCount(
+ int* channel_count) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> result =
+ Java_MediaCodecBridge_getOutputFormat(env, j_media_codec_.obj());
+ MediaCodecStatus status = static_cast<MediaCodecStatus>(
+ Java_GetOutputFormatResult_status(env, result.obj()));
+ if (status == MEDIA_CODEC_OK)
+ *channel_count = Java_GetOutputFormatResult_channelCount(env, result.obj());
+ return status;
+}
+
MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer(
int index,
const uint8_t* data,
@@ -301,25 +313,11 @@ MediaCodecStatus SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index,
return MEDIA_CODEC_OK;
}
-MediaCodecStatus SdkMediaCodecBridge::CopyFromOutputBuffer(int index,
- size_t offset,
- void* dst,
- size_t num) {
- void* src_data = nullptr;
- size_t src_capacity = 0;
- MediaCodecStatus status =
- GetOutputBufferAddress(index, offset, &src_data, &src_capacity);
- if (status == MEDIA_CODEC_OK) {
- CHECK_GE(src_capacity, num);
- memcpy(dst, src_data, num);
- }
- return status;
-}
-
-MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress(int index,
- size_t offset,
- void** addr,
- size_t* capacity) {
+MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress(
+ int index,
+ size_t offset,
+ const uint8_t** addr,
+ size_t* capacity) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_buffer(
Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index));
@@ -327,9 +325,9 @@ MediaCodecStatus SdkMediaCodecBridge::GetOutputBufferAddress(int index,
return MEDIA_CODEC_ERROR;
const size_t total_capacity = env->GetDirectBufferCapacity(j_buffer.obj());
CHECK_GE(total_capacity, offset);
- *addr =
- reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj())) +
- offset;
+ *addr = reinterpret_cast<const uint8_t*>(
+ env->GetDirectBufferAddress(j_buffer.obj())) +
+ offset;
*capacity = total_capacity - offset;
return MEDIA_CODEC_OK;
}
@@ -511,6 +509,7 @@ bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
LOG(ERROR) << "Invalid AAC header";
return false;
}
+
const size_t kCsdLength = 2;
uint8_t csd[kCsdLength];
csd[0] = profile << 3 | frequency_index >> 1;
@@ -558,6 +557,15 @@ bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format,
return true;
}
+bool AudioCodecBridge::CreateAudioTrack(int sampling_rate, int channel_count) {
+ DVLOG(2) << __FUNCTION__ << ": samping_rate:" << sampling_rate
+ << " channel_count:" << channel_count;
+
+ JNIEnv* env = AttachCurrentThread();
+ return Java_MediaCodecBridge_createAudioTrack(env, media_codec(),
+ sampling_rate, channel_count);
+}
+
MediaCodecStatus AudioCodecBridge::PlayOutputBuffer(int index,
size_t size,
size_t offset,
@@ -566,7 +574,7 @@ MediaCodecStatus AudioCodecBridge::PlayOutputBuffer(int index,
DCHECK_LE(0, index);
int numBytes = base::checked_cast<int>(size);
- void* buffer = nullptr;
+ const uint8_t* buffer = nullptr;
size_t capacity = 0;
MediaCodecStatus status =
GetOutputBufferAddress(index, offset, &buffer, &capacity);
@@ -577,8 +585,8 @@ MediaCodecStatus AudioCodecBridge::PlayOutputBuffer(int index,
CHECK_GE(numBytes, 0);
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray(
- env, static_cast<uint8_t*>(buffer), numBytes);
+ ScopedJavaLocalRef<jbyteArray> byte_array =
+ base::android::ToJavaByteArray(env, buffer, numBytes);
*playback_pos = Java_MediaCodecBridge_playOutputBuffer(
env, media_codec(), byte_array.obj(), postpone);
return status;
diff --git a/chromium/media/base/android/sdk_media_codec_bridge.h b/chromium/media/base/android/sdk_media_codec_bridge.h
index e23400df319..2c52ede9060 100644
--- a/chromium/media/base/android/sdk_media_codec_bridge.h
+++ b/chromium/media/base/android/sdk_media_codec_bridge.h
@@ -34,6 +34,7 @@ class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge {
void Stop() override;
MediaCodecStatus GetOutputSize(gfx::Size* size) override;
MediaCodecStatus GetOutputSamplingRate(int* sampling_rate) override;
+ MediaCodecStatus GetOutputChannelCount(int* channel_count) override;
MediaCodecStatus QueueInputBuffer(
int index,
const uint8_t* data,
@@ -63,10 +64,10 @@ class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge {
MediaCodecStatus GetInputBuffer(int input_buffer_index,
uint8_t** data,
size_t* capacity) override;
- MediaCodecStatus CopyFromOutputBuffer(int index,
- size_t offset,
- void* dst,
- size_t num) override;
+ MediaCodecStatus GetOutputBufferAddress(int index,
+ size_t offset,
+ const uint8_t** addr,
+ size_t* capacity) override;
static bool RegisterSdkMediaCodecBridge(JNIEnv* env);
@@ -75,14 +76,6 @@ class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge {
bool is_secure,
MediaCodecDirection direction);
- // Called to get the buffer address given the output buffer index and offset.
- // The size of available data to read is written to |*capacity| and the
- // address to read from is written to |*addr|.
- // Returns MEDIA_CODEC_ERROR if a error occurs, or MEDIA_CODEC_OK otherwise.
- MediaCodecStatus GetOutputBufferAddress(int index,
- size_t offset,
- void** addr,
- size_t* capacity);
jobject media_codec() { return j_media_codec_.obj(); }
MediaCodecDirection direction_;
@@ -106,7 +99,7 @@ class MEDIA_EXPORT AudioCodecBridge : public SdkMediaCodecBridge {
// See MediaCodecUtil::IsKnownUnaccelerated().
static bool IsKnownUnaccelerated(const AudioCodec& codec);
- // Start the audio codec bridge. If |play_audio| is true this method creates
+ // Starts the audio codec bridge. If |play_audio| is true this method creates
// Android AudioTrack object for the actual audio playback
// (http://developer.android.com/reference/android/media/AudioTrack.html).
bool ConfigureAndStart(const AudioDecoderConfig& config,
@@ -126,6 +119,11 @@ class MEDIA_EXPORT AudioCodecBridge : public SdkMediaCodecBridge {
bool play_audio,
jobject media_crypto) WARN_UNUSED_RESULT;
+ // Creates AudioTrack object for |sampling_rate| and |channel_count|
+ // (http://developer.android.com/reference/android/media/AudioTrack.html).
+ // Returns true in the case of success, false otherwise.
+ bool CreateAudioTrack(int sampling_rate, int channel_count);
+
// Plays the output buffer right away or save for later playback if |postpone|
// is set to true. This call must be called after DequeueOutputBuffer() and
// before ReleaseOutputBuffer. The data is extracted from the output buffers
diff --git a/chromium/media/base/android/video_media_codec_decoder.cc b/chromium/media/base/android/video_media_codec_decoder.cc
index e9a305830a4..e43dfbe51f4 100644
--- a/chromium/media/base/android/video_media_codec_decoder.cc
+++ b/chromium/media/base/android/video_media_codec_decoder.cc
@@ -205,7 +205,7 @@ void VideoMediaCodecDecoder::DissociatePTSFromTime() {
start_pts_ = last_seen_pts_ = kNoTimestamp();
}
-void VideoMediaCodecDecoder::OnOutputFormatChanged() {
+bool VideoMediaCodecDecoder::OnOutputFormatChanged() {
DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
gfx::Size prev_size = video_size_;
@@ -218,6 +218,7 @@ void VideoMediaCodecDecoder::OnOutputFormatChanged() {
media_task_runner_->PostTask(
FROM_HERE, base::Bind(video_size_changed_cb_, video_size_));
}
+ return true;
}
void VideoMediaCodecDecoder::Render(int buffer_index,
diff --git a/chromium/media/base/android/video_media_codec_decoder.h b/chromium/media/base/android/video_media_codec_decoder.h
index 03497269ba1..9aab5e30f80 100644
--- a/chromium/media/base/android/video_media_codec_decoder.h
+++ b/chromium/media/base/android/video_media_codec_decoder.h
@@ -67,7 +67,7 @@ class VideoMediaCodecDecoder : public MediaCodecDecoder {
ConfigStatus ConfigureInternal(jobject media_crypto) override;
void AssociateCurrentTimeWithPTS(base::TimeDelta pts) override;
void DissociatePTSFromTime() override;
- void OnOutputFormatChanged() override;
+ bool OnOutputFormatChanged() override;
void Render(int buffer_index,
size_t offset,
size_t size,
diff --git a/chromium/media/base/video_decoder.h b/chromium/media/base/video_decoder.h
index d6abf03e175..5a474b56e21 100644
--- a/chromium/media/base/video_decoder.h
+++ b/chromium/media/base/video_decoder.h
@@ -65,6 +65,10 @@ class MEDIA_EXPORT VideoDecoder {
// Upon reinitialization, all internal buffered frames will be dropped.
// 2) This method should not be called during pending decode or reset.
// 3) No VideoDecoder calls should be made before |init_cb| is executed.
+ // 4) VideoDecoders should take care to run |output_cb| as soon as the frame
+ // is ready (i.e. w/o thread trampolining) since it can strongly affect frame
+ // delivery times with high-frame-rate material. See Decode() for additional
+ // notes.
virtual void Initialize(const VideoDecoderConfig& config,
bool low_delay,
CdmContext* cdm_context,
@@ -84,9 +88,10 @@ class MEDIA_EXPORT VideoDecoder {
// called again).
//
// After decoding is finished the decoder calls |output_cb| specified in
- // Initialize() for each decoded frame. In general |output_cb| may be called
- // before or after |decode_cb|, but software decoders normally call
- // |output_cb| before calling |decode_cb|, i.e. while Decode() is pending.
+ // Initialize() for each decoded frame. |output_cb| is always called before
+ // |decode_cb|. However, |output_cb| may be called before Decode() returns, if
+ // other behavior is desired callers should ensure that |output_cb| will
+ // trampoline as necessary.
//
// If |buffer| is an EOS buffer then the decoder must be flushed, i.e.
// |output_cb| must be called for each frame pending in the queue and