-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Conversation
Decode and add vorbis comments from the flac file to metadata. google#5527
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. What to do if you already signed the CLAIndividual signers
Corporate signers
ℹ️ Googlers: Go here for more info. |
I signed it |
@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 = |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 */ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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; |
There was a problem hiding this comment.
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), |
There was a problem hiding this comment.
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.
@ojw28 @harishdm @umangsaini I've made some changes, please take a look. |
There was a problem hiding this 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; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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).
Decode and add vorbis comments from the flac file to metadata.
@ojw28 @umangsaini @harishdm
#5527