📄 mpeg3atrack.c
字号:
#include "libmpeg3.h"#include "mpeg3protos.h"#include "mpeg3demux.h"#include "mp4av.h"#include <stdlib.h>static int mpeg3_atrack_get_mp3_info (mpeg3_atrack_t *atrack){ uint8_t hdr[4]; mpeg3_demuxer_t *demux; MP4AV_Mp3Header temp; demux = atrack->demuxer; hdr[1] = mpeg3demux_read_char(demux); do { hdr[0] = hdr[1]; hdr[1] = mpeg3demux_read_char(demux); } while (((hdr[0] != 0xff) || ((hdr[1] & 0xe0) != 0xe0)) && !mpeg3demux_eof(demux)); if (mpeg3demux_eof(demux)) return -1; hdr[2] = mpeg3demux_read_char(demux); hdr[3] = mpeg3demux_read_char(demux); temp = MP4AV_Mp3HeaderFromBytes(hdr); atrack->sample_rate = MP4AV_Mp3GetHdrSamplingRate(temp); atrack->channels = MP4AV_Mp3GetChannels(temp); atrack->samples_per_frame = MP4AV_Mp3GetHdrSamplingWindow(temp); return 0;}static int mpeg3_atrack_get_aac_info (mpeg3_atrack_t *atrack){ uint8_t hdr[16]; mpeg3_demuxer_t *demux; uint16_t hdr_size; uint16_t ix; demux = atrack->demuxer; hdr[1] = mpeg3demux_read_char(demux); do { hdr[0] = hdr[1]; hdr[1] = mpeg3demux_read_char(demux); } while (((hdr[0] != 0xff) || ((hdr[1] & 0xf0) != 0xf0)) && !mpeg3demux_eof(demux)); if (mpeg3demux_eof(demux)) return -1; hdr_size = MP4AV_AdtsGetHeaderByteSize(hdr); if (hdr_size > sizeof(hdr)) return -1; for (ix = 2; ix < hdr_size; ix++) { hdr[ix] = mpeg3demux_read_char(demux); } if (mpeg3demux_eof(demux)) return -1; atrack->sample_rate = MP4AV_AdtsGetSamplingRate(hdr); atrack->channels = MP4AV_AdtsGetChannels(hdr); atrack->samples_per_frame = 1024; // always the same return 0;}static int mpeg3_ac3_samplerates[] = { 48000, 44100, 32000 };struct mpeg3_framesize_s{ unsigned short bit_rate; unsigned short frm_size[3];};static struct mpeg3_framesize_s framesize_codes[] = { { 32 ,{64 ,69 ,96 } }, { 32 ,{64 ,70 ,96 } }, { 40 ,{80 ,87 ,120 } }, { 40 ,{80 ,88 ,120 } }, { 48 ,{96 ,104 ,144 } }, { 48 ,{96 ,105 ,144 } }, { 56 ,{112 ,121 ,168 } }, { 56 ,{112 ,122 ,168 } }, { 64 ,{128 ,139 ,192 } }, { 64 ,{128 ,140 ,192 } }, { 80 ,{160 ,174 ,240 } }, { 80 ,{160 ,175 ,240 } }, { 96 ,{192 ,208 ,288 } }, { 96 ,{192 ,209 ,288 } }, { 112 ,{224 ,243 ,336 } }, { 112 ,{224 ,244 ,336 } }, { 128 ,{256 ,278 ,384 } }, { 128 ,{256 ,279 ,384 } }, { 160 ,{320 ,348 ,480 } }, { 160 ,{320 ,349 ,480 } }, { 192 ,{384 ,417 ,576 } }, { 192 ,{384 ,418 ,576 } }, { 224 ,{448 ,487 ,672 } }, { 224 ,{448 ,488 ,672 } }, { 256 ,{512 ,557 ,768 } }, { 256 ,{512 ,558 ,768 } }, { 320 ,{640 ,696 ,960 } }, { 320 ,{640 ,697 ,960 } }, { 384 ,{768 ,835 ,1152 } }, { 384 ,{768 ,836 ,1152 } }, { 448 ,{896 ,975 ,1344 } }, { 448 ,{896 ,976 ,1344 } }, { 512 ,{1024 ,1114 ,1536 } }, { 512 ,{1024 ,1115 ,1536 } }, { 576 ,{1152 ,1253 ,1728 } }, { 576 ,{1152 ,1254 ,1728 } }, { 640 ,{1280 ,1393 ,1920 } }, { 640 ,{1280 ,1394 ,1920 } }};/* Audio channel modes */static short mpeg3_ac3_acmodes[] = {2, 1, 2, 3, 3, 4, 4, 5};static int mpeg3_atrack_get_ac3_info (mpeg3_atrack_t *atrack){ uint16_t code, mask; unsigned int sampling_freq_code, framesize_code; unsigned int acmod; unsigned int skipbits; mpeg3_demuxer_t *demux; demux = atrack->demuxer; code = mpeg3demux_read_char(demux); do { code &= 0xff; code <<= 8; code |= mpeg3demux_read_char(demux); } while (!mpeg3demux_eof(demux) && code != MPEG3_AC3_START_CODE); if (mpeg3demux_eof(demux)) return -1; // 2 bytes CRC mpeg3demux_read_char(demux); mpeg3demux_read_char(demux); code = mpeg3demux_read_char(demux); sampling_freq_code = (code >> 6) & 0x3; framesize_code = code & 0x3f; // bsid and bsmod mpeg3demux_read_char(demux); // acmod is 3 bits code = mpeg3demux_read_char(demux) << 8; code |= mpeg3demux_read_char(demux); if (mpeg3demux_eof(demux)) return -1; atrack->sample_rate = mpeg3_ac3_samplerates[sampling_freq_code]; atrack->framesize = 2 * framesize_codes[framesize_code].frm_size[sampling_freq_code]; atrack->samples_per_frame = 1536; // fixed amount from rfc draft acmod = (code >> 13) & 0x7; atrack->channels = mpeg3_ac3_acmodes[acmod]; skipbits = 3; if ((acmod & 0x1) && (acmod != 1)) { skipbits += 2; } if (acmod & 0x4) skipbits += 2; if (acmod == 0x2) skipbits += 2; mask = 1 << (15 - skipbits); if ((code & mask) != 0) atrack->channels++; return 0;}static int mpeg3_atrack_suck_frame_info (mpeg3_atrack_t *atrack){ mpeg3_demuxer_t *demux; demux = atrack->demuxer; if (atrack->format == AUDIO_UNKNOWN) { uint16_t code; code = mpeg3demux_read_char(demux); code <<= 8; code |= mpeg3demux_read_char(demux); if (code == MPEG3_AC3_START_CODE) { atrack->format = AUDIO_AC3; } else if ((code & 0xfff8) == 0xfff8) { atrack->format = AUDIO_MPEG; } else { atrack->format = AUDIO_AAC; } code = mpeg3demux_read_prev_char(demux); code = mpeg3demux_read_prev_char(demux); } switch (atrack->format) { case AUDIO_PCM: atrack->sample_rate = 48000; atrack->channels = 2; atrack->framesize = 0x7db; break; case AUDIO_MPEG: if (mpeg3_atrack_get_mp3_info(atrack) < 0) return -1; break; case AUDIO_AC3: if (mpeg3_atrack_get_ac3_info(atrack) < 0) return -1; break; case AUDIO_AAC: if (mpeg3_atrack_get_aac_info(atrack) < 0) return -1; break; } mpeg3demux_seek_start(demux);}mpeg3_atrack_t* mpeg3_new_atrack(mpeg3_t *file, int stream_id, int format, mpeg3_demuxer_t *demuxer, int number){ mpeg3_atrack_t *new_atrack; new_atrack = calloc(1, sizeof(mpeg3_atrack_t)); new_atrack->file = file; new_atrack->channels = 0; new_atrack->sample_rate = 0; new_atrack->total_samples = 0; new_atrack->percentage_seek = -1; new_atrack->demuxer = mpeg3_new_demuxer(file, 1, 0, stream_id); if(new_atrack->demuxer) mpeg3demux_copy_titles(new_atrack->demuxer, demuxer); new_atrack->current_position = 0; new_atrack->format = format; if (mpeg3_atrack_suck_frame_info(new_atrack) < 0 || new_atrack->format == AUDIO_UNKNOWN) {/* Failed */ mpeg3_delete_atrack(file, new_atrack); new_atrack = NULL; } //printf("mpeg3 demux length %g\n", mpeg3demux_length(new_atrack->demuxer));// Copy pointers if(file->sample_offsets) { new_atrack->sample_offsets = file->sample_offsets[number]; new_atrack->total_sample_offsets = file->total_sample_offsets[number]; new_atrack->total_frames = new_atrack->total_sample_offsets / new_atrack->samples_per_frame; } else { double time; if (new_atrack->samples_per_frame != 0) { time = mpeg3demux_length(new_atrack->demuxer); time *= new_atrack->sample_rate; time /= new_atrack->samples_per_frame; new_atrack->total_frames = (uint32_t)time; new_atrack->total_sample_offsets = new_atrack->total_frames * new_atrack->samples_per_frame; //printf("total frames %d\n", new_atrack->total_frames); } else { new_atrack->total_frames = 0; new_atrack->total_sample_offsets = 0; } } //printf("total offsets %ld\n", new_atrack->total_sample_offsets); return new_atrack;}int mpeg3_delete_atrack(mpeg3_t *file, mpeg3_atrack_t *atrack){ if(atrack->demuxer) mpeg3_delete_demuxer(atrack->demuxer); free(atrack); return 0;}static int mpeg3_atrack_check_length (unsigned char **output, uint32_t cmplen, uint32_t *maxlen){ if (cmplen > *maxlen) { *output = (unsigned char *)realloc(*output, cmplen); if (*output == NULL) return -1; *maxlen = cmplen; } return 0;} static int mpeg3_atrack_read_pcm_frame (mpeg3_atrack_t *atrack, unsigned char **output, uint32_t *len, uint32_t *maxlen){ uint16_t code; mpeg3_demuxer_t *demux; uint32_t frame_sample; int ret; demux = atrack->demuxer; code = mpeg3demux_read_char(demux); do { code <<= 8; code |= mpeg3demux_read_char(demux); } while (!mpeg3demux_eof(demux) && code != MPEG3_PCM_START_CODE); if (mpeg3demux_eof(demux)) return -1; frame_sample = (atrack->framesize - 3) / atrack->channels / 2; *len = frame_sample * atrack->channels * (sizeof(uint16_t)); if (mpeg3_atrack_check_length(output, *len, maxlen) < 0) return -1; ret = mpeg3demux_read_data(demux, *output, *len); if (ret != *len) return -1; return 0;}static int mpeg3_atrack_read_mp3_frame (mpeg3_atrack_t *atrack, unsigned char **output, uint32_t *len, uint32_t *maxlen){ uint8_t code[4]; mpeg3_demuxer_t *demux; uint32_t frame_samples; int ret; MP4AV_Mp3Header temp; int cnt = 1; demux = atrack->demuxer; code[1] = mpeg3demux_read_char(demux); do { code[0] = code[1]; code[1] = mpeg3demux_read_char(demux); cnt++; } while (!mpeg3demux_eof(demux) && (code[0] != 0xff || ((code[1] & 0xe0) != 0xe0))); if (mpeg3demux_eof(demux)) return -1; code[2] = mpeg3demux_read_char(demux); code[3] = mpeg3demux_read_char(demux); temp = MP4AV_Mp3HeaderFromBytes(code); *len = MP4AV_Mp3GetFrameSize(temp); //printf("header is %08x framesize %d\n", temp, *len); if (mpeg3_atrack_check_length(output, *len, maxlen) < 0) return -1; memcpy(*output, code, 4); ret = mpeg3demux_read_data(demux, *output + 4, *len - 4); if (ret != *len - 4) return -1; return 0;}static int mpeg3_atrack_read_aac_frame (mpeg3_atrack_t *atrack, unsigned char **output, uint32_t *len, uint32_t *maxlen){ mpeg3_demuxer_t *demux; uint16_t hdr_size, ix; uint32_t bytes; unsigned char hdr[16]; int ret; demux = atrack->demuxer; hdr[1] = mpeg3demux_read_char(demux); do { hdr[0] = hdr[1]; hdr[1] = mpeg3demux_read_char(demux); } while (((hdr[0] != 0xff) || ((hdr[1] & 0xf0) != 0xf0)) && !mpeg3demux_eof(demux)); bytes = atrack->channels * sizeof(uint16_t) * atrack->samples_per_frame; if (mpeg3demux_eof(demux)) return -1; hdr_size = MP4AV_AdtsGetHeaderByteSize(hdr); if (hdr_size > sizeof(hdr)) return -1; for (ix = 2; ix < hdr_size; ix++) { hdr[ix] = mpeg3demux_read_char(demux); } if (mpeg3demux_eof(demux)) return -1; bytes = MP4AV_AdtsGetFrameSize(hdr); *len = bytes; if (mpeg3_atrack_check_length(output, *len, maxlen) < 0) return -1; memcpy(*output, hdr, hdr_size); ret = mpeg3demux_read_data(demux, *output + hdr_size, *len - hdr_size); if (ret != *len - hdr_size) return -1; return 0;}static int mpeg3_atrack_read_ac3_frame (mpeg3_atrack_t *atrack, unsigned char **output, uint32_t *len, uint32_t *maxlen){ uint16_t code; mpeg3_demuxer_t *demux; int ret; demux = atrack->demuxer; code = mpeg3demux_read_char(demux); do { code &= 0xff; code <<= 8; code |= mpeg3demux_read_char(demux); } while (!mpeg3demux_eof(demux) && code != MPEG3_AC3_START_CODE); if (mpeg3demux_eof(demux)) return -1; *len = atrack->framesize; if (mpeg3_atrack_check_length(output, *len, maxlen) < 0) return -1; *output[0] = code >> 8; *output[1] = code & 0xff; ret = mpeg3demux_read_data(demux, *output + 2, *len - 2); if (ret != *len - 2) return -1; return 0;}int mpeg3_atrack_read_frame (mpeg3_atrack_t *atrack, unsigned char **output, uint32_t *len, uint32_t *maxlen){ if (atrack->percentage_seek >= 0) { mpeg3demux_seek_percentage(atrack->demuxer, atrack->percentage_seek); atrack->percentage_seek = -1; } switch (atrack->format) { case AUDIO_PCM: return (mpeg3_atrack_read_pcm_frame(atrack, output, len, maxlen)); case AUDIO_MPEG: return (mpeg3_atrack_read_mp3_frame(atrack, output, len, maxlen)); case AUDIO_AC3: return (mpeg3_atrack_read_ac3_frame(atrack, output, len, maxlen)); case AUDIO_AAC: return (mpeg3_atrack_read_aac_frame(atrack, output, len, maxlen)); } return -1;}int mpeg3atrack_seek_percentage(mpeg3_atrack_t *atrack, double percentage){ atrack->percentage_seek = percentage; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -