demux_real.c

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

C
1,820
字号
			buf[4] = 0;		    }		    else		    {					/* Interleaver id */			get_str(1, demuxer, buf, sizeof(buf));			priv->intl_id[stream_id] = MKTAG(buf[0], buf[1], buf[2], buf[3]);			/* Codec FourCC */			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/8;		    sh->wf->nBlockAlign = frame_size;		    sh->wf->cbSize = 0;		    sh->format = MKTAG(buf[0], buf[1], buf[2], buf[3]);		    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->nBlockAlign = 0x14;                            break;			case MKTAG('2', '8', '_', '8'):			    sh->wf->nBlockAlign = coded_frame_size;			    break;			case MKTAG('s', 'i', 'p', 'r'):			case MKTAG('a', 't', 'r', 'c'):			case MKTAG('c', 'o', 'o', 'k'):			    // realaudio codec plugins - common:			    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);			    // Check extradata len, we can't store bigger values in cbSize anyway			    if ((unsigned)codecdata_length > 0xffff) {			        mp_msg(MSGT_DEMUX,MSGL_ERR,"Extradata too big (%d)\n", codecdata_length);				goto skip_this_chunk;			    }			    sh->wf->cbSize = codecdata_length;			    sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX)+sh->wf->cbSize);			    stream_read(demuxer->stream, ((char*)(sh->wf+1)), codecdata_length); // extras                if (priv->intl_id[stream_id] == MKTAG('g', 'e', 'n', 'r'))    			    sh->wf->nBlockAlign = sub_packet_size;    			else    			    sh->wf->nBlockAlign = coded_frame_size;			    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);				sh->codecdatatype = 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);		    }		    // Interleaver setup		    priv->sub_packet_size[stream_id] = sub_packet_size;		    priv->sub_packet_h[stream_id] = sub_packet_h;		    priv->coded_framesize[stream_id] = coded_frame_size;		    priv->audiopk_size[stream_id] = frame_size;		    sh->wf->wFormatTag = sh->format;		    		    mp_msg(MSGT_DEMUX,MSGL_V,"audio fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format);		    if ( mp_msg_test(MSGT_DEMUX,MSGL_V) )		    print_wave_header(sh->wf, MSGL_V);		    /* 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){			sh->ds=demuxer->audio;			demuxer->audio->sh=sh;        	priv->audio_buf = calloc(priv->sub_packet_h[demuxer->audio->id], priv->audiopk_size[demuxer->audio->id]);        	priv->audio_timestamp = calloc(priv->sub_packet_h[demuxer->audio->id], sizeof(double));		    }		    		    ++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);    		    mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "real", 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 if (strstr(mimet,"x-pn-encrypted-ra")) {		 mp_msg(MSGT_DEMUX,MSGL_ERR,"Encrypted audio is not supported\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")) {		stream_skip(demuxer->stream, 4);  // VIDO length, same as codec_data_size		tmp = stream_read_dword(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);		    mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "real", 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));		    memset(sh->bih, 0, sizeof(BITMAPINFOHEADER));	    	    sh->bih->biSize = sizeof(BITMAPINFOHEADER);		    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 and store codec extradata			    unsigned int cnt = codec_data_size - (stream_tell(demuxer->stream) - codec_pos);			    if (cnt > 0x7fffffff - sizeof(BITMAPINFOHEADER)) {			        mp_msg(MSGT_DEMUX, MSGL_ERR,"Extradata too big (%u)\n", cnt);			    } else  {				sh->bih = realloc(sh->bih, sizeof(BITMAPINFOHEADER) + cnt);			        sh->bih->biSize += cnt;				stream_read(demuxer->stream, ((unsigned char*)(sh->bih+1)), cnt);			    }		    } 		    if(sh->format == 0x30315652 && ((unsigned char*)(sh->bih+1))[6] == 0x30)			    sh->bih->biCompression = sh->format = mmioFOURCC('R', 'V', '1', '3');		    		    /* Select video stream with highest bitrate if multirate file*/		    if (priv->is_multirate && ((demuxer->video->id == -1) ||		                               ((demuxer->video->id >= 0) && priv->v_bitrate && (bitrate > priv->v_bitrate)))) {			    demuxer->video->id = stream_id;			    priv->v_bitrate = bitrate;			    mp_msg(MSGT_DEMUX,MSGL_DBG2,"Multirate autoselected video id %d with bitrate %d\n", stream_id, bitrate);		    }		    if(demuxer->video->id==stream_id){			sh->ds=demuxer->video;			demuxer->video->sh=sh;		    }		    		    ++v_streams;		}	  } else {		 mp_msg(MSGT_DEMUX,MSGL_V,"Unknown video stream format\n");	  }	} else if (strstr(mimet,"logical-")) {		 if (strstr(mimet,"fileinfo")) {		     mp_msg(MSGT_DEMUX,MSGL_V,"Got a logical-fileinfo chunk\n");		 } else if (strstr(mimet,"-audio") || strstr(mimet,"-video")) {		    int i, stream_cnt;		    int stream_list[MAX_STREAMS];		    		    priv->is_multirate = 1;		    stream_skip(demuxer->stream, 4); // Length of codec data (repeated)		    stream_cnt = stream_read_dword(demuxer->stream); // Get number of audio or video streams		    if ((unsigned)stream_cnt >= MAX_STREAMS) {		        mp_msg(MSGT_DEMUX,MSGL_ERR,"Too many streams in %s. Big troubles ahead.\n", mimet);		        goto skip_this_chunk;		    }		    for (i = 0; i < stream_cnt; i++)		        stream_list[i] = stream_read_word(demuxer->stream);		    for (i = 0; i < stream_cnt; i++)		        if ((unsigned)stream_list[i] >= MAX_STREAMS) {		            mp_msg(MSGT_DEMUX,MSGL_ERR,"Stream id out of range: %d. Ignored.\n", stream_list[i]);		            stream_skip(demuxer->stream, 4); // Skip DATA offset for broken stream		        } else {		            priv->str_data_offset[stream_list[i]] = stream_read_dword(demuxer->stream);		            mp_msg(MSGT_DEMUX,MSGL_V,"Stream %d with DATA offset 0x%08x\n", stream_list[i], priv->str_data_offset[stream_list[i]]);		        }		    // Skip the rest of this chunk		 } else 		     mp_msg(MSGT_DEMUX,MSGL_V,"Unknown logical stream\n");		}		else {		    mp_msg(MSGT_DEMUX, MSGL_ERR, "Not audio/video stream or unsupported!\n");		}//		break;//	    default:skip_this_chunk:		/* skip codec info */		tmp = stream_tell(demuxer->stream) - codec_pos;		mp_msg(MSGT_DEMUX,MSGL_V,"### skipping %d bytes of codec info\n", codec_data_size - tmp);#if 0		{ int i;		  for(i=0;i<codec_data_size - tmp;i++)		      mp_msg(MSGT_DEMUX, MSGL_V," %02X",stream_read_char(demuxer->stream));		  mp_msg(MSGT_DEMUX, MSGL_V,"\n");		}#else		stream_skip(demuxer->stream, codec_data_size - tmp);#endif		if (mimet)		    free (mimet);		break;//	    }	    }	    case MKTAG('D', 'A', 'T', 'A'):		goto header_end;	    case MKTAG('I', 'N', 'D', 'X'):	    default:		mp_msg(MSGT_DEMUX,MSGL_V,"Unknown chunk: %x\n", chunk_id);		stream_skip(demuxer->stream, chunk_size - 10);		break;	}    }header_end:    if(priv->is_multirate) {        mp_msg(MSGT_DEMUX,MSGL_V,"Selected video id %d audio id %d\n", demuxer->video->id, demuxer->audio->id);        /* Perform some sanity checks to avoid checking streams id all over the code*/        if (demuxer->audio->id >= MAX_STREAMS) {            mp_msg(MSGT_DEMUX,MSGL_ERR,"Invalid audio stream %d. No sound will be played.\n", demuxer->audio->id);            demuxer->audio->id = -2;        } else if ((demuxer->audio->id >= 0) && (priv->str_data_offset[demuxer->audio->id] == 0)) {            mp_msg(MSGT_DEMUX,MSGL_ERR,"Audio stream %d not found. No sound will be played.\n", demuxer->audio->id);            demuxer->audio->id = -2;        }        if (demuxer->video->id >= MAX_STREAMS) {            mp_msg(MSGT_DEMUX,MSGL_ERR,"Invalid video stream %d. No video will be played.\n", demuxer->video->id);            demuxer->video->id = -2;        } else if ((demuxer->video->id >= 0) && (priv->str_data_offset[demuxer->video->id] == 0)) {            mp_msg(MSGT_DEMUX,MSGL_ERR,"Video stream %d not found. No video will be played.\n", demuxer->video->id);            demuxer->video->id = -2;        }    }    if(priv->is_multirate && ((demuxer->video->id >= 0) || (demuxer->audio->id  >=0))) {        /* If audio or video only, seek to right place and behave like standard file */        if (demuxer->video->id < 0) {            // Stream is audio only, or -novideo            stream_seek(demuxer->stream, priv->data_chunk_offset = priv->str_data_offset[demuxer->audio->id]+10);            priv->is_multirate = 0;        }        if (demuxer->audio->id < 0) {            // Stream is video only, or -nosound            stream_seek(demuxer->stream, priv->data_chunk_offset = priv->str_data_offset[demuxer->video->id]+10);            priv->is_multirate = 0;        }    }  if(!priv->is_multirate) {    //printf("i=%d num_of_headers=%d   \n",i,num_of_headers);    priv->num_of_packets = stream_read_dword(demuxer->stream);    stream_skip(demuxer->stream, 4); /* next data header */    mp_msg(MSGT_DEMUX,MSGL_V,"Packets in file: %d\n", priv->num_of_packets);    if (priv->num_of_packets == 0)	priv->num_of_packets = -10;  } else {        priv->audio_curpos = priv->str_data_offset[demuxer->audio->id] + 18;        stream_seek(demuxer->stream, priv->str_data_offset[demuxer->audio->id]+10);         priv->a_num_of_packets=priv->a_num_of_packets = stream_read_dword(demuxer->stream);              priv->video_curpos = priv->str_data_offset[demuxer->video->id] + 18;                stream_seek(demuxer->stream, priv->str_data_offset[demuxer->video->id]+10);        priv->v_num_of_packets = stream_read_dword(demuxer->stream);        priv->stream_switch = 1;        /* Index required for multirate playback, force building if it's not there */        /* but respect user request to force index regeneration */        if (index_mode == -1)            index_mode = 1;    }    priv->audio_need_keyframe = 0;    priv->video_after_seek = 0;    switch (index_mode){	case -1: // untouched	    	    if (priv->index_chunk_offset && parse_index_chunk(demuxer))	    {				demuxer->seekable = 1;	    }	    	    break;	case 1: // use (generate index)	    if (priv->index_chunk_offset && parse_index_chunk(demuxer))	    {		demuxer->seekable = 1;	    } else {		generate_index(demuxer);		demuxer->seekable = 1;	    }

⌨️ 快捷键说明

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