demux_audio.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 796 行 · 第 1/2 页

C
796
字号
     //F("mp3_totaltime = %d count = %d\n",(unsigned int)(mp3_totaltime *1000.0),dcount);     //F("s->eof = %d\n",s->eof);    free(mp3_found);    mp3_found = NULL;    //F("BBBBB\n");    if(s->end_pos) {      char tag[4];    //F("AAAAAAAA\n");      stream_seek(s,s->end_pos-128);      stream_read(s,tag,3);      tag[3] = '\0';      if(strcmp(tag,"TAG"))	{		demuxer->movi_end = s->end_pos;		   }   else {	char buf[31];	uint8_t g;	demuxer->movi_end = stream_tell(s)-3;//	F("demuxer->movi_end = %d demuxer->movi_start = %d sh_audio->i_bps = %d\n",demuxer->movi_end,demuxer->movi_start,sh_audio->i_bps);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Title",buf);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Artist",buf);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Album",buf);	stream_read(s,buf,4);	buf[4] = '\0';	demux_info_add(demuxer,"Year",buf);	stream_read(s,buf,30);	buf[30] = '\0';	demux_info_add(demuxer,"Comment",buf);	if(buf[28] == 0 && buf[29] != 0) {	  uint8_t trk = (uint8_t)buf[29];	  sprintf(buf,"%d",trk);	  demux_info_add(demuxer,"Track",buf);	}	g = stream_read_char(s);	demux_info_add(demuxer,"Genre",genres[g]);      }    }    break;  case WAV: {    unsigned int chunk_type;    unsigned int chunk_size;    WAVEFORMATEX* w;    int l;    l = stream_read_dword_le(s);    if(l < 16) {      mp_msg(MSGT_DEMUX,MSGL_ERR,"[demux_audio] Bad wav header length: too short (%d)!!!\n",l);      l = 16;    }    if(l > MAX_WAVHDR_LEN) {      mp_msg(MSGT_DEMUX,MSGL_ERR,"[demux_audio] Bad wav header length: too long (%d)!!!\n",l);      l = 16;    }    sh_audio->wf = w = malloc(l > sizeof(WAVEFORMATEX) ? l : sizeof(WAVEFORMATEX));    w->wFormatTag = sh_audio->format = stream_read_word_le(s);    w->nChannels = sh_audio->channels = stream_read_word_le(s);    w->nSamplesPerSec = sh_audio->samplerate = stream_read_dword_le(s);    w->nAvgBytesPerSec = stream_read_dword_le(s);    w->nBlockAlign = stream_read_word_le(s);    w->wBitsPerSample = stream_read_word_le(s);    sh_audio->samplesize = (w->wBitsPerSample + 7) / 8;    w->cbSize = 0;    sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;    l -= 16;    if (l > 0) {    w->cbSize = stream_read_word_le(s);    l -= 2;     if (w->cbSize > 0) {      if (l < w->cbSize) {        mp_msg(MSGT_DEMUX,MSGL_ERR,"[demux_audio] truncated extradata (%d < %d)\n",	l,w->cbSize);        stream_read(s,(char*)((char*)(w)+sizeof(WAVEFORMATEX)),l);        l = 0;      } else {        stream_read(s,(char*)((char*)(w)+sizeof(WAVEFORMATEX)),w->cbSize);        l -= w->cbSize;      }     }    }    if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_wave_header(w, MSGL_V);    if(l)      stream_skip(s,l);    do    {      chunk_type = stream_read_fourcc(demuxer->stream);      chunk_size = stream_read_dword_le(demuxer->stream);      if (chunk_type != mmioFOURCC('d', 'a', 't', 'a'))        stream_skip(demuxer->stream, chunk_size);    } while (!s->eof && chunk_type != mmioFOURCC('d', 'a', 't', 'a'));    demuxer->movi_start = stream_tell(s);    demuxer->movi_end = chunk_size ? demuxer->movi_start + chunk_size : s->end_pos;//    printf("wav: %X .. %X\n",(int)demuxer->movi_start,(int)demuxer->movi_end);    // Check if it contains dts audio    if((w->wFormatTag == 0x01) && (w->nChannels == 2) && (w->nSamplesPerSec == 44100)) {	unsigned char buf[16384]; // vlc uses 16384*4 (4 dts frames)	unsigned int i;	stream_read(s, buf, sizeof(buf));	for (i = 0; i < sizeof(buf) - 5; i += 2) {	    // DTS, 14 bit, LE	    if((buf[i] == 0xff) && (buf[i+1] == 0x1f) && (buf[i+2] == 0x00) &&	       (buf[i+3] == 0xe8) && ((buf[i+4] & 0xfe) == 0xf0) && (buf[i+5] == 0x07)) {		sh_audio->format = 0x2001;		mp_msg(MSGT_DEMUX,MSGL_V,"[demux_audio] DTS audio in wav, 14 bit, LE\n");		break;	    }	    // DTS, 14 bit, BE	    if((buf[i] == 0x1f) && (buf[i+1] == 0xff) && (buf[i+2] == 0xe8) &&	       (buf[i+3] == 0x00) && (buf[i+4] == 0x07) && ((buf[i+5] & 0xfe) == 0xf0)) {		sh_audio->format = 0x2001;		mp_msg(MSGT_DEMUX,MSGL_V,"[demux_audio] DTS audio in wav, 14 bit, BE\n");		break;	    }	    // DTS, 16 bit, BE	    if((buf[i] == 0x7f) && (buf[i+1] == 0xfe) && (buf[i+2] == 0x80) &&	       (buf[i+3] == 0x01)) {		sh_audio->format = 0x2001;		mp_msg(MSGT_DEMUX,MSGL_V,"[demux_audio] DTS audio in wav, 16 bit, BE\n");		break;	    }	    // DTS, 16 bit, LE	    if((buf[i] == 0xfe) && (buf[i+1] == 0x7f) && (buf[i+2] == 0x01) &&	       (buf[i+3] == 0x80)) {		sh_audio->format = 0x2001;		mp_msg(MSGT_DEMUX,MSGL_V,"[demux_audio] DTS audio in wav, 16 bit, LE\n");		break;	    }	}	if (sh_audio->format == 0x2001)	    mp_msg(MSGT_DEMUX,MSGL_DBG2,"[demux_audio] DTS sync offset = %u\n", i);    }    stream_seek(s,demuxer->movi_start);  } break;  case fLaC:	    sh_audio->format = mmioFOURCC('f', 'L', 'a', 'C');	    demuxer->movi_start = stream_tell(s) - 4;	    demuxer->movi_end = s->end_pos;	    if (demuxer->movi_end > demuxer->movi_start) {	      // try to find out approx. bitrate	      int64_t size = demuxer->movi_end - demuxer->movi_start;	      int64_t num_samples = 0;	      int32_t srate = 0;	      stream_skip(s, 14);	      stream_read(s, (char *)&srate, 3);	      srate = be2me_32(srate) >> 12;	      stream_read(s, (char *)&num_samples, 5);	      num_samples = (be2me_64(num_samples) >> 24) & 0xfffffffffULL;	      if (num_samples && srate)	        sh_audio->i_bps = size * srate / num_samples;	    }	    if (sh_audio->i_bps < 1) // guess value to prevent crash	      sh_audio->i_bps = 64 * 1024;	    get_flac_metadata (demuxer);	    break;  }  priv = malloc(sizeof(da_priv_t));  priv->frmt = frmt;  priv->next_pts = 0;  demuxer->priv = priv;  demuxer->audio->id = 0;  demuxer->audio->sh = sh_audio;  sh_audio->ds = demuxer->audio;  sh_audio->samplerate = sh_audio->audio.dwRate;  if(stream_tell(s) != demuxer->movi_start)  {    mp_msg(MSGT_DEMUX, MSGL_V, "demux_audio: seeking from 0x%X to start pos 0x%X\n",            (int)stream_tell(s), (int)demuxer->movi_start);    stream_seek(s,demuxer->movi_start);    if (stream_tell(s) != demuxer->movi_start) {      mp_msg(MSGT_DEMUX, MSGL_V, "demux_audio: seeking failed, now at 0x%X!\n",              (int)stream_tell(s));      if (next_frame_pos) {        mp_msg(MSGT_DEMUX, MSGL_V, "demux_audio: seeking to 0x%X instead\n",                (int)next_frame_pos);        stream_seek(s, next_frame_pos);      }    }  }  mp_msg(MSGT_DEMUX,MSGL_V,"demux_audio: audio data 0x%X - 0x%X  \n",(int)demuxer->movi_start,(int)demuxer->movi_end);  return DEMUXER_TYPE_AUDIO;}static int demux_audio_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) {  int l;  demux_packet_t* dp;  sh_audio_t* sh_audio = ds->sh;  demuxer_t* demux = ds->demuxer;  da_priv_t* priv = demux->priv;  double this_pts = priv->next_pts;  stream_t* s = demux->stream;	int mp3_freq, mp3_chans, mp3_flen, mpa_layer, mpa_spf, mpa_br;  if(s->eof)    return 0;  switch(priv->frmt) {  case MP3 :        while(1) {      uint8_t hdr[4];      stream_read(s,hdr,4);      if (s->eof)        return 0;            l = mp_get_mp3_header(hdr, &mp3_chans, &mp3_freq,                                &mpa_spf, &mpa_layer, &mpa_br);                                    //l = mp_decode_mp3_header(hdr);      if(l < 0) {	if (demux->movi_end && stream_tell(s) >= demux->movi_end)	  return 0; // might be ID3 tag, i.e. EOF	stream_skip(s,-3);      } else {	dp = new_demux_packet(l);	memcpy(dp->buffer,hdr,4);	if (stream_read(s,dp->buffer + 4,l-4) != l-4)	{	  free_demux_packet(dp);	  return 0;	}	//priv->next_pts += sh_audio->audio.dwScale/(double)sh_audio->samplerate;	priv->next_pts += (double)mpa_spf / (double)mp3_freq;			break;      }    } break;  case WAV : {    unsigned align = sh_audio->wf->nBlockAlign;    l = sh_audio->wf->nAvgBytesPerSec;    if (demux->movi_end && l > demux->movi_end - stream_tell(s)) {      // do not read beyond end, there might be junk after data chunk      l = demux->movi_end - stream_tell(s);      if (l <= 0) return 0;    }    if (align)      l = (l + align - 1) / align * align;    dp = new_demux_packet(l);    l = stream_read(s,dp->buffer,l);    priv->next_pts += l/(double)sh_audio->i_bps;    break;  }  case fLaC: {    l = 65535;    dp = new_demux_packet(l);    l = stream_read(s,dp->buffer,l);    /* FLAC is not a constant-bitrate codec. These values will be wrong. */    priv->next_pts += l/(double)sh_audio->i_bps;    break;  }  default:    mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_MPDEMUX_AUDIO_UnknownFormat,priv->frmt);    return 0;  }  resize_demux_packet(dp, l);  dp->pts = this_pts;  sh_audio->pts = this_pts;	ds_add_packet(ds, dp);  return 1;}static void high_res_mp3_seek(demuxer_t *demuxer,float time) {  uint8_t hdr[4];  int len,nf;  da_priv_t* priv = demuxer->priv;  sh_audio_t* sh = (sh_audio_t*)demuxer->audio->sh;  int mp3_freq, mp3_chans, mp3_flen, mpa_layer, mpa_spf, mpa_br;    nf = time*sh->samplerate/sh->audio.dwScale;  while(nf > 0) {    stream_read(demuxer->stream,hdr,4);    len =  mp_get_mp3_header(hdr, &mp3_chans, &mp3_freq,                                &mpa_spf, &mpa_layer, &mpa_br);    if(len < 0) {      stream_skip(demuxer->stream,-3);      continue;    }    stream_skip(demuxer->stream,len-4);    priv->next_pts += (double)mpa_spf / (double)mp3_freq;    nf--;  }  sh->pts = priv->next_pts; }static void demux_audio_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){  sh_audio_t* sh_audio;  stream_t* s;  int base,pos;  float len;  da_priv_t* priv;  if(!(sh_audio = demuxer->audio->sh))    return;  s = demuxer->stream;  priv = demuxer->priv;  if(priv->frmt == MP3 && hr_mp3_seek && !(flags & 2)) {    len = (flags & 1) ? rel_seek_secs - priv->next_pts : rel_seek_secs;    if(len < 0) {      stream_seek(s,demuxer->movi_start);      len = priv->next_pts + len;      priv->next_pts = 0;    }    if(len > 0)      high_res_mp3_seek(demuxer,len);    return;  }  base = flags&1 ? demuxer->movi_start : stream_tell(s);  if(flags&2)    pos = base + ((demuxer->movi_end - demuxer->movi_start)*rel_seek_secs);  else    pos = base + (rel_seek_secs*sh_audio->i_bps);  if(demuxer->movi_end && pos >= demuxer->movi_end) {     pos = demuxer->movi_end;  } else if(pos < demuxer->movi_start)    pos = demuxer->movi_start;  priv->next_pts = (pos-demuxer->movi_start)/(double)sh_audio->i_bps;    switch(priv->frmt) {  case WAV:    pos -= (pos - demuxer->movi_start) %            (sh_audio->wf->nBlockAlign ? sh_audio->wf->nBlockAlign :             (sh_audio->channels * sh_audio->samplesize));    break;  }  stream_seek(s,pos);}static void demux_close_audio(demuxer_t* demuxer) {  da_priv_t* priv = demuxer->priv;  if(!priv)    return;  free(priv);  mp3_totaltime = 0;}static int demux_audio_control(demuxer_t *demuxer,int cmd, void *arg){    sh_audio_t *sh_audio=demuxer->audio->sh;    //int audio_length = demuxer->movi_end / sh_audio->i_bps;        float audio_length;    if(mp3_totaltime > 0)    	audio_length = mp3_totaltime;    else	    	audio_length = (float)(demuxer->movi_end - demuxer->movi_start)/ sh_audio->i_bps;  	    da_priv_t* priv = demuxer->priv;	        switch(cmd) {	case DEMUXER_CTRL_GET_TIME_LENGTH:	    if (audio_length<=0) return DEMUXER_CTRL_DONTKNOW;	    *((double *)arg)=(double)audio_length;	    return DEMUXER_CTRL_GUESS;	case DEMUXER_CTRL_GET_PERCENT_POS:	    if (audio_length<=0)     		return DEMUXER_CTRL_DONTKNOW;    	    *((int *)arg)=(int)( (priv->next_pts*100)  / audio_length);	    return DEMUXER_CTRL_OK;	default:	    return DEMUXER_CTRL_NOTIMPL;    }}demuxer_desc_t demuxer_desc_audio = {  "Audio demuxer",  "audio",  "Audio file",  "?",  "Audio only files",  DEMUXER_TYPE_AUDIO,  0, // unsafe autodetect  demux_audio_open,  demux_audio_fill_buffer,  NULL,  demux_close_audio,  demux_audio_seek,  demux_audio_control};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?