📄 demux_real.c
字号:
#ifdef MP_DEBUG#define stream_skip(st,siz) { int i; for(i=0;i<siz;i++) mp_msg(MSGT_DEMUX,MSGL_V," %02X",stream_read_char(st)); mp_msg(MSGT_DEMUX,MSGL_V,"\n");}#endif if (!strncmp(mimet,"audio/",6)) { if (strstr(mimet,"x-pn-realaudio") || strstr(mimet,"x-pn-multirate-realaudio")) { // skip unknown shit - FIXME: find a better/cleaner way! len=codec_data_size; tmp = stream_read_dword(demuxer->stream);// mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_real: type_spec: len=%d fpos=0x%X first_dword=0x%X (%.4s) \n",// (int)codec_data_size,(int)codec_pos,tmp,&tmp); while(--len>=8){ if(tmp==MKTAG(0xfd, 'a', 'r', '.')) break; // audio tmp=(tmp<<8)|stream_read_char(demuxer->stream); } if (tmp != MKTAG(0xfd, 'a', 'r', '.')) { mp_msg(MSGT_DEMUX,MSGL_V,"Audio: can't find .ra in codec data\n"); } else { /* audio header */ sh_audio_t *sh = new_sh_audio(demuxer, stream_id); char buf[128]; /* for codec name */ int frame_size; int sub_packet_size; int sub_packet_h; int version; int flavor; int coded_frame_size; int codecdata_length; int i; char *buft; int hdr_size; mp_msg(MSGT_DEMUX,MSGL_V,"Found audio stream!\n"); version = stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"version: %d\n", version);// stream_skip(demuxer->stream, 2); /* version (4 or 5) */ if (version == 3) { stream_skip(demuxer->stream, 2); stream_skip(demuxer->stream, 10); stream_skip(demuxer->stream, 4); // Name, author, (c) are also in CONT tag if ((i = stream_read_char(demuxer->stream)) != 0) { buft = malloc(i+1); stream_read(demuxer->stream, buft, i); buft[i] = 0; demux_info_add(demuxer, "Name", buft); free(buft); } if ((i = stream_read_char(demuxer->stream)) != 0) { buft = malloc(i+1); stream_read(demuxer->stream, buft, i); buft[i] = 0; demux_info_add(demuxer, "Author", buft); free(buft); } if ((i = stream_read_char(demuxer->stream)) != 0) { buft = malloc(i+1); stream_read(demuxer->stream, buft, i); buft[i] = 0; demux_info_add(demuxer, "Copyright", buft); free(buft); } if ((i = stream_read_char(demuxer->stream)) != 0) mp_msg(MSGT_DEMUX,MSGL_WARN,"Last header byte is not zero!\n"); stream_skip(demuxer->stream, 1); i = stream_read_char(demuxer->stream); sh->format = stream_read_dword_le(demuxer->stream); if (i != 4) { mp_msg(MSGT_DEMUX,MSGL_WARN,"Audio FourCC size is not 4 (%d), please report to " "MPlayer developers\n", i); stream_skip(demuxer->stream, i - 4); } if (sh->format != mmioFOURCC('l','p','c','J')) { mp_msg(MSGT_DEMUX,MSGL_WARN,"Version 3 audio with FourCC %8x, please report to " "MPlayer developers\n", sh->format); } sh->channels = 1; sh->samplesize = 16; sh->samplerate = 8000; frame_size = 240; strcpy(buf, "14_4"); } else { stream_skip(demuxer->stream, 2); // 00 00 stream_skip(demuxer->stream, 4); /* .ra4 or .ra5 */ stream_skip(demuxer->stream, 4); // ??? stream_skip(demuxer->stream, 2); /* version (4 or 5) */// stream_skip(demuxer->stream, 4); // header size == 0x4E hdr_size = stream_read_dword(demuxer->stream); // header size mp_msg(MSGT_DEMUX,MSGL_V,"header size: %d\n", hdr_size); flavor = stream_read_word(demuxer->stream);/* codec flavor id */ coded_frame_size = stream_read_dword(demuxer->stream);/* needed by codec */ //stream_skip(demuxer->stream, 4); /* coded frame size */ stream_skip(demuxer->stream, 4); // big number stream_skip(demuxer->stream, 4); // bigger number stream_skip(demuxer->stream, 4); // 2 || -''-// stream_skip(demuxer->stream, 2); // 0x10 sub_packet_h = stream_read_word(demuxer->stream);// stream_skip(demuxer->stream, 2); /* coded frame size */ frame_size = stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"frame_size: %d\n", frame_size); sub_packet_size = stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"sub_packet_size: %d\n", sub_packet_size); stream_skip(demuxer->stream, 2); // 0 if (version == 5) stream_skip(demuxer->stream, 6); //0,srate,0 sh->samplerate = stream_read_word(demuxer->stream); stream_skip(demuxer->stream, 2); // 0 sh->samplesize = stream_read_word(demuxer->stream)/8; sh->channels = stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"samplerate: %d, channels: %d\n", sh->samplerate, sh->channels); if (version == 5) { stream_skip(demuxer->stream, 4); // "genr" stream_read(demuxer->stream, buf, 4); // fourcc buf[4] = 0; } else { /* Desc #1 */ skip_str(1, demuxer); /* Desc #2 */ get_str(1, demuxer, buf, sizeof(buf)); } } /* Emulate WAVEFORMATEX struct: */ sh->wf = malloc(sizeof(WAVEFORMATEX)); memset(sh->wf, 0, sizeof(WAVEFORMATEX)); sh->wf->nChannels = sh->channels; sh->wf->wBitsPerSample = sh->samplesize*8; sh->wf->nSamplesPerSec = sh->samplerate; sh->wf->nAvgBytesPerSec = bitrate; sh->wf->nBlockAlign = frame_size; sh->wf->cbSize = 0; sh->format = MKTAG(buf[0], buf[1], buf[2], buf[3]);#if 0 switch (sh->format){ case MKTAG('d', 'n', 'e', 't'): mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET (AC3 with low-bitrate extension)\n"); break; case MKTAG('s', 'i', 'p', 'r'): mp_msg(MSGT_DEMUX,MSGL_V,"Audio: SiproLab's ACELP.net\n"); break; case MKTAG('c', 'o', 'o', 'k'): mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Real's GeneralCooker (?) (RealAudio G2?) (unsupported)\n"); break; case MKTAG('a', 't', 'r', 'c'): mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Sony ATRAC3 (RealAudio 8) (unsupported)\n"); break; default: mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%s)\n", buf); }#endif switch (sh->format) { case MKTAG('d', 'n', 'e', 't'): mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET -> AC3\n");// sh->format = 0x2000; break; case MKTAG('1', '4', '_', '4'): sh->wf->cbSize = 10; sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); ((short*)(sh->wf+1))[0]=0; ((short*)(sh->wf+1))[1]=240; ((short*)(sh->wf+1))[2]=0; ((short*)(sh->wf+1))[3]=0x14; ((short*)(sh->wf+1))[4]=0; break; case MKTAG('2', '8', '_', '8'): sh->wf->cbSize = 10; sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); ((short*)(sh->wf+1))[0]=sub_packet_size; ((short*)(sh->wf+1))[1]=sub_packet_h; ((short*)(sh->wf+1))[2]=flavor; ((short*)(sh->wf+1))[3]=coded_frame_size; ((short*)(sh->wf+1))[4]=0; break; case MKTAG('s', 'i', 'p', 'r'):#if 0 sh->format = 0x130; /* for buggy directshow loader */ sh->wf->cbSize = 4; sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); sh->wf->wBitsPerSample = 0; sh->wf->nAvgBytesPerSec = 1055; sh->wf->nBlockAlign = 19;// sh->wf->nBlockAlign = frame_size / 288; buf[0] = 30; buf[1] = 1; buf[2] = 1; buf[3] = 0; memcpy((sh->wf+18), (char *)&buf[0], 4);// sh->wf[sizeof(WAVEFORMATEX)+1] = 30;// sh->wf[sizeof(WAVEFORMATEX)+2] = 1;// sh->wf[sizeof(WAVEFORMATEX)+3] = 1;// sh->wf[sizeof(WAVEFORMATEX)+4] = 0; break;#endif case MKTAG('a', 't', 'r', 'c'):#if 0 sh->format = 0x270; /* 14 bytes extra header needed ! */ sh->wf->cbSize = 14; sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); sh->wf->nAvgBytesPerSec = 16537; // 8268 sh->wf->nBlockAlign = 384; // 192 sh->wf->wBitsPerSample = 0; /* from AVI created by VirtualDub */ break;#endif case MKTAG('c', 'o', 'o', 'k'): // realaudio codec plugins - common:// sh->wf->cbSize = 4+2+24; stream_skip(demuxer->stream,3); // Skip 3 unknown bytes if (version==5) stream_skip(demuxer->stream,1); // Skip 1 additional unknown byte codecdata_length=stream_read_dword(demuxer->stream); sh->wf->cbSize = 10+codecdata_length; sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize); ((short*)(sh->wf+1))[0]=sub_packet_size; ((short*)(sh->wf+1))[1]=sub_packet_h; ((short*)(sh->wf+1))[2]=flavor; ((short*)(sh->wf+1))[3]=coded_frame_size; ((short*)(sh->wf+1))[4]=codecdata_length;// stream_read(demuxer->stream, ((char*)(sh->wf+1))+6, 24); // extras stream_read(demuxer->stream, ((char*)(sh->wf+1))+10, codecdata_length); // extras break; case MKTAG('r', 'a', 'a', 'c'): case MKTAG('r', 'a', 'c', 'p'): /* This is just AAC. The two or five bytes of */ /* config data needed for libfaad are stored */ /* after the audio headers. */ stream_skip(demuxer->stream,3); // Skip 3 unknown bytes if (version==5) stream_skip(demuxer->stream,1); // Skip 1 additional unknown byte codecdata_length=stream_read_dword(demuxer->stream); if (codecdata_length>=1) { sh->codecdata_len = codecdata_length - 1; sh->codecdata = calloc(sh->codecdata_len, 1); stream_skip(demuxer->stream, 1); stream_read(demuxer->stream, sh->codecdata, sh->codecdata_len); } sh->format = mmioFOURCC('M', 'P', '4', 'A'); break; default: mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%s)\n", buf); } sh->wf->wFormatTag = sh->format; if (verbose > 0) print_wave_header(sh->wf); /* Select audio stream with highest bitrate if multirate file*/ if (priv->is_multirate && ((demuxer->audio->id == -1) || ((demuxer->audio->id >= 0) && priv->a_bitrate && (bitrate > priv->a_bitrate)))) { demuxer->audio->id = stream_id; priv->a_bitrate = bitrate; mp_msg(MSGT_DEMUX,MSGL_DBG2,"Multirate autoselected audio id %d with bitrate %d\n", stream_id, bitrate); } if(demuxer->audio->id==stream_id){ demuxer->audio->id=stream_id; sh->ds=demuxer->audio; demuxer->audio->sh=sh; } ++a_streams;#ifdef stream_skip#undef stream_skip#endif } } else if (strstr(mimet,"X-MP3-draft-00")) { sh_audio_t *sh = new_sh_audio(demuxer, stream_id); /* Emulate WAVEFORMATEX struct: */ sh->wf = malloc(sizeof(WAVEFORMATEX)); memset(sh->wf, 0, sizeof(WAVEFORMATEX)); sh->wf->nChannels = 0;//sh->channels; sh->wf->wBitsPerSample = 16; sh->wf->nSamplesPerSec = 0;//sh->samplerate; sh->wf->nAvgBytesPerSec = 0;//bitrate; sh->wf->nBlockAlign = 0;//frame_size; sh->wf->cbSize = 0; sh->wf->wFormatTag = sh->format = mmioFOURCC('a','d','u',0x55); if(demuxer->audio->id==stream_id){ sh->ds=demuxer->audio; demuxer->audio->sh=sh; } ++a_streams; } else if (strstr(mimet,"x-ralf-mpeg4")) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Real lossless audio not supported yet\n"); } else { mp_msg(MSGT_DEMUX,MSGL_V,"Unknown audio stream format\n"); } } else if (!strncmp(mimet,"video/",6)) { if (strstr(mimet,"x-pn-realvideo") || strstr(mimet,"x-pn-multirate-realvideo")) { tmp = stream_read_dword(demuxer->stream);// mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_real: type_spec: len=%d fpos=0x%X first_dword=0x%X (%.4s) \n",// (int)codec_data_size,(int)codec_pos,tmp,&tmp); // skip unknown shit - FIXME: find a better/cleaner way! len=codec_data_size; while(--len>=8){ if(tmp==MKTAG('O', 'D', 'I', 'V')) break; // video tmp=(tmp<<8)|stream_read_char(demuxer->stream); } if(tmp != MKTAG('O', 'D', 'I', 'V')) { mp_msg(MSGT_DEMUX,MSGL_V,"Video: can't find VIDO in codec data\n"); } else { /* video header */ sh_video_t *sh = new_sh_video(demuxer, stream_id); sh->format = stream_read_dword_le(demuxer->stream); /* fourcc */ mp_msg(MSGT_DEMUX,MSGL_V,"video fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format); /* emulate BITMAPINFOHEADER */ sh->bih = malloc(sizeof(BITMAPINFOHEADER)+16); memset(sh->bih, 0, sizeof(BITMAPINFOHEADER)+16); sh->bih->biSize = 48; sh->disp_w = sh->bih->biWidth = stream_read_word(demuxer->stream); sh->disp_h = sh->bih->biHeight = stream_read_word(demuxer->stream); sh->bih->biPlanes = 1; sh->bih->biBitCount = 24; sh->bih->biCompression = sh->format; sh->bih->biSizeImage= sh->bih->biWidth*sh->bih->biHeight*3; sh->fps = (float) stream_read_word(demuxer->stream); if (sh->fps<=0) sh->fps=24; // we probably won't even care about fps sh->frametime = 1.0f/sh->fps; #if 1 stream_skip(demuxer->stream, 4);#else mp_msg(MSGT_DEMUX, MSGL_V,"unknown1: 0x%X \n",stream_read_dword(demuxer->stream)); mp_msg(MSGT_DEMUX, MSGL_V,"unknown2: 0x%X \n",stream_read_word(demuxer->stream)); mp_msg(MSGT_DEMUX, MSGL_V,"unknown3: 0x%X \n",stream_read_word(demuxer->stream));#endif// if(sh->format==0x30335652 || sh->format==0x30325652 ) if(1) { int tmp=stream_read_word(demuxer->stream); if(tmp>0){ sh->fps=tmp; sh->frametime = 1.0f/sh->fps; } } else { int fps=stream_read_word(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_WARN,"realvid: ignoring FPS = %d\n",fps); } stream_skip(demuxer->stream, 2); // read codec sub-format (to make difference between low and high rate codec) ((unsigned int*)(sh->bih+1))[0]=stream_read_dword(demuxer->stream); /* h263 hack */ tmp = stream_read_dword(demuxer->stream); ((unsigned int*)(sh->bih+1))[1]=tmp; mp_msg(MSGT_DEMUX,MSGL_V,"H.263 ID: %x\n", tmp); switch (tmp) { case 0x10000000: /* sub id: 0 */ /* codec id: rv10 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -