summaryrefslogtreecommitdiff
path: root/drivers/opus/info.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/opus/info.c')
-rw-r--r--drivers/opus/info.c100
1 files changed, 82 insertions, 18 deletions
diff --git a/drivers/opus/info.c b/drivers/opus/info.c
index 8175a013ac..b94393351e 100644
--- a/drivers/opus/info.c
+++ b/drivers/opus/info.c
@@ -9,9 +9,7 @@
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
* *
********************************************************************/
-#ifdef OPUS_ENABLED
#include "opus/opus_config.h"
-#endif
#include "opus/internal.h"
#include <limits.h>
@@ -92,8 +90,11 @@ void opus_tags_init(OpusTags *_tags){
}
void opus_tags_clear(OpusTags *_tags){
+ int ncomments;
int ci;
- for(ci=_tags->comments;ci-->0;)_ogg_free(_tags->user_comments[ci]);
+ ncomments=_tags->comments;
+ if(_tags->user_comments!=NULL)ncomments++;
+ for(ci=ncomments;ci-->0;)_ogg_free(_tags->user_comments[ci]);
_ogg_free(_tags->user_comments);
_ogg_free(_tags->comment_lengths);
_ogg_free(_tags->vendor);
@@ -103,19 +104,27 @@ void opus_tags_clear(OpusTags *_tags){
static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){
char **user_comments;
int *comment_lengths;
+ int cur_ncomments;
+ char *binary_suffix_data;
+ int binary_suffix_len;
size_t size;
if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT;
size=sizeof(*_tags->comment_lengths)*(_ncomments+1);
if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT;
+ cur_ncomments=_tags->comments;
+ comment_lengths=_tags->comment_lengths;
+ binary_suffix_len=comment_lengths==NULL?0:comment_lengths[cur_ncomments];
comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size);
if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT;
- comment_lengths[_ncomments]=0;
+ comment_lengths[_ncomments]=binary_suffix_len;
_tags->comment_lengths=comment_lengths;
size=sizeof(*_tags->user_comments)*(_ncomments+1);
if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT;
+ user_comments=_tags->user_comments;
+ binary_suffix_data=user_comments==NULL?NULL:user_comments[cur_ncomments];
user_comments=(char **)_ogg_realloc(_tags->user_comments,size);
if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT;
- user_comments[_ncomments]=NULL;
+ user_comments[_ncomments]=binary_suffix_data;
_tags->user_comments=user_comments;
return 0;
}
@@ -192,6 +201,13 @@ static int opus_tags_parse_impl(OpusTags *_tags,
_data+=count;
len-=count;
}
+ if(len>0&&(_data[0]&1)){
+ if(len>(opus_uint32)INT_MAX)return OP_EFAULT;
+ _tags->user_comments[ncomments]=(char *)_ogg_malloc(len);
+ if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT;
+ memcpy(_tags->user_comments[ncomments],_data,len);
+ _tags->comment_lengths[ncomments]=(int)len;
+ }
return 0;
}
@@ -232,6 +248,16 @@ static int opus_tags_copy_impl(OpusTags *_dst,const OpusTags *_src){
_dst->comment_lengths[ci]=len;
_dst->comments=ci+1;
}
+ if(_src->comment_lengths!=NULL){
+ int len;
+ len=_src->comment_lengths[ncomments];
+ if(len>0){
+ _dst->user_comments[ncomments]=(char *)_ogg_malloc(len);
+ if(OP_UNLIKELY(_dst->user_comments[ncomments]==NULL))return OP_EFAULT;
+ memcpy(_dst->user_comments[ncomments],_src->user_comments[ncomments],len);
+ _dst->comment_lengths[ncomments]=len;
+ }
+ }
return 0;
}
@@ -257,34 +283,52 @@ int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){
tag_len=strlen(_tag);
value_len=strlen(_value);
/*+2 for '=' and '\0'.*/
- _tags->comment_lengths[ncomments]=0;
- _tags->user_comments[ncomments]=comment=
- (char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2));
+ comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2));
if(OP_UNLIKELY(comment==NULL))return OP_EFAULT;
memcpy(comment,_tag,sizeof(*comment)*tag_len);
comment[tag_len]='=';
memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1));
+ _tags->user_comments[ncomments]=comment;
_tags->comment_lengths[ncomments]=tag_len+value_len+1;
_tags->comments=ncomments+1;
return 0;
}
int opus_tags_add_comment(OpusTags *_tags,const char *_comment){
- int comment_len;
- int ncomments;
- int ret;
+ char *comment;
+ int comment_len;
+ int ncomments;
+ int ret;
ncomments=_tags->comments;
ret=op_tags_ensure_capacity(_tags,ncomments+1);
if(OP_UNLIKELY(ret<0))return ret;
comment_len=(int)strlen(_comment);
- _tags->comment_lengths[ncomments]=0;
- _tags->user_comments[ncomments]=op_strdup_with_len(_comment,comment_len);
+ comment=op_strdup_with_len(_comment,comment_len);
if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT;
+ _tags->user_comments[ncomments]=comment;
_tags->comment_lengths[ncomments]=comment_len;
_tags->comments=ncomments+1;
return 0;
}
+int opus_tags_set_binary_suffix(OpusTags *_tags,
+ const unsigned char *_data,int _len){
+ unsigned char *binary_suffix_data;
+ int ncomments;
+ int ret;
+ if(_len<0||_len>0&&(_data==NULL||!(_data[0]&1)))return OP_EINVAL;
+ ncomments=_tags->comments;
+ ret=op_tags_ensure_capacity(_tags,ncomments);
+ if(OP_UNLIKELY(ret<0))return ret;
+ binary_suffix_data=
+ (unsigned char *)_ogg_realloc(_tags->user_comments[ncomments],_len);
+ if(OP_UNLIKELY(binary_suffix_data==NULL))return OP_EFAULT;
+ memcpy(binary_suffix_data,_data,_len);
+ _tags->user_comments[ncomments]=(char *)binary_suffix_data;
+ _tags->comment_lengths[ncomments]=_len;
+ return 0;
+}
+
int opus_tagcompare(const char *_tag_name,const char *_comment){
return opus_tagncompare(_tag_name,strlen(_tag_name),_comment);
}
@@ -332,19 +376,31 @@ int opus_tags_query_count(const OpusTags *_tags,const char *_tag){
return found;
}
-int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
+const unsigned char *opus_tags_get_binary_suffix(const OpusTags *_tags,
+ int *_len){
+ int ncomments;
+ int len;
+ ncomments=_tags->comments;
+ len=_tags->comment_lengths==NULL?0:_tags->comment_lengths[ncomments];
+ *_len=len;
+ OP_ASSERT(len==0||_tags->user_comments!=NULL);
+ return len>0?(const unsigned char *)_tags->user_comments[ncomments]:NULL;
+}
+
+static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8,
+ const char *_tag_name,size_t _tag_len){
char **comments;
int ncomments;
int ci;
comments=_tags->user_comments;
ncomments=_tags->comments;
- /*Look for the first valid R128_TRACK_GAIN tag and use that.*/
+ /*Look for the first valid tag with the name _tag_name and use that.*/
for(ci=0;ci<ncomments;ci++){
- if(opus_tagncompare("R128_TRACK_GAIN",15,comments[ci])==0){
+ if(opus_tagncompare(_tag_name,_tag_len,comments[ci])==0){
char *p;
opus_int32 gain_q8;
int negative;
- p=comments[ci]+16;
+ p=comments[ci]+_tag_len+1;
negative=0;
if(*p=='-'){
negative=-1;
@@ -358,7 +414,7 @@ int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
p++;
}
/*This didn't look like a signed 16-bit decimal integer.
- Not a valid R128_TRACK_GAIN tag.*/
+ Not a valid gain tag.*/
if(*p!='\0')continue;
*_gain_q8=(int)(gain_q8+negative^negative);
return 0;
@@ -367,6 +423,14 @@ int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
return OP_FALSE;
}
+int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8){
+ return opus_tags_get_gain(_tags,_gain_q8,"R128_ALBUM_GAIN",15);
+}
+
+int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
+ return opus_tags_get_gain(_tags,_gain_q8,"R128_TRACK_GAIN",15);
+}
+
static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){
return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0
&&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0;