demuxer.c

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

C
1,287
字号
    }    if(demux->video->packs>=MAX_PACKS || demux->video->bytes>=MAX_PACK_BYTES){      mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyVideoInBuffer,demux->video->packs,demux->video->bytes);      mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI);      break;    }    //F("1\n");    if(!demux_fill_buffer(demux,ds)){       //F("5\n");       mp_dbg(MSGT_DEMUXER,MSGL_DBG2,"ds_fill_buffer()->demux_fill_buffer() failed\n");       break; // EOF    }  }  ds->buffer_pos=ds->buffer_size=0;  ds->buffer=NULL;  ds->current=NULL;  mp_msg(MSGT_DEMUXER,MSGL_V,"ds_fill_buffer: EOF reached (stream: %s)  \n",ds==demux->audio?"audio":"video");  ds->eof=1;  return 0;}int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len){int x;int bytes=0;while(len>0){  x=ds->buffer_size-ds->buffer_pos;  if(x==0){    if(!ds_fill_buffer(ds)) return bytes;  } else {    if(x>len) x=len;    if(mem) fast_memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x);    bytes+=x;len-=x;ds->buffer_pos+=x;  }}return bytes;}int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len){int x;int bytes=0;while(len>0){  x=ds->buffer_size-ds->buffer_pos;  if(x==0){    if(!ds_fill_buffer(ds)) return bytes;  } else {    if(x>len) x=len;    if(mem) fast_memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x);    bytes+=x;len-=x;ds->buffer_pos+=x;    return bytes; // stop at end of package! (for correct timestamping)  }}return bytes;}/** * \brief read data until the given 3-byte pattern is encountered, up to maxlen * \param mem memory to read data into, may be NULL to discard data * \param maxlen maximum number of bytes to read * \param read number of bytes actually read * \param pattern pattern to search for (lowest 8 bits are ignored) * \return whether pattern was found */int demux_pattern_3(demux_stream_t *ds, unsigned char *mem, int maxlen,                    int *read, uint32_t pattern) {  register uint32_t head = 0xffffff00;  register uint32_t pat = pattern & 0xffffff00;  int total_len = 0;  do {    register unsigned char *ds_buf = &ds->buffer[ds->buffer_size];    int len = ds->buffer_size - ds->buffer_pos;    register long pos = -len;    if (unlikely(pos >= 0)) { // buffer is empty      ds_fill_buffer(ds);      continue;    }    do {      head |= ds_buf[pos];      head <<= 8;    } while (++pos && head != pat);    len += pos;    if (total_len + len > maxlen)      len = maxlen - total_len;    len = demux_read_data(ds, mem ? &mem[total_len] : NULL, len);    total_len += len;  } while ((head != pat || total_len < 3) && total_len < maxlen && !ds->eof);  if (read)    *read = total_len;  return total_len >= 3 && head == pat;}void ds_free_packs(demux_stream_t *ds){  demux_packet_t *dp=ds->first;  while(dp){    demux_packet_t *dn=dp->next;    free_demux_packet(dp);    dp=dn;  }  if(ds->asf_packet){    // free unfinished .asf fragments:    free(ds->asf_packet->buffer);    free(ds->asf_packet);    ds->asf_packet=NULL;  }  ds->first=ds->last=NULL;  ds->packs=0; // !!!!!  ds->bytes=0;  if(ds->current) free_demux_packet(ds->current);  ds->current=NULL;  ds->buffer=NULL;  ds->buffer_pos=ds->buffer_size;  ds->pts=0; ds->pts_bytes=0;}int ds_get_packet(demux_stream_t *ds,unsigned char **start){    while(1){        int len;        if(ds->buffer_pos>=ds->buffer_size){          if(!ds_fill_buffer(ds)){            // EOF            *start = NULL;            return -1;          }        }        len=ds->buffer_size-ds->buffer_pos;        *start = &ds->buffer[ds->buffer_pos];        ds->buffer_pos+=len;        return len;    }}int ds_get_packet_pts(demux_stream_t *ds,unsigned char **start, double *pts){    int len;    *pts = MP_NOPTS_VALUE;    if(ds->buffer_pos>=ds->buffer_size){	if (!ds_fill_buffer(ds)) {            // EOF            *start = NULL;            return -1;	}    }    // Should use MP_NOPTS_VALUE for "unknown pts" in the packets too    // Return pts unless this read starts from the middle of a packet    if (!ds->buffer_pos && (correct_pts || ds->current->pts))	*pts = ds->current->pts;    len=ds->buffer_size-ds->buffer_pos;    *start = &ds->buffer[ds->buffer_pos];    ds->buffer_pos+=len;    return len;}int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start){    while(1){        int len;        if(ds->buffer_pos>=ds->buffer_size){          *start = NULL;          if(!ds->packs) return -1; // no sub          if(!ds_fill_buffer(ds)) return -1; // EOF        }        len=ds->buffer_size-ds->buffer_pos;        *start = &ds->buffer[ds->buffer_pos];        ds->buffer_pos+=len;        return len;    }}double ds_get_next_pts(demux_stream_t *ds){  demuxer_t* demux = ds->demuxer;  while(!ds->first) {    if(demux->audio->packs>=MAX_PACKS || demux->audio->bytes>=MAX_PACK_BYTES){      mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyAudioInBuffer,demux->audio->packs,demux->audio->bytes);      mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI);      return MP_NOPTS_VALUE;    }    if(demux->video->packs>=MAX_PACKS || demux->video->bytes>=MAX_PACK_BYTES){      mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyVideoInBuffer,demux->video->packs,demux->video->bytes);      mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI);      return MP_NOPTS_VALUE;    }    if(!demux_fill_buffer(demux,ds))      return MP_NOPTS_VALUE;  }  return ds->first->pts;}// ====================================================================void demuxer_help(void){  int i;  mp_msg(MSGT_DEMUXER, MSGL_INFO, "Available demuxers:\n");  mp_msg(MSGT_DEMUXER, MSGL_INFO, " demuxer:  type  info:  (comment)\n");  mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXERS\n");  for (i = 0; demuxer_list[i]; i++) {    if (demuxer_list[i]->type > DEMUXER_TYPE_MAX) // Don't display special demuxers      continue;    if (demuxer_list[i]->comment && strlen(demuxer_list[i]->comment))      mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s  %2d   %s (%s)\n",             demuxer_list[i]->name, demuxer_list[i]->type, demuxer_list[i]->info, demuxer_list[i]->comment);    else      mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s  %2d   %s\n",             demuxer_list[i]->name, demuxer_list[i]->type, demuxer_list[i]->info);  }}/** * Get demuxer type for a given demuxer name * * @param demuxer_name    string with demuxer name of demuxer number * @param force           will be set if demuxer should be forced. *                        May be NULL. * @return                DEMUXER_TYPE_xxx, -1 if error or not found */int get_demuxer_type_from_name(char *demuxer_name, int *force){  int i;  long type_int;  char *endptr;  if (!demuxer_name || !demuxer_name[0])    return DEMUXER_TYPE_UNKNOWN;  if (force) *force = demuxer_name[0] == '+';  if (demuxer_name[0] == '+')    demuxer_name = &demuxer_name[1];  for (i = 0; demuxer_list[i]; i++) {    if (demuxer_list[i]->type > DEMUXER_TYPE_MAX) // Can't select special demuxers from commandline      continue;    if (strcmp(demuxer_name, demuxer_list[i]->name) == 0)      return  demuxer_list[i]->type;  }  // No match found, try to parse name as an integer (demuxer number)  type_int = strtol(demuxer_name, &endptr, 0);  if (*endptr) // Conversion failed    return -1;  if ((type_int > 0) && (type_int <= DEMUXER_TYPE_MAX))    return (int)type_int;  return -1;}int extension_parsing=1; // 0=off 1=mixed (used only for unstable formats)int correct_pts=0;/*  NOTE : Several demuxers may be opened at the same time so  demuxers should NEVER rely on an external var to enable them  self. If a demuxer can't do any autodection it should only use  file_format. The user can explictly set file_format with the -demuxer  option so there is really no need for another extra var.  For conivence an option can be added to set file_format directly  to the right type (ex: rawaudio,rawvideo).  Also the stream can override the file_format so a demuxer wich rely  on a special stream type can set file_format at the stream level  (ex: tv,mf).*/static demuxer_t* demux_open_stream(stream_t *stream, int file_format,                    int force, int audio_id, int video_id, int dvdsub_id,                    char* filename) {//int file_format=(*file_format_ptr);demuxer_t *demuxer=NULL;sh_video_t *sh_video=NULL;demuxer_desc_t *demuxer_desc;int fformat = 0;int i;//printf("demux_open(%p,%d,%d,%d,%d)  \n",stream,file_format,audio_id,video_id,dvdsub_id);//F("demux_open(%p,%d,%d,%d,%d %s)  \n",stream,file_format,audio_id,video_id,dvdsub_id,filename);// If somebody requested a demuxer check itif (file_format) {//F("1\n")  if ((demuxer_desc = get_demuxer_desc_from_type(file_format))) {//F("2\n")    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);//F("3\n")    if (demuxer_desc->check_file)      fformat = demuxer_desc->check_file(demuxer);//F("4\n")          if (force || !demuxer_desc->check_file)      fformat = demuxer_desc->type;    if (fformat != 0) {      if (fformat == demuxer_desc->type) {        demuxer_t *demux2 = demuxer;        // Move messages to demuxer detection code?        mp_msg(MSGT_DEMUXER, MSGL_INFO, MSGTR_Detected_XXX_FileFormat, demuxer_desc->shortdesc);        file_format = demuxer_desc->type = fformat;        if (!demuxer->desc->open || (demux2 = demuxer->desc->open(demuxer))) {          demuxer = demux2;          goto dmx_open;        }      } else {        // Format changed after check, recurse //F("5\n")               free_demuxer(demuxer); //F("6\n")                return demux_open_stream(stream, fformat, force,                 audio_id, video_id, dvdsub_id, filename);      }    }    // Check failed for forced demuxer, quit    free_demuxer(demuxer);    return NULL;  }}#if 0// Test demuxers with safe file checksfor (i = 0; (demuxer_desc = demuxer_list[i]); i++) {	//F("%d",i);  if (demuxer_desc->safe_check) {  	//F("new demuxer\n");    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);    //F("new demuxer\n");    if ((fformat = demuxer_desc->check_file(demuxer)) != 0) {     // F("8\n");      if (fformat == demuxer_desc->type) {        demuxer_t *demux2 = demuxer;        mp_msg(MSGT_DEMUXER, MSGL_INFO, MSGTR_Detected_XXX_FileFormat, demuxer_desc->shortdesc);        file_format = fformat;        if (!demuxer->desc->open || (demux2 = demuxer->desc->open(demuxer))) {          demuxer = demux2;          goto dmx_open;        }      } else {        if (fformat == DEMUXER_TYPE_PLAYLIST)          return demuxer; // handled in mplayer.c        // Format changed after check, recurse   //     F("4\n");        free_demuxer(demuxer);   //     F("5\n");        demuxer=demux_open_stream(stream, fformat, force,                  audio_id, video_id, dvdsub_id, filename);        if(demuxer) return demuxer; // done!        file_format = DEMUXER_TYPE_UNKNOWN;      }    }    free_demuxer(demuxer);    demuxer = NULL;  }}#endif// If no forced demuxer perform file extension based detection// Ok. We're over the stable detectable fileformats, the next ones are a bit// fuzzy. So by default (extension_parsing==1) try extension-based detection// first:if(file_format==DEMUXER_TYPE_UNKNOWN && filename && extension_parsing==1){  file_format=demuxer_type_by_filename(filename);  if(file_format!=DEMUXER_TYPE_UNKNOWN){    // we like recursion :)    demuxer=demux_open_stream(stream, file_format, force,              audio_id, video_id, dvdsub_id, filename);    if(demuxer) return demuxer; // done!    file_format=DEMUXER_TYPE_UNKNOWN; // continue fuzzy guessing...    mp_msg(MSGT_DEMUXER,MSGL_V,"demuxer: continue fuzzy content-based format guessing...\n");  }}#if 1// Test demuxers with safe file checksfor (i = 0; (demuxer_desc = demuxer_list[i]); i++) {	//F("%d",i);  if (demuxer_desc->safe_check) {  	//F("new demuxer\n");    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);    //F("new demuxer\n");    if ((fformat = demuxer_desc->check_file(demuxer)) != 0) {     // F("8\n");      if (fformat == demuxer_desc->type) {        demuxer_t *demux2 = demuxer;        mp_msg(MSGT_DEMUXER, MSGL_INFO, MSGTR_Detected_XXX_FileFormat, demuxer_desc->shortdesc);        file_format = fformat;        if (!demuxer->desc->open || (demux2 = demuxer->desc->open(demuxer))) {          demuxer = demux2;          goto dmx_open;        }      } else {        if (fformat == DEMUXER_TYPE_PLAYLIST)          return demuxer; // handled in mplayer.c        // Format changed after check, recurse   //     F("4\n");        free_demuxer(demuxer);   //     F("5\n");        demuxer=demux_open_stream(stream, fformat, force,                  audio_id, video_id, dvdsub_id, filename);        if(demuxer) return demuxer; // done!        file_format = DEMUXER_TYPE_UNKNOWN;      }    }    free_demuxer(demuxer);    demuxer = NULL;  }}#endif// Try detection for all other demuxersfor (i = 0; (demuxer_desc = demuxer_list[i]); i++) {  if (!demuxer_desc->safe_check && demuxer_desc->check_file) {    demuxer = new_demuxer(stream,demuxer_desc->type,audio_id,video_id,dvdsub_id,filename);    if ((fformat = demuxer_desc->check_file(demuxer)) != 0) {      if (fformat == demuxer_desc->type) {        demuxer_t *demux2 = demuxer;        mp_msg(MSGT_DEMUXER, MSGL_INFO, MSGTR_Detected_XXX_FileFormat, demuxer_desc->shortdesc);        file_format = fformat;        if (!demuxer->desc->open || (demux2 = demuxer->desc->open(demuxer))) {          demuxer = demux2;          goto dmx_open;        }      } else {        if (fformat == DEMUXER_TYPE_PLAYLIST)          return demuxer; // handled in mplayer.c        // Format changed after check, recurse        free_demuxer(demuxer);        demuxer=demux_open_stream(stream, fformat, force,                  audio_id, video_id, dvdsub_id, filename);        if(demuxer) return demuxer; // done!        file_format = DEMUXER_TYPE_UNKNOWN;      }    }    free_demuxer(demuxer);    demuxer = NULL;  }}

⌨️ 快捷键说明

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