move the opus-related functions in opus.cc

This commit is contained in:
Frédéric Mangano-Tarumi 2018-11-03 17:18:15 -04:00
parent 06520bf87e
commit 3c0aad169b
4 changed files with 166 additions and 143 deletions

View File

@ -15,7 +15,11 @@ pkg_check_modules(OGG REQUIRED ogg)
configure_file(src/config.h.in config.h @ONLY)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(opustags src/opustags.cc)
add_executable(
opustags
src/opus.cc
src/opustags.cc
)
target_compile_options(opustags PUBLIC ${OGG_CFLAGS})
target_link_libraries(opustags PUBLIC ${OGG_LIBRARIES})

153
src/opus.cc Normal file
View File

@ -0,0 +1,153 @@
#include "opustags.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#define htole32(x) OSSwapHostToLittleInt32(x)
#define le32toh(x) OSSwapLittleToHostInt32(x)
#endif
int ot::parse_tags(char *data, long len, opus_tags *tags)
{
long pos;
if (len < 8+4+4)
return -1;
if (strncmp(data, "OpusTags", 8) != 0)
return -1;
// Vendor
pos = 8;
tags->vendor_length = le32toh(*((uint32_t*) (data + pos)));
tags->vendor_string = data + pos + 4;
pos += 4 + tags->vendor_length;
if (pos + 4 > len)
return -1;
// Count
tags->count = le32toh(*((uint32_t*) (data + pos)));
if (tags->count == 0)
return 0;
tags->lengths = static_cast<uint32_t*>(calloc(tags->count, sizeof(uint32_t)));
if (tags->lengths == NULL)
return -1;
tags->comment = static_cast<const char**>(calloc(tags->count, sizeof(char*)));
if (tags->comment == NULL) {
free(tags->lengths);
return -1;
}
pos += 4;
// Comment
uint32_t i;
for (i=0; i<tags->count; i++) {
tags->lengths[i] = le32toh(*((uint32_t*) (data + pos)));
tags->comment[i] = data + pos + 4;
pos += 4 + tags->lengths[i];
if (pos > len)
return -1;
}
if (pos < len)
fprintf(stderr, "warning: %ld unused bytes at the end of the OpusTags packet\n", len - pos);
return 0;
}
int ot::render_tags(opus_tags *tags, ogg_packet *op)
{
// Note: op->packet must be manually freed.
op->b_o_s = 0;
op->e_o_s = 0;
op->granulepos = 0;
op->packetno = 1;
long len = 8 + 4 + tags->vendor_length + 4;
uint32_t i;
for (i=0; i<tags->count; i++)
len += 4 + tags->lengths[i];
op->bytes = len;
char *data = static_cast<char*>(malloc(len));
if (!data)
return -1;
op->packet = (unsigned char*) data;
uint32_t n;
memcpy(data, "OpusTags", 8);
n = htole32(tags->vendor_length);
memcpy(data+8, &n, 4);
memcpy(data+12, tags->vendor_string, tags->vendor_length);
data += 12 + tags->vendor_length;
n = htole32(tags->count);
memcpy(data, &n, 4);
data += 4;
for (i=0; i<tags->count; i++) {
n = htole32(tags->lengths[i]);
memcpy(data, &n, 4);
memcpy(data+4, tags->comment[i], tags->lengths[i]);
data += 4 + tags->lengths[i];
}
return 0;
}
static int match_field(const char *comment, uint32_t len, const char *field)
{
size_t field_len;
for (field_len = 0; field[field_len] != '\0' && field[field_len] != '='; field_len++);
if (len <= field_len)
return 0;
if (comment[field_len] != '=')
return 0;
if (strncmp(comment, field, field_len) != 0)
return 0;
return 1;
}
void ot::delete_tags(opus_tags *tags, const char *field)
{
uint32_t i;
for (i=0; i<tags->count; i++) {
if (match_field(tags->comment[i], tags->lengths[i], field)) {
// We want to delete the current element, so we move the last tag at
// position i, then decrease the array size. We need decrease i to inspect
// at the next iteration the tag we just moved.
tags->count--;
tags->lengths[i] = tags->lengths[tags->count];
tags->comment[i] = tags->comment[tags->count];
--i;
// No need to resize the arrays.
}
}
}
int ot::add_tags(opus_tags *tags, const char **tags_to_add, uint32_t count)
{
if (count == 0)
return 0;
uint32_t *lengths = static_cast<uint32_t*>(realloc(tags->lengths, (tags->count + count) * sizeof(uint32_t)));
const char **comment = static_cast<const char**>(realloc(tags->comment, (tags->count + count) * sizeof(char*)));
if (lengths == NULL || comment == NULL)
return -1;
tags->lengths = lengths;
tags->comment = comment;
uint32_t i;
for (i=0; i<count; i++) {
tags->lengths[tags->count + i] = strlen(tags_to_add[i]);
tags->comment[tags->count + i] = tags_to_add[i];
}
tags->count += count;
return 0;
}
void ot::print_tags(opus_tags *tags)
{
for (uint32_t i=0; i<tags->count; i++) {
fwrite(tags->comment[i], 1, tags->lengths[i], stdout);
puts("");
}
}
void ot::free_tags(opus_tags *tags)
{
if (tags->count > 0) {
free(tags->lengths);
free(tags->comment);
}
}

View File

@ -11,150 +11,8 @@
#include <unistd.h>
#include <ogg/ogg.h>
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#define htole32(x) OSSwapHostToLittleInt32(x)
#define le32toh(x) OSSwapLittleToHostInt32(x)
#endif
using namespace ot;
int parse_tags(char *data, long len, opus_tags *tags){
long pos;
if(len < 8+4+4)
return -1;
if(strncmp(data, "OpusTags", 8) != 0)
return -1;
// Vendor
pos = 8;
tags->vendor_length = le32toh(*((uint32_t*) (data + pos)));
tags->vendor_string = data + pos + 4;
pos += 4 + tags->vendor_length;
if(pos + 4 > len)
return -1;
// Count
tags->count = le32toh(*((uint32_t*) (data + pos)));
if(tags->count == 0)
return 0;
tags->lengths = static_cast<uint32_t*>(calloc(tags->count, sizeof(uint32_t)));
if(tags->lengths == NULL)
return -1;
tags->comment = static_cast<const char**>(calloc(tags->count, sizeof(char*)));
if(tags->comment == NULL){
free(tags->lengths);
return -1;
}
pos += 4;
// Comment
uint32_t i;
for(i=0; i<tags->count; i++){
tags->lengths[i] = le32toh(*((uint32_t*) (data + pos)));
tags->comment[i] = data + pos + 4;
pos += 4 + tags->lengths[i];
if(pos > len)
return -1;
}
if(pos < len)
fprintf(stderr, "warning: %ld unused bytes at the end of the OpusTags packet\n", len - pos);
return 0;
}
int render_tags(opus_tags *tags, ogg_packet *op){
// Note: op->packet must be manually freed.
op->b_o_s = 0;
op->e_o_s = 0;
op->granulepos = 0;
op->packetno = 1;
long len = 8 + 4 + tags->vendor_length + 4;
uint32_t i;
for(i=0; i<tags->count; i++)
len += 4 + tags->lengths[i];
op->bytes = len;
char *data = static_cast<char*>(malloc(len));
if(!data)
return -1;
op->packet = (unsigned char*) data;
uint32_t n;
memcpy(data, "OpusTags", 8);
n = htole32(tags->vendor_length);
memcpy(data+8, &n, 4);
memcpy(data+12, tags->vendor_string, tags->vendor_length);
data += 12 + tags->vendor_length;
n = htole32(tags->count);
memcpy(data, &n, 4);
data += 4;
for(i=0; i<tags->count; i++){
n = htole32(tags->lengths[i]);
memcpy(data, &n, 4);
memcpy(data+4, tags->comment[i], tags->lengths[i]);
data += 4 + tags->lengths[i];
}
return 0;
}
int match_field(const char *comment, uint32_t len, const char *field){
size_t field_len;
for(field_len = 0; field[field_len] != '\0' && field[field_len] != '='; field_len++);
if(len <= field_len)
return 0;
if(comment[field_len] != '=')
return 0;
if(strncmp(comment, field, field_len) != 0)
return 0;
return 1;
}
void delete_tags(opus_tags *tags, const char *field){
uint32_t i;
for(i=0; i<tags->count; i++){
if(match_field(tags->comment[i], tags->lengths[i], field)){
// We want to delete the current element, so we move the last tag at position i, then
// decrease the array size. We need decrease i to inspect at the next iteration the tag
// we just moved.
tags->count--;
tags->lengths[i] = tags->lengths[tags->count];
tags->comment[i] = tags->comment[tags->count];
--i;
// No need to resize the arrays.
}
}
}
int add_tags(opus_tags *tags, const char **tags_to_add, uint32_t count){
if(count == 0)
return 0;
uint32_t *lengths = static_cast<uint32_t*>(realloc(tags->lengths, (tags->count + count) * sizeof(uint32_t)));
const char **comment = static_cast<const char**>(realloc(tags->comment, (tags->count + count) * sizeof(char*)));
if(lengths == NULL || comment == NULL)
return -1;
tags->lengths = lengths;
tags->comment = comment;
uint32_t i;
for(i=0; i<count; i++){
tags->lengths[tags->count + i] = strlen(tags_to_add[i]);
tags->comment[tags->count + i] = tags_to_add[i];
}
tags->count += count;
return 0;
}
void print_tags(opus_tags *tags){
for(uint32_t i=0; i<tags->count; i++){
fwrite(tags->comment[i], 1, tags->lengths[i], stdout);
puts("");
}
}
void free_tags(opus_tags *tags){
if(tags->count > 0){
free(tags->lengths);
free(tags->comment);
}
}
int write_page(ogg_page *og, FILE *stream){
if((ssize_t) fwrite(og->header, 1, og->header_len, stream) < og->header_len)
return -1;

View File

@ -4,6 +4,7 @@
*/
#include <cstdint>
#include <ogg/ogg.h>
namespace ot {
@ -27,6 +28,13 @@ struct opus_tags {
const char **comment;
};
int parse_tags(char *data, long len, opus_tags *tags);
int render_tags(opus_tags *tags, ogg_packet *op);
void delete_tags(opus_tags *tags, const char *field);
int add_tags(opus_tags *tags, const char **tags_to_add, uint32_t count);
void print_tags(opus_tags *tags);
void free_tags(opus_tags *tags);
/** \} */
}