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 + -
显示快捷键?