demux_real.c

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

C
1,820
字号
            (priv->intl_id[stream_id] == mmioFOURCC('g', 'e', 'n', 'r')) ||            (priv->intl_id[stream_id] == mmioFOURCC('s', 'i', 'p', 'r'))) {            sps = priv->sub_packet_size[stream_id];            sph = priv->sub_packet_h[stream_id];            cfs = priv->coded_framesize[stream_id];            w = priv->audiopk_size[stream_id];            spc = priv->sub_packet_cnt;            switch (priv->intl_id[stream_id]) {                case mmioFOURCC('I', 'n', 't', '4'):                    if (len < cfs * sph/2)                        goto discard;                    for (x = 0; x < sph / 2; x++)                        stream_read(demuxer->stream, priv->audio_buf + x * 2 * w + spc * cfs, cfs);                    break;                case mmioFOURCC('g', 'e', 'n', 'r'):                    if (len < w)                        goto discard;                    for (x = 0; x < w / sps; x++)                        stream_read(demuxer->stream, priv->audio_buf + sps * (sph * x + ((sph + 1) / 2) * (spc & 1) +                                    (spc >> 1)), sps);                    break;                case mmioFOURCC('s', 'i', 'p', 'r'):                    if (len < w)                        goto discard;                    stream_read(demuxer->stream, priv->audio_buf + spc * w, w);                    if (spc == sph - 1) {                        int n;                        int bs = sph * w * 2 / 96;  // nibbles per subpacket                        // Perform reordering                        for(n=0; n < 38; n++) {                            int j;                            int i = bs * sipr_swaps[n][0];                            int o = bs * sipr_swaps[n][1];                            // swap nibbles of block 'i' with 'o'      TODO: optimize                            for(j = 0;j < bs; j++) {                                int x = (i & 1) ? (priv->audio_buf[i >> 1] >> 4) : (priv->audio_buf[i >> 1] & 0x0F);                                int y = (o & 1) ? (priv->audio_buf[o >> 1] >> 4) : (priv->audio_buf[o >> 1] & 0x0F);                                if(o & 1)                                    priv->audio_buf[o >> 1] = (priv->audio_buf[o >> 1] & 0x0F) | (x << 4);                                else                                    priv->audio_buf[o >> 1] = (priv->audio_buf[o >> 1] & 0xF0) | x;                                if(i & 1)                                    priv->audio_buf[i >> 1] = (priv->audio_buf[i >> 1] & 0x0F) | (y << 4);                                else                                    priv->audio_buf[i >> 1] = (priv->audio_buf[i >> 1] & 0xF0) | y;                                ++i; ++o;                            }                        }                    }                    break;            }            priv->audio_need_keyframe = 0;            //(user_correct_pts > 0 ? MP_NOPTS_VALUE : 0)            priv->audio_timestamp[priv->sub_packet_cnt] = (priv->a_pts==timestamp) ? 0 : (timestamp/1000.0);            priv->a_pts = timestamp;            if (priv->sub_packet_cnt == 0)                priv->audio_filepos = demuxer->filepos;            if (++(priv->sub_packet_cnt) < sph)                audioreorder_getnextpk = 1;            else {                int apk_usize = ((WAVEFORMATEX*)((sh_audio_t*)ds->sh)->wf)->nBlockAlign;                audioreorder_getnextpk = 0;                priv->sub_packet_cnt = 0;                // Release all the audio packets                for (x = 0; x < sph*w/apk_usize; x++) {                    dp = new_demux_packet(apk_usize);                    memcpy(dp->buffer, priv->audio_buf + x * apk_usize, apk_usize);                    /* Put timestamp only on packets that correspond to original audio packets in file */		    if (x * apk_usize % w == 0)			dp->pts = priv->audio_timestamp[x * apk_usize / w];                    dp->pos = priv->audio_filepos; // all equal                    dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe                    ds_add_packet(ds, dp);                }            }        } else { // No interleaving            dp = new_demux_packet(len);            stream_read(demuxer->stream, dp->buffer, len);#ifdef CRACK_MATRIX	    mp_msg(MSGT_DEMUX, MSGL_V,"*** audio block len=%d\n",len);	    { // HACK - used for reverse engineering the descrambling matrix		FILE* f=fopen("test.rm","r+");		fseek(f,spos,SEEK_SET);		++cnt;//		    for(i=0;i<len;i++) dp->buffer[i]=i/0x12;//		    for(i=0;i<len;i++) dp->buffer[i]=i;//		    for(i=0;i<len;i++) dp->buffer[i]=cnt;//		    for(i=0;i<len;i++) dp->buffer[i]=cnt<<4;		    for(i=0;i<len;i++) dp->buffer[i]=(i==cnt2) ? (cnt+16*(8+cnt)) : 0;		if(cnt==6){ cnt=0; ++cnt2; }		fwrite(dp->buffer, len, 1, f);		fclose(f);		if(cnt2>0x150) *((int*)NULL)=1; // sig11 :)	    }#endif#if 0	    if( ((sh_audio_t *)ds->sh)->format == 0x2000) {		// if DNET, swap bytes, as DNET is byte-swapped AC3:		char *ptr = dp->buffer;		int i;		for (i = 0; i < len; i += 2)		{		    const char tmp = ptr[0];		    ptr[0] = ptr[1];		    ptr[1] = tmp;		    ptr += 2;		}	    }#endif	    if (priv->audio_need_keyframe == 1) {		priv->audio_need_keyframe = 0;	    } else if(priv->a_pts != timestamp)	        dp->pts = timestamp/1000.0;	    priv->a_pts=timestamp;	    dp->pos = demuxer->filepos;	    dp->flags = (flags & 0x2) ? 0x10 : 0;	    ds_add_packet(ds, dp);        } // codec_id check, codec default case	}// we will not use audio index if we use -idx and have a video	if(!demuxer->video->sh && index_mode == 2 && (unsigned)demuxer->audio->id < MAX_STREAMS)		while (priv->current_apacket + 1 < priv->index_table_size[demuxer->audio->id] &&		       timestamp > priv->index_table[demuxer->audio->id][priv->current_apacket].timestamp)			priv->current_apacket += 1;		if(priv->is_multirate)		while (priv->a_idx_ptr + 1 < priv->index_table_size[demuxer->audio->id] &&		       timestamp > priv->index_table[demuxer->audio->id][priv->a_idx_ptr + 1].timestamp) {			priv->a_idx_ptr++;			priv->audio_curpos = stream_tell(demuxer->stream);			priv->stream_switch = 1;		}    // If we're reordering audio packets and we need more data get it    if (audioreorder_getnextpk)        continue;		return 1;    } 	  if(demuxer->video->id==stream_id){got_video:	ds=demuxer->video;	mp_dbg(MSGT_DEMUX,MSGL_DBG2, "packet is video (id: %d)\n", stream_id);		// parse video chunk:	{	    // we need a more complicated, 2nd level demuxing, as the video	    // frames are stored fragmented in the video chunks :(	    sh_video_t *sh_video = ds->sh;	    demux_packet_t *dp;	    unsigned vpkg_header, vpkg_length, vpkg_offset;	    int vpkg_seqnum=-1;	    int vpkg_subseq=0; 	    while(len>2){		dp_hdr_t* dp_hdr;		unsigned char* dp_data;		uint32_t* extra;    //  unsigned char *extra;//		printf("xxx len=%d  \n",len);		// read packet header		// bit 7: 1=last block in block chain		// bit 6: 1=short header (only one block?)		vpkg_header=stream_read_char(demuxer->stream); --len;		mp_dbg(MSGT_DEMUX,MSGL_DBG2, "hdr: %02X (len=%d) ",vpkg_header,len);		if (0x40==(vpkg_header&0xc0)) {		    // seems to be a very short header	    	    // 2 bytes, purpose of the second byte yet unknown	    	    int bummer;		    bummer=stream_read_char(demuxer->stream); --len; 		    mp_dbg(MSGT_DEMUX,MSGL_DBG2,  "%02X",bummer); 	    	    vpkg_offset=0; 		    vpkg_length=len;		} else {				    if (0==(vpkg_header&0x40)) {			// sub-seqnum (bits 0-6: number of fragment. bit 7: ???)		        vpkg_subseq=stream_read_char(demuxer->stream);	                --len;		        mp_dbg(MSGT_DEMUX,MSGL_DBG2,  "subseq: %02X ",vpkg_subseq);			vpkg_subseq&=0x7f;	            }	  	    // size of the complete packet		    // bit 14 is always one (same applies to the offset)		    vpkg_length=stream_read_word(demuxer->stream);		    len-=2;		    mp_dbg(MSGT_DEMUX,MSGL_DBG2, "l: %02X %02X ",vpkg_length>>8,vpkg_length&0xff);		    if (!(vpkg_length&0xC000)) {			vpkg_length<<=16;		        vpkg_length|=(uint16_t)stream_read_word(demuxer->stream);		        mp_dbg(MSGT_DEMUX,MSGL_DBG2, "l+: %02X %02X ",(vpkg_length>>8)&0xff,vpkg_length&0xff);	    	     len-=2;		    } else		    vpkg_length&=0x3fff;		    // offset of the following data inside the complete packet		    // Note: if (hdr&0xC0)==0x80 then offset is relative to the		    // _end_ of the packet, so it's equal to fragment size!!!		    vpkg_offset=stream_read_word(demuxer->stream);	            len-=2;		    mp_dbg(MSGT_DEMUX,MSGL_DBG2, "o: %02X %02X ",vpkg_offset>>8,vpkg_offset&0xff);		    if (!(vpkg_offset&0xC000)) {			vpkg_offset<<=16;		        vpkg_offset|=(uint16_t)stream_read_word(demuxer->stream);		        mp_dbg(MSGT_DEMUX,MSGL_DBG2, "o+: %02X %02X ",(vpkg_offset>>8)&0xff,vpkg_offset&0xff);	    	        len-=2;		    } else		    vpkg_offset&=0x3fff;		    vpkg_seqnum=stream_read_char(demuxer->stream); --len;		    mp_dbg(MSGT_DEMUX,MSGL_DBG2, "seq: %02X ",vpkg_seqnum);	        } 		mp_dbg(MSGT_DEMUX,MSGL_DBG2, "\n");                mp_dbg(MSGT_DEMUX,MSGL_DBG2, "blklen=%d\n", len);		mp_msg(MSGT_DEMUX,MSGL_DBG2, "block: hdr=0x%0x, len=%d, offset=%d, seqnum=%d\n",		    vpkg_header, vpkg_length, vpkg_offset, vpkg_seqnum); 	if(ds->asf_packet){		    dp=ds->asf_packet;		    dp_hdr=(dp_hdr_t*)dp->buffer;		    dp_data=dp->buffer+sizeof(dp_hdr_t);		    extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab);		    //extra=(unsigned char*)(dp->buffer+dp_hdr->chunktab);		    mp_dbg(MSGT_DEMUX,MSGL_DBG2, "we have an incomplete packet (oldseq=%d new=%d)\n",ds->asf_seq,vpkg_seqnum);		    // we have an incomplete packet:		    if(ds->asf_seq!=vpkg_seqnum){			// this fragment is for new packet, close the old one			mp_msg(MSGT_DEMUX,MSGL_DBG2, "closing probably incomplete packet, len: %d  \n",dp->len);			if(priv->video_after_seek){				priv->kf_base = 0;				priv->kf_pts = dp_hdr->timestamp;				dp->pts=				real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format);				priv->video_after_seek = 0;			} else if (dp_hdr->len >= 3)			    dp->pts =			    real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format);			ds_add_packet(ds,dp);			ds->asf_packet=NULL;		    } else {			// append data to it!			++dp_hdr->chunks;			mp_msg(MSGT_DEMUX,MSGL_DBG2,"[chunks=%d  subseq=%d]\n",dp_hdr->chunks,vpkg_subseq);			if(dp_hdr->chunktab+8*(1+dp_hdr->chunks)>dp->len){			    // increase buffer size, this should not happen!			    mp_msg(MSGT_DEMUX,MSGL_WARN, "chunktab buffer too small!!!!!\n");			    dp->len=dp_hdr->chunktab+8*(4+dp_hdr->chunks);			    dp->buffer=realloc(dp->buffer,dp->len+FF_INPUT_BUFFER_PADDING_SIZE);			    memset(dp->buffer + dp->len, 0, FF_INPUT_BUFFER_PADDING_SIZE);			    // re-calc pointers:			    dp_hdr=(dp_hdr_t*)dp->buffer;			    dp_data=dp->buffer+sizeof(dp_hdr_t);			    extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab);			    //extra=(unsigned char *)(dp->buffer+dp_hdr->chunktab);			}			extra[2*dp_hdr->chunks+0]=1;			extra[2*dp_hdr->chunks+1]=dp_hdr->len;						//extra[2*dp_hdr->chunks + 0]=1;			//extra[2*dp_hdr->chunks + 1]=0;			//extra[2*dp_hdr->chunks + 2]=0;			//extra[2*dp_hdr->chunks + 3]=0;						//extra[2*dp_hdr->chunks + 4]=dp_hdr->len & 0x0ff;			//extra[2*dp_hdr->chunks + 5]=(dp_hdr->len >> 8) & 0x0ff;			//extra[2*dp_hdr->chunks + 6]=(dp_hdr->len >> 16) & 0x0ff;			//extra[2*dp_hdr->chunks + 7]=(dp_hdr->len >> 24) & 0x0ff;			if(0x80==(vpkg_header&0xc0)){			    // last fragment!			    if(dp_hdr->len!=vpkg_length-vpkg_offset)				mp_msg(MSGT_DEMUX,MSGL_V,"warning! assembled.len=%d  frag.len=%d  total.len=%d  \n",dp->len,vpkg_offset,vpkg_length-vpkg_offset);            		    stream_read(demuxer->stream, dp_data+dp_hdr->len, vpkg_offset);			    if((dp_data[dp_hdr->len]&0x20) && (sh_video->format==0x30335652)) --dp_hdr->chunks; else			    dp_hdr->len+=vpkg_offset;			    len-=vpkg_offset; 			    mp_dbg(MSGT_DEMUX,MSGL_DBG2, "fragment (%d bytes) appended, %d bytes left\n",vpkg_offset,len);			    // we know that this is the last fragment -> we can close the packet!			    if(priv->video_after_seek){				    priv->kf_base = 0;				    priv->kf_pts = dp_hdr->timestamp;				    dp->pts=				    real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format);				    priv->video_after_seek = 0;			    } else if (dp_hdr->len >= 3)				dp->pts =				real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format);			    ds_add_packet(ds,dp);			    ds->asf_packet=NULL;			    // continue parsing			    continue;			}			// non-last fragment:			if(dp_hdr->len!=vpkg_offset)			{				  mp_msg(MSGT_DEMUX,MSGL_V,"warning! assembled.len=%d  offset=%d  frag.len=%d  total.len=%d  \n",dp->len,vpkg_offset,len,vpkg_length);			 					}			        stream_read(demuxer->stream, dp_data+dp_hdr->len, len);			if((dp_data[dp_hdr->len]&0x20) && (sh_video->format==0x30335652)) --dp_hdr->chunks; else			dp_hdr->len+=len;			len=0;			break; // no more fragments in this chunk!		    }		}					// create new packet!		int vpkg_length_align = ((vpkg_length + 3) & (~3));		//dp = new_demux_packet(sizeof(dp_hdr_t)+vpkg_length+8*(1+2*(vpkg_header&0x3F)));		dp = new_demux_packet(sizeof(dp_hdr_t)+vpkg_length_align+8*(1+2*((vpkg_header)&0x3F)));	 	// the timestamp seems to be in milliseconds    dp->pos = demuxer->filepos;    dp->flags = (flags & 0x2) ? 0x10 : 0;		ds->asf_seq = vpkg_seqnum;		dp_hdr=(dp_hdr_t*)dp->buffer;		dp_hdr->chunks=0;		dp_hdr->timestamp=timestamp;		dp_hdr->chunktab=sizeof(dp_hdr_t)+vpkg_length_align;		dp_data=dp->buffer+sizeof(dp_hdr_t);		//extra=(uint32_t*)(dp->buffer+dp_hdr->chunktab);	 	extra=(unsigned char*)(dp->buffer+dp_hdr->chunktab);		extra[0]=1; extra[1]=0; // offset of the first chunk//		 	extra[0] = 1;//		 	extra[1] = 0;//		 	extra[2] = 0;//		 	extra[3] = 0;//		 	extra[4] = 0;//		 	extra[5] = 0;//		 	extra[6] = 0;//		 	extra[7] = 0;		 			if(0x00==(vpkg_header&0xc0)){		    // first fragment:		    		    //F("vpkg_length = %d len = %d\n",vpkg_length,len);		    if(vpkg_length >= len)		    {		    		dp_hdr->len=len;		    		stream_read(demuxer->stream, dp_data, len);		    }		    else		    {			    	dp_hdr->len=vpkg_length;		    	 		    	stream_read(demuxer->stream, dp_data,vpkg_length );		    	seterrorseek();		    }		    ds->asf_packet=dp;		    len=0;		    if(priv->video_after_seek){		        priv->kf_base = 0;		        priv->kf_pts = dp_hdr->timestamp;		        dp->pts=		        real_fix_timestamp(priv,dp_data,dp_hdr->timestamp,sh_video->frametime,sh_video->format);		        priv->video_after_seek = 0;		    }		    break;		}		// whole packet (not fragmented):

⌨️ 快捷键说明

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