demux_mov.c

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

C
1,854
字号
		// if image size is zero, fallback to display size		if(!sh->disp_w && !sh->disp_h) {		  sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8);		  sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8);		} else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){		  // codec and display width differ... use display one for aspect		  sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8);		  sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8);		}				if(depth>32+8) mp_msg(MSGT_DEMUX, MSGL_INFO,"*** depth = 0x%X\n",depth);		// palettized?		gray = 0;		if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale		if ((depth == 2) || (depth == 4) || (depth == 8))		  palette_count = (1 << depth);		else		  palette_count = 0;		// emulate BITMAPINFOHEADER:		if (palette_count)		{		  sh->bih=malloc(sizeof(BITMAPINFOHEADER) + palette_count * 4);		  memset(sh->bih,0,sizeof(BITMAPINFOHEADER) + palette_count * 4);		  sh->bih->biSize=40 + palette_count * 4;		  // fetch the relevant fields		  flag = BE_16(&trak->stdata[hdr_ptr]);		  hdr_ptr += 2;		  start = BE_32(&trak->stdata[hdr_ptr]);		  hdr_ptr += 4;		  count_flag = BE_16(&trak->stdata[hdr_ptr]);		  hdr_ptr += 2;		  end = BE_16(&trak->stdata[hdr_ptr]);		  hdr_ptr += 2;		  palette_map = (unsigned char *)sh->bih + 40;		  mp_msg(MSGT_DEMUX, MSGL_V, "Allocated %d entries for palette\n",		    palette_count);		  mp_msg(MSGT_DEMUX, MSGL_DBG2, "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n",		    start, end, count_flag, flag);		  /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/		  // load default palette		  if (flag & 0x08)		  {		    if (gray)		    {		      mp_msg(MSGT_DEMUX, MSGL_V, "Using default QT grayscale palette\n");		      if (palette_count == 16)		        memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4);		      else if (palette_count == 256) {		        memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4);		        if (trak->fourcc == mmioFOURCC('c','v','i','d')) {		          int i;		          // Hack for grayscale CVID, negative palette		          // If you have samples where this is not required contact me (rxt)		          mp_msg(MSGT_DEMUX, MSGL_V, "MOV: greyscale cvid with default palette,"		            " enabling negative palette hack.\n");		          for (i = 0; i < 256 * 4; i++)		            palette_map[i] = palette_map[i] ^ 0xff;		        }		      }		    }		    else		    {		      mp_msg(MSGT_DEMUX, MSGL_V, "Using default QT colour palette\n");		      if (palette_count == 4)		        memcpy(palette_map, qt_default_palette_4, 4 * 4);		      else if (palette_count == 16)		        memcpy(palette_map, qt_default_palette_16, 16 * 4);		      else if (palette_count == 256)		        memcpy(palette_map, qt_default_palette_256, 256 * 4);		    }		  }		  // load palette from file		  else		  {		    mp_msg(MSGT_DEMUX, MSGL_V, "Loading palette from file\n");		    for (i = start; i <= end; i++)		    {		      entry = BE_16(&trak->stdata[hdr_ptr]);		      hdr_ptr += 2;		      // apparently, if count_flag is set, entry is same as i		      if (count_flag & 0x8000)		        entry = i;		      // only care about top 8 bits of 16-bit R, G, or B value		      if (entry <= palette_count && entry >= 0)		      {		        palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0];		        palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2];		        palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4];		        mp_dbg(MSGT_DEMUX, MSGL_DBG2, "QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n",			    entry, palette_count,			    palette_map[entry * 4 + 2], 			    palette_map[entry * 4 + 1],			    palette_map[entry * 4 + 0]);		      }		      else		        mp_msg(MSGT_DEMUX, MSGL_V, "QT palette: skipped entry (out of count): %d of %d\n",			    entry, palette_count);		      hdr_ptr += 6;		    }		  }		}		else		{		 if (trak->fourcc == mmioFOURCC('a','v','c','1')) {		  if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADER)) {		    mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid extradata size %d, skipping\n",trak->stream_header_len);		    trak->stream_header_len = 0;		  }		  sh->bih=malloc(sizeof(BITMAPINFOHEADER) + trak->stream_header_len);		  memset(sh->bih,0,sizeof(BITMAPINFOHEADER) + trak->stream_header_len);		  sh->bih->biSize=40  + trak->stream_header_len;		  memcpy(((unsigned char *)sh->bih)+40,  trak->stream_header, trak->stream_header_len);		  free (trak->stream_header);		  trak->stream_header_len = 0;		  trak->stream_header = NULL;		 } else {		  sh->bih=malloc(sizeof(BITMAPINFOHEADER));		  memset(sh->bih,0,sizeof(BITMAPINFOHEADER));		  sh->bih->biSize=40;		 }		}		sh->bih->biWidth=sh->disp_w;		sh->bih->biHeight=sh->disp_h;		sh->bih->biPlanes=0;		sh->bih->biBitCount=depth;		sh->bih->biCompression=trak->fourcc;		sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight;		mp_msg(MSGT_DEMUX, MSGL_V, "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount);		if(trak->tkdata_len>81)		mp_msg(MSGT_DEMUX, MSGL_V, "Display size: %d x %d\n",		    trak->tkdata[77]|(trak->tkdata[76]<<8),		    trak->tkdata[81]|(trak->tkdata[80]<<8));		mp_msg(MSGT_DEMUX, MSGL_V, "Fourcc: %.4s  Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43);		//		if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){//		    // (auto)selected video track://		    demuxer->video->id=priv->track_db;//		    demuxer->video->sh=sh; sh->ds=demuxer->video;//		}    return 1;}static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){    mov_priv_t* priv=demuxer->priv;//    printf("lschunks (level=%d,endpos=%x)\n", level, endpos);    while(1){	off_t pos;	off_t len;	unsigned int id;	//	pos=stream_tell(demuxer->stream);//	printf("stream_tell==%d\n",pos);	if(pos>=endpos) return; // END	len=stream_read_dword(demuxer->stream);//	printf("len==%d\n",len);	if(len<8) return; // error	len-=8;	id=stream_read_dword(demuxer->stream);	//	mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s  %d\n",(char *)&id,(int)len);	//	if(trak){	  if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0)	    return;	} else { /* not in track */	  switch(id) {	    case MOV_FOURCC('m','v','h','d'): {		int version = stream_read_char(demuxer->stream);		stream_skip(demuxer->stream, (version == 1) ? 19 : 11);		priv->timescale=stream_read_dword(demuxer->stream);		if (version == 1)		    priv->duration=stream_read_qword(demuxer->stream);		else		    priv->duration=stream_read_dword(demuxer->stream);		mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sMovie header (%d bytes): tscale=%d  dur=%d\n",level,"",(int)len,		    (int)priv->timescale,(int)priv->duration);		break;	    }	    case MOV_FOURCC('t','r','a','k'): {//	    if(trak) printf("MOV: Warning! trak in trak?\n");	    if(priv->track_db>=MOV_MAX_TRACKS){		mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk);		return;	    }	    if(!priv->track_db) mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n");	    trak=malloc(sizeof(mov_track_t));	    memset(trak,0,sizeof(mov_track_t));	    mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db);	    trak->id=priv->track_db;	    priv->tracks[priv->track_db]=trak;	    lschunks(demuxer,level+1,pos+len,trak);	    mov_build_index(trak,priv->timescale);	    switch(trak->type){	    case MOV_TRAK_AUDIO: {		sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db);		mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "mov", priv->track_db);		gen_sh_audio(sh, trak, priv->timescale);		break;	    }	    case MOV_TRAK_VIDEO: {		sh_video_t* sh=new_sh_video(demuxer,priv->track_db);		mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "mov", priv->track_db);		gen_sh_video(sh, trak, priv->timescale);		break;	    }	    case MOV_TRAK_GENERIC:		if (trak->fourcc == mmioFOURCC('m','p','4','s') ||		    trak->fourcc == mmioFOURCC('t','x','3','g') ||		    trak->fourcc == mmioFOURCC('t','e','x','t')) {			sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db);			mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_SubtitleID, "mov", priv->track_db);			if (trak->fourcc == mmioFOURCC('m','p','4','s'))				init_vobsub(sh, trak);			else				sh->type = 't';		} else		mp_msg(MSGT_DEMUX, MSGL_V, "Generic track - not completely understood! (id: %d)\n",		    trak->id);		/* XXX: Also this contains the FLASH data */#if 0	    {		int pos = stream_tell(demuxer->stream);		int i;		int fd;		char name[20];			for (i=0; i<trak->samples_size; i++)		{		    char buf[trak->samples[i].size];		    stream_seek(demuxer->stream, trak->samples[i].pos);		    snprintf((char *)&name[0], 20, "samp%d", i);		    fd = open((char *)&name[0], O_CREAT|O_WRONLY);		    stream_read(demuxer->stream, &buf[0], trak->samples[i].size);		    write(fd, &buf[0], trak->samples[i].size);		    close(fd);		 }		for (i=0; i<trak->chunks_size; i++)		{		    char buf[trak->length];		    stream_seek(demuxer->stream, trak->chunks[i].pos);		    snprintf((char *)&name[0], 20, "chunk%d", i);		    fd = open((char *)&name[0], O_CREAT|O_WRONLY);		    stream_read(demuxer->stream, &buf[0], trak->length);		    write(fd, &buf[0], trak->length);		    close(fd);		 }		 if (trak->samplesize > 0)		 {		    char *buf;		    		    buf = malloc(trak->samplesize);		    stream_seek(demuxer->stream, trak->chunks[0].pos);		    snprintf((char *)&name[0], 20, "trak%d", trak->id);		    fd = open((char *)&name[0], O_CREAT|O_WRONLY);		    stream_read(demuxer->stream, buf, trak->samplesize);		    write(fd, buf, trak->samplesize);		    close(fd);		 }		 stream_seek(demuxer->stream, pos);	    }		#endif		break;	    default:		mp_msg(MSGT_DEMUX, MSGL_V, "Unknown track type found (type: %d)\n", trak->type);		break;	    }	    mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n");	    priv->track_db++;	    trak=NULL;	    break;	}#ifndef HAVE_ZLIB	case MOV_FOURCC('c','m','o','v'): {	    mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr);	    return;	}#else	case MOV_FOURCC('m','o','o','v'):	case MOV_FOURCC('c','m','o','v'): {//	    mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr);	    lschunks(demuxer,level+1,pos+len,NULL);	    break;	}	case MOV_FOURCC('d','c','o','m'): {//	    int temp=stream_read_dword(demuxer->stream);	    unsigned int algo=be2me_32(stream_read_dword(demuxer->stream));	    mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header uses %.4s algo!\n",(char *)&algo);	    break;	}	case MOV_FOURCC('c','m','v','d'): {//	    int temp=stream_read_dword(demuxer->stream);	    unsigned int moov_sz=stream_read_dword(demuxer->stream);	    unsigned int cmov_sz=len-4;	    unsigned char* cmov_buf;	    unsigned char* moov_buf;	    int zret;	    z_stream zstrm;	    stream_t* backup;	    if (moov_sz > SIZE_MAX - 16) {              mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid cmvd atom size %d\n", moov_sz);              break;            }	    cmov_buf=malloc(cmov_sz);	    moov_buf=malloc(moov_sz+16);	    mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header size: %d / %d\n",cmov_sz,moov_sz);	    stream_read(demuxer->stream,cmov_buf,cmov_sz);	      zstrm.zalloc          = (alloc_func)0;	      zstrm.zfree           = (free_func)0;	      zstrm.opaque          = (voidpf)0;	      zstrm.next_in         = cmov_buf;	      zstrm.avail_in        = cmov_sz;	      zstrm.next_out        = moov_buf;	      zstrm.avail_out       = moov_sz;	    	      zret = inflateInit(&zstrm);	      if (zret != Z_OK)		{ mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov: inflateInit err %d\n",zret);		return;		}	      zret = inflate(&zstrm, Z_NO_FLUSH);	      if ((zret != Z_OK) && (zret != Z_STREAM_END))		{ mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov inflate: ERR %d\n",zret);		return;		}#if 0	      else {		FILE *DecOut;		DecOut = fopen("Out.bin", "w");		fwrite(moov_buf, 1, moov_sz, DecOut);		fclose(DecOut);	      }#endif	      if(moov_sz != zstrm.total_out)	        mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! moov size differs cmov: %d  zlib: %ld\n",moov_sz,zstrm.total_out);	      zret = inflateEnd(&zstrm);	      	      backup=demuxer->stream;	       demuxer->stream=new_memory_stream(moov_buf,moov_sz);	       stream_skip(demuxer->stream,8);	       lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov'	       //free_stream(demuxer->stream);	      demuxer->stream=backup;	      free(cmov_buf);	      free(moov_buf);	    	      break;	}#endif	case MOV_FOURCC('u','d','t','a'):	{	    unsigned int udta_id;	    off_t udta_len;	    off_t udta_size = len;		    mp_msg(MSGT_DEMUX, MSGL_DBG2, "mov: user data record found\n");	    mp_msg(MSGT_DEMUX, MSGL_V, "Quicktime Clip Info:\n");	    while((len > 8) && (udta_size > 8))	    {		udta_len = stream_read_dword(demuxer->stream);		udta_id = stream_read_dword(demuxer->stream);		udta_size -= 8;		mp_msg(MSGT_DEMUX, MSGL_DBG2, "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len);

⌨️ 快捷键说明

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