demux_asf.c

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

C
710
字号
//  ASF file parser for DEMUXER v0.3  by A'rpi/ESP-team#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream/stream.h"#include "asf.h"#include "demuxer.h"#include "libvo/fastmemcpy.h"/* * Load 16/32-bit values in little endian byte order * from an unaligned address */#ifdef ARCH_X86#define	LOAD_LE32(p)	(*(unsigned int*)(p))#define	LOAD_LE16(p)	(*(unsigned short*)(p))#define	LOAD_BE32(p)	(((unsigned char*)(p))[3]     | \ 			 ((unsigned char*)(p))[2]<< 8 | \ 			 ((unsigned char*)(p))[1]<<16 | \ 			 ((unsigned char*)(p))[0]<<24 )#else#define	LOAD_LE32(p)	(((unsigned char*)(p))[0]     | \ 			 ((unsigned char*)(p))[1]<< 8 | \ 			 ((unsigned char*)(p))[2]<<16 | \ 			 ((unsigned char*)(p))[3]<<24 )#define	LOAD_LE16(p)	(((unsigned char*)(p))[0]     | \			 ((unsigned char*)(p))[1]<<8)#define	LOAD_BE32(p)	(*(unsigned int*)(p))#endif// defined at asfheader.c:extern int asf_check_header(demuxer_t *demuxer);extern int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf);// based on asf file-format doc by Eugene [http://divx.euro.ru]static void asf_descrambling(unsigned char **src,unsigned len, struct asf_priv* asf){  unsigned char *dst=malloc(len);  unsigned char *s2=*src;  unsigned i=0,x,y;  while(len>=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b+i){//    mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d  b=%d)\n",w,asf_scrambling_b);	//i+=asf_scrambling_h*asf_scrambling_w;	for(x=0;x<asf->scrambling_w;x++)	  for(y=0;y<asf->scrambling_h;y++){	    fast_memcpy(dst+i,s2+(y*asf->scrambling_w+x)*asf->scrambling_b,asf->scrambling_b);		i+=asf->scrambling_b;	  }	s2+=asf->scrambling_h*asf->scrambling_w*asf->scrambling_b;  }  //if(i<len) fast_memcpy(dst+i,src+i,len-i);  free(*src);  *src = dst;}/***************************************************************** * \brief initializes asf private data * */static void init_priv (struct asf_priv* asf){  asf->last_vid_seq=-1;  asf->vid_ext_timing_index=-1;  asf->aud_ext_timing_index=-1;  asf->vid_ext_frame_index=-1;}#ifdef USE_LIBAVCODEC_SO#include <ffmpeg/avcodec.h>#elif defined(USE_LIBAVCODEC)#include "libavcodec/avcodec.h"#else#define FF_INPUT_BUFFER_PADDING_SIZE 8#endifstatic void demux_asf_append_to_packet(demux_packet_t* dp,unsigned char *data,int len,int offs){  if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d  \n",dp->len,offs);  dp->buffer=realloc(dp->buffer,dp->len+len+FF_INPUT_BUFFER_PADDING_SIZE);  fast_memcpy(dp->buffer+dp->len,data,len);  memset(dp->buffer+dp->len+len, 0, FF_INPUT_BUFFER_PADDING_SIZE);  mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len);  dp->len+=len;}static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,uint64_t time,unsigned short dur,int offs,int keyframe){  struct asf_priv* asf = demux->priv;  demux_stream_t *ds=NULL;  int close_seg=0;    mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len);    if(demux->video->id==-1)    if(demux->v_streams[id])        demux->video->id=id;  if(demux->audio->id==-1)    if(demux->a_streams[id])        demux->audio->id=id;  if(id==demux->audio->id){      // audio      ds=demux->audio;      if(!ds->sh){        ds->sh=demux->a_streams[id];        mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id);      }  } else   if(id==demux->video->id){      // video      ds=demux->video;      if(!ds->sh){        ds->sh=demux->v_streams[id];        mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id);      }  }    if(ds){    if(ds->asf_packet){      demux_packet_t* dp=ds->asf_packet;      if (ds==demux->video && asf->asf_is_dvr_ms) {        if (asf->new_vid_frame_seg) {          dp->pos=demux->filepos;          close_seg = 1;        } else seq = ds->asf_seq;      } else close_seg = ds->asf_seq!=seq;      if(close_seg){        // closed segment, finalize packet:		if(ds==demux->audio)		  if(asf->scrambling_h>1 && asf->scrambling_w>1 && asf->scrambling_b>0)		    asf_descrambling(&ds->asf_packet->buffer,ds->asf_packet->len,asf);        ds_add_packet(ds,ds->asf_packet);        ds->asf_packet=NULL;      } else {        // append data to it!        demux_asf_append_to_packet(dp,data,len,offs);        // we are ready now.        return 1;      }    }    // create new packet:    { demux_packet_t* dp;      if(offs>0){        mp_msg(MSGT_DEMUX,MSGL_V,"warning!  broken fragment, %d bytes missing  \n",offs);        return 0;      }      dp=new_demux_packet(len);      fast_memcpy(dp->buffer,data,len);      if (asf->asf_is_dvr_ms)        dp->pts=time*0.0000001;      else        dp->pts=time*0.001;      dp->flags=keyframe;//      if(ds==demux->video) printf("ASF time: %8d  dur: %5d  \n",time,dur);      dp->pos=demux->filepos;      ds->asf_packet=dp;      ds->asf_seq=seq;      // we are ready now.      return 1;    }  }  return 0;}/***************************************************************** * \brief read the replicated data associated with each segment * \parameter pp reference to replicated data * \parameter id stream number * \parameter seq media object number * \parameter keyframe key frame indicator - set to zero if keyframe, non-zero otherwise * \parameter seg_time set to payload time when valid, if audio or new video frame payload, zero otherwise * */static void get_payload_extension_data(demuxer_t *demux, unsigned char** pp, unsigned char id, unsigned int seq, int *keyframe, uint64_t *seg_time){    struct asf_priv* asf = demux->priv;    uint64_t payload_time; //100ns units    int i, ext_max, ext_timing_index;    uint8_t *pi = *pp+4;    if(demux->video->id==-1)        if(demux->v_streams[id])            demux->video->id=id;    if(demux->audio->id==-1)        if(demux->a_streams[id])            demux->audio->id=id;    if (id!=demux->video->id && id!=demux->audio->id) return;    if (id==demux->video->id) {      ext_max = asf->vid_repdata_count;      ext_timing_index = asf->vid_ext_timing_index;    } else {      ext_max = asf->aud_repdata_count;      ext_timing_index = asf->aud_ext_timing_index;    }    *seg_time=0.0;    asf->new_vid_frame_seg = 0;    for (i=0; i<ext_max; i++) {            uint16_t payextsize;        uint8_t segment_marker;        if (id==demux->video->id)            payextsize = asf->vid_repdata_sizes[i];        else            payextsize = asf->aud_repdata_sizes[i];        if (payextsize == 65535) {            payextsize = LOAD_LE16(pi);            pi+=2;        }               // if this is the timing info extension then read the payload time        if (i == ext_timing_index)            payload_time =  (uint64_t) LOAD_LE32(pi+8) | (uint64_t)LOAD_LE32(pi+8 + 4) << 32;                // if this is the video frame info extension then         // set the keyframe indicator, the 'new frame segment' indicator        // and (initially) the 'frame time'        if (i == asf->vid_ext_frame_index && id==demux->video->id) {            segment_marker = pi[0];            // Known video stream segment_marker values that            // contain useful information:            //            // NTSC/ATSC (29.97fps):        0X4A 01001010            //                              0X4B 01001011            //                              0X49 01001001            //            // PAL/ATSC (25fps):            0X3A 00111010            //                              0X3B 00111011            //                              0X39 00111001            //            // ATSC progressive (29.97fps): 0X7A 01111010            //                              0X7B 01111011            //                              0X79 01111001            //   11111111            //       ^    this is new video frame marker            //            //   ^^^^     these bits indicate the framerate            //            0X4 is 29.97i, 0X3 is 25i, 0X7 is 29.97p, ???=25p             //            //        ^^^ these bits indicate the frame type:            //              001 means I-frame            //              010 and 011 probably mean P and B            asf->new_vid_frame_seg = (0X08 & segment_marker) && seq != asf->last_vid_seq;            if (asf->new_vid_frame_seg) asf->last_vid_seq = seq;            if (asf->avg_vid_frame_time == 0) {                // set the average frame time initially (in 100ns units).                 // This is based on what works for known samples.                // It can be extended if more samples of different types can be obtained.                if (((segment_marker & 0XF0) >> 4) == 4) {                    asf->avg_vid_frame_time = (uint64_t)((1.001 / 30.0) * 10000000.0);                    asf->know_frame_time=1;                } else if (((segment_marker & 0XF0) >> 4) == 3) {                    asf->avg_vid_frame_time = (uint64_t)(0.04 * 10000000.0);                    asf->know_frame_time=1;                } else if (((segment_marker & 0XF0) >> 4) == 6) {                    asf->avg_vid_frame_time = (uint64_t)(0.02 * 10000000.0);                    asf->know_frame_time=1;                } else if (((segment_marker & 0XF0) >> 4) == 7) {                    asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0);                    asf->know_frame_time=1;                } else {                    // we dont know the frame time initially so                     // make a guess and then recalculate as we go.                    asf->avg_vid_frame_time = (uint64_t)((1.001 / 60.0) * 10000000.0);                     asf->know_frame_time=0;                }            }            *keyframe = (asf->new_vid_frame_seg && (segment_marker & 0X07) == 1);        }        pi +=payextsize;    }    if (id==demux->video->id && asf->new_vid_frame_seg) {            asf->vid_frame_ct++;        // Some samples only have timings on key frames and         // the rest contain non-cronological timestamps. Interpolating        // the values between key frames works for all samples.        if (*keyframe) {            asf->found_first_key_frame=1;            if (!asf->know_frame_time && asf->last_key_payload_time > 0) {                // We dont know average frametime so recalculate.                // Giving precedence to the 'weight' of the existing                // average limits damage done to new value when there is                // a sudden time jump which happens occasionally.                asf->avg_vid_frame_time =                    (0.9 * asf->avg_vid_frame_time) +                   (0.1 * ((payload_time - asf->last_key_payload_time) / asf->vid_frame_ct));            }            asf->last_key_payload_time = payload_time;            asf->vid_frame_ct = 1;            *seg_time = payload_time;        } else            *seg_time = (asf->last_key_payload_time  + (asf->avg_vid_frame_time * (asf->vid_frame_ct-1)));    }    if (id==demux->audio->id) {        if (payload_time != -1)            asf->last_aud_diff = payload_time - asf->last_aud_pts;        asf->last_aud_pts += asf->last_aud_diff;        *seg_time = asf->last_aud_pts;   }}//static int num_elementary_packets100=0;//static int num_elementary_packets101=0;// return value://     0 = EOF or no stream found//     1 = successfully read a packetstatic int demux_asf_fill_buffer(demuxer_t *demux, demux_stream_t *ds){  struct asf_priv* asf = demux->priv;  demux->filepos=stream_tell(demux->stream);  // Brodcast stream have movi_start==movi_end  // Better test ?  if((demux->movi_start < demux->movi_end) && (demux->filepos>=demux->movi_end)){          demux->stream->eof=1;          return 0;  }    stream_read(demux->stream,asf->packet,asf->packetsize);    if(demux->stream->eof) return 0; // EOF        {	    unsigned char* p=asf->packet;            unsigned char* p_end=asf->packet+asf->packetsize;            unsigned char flags=p[0];            unsigned char segtype=p[1];            unsigned padding;            unsigned plen;	    unsigned sequence;            unsigned long time=0;            unsigned short duration=0;            int segs=1;            unsigned char segsizetype=0x80;            int seg=-1;            

⌨️ 快捷键说明

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