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:
nicodvb 2005-05-12 17:35:58 +00:00
parent 4515c02ea4
commit 3d450d0389
3 changed files with 146 additions and 69 deletions

View File

@ -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);

View File

@ -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))

View File

@ -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: