Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[linux] Implement libiamf-based IAMF decoder #4221

Merged
merged 31 commits into from
Oct 24, 2024

Conversation

osagie98
Copy link
Contributor

@osagie98 osagie98 commented Oct 7, 2024

Implements a libiamf-based audio decoder.

Decoder specific code is guarded behind a GN flag enable_iamf_decode, which controls the ENABLE_IAMF_DECODE macro. enable_iamf_decode is off by default, so the new code doesn't build.

b/341792042

@osagie98 osagie98 marked this pull request as ready for review October 8, 2024 19:25
media/base/starboard_utils.cc Outdated Show resolved Hide resolved
media/base/starboard_utils.cc Outdated Show resolved Hide resolved
media/base/starboard_utils.cc Outdated Show resolved Hide resolved
starboard/shared/libiamf/iamf_decoder_utils.h Show resolved Hide resolved
decoder_ = IAMF_decoder_open();
if (!decoder_) {
SB_LOG(ERROR) << "Error creating libiamf decoder";
ReportError("Error creating libiamf decoder");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error_cb_ hasn't been set yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider checking is_valid() inside PlayerComponentsFactory as we no longer report an error here.

starboard/shared/libiamf/iamf_decoder_utils.cc Outdated Show resolved Hide resolved
Comment on lines 187 to 195
if (bytes_read == str_size) {
if (buf[bytes_read - 1] != '\0') {
return -1;
}
} else {
if (buf[bytes_read] != '\0') {
return -1;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for you to elaborate when these failure cases may happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified the implementation. This should only fail if a string is read that doesn't have a null terminator, which could happen if we read up to the end of the buffer, or the full 128 bytes, whichever is first.

starboard/shared/libiamf/iamf_decoder_utils.cc Outdated Show resolved Hide resolved
starboard/shared/libiamf/iamf_decoder_utils.cc Outdated Show resolved Hide resolved
starboard/shared/libiamf/iamf_decoder_utils.cc Outdated Show resolved Hide resolved
media/base/starboard_utils.cc Outdated Show resolved Hide resolved
Comment on lines 29 to 32
bool HasSupportedIamfProfile(const IamfMimeUtil* mime_util) {
return mime_util->primary_profile() == kIamfProfileSimple ||
mime_util->additional_profile() == kIamfProfileBase;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different than the previous implementation, where primary profile can be base and additional profile can be simple. Just wanted to double check if this is expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

#if SB_API_VERSION >= 15 && ENABLE_IAMF_DECODE
} else if (audio_stream_info.codec == kSbMediaAudioCodecIamf) {
SB_LOG(INFO) << "Playing audio using IamfAudioDecoder.";
return std::unique_ptr<AudioDecoder>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check if it's valid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, done

return false;
}

if (samples_decoded > info.num_samples) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can samples_decoded be info.num_samples - 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I've seen, IAMF_decoder_decode() should decode every sample indicated by the Codec config OBU if we pass it a complete access unit, which we do here.
Context:
https://github.com/AOMediaCodec/libiamf/blob/780ec7a112d4cea6350504e65d164526e01938a2/code/include/IAMF_decoder.h#L97

https://aomediacodec.github.io/iamf/#obu-codecconfig

samples_per_second_ = info.sample_rate;
}

// TODO: Enable partial audio once float32 pcm output is available.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the TODO here, what would happen for the following AdjustForDiscardedDurations() call when discarded_duration_from_front or discarded_duration_from_back isn't 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I had it commented out earlier and at some point removed the comment. I removed that section entirely, partial audio won't be supported at all at this time.

stream_ended_ = false;
decoded_audios_ = std::queue<scoped_refptr<DecodedAudio>>(); // clear

CancelPendingJobs();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: there aren't any pending jobs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (bytes_read == max_bytes_to_read) {
// Ensure that the string is null terminated.
if (buf[bytes_read] != '\0') {
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return -1;?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return ++bytes_read;
}

int pos_ = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: move pos_ below the two variables as they will be initialized in the ctor and never modified after.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


BufferReader reader(input_buffer->data(), input_buffer->size());

while (!info->is_valid() && reader.pos() < reader.size()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we should have a fast forward mode that skips all config OBUs so we can return the encoded data. The detailed config OBU info is only used to configure the decoder once when it's created.

Feel free to add it as a TODO and finish this in future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added TODO

@osagie98 osagie98 marked this pull request as draft October 17, 2024 23:15
@osagie98 osagie98 marked this pull request as ready for review October 18, 2024 20:38
@osagie98 osagie98 enabled auto-merge (squash) October 24, 2024 21:15
@osagie98 osagie98 merged commit 38e817e into youtube:25.lts.1+ Oct 24, 2024
300 of 301 checks passed
@osagie98 osagie98 deleted the iamf-decode-linux branch October 25, 2024 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants