mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 04:36:24 +01:00
vorbis extradata is now passed from demuxer to decoder in matroska's way
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@15421 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
4515c02ea4
commit
3d450d0389
@ -60,6 +60,8 @@ static int preinit(sh_audio_t *sh)
|
||||
|
||||
static int init(sh_audio_t *sh)
|
||||
{
|
||||
unsigned int offset, i, length, hsizes[3], *headers[3];
|
||||
unsigned char* extradata;
|
||||
ogg_packet op;
|
||||
vorbis_comment vc;
|
||||
struct ov_struct_st *ov;
|
||||
@ -69,31 +71,66 @@ static int init(sh_audio_t *sh)
|
||||
free(ov); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
if(! sh->wf) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent! exit\n");
|
||||
ERROR();
|
||||
}
|
||||
|
||||
if(! sh->wf->cbSize) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent!, exit\n");
|
||||
ERROR();
|
||||
}
|
||||
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_V,"ad_vorbis, extradata seems is %d bytes long\n", sh->wf->cbSize);
|
||||
extradata = (char*) (sh->wf+1);
|
||||
if(!extradata) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be NULL!, exit\n");
|
||||
ERROR();
|
||||
}
|
||||
|
||||
if(*extradata != 2) {
|
||||
mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
|
||||
ERROR();
|
||||
}
|
||||
|
||||
offset = 1;
|
||||
for (i=0; i < 2; i++) {
|
||||
length = 0;
|
||||
while ((extradata[offset] == (unsigned char) 0xFF) && length < sh->wf->cbSize) {
|
||||
length += 255;
|
||||
offset++;
|
||||
}
|
||||
if(offset >= (sh->wf->cbSize - 1)) {
|
||||
mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
|
||||
ERROR();
|
||||
}
|
||||
length += extradata[offset];
|
||||
offset++;
|
||||
mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, offset: %u, length: %u\n", offset, length);
|
||||
hsizes[i] = length;
|
||||
}
|
||||
|
||||
headers[0] = &extradata[offset];
|
||||
headers[1] = &extradata[offset + hsizes[0]];
|
||||
headers[2] = &extradata[offset + hsizes[0] + hsizes[1]];
|
||||
hsizes[2] = sh->wf->cbSize - offset - hsizes[0] - hsizes[1];
|
||||
mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, header sizes: %d %d %d\n", hsizes[0], hsizes[1], hsizes[2]);
|
||||
|
||||
/// Init the decoder with the 3 header packets
|
||||
ov = (struct ov_struct_st*)malloc(sizeof(struct ov_struct_st));
|
||||
vorbis_info_init(&ov->vi);
|
||||
vorbis_comment_init(&vc);
|
||||
op.bytes = ds_get_packet(sh->ds,&op.packet);
|
||||
op.b_o_s = 1;
|
||||
/// Header
|
||||
if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: initial (identification) header broken!\n");
|
||||
ERROR();
|
||||
}
|
||||
op.bytes = ds_get_packet(sh->ds,&op.packet);
|
||||
op.b_o_s = 0;
|
||||
/// Comments
|
||||
if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: comment header broken!\n");
|
||||
ERROR();
|
||||
}
|
||||
op.bytes = ds_get_packet(sh->ds,&op.packet);
|
||||
//// Codebook
|
||||
if(vorbis_synthesis_headerin(&ov->vi,&vc,&op)<0) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n");
|
||||
ERROR();
|
||||
} else { /// Print the infos
|
||||
float rg_gain=0.f, rg_peak=0.f;
|
||||
for(i=0; i<3; i++) {
|
||||
op.bytes = hsizes[i];
|
||||
op.packet = headers[i];
|
||||
op.b_o_s = (i == 0);
|
||||
if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: header n. %d broken! len=%d\n", i, op.bytes);
|
||||
ERROR();
|
||||
}
|
||||
if(i == 2) {
|
||||
float rg_gain=0.f, rg_peak=0.f;
|
||||
char **ptr=vc.user_comments;
|
||||
while(*ptr){
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);
|
||||
@ -130,7 +167,9 @@ static int init(sh_audio_t *sh)
|
||||
if(rg_gain || rg_peak)
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain, rg_peak, ov->rg_scale);
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);
|
||||
}
|
||||
}
|
||||
|
||||
vorbis_comment_clear(&vc);
|
||||
|
||||
// printf("lower=%d upper=%d \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);
|
||||
|
@ -1781,48 +1781,8 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track)
|
||||
track->a_formattag = mmioFOURCC('M', 'P', '4', 'A');
|
||||
else if (!strcmp(track->codec_id, MKV_A_VORBIS))
|
||||
{
|
||||
unsigned char *c;
|
||||
uint32_t offset, length;
|
||||
|
||||
if (track->private_data == NULL)
|
||||
return 1;
|
||||
|
||||
c = (unsigned char *) track->private_data;
|
||||
if (*c != 2)
|
||||
{
|
||||
mp_msg (MSGT_DEMUX, MSGL_WARN, "[mkv] Vorbis track does not "
|
||||
"contain valid headers.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
offset = 1;
|
||||
for (i=0; i < 2; i++)
|
||||
{
|
||||
length = 0;
|
||||
while (c[offset] == (unsigned char) 0xFF
|
||||
&& length < track->private_size)
|
||||
{
|
||||
length += 255;
|
||||
offset++;
|
||||
}
|
||||
if (offset >= (track->private_size - 1))
|
||||
{
|
||||
mp_msg (MSGT_DEMUX, MSGL_WARN, "[mkv] Vorbis track "
|
||||
"does not contain valid headers.\n");
|
||||
return 1;
|
||||
}
|
||||
length += c[offset];
|
||||
offset++;
|
||||
track->header_sizes[i] = length;
|
||||
}
|
||||
|
||||
track->headers[0] = &c[offset];
|
||||
track->headers[1] = &c[offset + track->header_sizes[0]];
|
||||
track->headers[2] = &c[offset + track->header_sizes[0] +
|
||||
track->header_sizes[1]];
|
||||
track->header_sizes[2] = track->private_size - offset
|
||||
- track->header_sizes[0] - track->header_sizes[1];
|
||||
|
||||
track->a_formattag = mmioFOURCC('v', 'r', 'b', 's');
|
||||
}
|
||||
else if (!strcmp(track->codec_id, MKV_A_QDMC))
|
||||
@ -1954,14 +1914,9 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track)
|
||||
}
|
||||
else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) /* VORBIS */
|
||||
{
|
||||
for (i=0; i < 3; i++)
|
||||
{
|
||||
dp = new_demux_packet (track->header_sizes[i]);
|
||||
memcpy (dp->buffer,track->headers[i],track->header_sizes[i]);
|
||||
dp->pts = 0;
|
||||
dp->flags = 0;
|
||||
ds_add_packet (demuxer->audio, dp);
|
||||
}
|
||||
sh_a->wf->cbSize = track->private_size;
|
||||
sh_a->wf = (WAVEFORMATEX*)realloc(sh_a->wf, sizeof(WAVEFORMATEX) + sh_a->wf->cbSize);
|
||||
memcpy((unsigned char *) (sh_a->wf+1), track->private_data, sh_a->wf->cbSize);
|
||||
}
|
||||
else if (track->private_size >= sizeof(real_audio_v4_props_t)
|
||||
&& !strncmp (track->codec_id, MKV_A_REALATRC, 7))
|
||||
|
@ -736,6 +736,86 @@ char *demux_ogg_sub_lang(demuxer_t *demuxer, int index) {
|
||||
|
||||
void demux_close_ogg(demuxer_t* demuxer);
|
||||
|
||||
static inline unsigned int store_ughvlc(unsigned char *s, unsigned int v)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
while(v >= 0xff)
|
||||
{
|
||||
*s++ = 0xff;
|
||||
v -= 0xff;
|
||||
n++;
|
||||
}
|
||||
*s = v;
|
||||
n++;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void fixup_vorbis_wf(sh_audio_t *sh)
|
||||
{
|
||||
int i, k, offset;
|
||||
ogg_packet op[3];
|
||||
unsigned char *buf[3];
|
||||
unsigned char *ptr;
|
||||
|
||||
for(i = 0; i < 3; i++) {
|
||||
op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
|
||||
mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%d\n", i, op[i].bytes);
|
||||
if(op[i].bytes < 0) {
|
||||
mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
|
||||
return;
|
||||
}
|
||||
buf[i] = malloc(op[i].bytes);
|
||||
if(!buf[i])
|
||||
return;
|
||||
memcpy(buf[i], op[i].packet, op[i].bytes);
|
||||
}
|
||||
|
||||
sh->wf = (WAVEFORMATEX*)calloc(1, sizeof(WAVEFORMATEX) + op[0].bytes + op[1].bytes + op[2].bytes + 64);
|
||||
ptr = (unsigned char*) (sh->wf+1);
|
||||
|
||||
ptr[0] = 2;
|
||||
offset = 1;
|
||||
offset += store_ughvlc(&ptr[offset], op[0].bytes);
|
||||
mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %d\n", offset);
|
||||
offset += store_ughvlc(&ptr[offset], op[1].bytes);
|
||||
mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %d\n", offset);
|
||||
for(i = 0; i < 3; i++) {
|
||||
mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d\n", op[i].bytes, offset, i);
|
||||
memcpy(&ptr[offset], buf[i], op[i].bytes);
|
||||
offset += op[i].bytes;
|
||||
}
|
||||
sh->wf->cbSize = offset;
|
||||
mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
|
||||
sh->wf = (WAVEFORMATEX*)realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
|
||||
|
||||
if(op[0].bytes >= 29) {
|
||||
unsigned int br, nombr, minbr, maxbr;
|
||||
ptr = buf[0];
|
||||
sh->channels = ptr[11];
|
||||
sh->samplerate = sh->wf->nSamplesPerSec = get_uint32(&ptr[12]);
|
||||
maxbr = get_uint32(&ptr[16]); //max
|
||||
nombr = get_uint32(&ptr[20]); //nominal
|
||||
minbr = get_uint32(&ptr[24]); //minimum
|
||||
br = maxbr / 8;
|
||||
if(!br)
|
||||
br = nombr / 8;
|
||||
if(!br)
|
||||
br = minbr / 8;
|
||||
sh->wf->nAvgBytesPerSec = br;
|
||||
sh->wf->wBitsPerSample = 16;
|
||||
sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
|
||||
|
||||
mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
|
||||
sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
|
||||
}
|
||||
free(buf[2]);
|
||||
free(buf[1]);
|
||||
free(buf[0]);
|
||||
}
|
||||
|
||||
|
||||
/// Open an ogg physical stream
|
||||
int demux_ogg_open(demuxer_t* demuxer) {
|
||||
ogg_demuxer_t* ogg_d;
|
||||
@ -1107,6 +1187,9 @@ int demux_ogg_open(demuxer_t* demuxer) {
|
||||
|
||||
mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":"");
|
||||
|
||||
if(sh_a->format == FOURCC_VORBIS)
|
||||
fixup_vorbis_wf(sh_a);
|
||||
|
||||
return 1;
|
||||
|
||||
err_out:
|
||||
|
Loading…
Reference in New Issue
Block a user