Older/MediaServer/libflv/source/mp3-header.c
amass 08340ad5c8
All checks were successful
Deploy / PullDocker (push) Successful in 11s
Deploy / Build (push) Successful in 1m54s
add codec.
2024-09-30 16:12:57 +00:00

234 lines
5.6 KiB
C

#include "mp3-header.h"
#include <stdint.h>
#include <string.h>
#include <assert.h>
// layer-1, layer-2, layer-3
static int s_bitrate_mpeg1[3][16] = {
{ 0/*free*/, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, -1 },
{ 0/*free*/, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, -1 },
{ 0/*free*/, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, -1 },
};
// layer-1, layer-2, layer-3
static int s_bitrate_mpeg2[3][16] = {
{ 0/*free*/, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000, -1 },
{ 0/*free*/, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, -1 },
{ 0/*free*/, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, -1 },
};
// layer-1, layer-2, layer-3
static int s_frequency_mpeg1[4] = { 44100, 48000, 32000, -1 };
static int s_frequency_mpeg2[4] = { 22050, 24000, 16000, -1 };
static int s_frequency_mpeg25[4] = { 11025, 12000, 8000, -1 };
// layer-1, layer-2, layer-3
//static int s_frames_mpeg1[3] = { 384, 1152, 1152 };
//static int s_frames_mpeg2[3] = { 384, 1152, 576 };
//static int s_frames_mpeg25[3] = { 384, 1152, 576 };
// layer-1 bytes = ((frames / 8 * bitrate) / frequency + padding * 4
// layer-2/3 bytes = ((frames / 8 * bitrate) / frequency + padding
int mp3_header_load(struct mp3_header_t* mp3, const void* data, int bytes)
{
const uint8_t* p;
if (bytes < 4)
return 0;
p = data;
if (0 == memcmp("TAG", p, 3))
{
if (bytes < 128/*ID3v1*/ + 4)
return 0;
p += 128;
}
else if (0 == memcmp("ID3", p, 3))
{
uint32_t n;
if (3 != p[3]/*version*/ || bytes < 10)
return 0;
n = (((uint32_t)p[6] & 0x7F) << 21) | (((uint32_t)p[7] & 0x7F) << 14) | (((uint32_t)p[8] & 0x7F) << 7) | (p[9] & 0x7F);
if (bytes < (int)n + 10)
return 0;
p += n + 10;
}
//sync: 1111 1111 111
if (0xFF != p[0] || 0xE0 != (p[1] & 0xE0))
{
assert(0);
return 0;
}
mp3->version = (p[1] >> 3) & 0x03;
mp3->layer = (p[1] >> 1) & 0x03;
mp3->protection = p[1] & 0x01;
mp3->bitrate_index = (p[2] >> 4) & 0x0F;
mp3->sampling_frequency = (p[2] >> 2) & 0x03;
mp3->priviate = p[2] & 0x01;
mp3->mode = (p[3] >> 6) & 0x03;
mp3->mode_extension = (p[3] >> 4) & 0x03;
mp3->copyright = (p[3] >> 3) & 0x01;
mp3->original = (p[3] >> 2) & 0x01;
mp3->emphasis = p[3] & 0x03;
return (int)(p - (uint8_t*)data) + 4;
}
int mp3_header_save(const struct mp3_header_t* mp3, void* data, int bytes)
{
uint8_t* p;
if (bytes < 4)
return 0;
p = data;
p[0] = 0xFF;
p[1] = (uint8_t)(0xE0 | (mp3->version << 3) | (mp3->layer << 1) | mp3->protection);
p[2] = (uint8_t)((mp3->bitrate_index << 4) | (mp3->sampling_frequency << 2) | 0x00 /*padding*/ | mp3->priviate);
p[3] = (uint8_t)((mp3->mode << 6) | (mp3->mode_extension << 4) | (mp3->copyright << 3) | (mp3->original << 2) | mp3->emphasis);
return 4;
}
int mp3_get_channel(const struct mp3_header_t* mp3)
{
return 0x03 == mp3->mode ? 1 : 2;
}
int mp3_get_bitrate(const struct mp3_header_t* mp3)
{
if (mp3->layer < 1 || mp3->layer > 3)
{
assert(0);
return -1;
}
switch (mp3->version)
{
case MP3_MPEG1:
return s_bitrate_mpeg1[3 - mp3->layer][mp3->bitrate_index];
case MP3_MPEG2:
case MP3_MPEG2_5:
return s_bitrate_mpeg2[3 - mp3->layer][mp3->bitrate_index];
default:
assert(0);
return -1;
}
}
static int mp3_find_bitrate(const int* arr, int bitrate)
{
int i;
for (i = 0; i < 16; i++)
{
if (bitrate == arr[i])
return i;
}
return -1;
}
int mp3_set_bitrate(struct mp3_header_t* mp3, int bitrate)
{
int r;
if (mp3->layer < 1 || mp3->layer > 3)
{
assert(0);
return -1;
}
switch (mp3->version)
{
case MP3_MPEG1:
r = mp3_find_bitrate(s_bitrate_mpeg1[3 - mp3->layer], bitrate);
break;
case MP3_MPEG2:
case MP3_MPEG2_5:
r = mp3_find_bitrate(s_bitrate_mpeg2[3 - mp3->layer], bitrate);
break;
default:
assert(0);
r = -1;
}
if (-1 == r)
return -1;
mp3->bitrate_index = (unsigned int)r;
return 0;
}
int mp3_get_frequency(const struct mp3_header_t* mp3)
{
if (mp3->sampling_frequency < 0 || mp3->sampling_frequency > 3)
return -1;
switch (mp3->version)
{
case MP3_MPEG1: return s_frequency_mpeg1[mp3->sampling_frequency];
case MP3_MPEG2: return s_frequency_mpeg2[mp3->sampling_frequency];
case MP3_MPEG2_5: return s_frequency_mpeg25[mp3->sampling_frequency];
default: assert(0); return -1;
}
}
static int mp3_find_frequency(const int* arr, int frequency)
{
int i;
for (i = 0; i < 4; i++)
{
if (frequency == arr[i])
return i;
}
return -1;
}
int mp3_set_frequency(struct mp3_header_t* mp3, int frequency)
{
int r;
switch (mp3->version)
{
case MP3_MPEG1:
r = mp3_find_frequency(s_frequency_mpeg1, frequency);
break;
case MP3_MPEG2:
r = mp3_find_frequency(s_frequency_mpeg2, frequency);
break;
case MP3_MPEG2_5:
r = mp3_find_frequency(s_frequency_mpeg25, frequency);
break;
default:
assert(0);
r = -1;
}
if (-1 == r)
return -1;
mp3->sampling_frequency = (unsigned int)r;
return 0;
}
#if defined(DEBUG) || defined(_DEBUG)
void mp3_header_test(void)
{
uint8_t v[4] = { 0xff, 0xfb, 0xe0, 0x64 };
uint8_t v2[4];
struct mp3_header_t mp3;
assert(4 == mp3_header_load(&mp3, v, 4));
assert(MP3_MPEG1 == mp3.version && MP3_LAYER3 == mp3.layer);
assert(14 == mp3.bitrate_index && 320000 == mp3_get_bitrate(&mp3));
assert(0 == mp3.sampling_frequency && 44100 == mp3_get_frequency(&mp3));
assert(1 == mp3.mode && 1 == mp3.protection);
assert(4 == mp3_header_save(&mp3, v2, 4));
assert(0 == memcmp(v, v2, 4));
}
#endif