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

Add vorbis comments support to flac extractor #6151

Merged
merged 3 commits into from
Jul 14, 2019

Conversation

vavadhani
Copy link
Contributor

@vavadhani vavadhani commented Jul 9, 2019

Decode and add vorbis comments from the flac file to metadata.

@ojw28 @umangsaini @harishdm

#5527

Decode and add vorbis comments from the flac file to metadata.

 google#5527
@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here (e.g. I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@vavadhani
Copy link
Contributor Author

I signed it

@ojw28
Copy link
Contributor

ojw28 commented Jul 9, 2019

@vavadhani - Please ensure you're registered under your company's Google CLA (this is distinct from the Android CLA). Thanks!

const FLAC__StreamMetadata_VorbisComment *vc =
&metadata->data.vorbis_comment;
mVorbisCommentValid = true;
mVorbisComment.metadataArray =
Copy link

Choose a reason for hiding this comment

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

These aren't freed anywhere.
Instead of malloc and copy, can we hold reference to &vc->comments[i]; and create required strings in flac_jni.cc flacDecodeVorbisComment()?
i.e. getVorbisComment() can return FLAC__StreamMetadata_VorbisComment*
That would avoid the need for malloc and copy here.

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 have reorganised the code according to other comments, and added the free to the character arrays that will be used.

@@ -110,6 +110,32 @@ DECODER_FUNC(jobject, flacDecodeMetadata, jlong jContext) {
streamInfo.total_samples);
}

DECODER_FUNC(jobject, flacDecodeVorbisComment, jlong jContext) {
Copy link
Contributor

Choose a reason for hiding this comment

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

For this to return something useful, does it rely on flacDecodeMetadata having been called previously (and specifically, on the call to context->parser->decodeMetadata() made on L94 above)?

If so, I think it would be much cleaner to rename FlacDecoderJni.decodeStreamInfo -> FlacDecoderJni.decodeMetadata and FlacStreamInfo -> FlacMetadata, and put the Arraylist<String> vorbisComment inside FlacMetadata

Here you'd pass the vorbisComment back as part of flacDecodeMetadata above, and the need for the separate flacDecodeVorbisComment would go away.

What do you think?

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, it does depend on the call to context->parser->decodeMetadata(). I will make this change and remove the separate call to flacDecodeVorbisComment.

Shall I push the refactor as a separate commit? Would it make the review easier?

Copy link
Contributor

Choose a reason for hiding this comment

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

Just adding separate commits as the code evolves is fine (and better than squashing + force pushing I think).

@@ -116,6 +126,8 @@ class FLACParser {
const FLAC__StreamMetadata_SeekTable *mSeekTable;
uint64_t firstFrameOffset;

bool mVorbisCommentValid;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Can we keep mVorbisCommentValid and mVorbisComment grouped together, maybe just under the mStreamInfo... params, with a similar comment to those.

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

import java.util.ArrayList;

/** Decodes vorbis comments */
public class VorbisCommentDecoder {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Please make classes final where possible, as it helps reduce our API surface. Ditto elsewhere.

Also, all other XXXDecoder classes in the metadata package implement MetadataDecoder, so this is slightly confusing. Given the data is already half decoded when it comes out of the JNI layer, it might be simpler just to merge this code into FlacDecoderJni or FlacExtractor.

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 will remove this class. I will also see how I can still run the tests without this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would making decodeVorbisComments a public static method in the StreamMetadata (previously StreamInfo) be acceptable?

Copy link
Contributor

Choose a reason for hiding this comment

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

You could pass the ArrayList<String> to the StreamMetadata constructor, have the constructor do the decoding, and have StreamMetadata hold the decoded Metadata directory rather than the ArrayList<String>.

do the decoding as part of the StreamMetadata constructor, and then have StreamMetadata hold the decoded Metadata directly rather than the ArrayList<String>.

The test would then be building a StreamMetadata and checking that the metadata field after construction is as expected.

* @return A {@link Metadata} structure with the vorbis comments as its entries.
*/
public Metadata decodeVorbisComments(@Nullable ArrayList<String> metadataStringList) {
if (metadataStringList == null || metadataStringList.size() == 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: Use .isEmpty() rather than size() == 0. Ditto below.

for (String commentEntry : metadataStringList) {
String[] keyValue;

keyValue = commentEntry.split(SEPARATOR);
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect that it's allowed to have the = character in the value. In other words KEY=VAL=UE is probably valid. In which case you should be looking the first instance of the separator only. You may find Util.splitAtFirst helpful for this.

If you agree, it would be good to have a test case for this as well.

/** Base class for Vorbis Comment Frames. */
public class VorbisCommentFrame implements Metadata.Entry {

/** The frame key and value */
Copy link
Contributor

Choose a reason for hiding this comment

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

When generating HTML Javadoc, this is going to attach "The frame key and value" to key, and nothing to value. Could you document each of them separately?

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

@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@@ -116,6 +126,8 @@ class FLACParser {
const FLAC__StreamMetadata_SeekTable *mSeekTable;
uint64_t firstFrameOffset;

bool mVorbisCommentValid;
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

for (FLAC__uint32 i = 0; i < vc.num_comments; ++i) {
FLAC__StreamMetadata_VorbisComment_Entry vce = vc.comments[i];
if (vce.entry != NULL) {
std::string comment(reinterpret_cast<char *>(vce.entry),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the mallocs here and the free. Using std::vector and std::string instead.

@vavadhani
Copy link
Contributor Author

vavadhani commented Jul 11, 2019

@ojw28 @harishdm @umangsaini I've made some changes, please take a look.

Copy link
Contributor

@ojw28 ojw28 left a comment

Choose a reason for hiding this comment

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

Thanks for the changes! This looks good to merge. I put some comments inline for future reference, but there's no need to push any changes. We'll take care of them as part of the process we use to get the change merged.

@@ -172,6 +172,22 @@ void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata) {
case FLAC__METADATA_TYPE_SEEKTABLE:
mSeekTable = &metadata->data.seek_table;
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if (!mVorbisCommentValid) {
FLAC__StreamMetadata_VorbisComment vc = metadata->data.vorbis_comment;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit (don't update): Avoid shortened variables names (e.g. use vorbisComment rather than vc).

* @param channels Number of channels of the FLAC stream.
* @param bitsPerSample Number of bits per sample of the FLAC stream.
* @param totalSamples Total samples of the FLAC stream.
* @param vorbisCommentList An {@link ArrayList<String>} that contains vorbis comments, which will
Copy link
Contributor

Choose a reason for hiding this comment

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

nit (don't update): No need to document the type of the argument in the comment, since it's already documented by the method signature.


/** Test for {@link FlacStreamMetadata}'s conversion of {@link ArrayList} to {@link Metadata}. */
@RunWith(AndroidJUnit4.class)
public final class VorbisCommentDecoderTest {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit (don't update): Should be FlacStreamMetadataTest now (and in the util package).

@ojw28 ojw28 merged commit 4b776ff into google:dev-v2 Jul 14, 2019
ojw28 added a commit that referenced this pull request Jul 14, 2019
ojw28 added a commit that referenced this pull request Jul 28, 2019
@google google locked and limited conversation to collaborators Oct 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants