⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpegsystem.cpp

📁 This code is based on mpeg_play, available from: http://bmrc.berkeley.edu/frame/research/mpeg/
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}void MPEGsystem::Read(){  int remaining;  int timeout;  /* Lock to prevent concurrent access to the stream */  SDL_mutexP(system_mutex);  timeout = READ_TIME_OUT;  remaining = read_buffer + read_size - pointer;  /* Only read data if buffer is rather empty */  if(remaining < MPEG_BUFFER_SIZE / 2)  {    if(remaining < 0)    {      /* Hum.. we'd better stop if we have already read past the buffer size */      errorstream = true;      SDL_mutexV(system_mutex);      return;    }    /* Replace unread data at the beginning of the stream */    memmove(read_buffer, pointer, remaining);#ifdef NO_GRIFF_MODS    read_size = SDL_RWread(source,                    read_buffer + remaining,                     READ_ALIGN(MPEG_BUFFER_SIZE - remaining));    if(read_size < 0)    {      perror("Read");      errorstream = true;      SDL_mutexV(system_mutex);      return;    }#else    /* Read new data */    int bytes_read    = 0;    int buffer_offset = remaining;    int bytes_to_read = READ_ALIGN(MPEG_BUFFER_SIZE - remaining);    int read_at_once = 0;    read_size = 0;    do    {      read_at_once =         SDL_RWread(source, read_buffer + buffer_offset, 1, bytes_to_read );      if(read_at_once < 0)      {        perror("Read");        errorstream = true;        SDL_mutexV(system_mutex);        return;      }      else      {        bytes_read    += read_at_once;        buffer_offset += read_at_once;        read_size     += read_at_once;        bytes_to_read -= read_at_once;      }    }    while( read_at_once>0 && bytes_to_read>0 );#endif    read_total += read_size;    packet_total ++;    if((MPEG_BUFFER_SIZE - remaining) != 0 && read_size <= 0)    {      if(read_size != 0)      {	errorstream = true;	SDL_mutexV(system_mutex);	return;      }    }    read_size += remaining;    /* Move the pointer */    pointer = read_buffer;      if(read_size == 0)    {      /* There is no more data */      endofstream = true;      SDL_mutexV(system_mutex);      return;    }  }  SDL_mutexV(system_mutex);}/* ASSUME: stream_list[0] = system stream *//*         packet length < MPEG_BUFFER_SIZE */Uint8 MPEGsystem::FillBuffer(){  Uint8 stream_id;  Uint32 packet_size;  Uint32 header_size;  /* - Read a new packet - */  Read();  if(Eof())  {    RequestBuffer();    return(0);  }  pointer += skip_zeros(pointer, read_buffer + read_size - pointer);   if((header_size = packet_header(pointer, read_buffer + read_size - pointer, &timestamp)) != 0)  {      pointer += header_size;      stream_list[0]->pos += header_size;#ifdef DEBUG_SYSTEM      fprintf(stderr, "MPEG packet header time: %lf\n", timestamp);#endif  }  if((header_size = stream_header(pointer, read_buffer + read_size - pointer, &packet_size, &stream_id, &stream_timestamp, timestamp)) != 0)  {      pointer += header_size;      stream_list[0]->pos += header_size;#ifdef DEBUG_SYSTEM      fprintf(stderr, "[%d] MPEG stream header [%d|%d] id: %d streamtime: %lf\n", read_total - read_size + (pointer - read_buffer),header_size, packet_size, stream_id, stream_timestamp);#endif  }  else  if(Match4(pointer, END_CODE, END_MASK) ||     Match4(pointer, END2_CODE, END2_MASK))  {    /* End codes belong to video stream */#ifdef DEBUG_SYSTEM    fprintf(stderr, "[%d] MPEG end code\n", read_total - read_size + (pointer - read_buffer));#endif    stream_id = exist_stream(VIDEO_STREAMID, 0xF0);    packet_size = 4;  }  else  {    stream_id = stream_list[0]->streamid;    if(!stream_list[1])    {       //Uint8 * packet_end;      packet_size = 0;      /* There is no system info in the stream */      /* If we're still a system stream, morph to an audio */      /* or video stream */      /* Sequence header -> gives framerate */      while((header_size = sequence_header(pointer+packet_size, read_buffer + read_size - pointer - packet_size, &frametime)) != 0)      {	stream_id = VIDEO_STREAMID;	stream_list[0]->streamid = stream_id;	packet_size += header_size;#ifdef DEBUG_SYSTEM	fprintf(stderr, "MPEG sequence header  frametime: %lf\n", frametime);#endif      }      /* GOP header */      while((header_size = gop_header(pointer+packet_size, read_buffer + read_size - pointer - packet_size, 0)) != 0)      {	packet_size += header_size; #ifdef DEBUG_SYSTEM	fprintf(stderr, "MPEG gop header\n");#endif      }      /* Picture header */      while((header_size = picture_header(pointer+packet_size, read_buffer + read_size - pointer - packet_size)) != 0)      {	packet_size += header_size;    // Warning: header size not quite correct (can be not byte aligned)	stream_timestamp += frametime; // but this is compensated by skipping a little more, as we don't need to be header aligned		packet_size += 4;              // after this, since we then check for the next header to know the slice size.#ifdef DEBUG_SYSTEM	fprintf(stderr, "MPEG picture header\n");#endif      }      /* Slice header */      while((header_size = slice_header(pointer+packet_size, read_buffer + read_size - pointer - packet_size)) != 0)      {	packet_size += header_size;    #ifdef DEBUG_SYSTEM	fprintf(stderr, "MPEG slice header\n");#endif      }      /* Audio frame */      if(audio_header(pointer+packet_size, &packet_size, &frametime))      {	  stream_id = AUDIO_STREAMID;	  stream_list[0]->streamid = stream_id;	  stream_timestamp += frametime;#ifdef DEBUG_SYSTEM	  fprintf(stderr, "MPEG audio header [%d] time: %lf @ %lf\n", packet_size, frametime, stream_timestamp);#endif      }      else      {	/* Check for next slice, picture, gop or sequence header */	register Uint8 * p;	register Uint8 c;		p = pointer + packet_size;      state0:	c = *p;	p++;	if(p >= read_buffer + read_size) goto end;	if(c != 0) goto state0;/* Not explicitly reached:      state1: */	c = *p;	p++;	if(p >= read_buffer + read_size) goto end;	if(c != 0) goto state0;      state2:	c = *p;	p++;	if(p >= read_buffer + read_size) goto end;	if(c == 0) goto state2;	if(c != 1) goto state0;/* Not explicitly reached:      state3: */	c = *p;	p++;	if(p >= read_buffer + read_size) goto end;	if(c <= 0xaf) goto end;	if(c == 0xb8) goto end;	if(c == 0xb3) goto end;	goto state0;      end:	if(p >= read_buffer + read_size) packet_size = (read_buffer + read_size) - pointer;	else packet_size = p - pointer - 4;      }      if(stream_id == SYSTEM_STREAMID)	stream_id = 0;    }    else    {#ifdef DEBUG_SYSTEM	fprintf(stderr,		"Warning: unexpected header %02x%02x%02x%02x at offset %d\n",		pointer[0],		pointer[1],		pointer[2],		pointer[3],		read_total - read_size + (pointer - read_buffer));#endif	pointer++;	stream_list[0]->pos++;	seek_next_header();	RequestBuffer();	return(0);    }  }  if(Eof())  {    RequestBuffer();    return(0);  }  assert(packet_size <= MPEG_BUFFER_SIZE);  if(skip_timestamp > timestamp){    int cur_seconds=int(timestamp)%60;    if (cur_seconds%5==0){      fprintf(stderr, "Skiping to %02d:%02d (%02d:%02d)\r",              int(skip_timestamp)/60, int(skip_timestamp)%60,              int(timestamp)/60, cur_seconds);    }    pointer += packet_size;    stream_list[0]->pos += packet_size;    /* since we skip data, request more */    RequestBuffer();    return (0);  }  switch(stream_id)  {    case 0:      /* Unknown stream, just get another packet */      pointer += packet_size;      stream_list[0]->pos += packet_size;      RequestBuffer();    return(0);    case SYSTEM_STREAMID:      /* System header */      /* This MPEG contain system information */      /* Parse the system header and create MPEG streams  */          /* Read the stream table */      pointer += 5;      stream_list[0]->pos += 5;      while (pointer[0] & 0x80 )      {	/* If the stream doesn't already exist */	if(!get_stream(pointer[0]))	{	  /* Create a new stream and add it to the list */	  add_stream(new MPEGstream(this, pointer[0]));	}	pointer += 3;	stream_list[0]->pos += 3;      }                /* Hack to detect video streams that are not advertised */      if ( ! exist_stream(VIDEO_STREAMID, 0xF0) ) {	if ( pointer[3] == 0xb3 ) {	  add_stream(new MPEGstream(this, VIDEO_STREAMID));	}      }      RequestBuffer();    return(stream_id);    default:      MPEGstream * stream;      /* Look for the stream the data must be given to */      stream = get_stream(stream_id);      if(!stream)      {		/* Hack to detect video or audio streams that are not declared in system header */	if ( ((stream_id & 0xF0) == VIDEO_STREAMID) && !exist_stream(stream_id, 0xFF) ) {#ifdef DEBUG_SYSTEM	  fprintf(stderr, "Undeclared video packet, creating a new video stream\n");#endif	    stream = new MPEGstream(this, stream_id);	    add_stream(stream);	}	else	if ( ((stream_id & 0xF0) == AUDIO_STREAMID) && !exist_stream(stream_id, 0xFF) ) {#ifdef DEBUG_SYSTEM	  fprintf(stderr, "Undeclared audio packet, creating a new audio stream\n");#endif	    stream = new MPEGstream(this, stream_id);	    add_stream(stream);	}	else	{	  /* No stream found for packet, skip it */	  pointer += packet_size;	  stream_list[0]->pos += packet_size;	  RequestBuffer();	  return(stream_id);	}      }      /* Insert the new data at the end of the stream */      if(pointer + packet_size <= read_buffer + read_size)      {	if(packet_size) stream->insert_packet(pointer, packet_size, stream_timestamp);	pointer += packet_size;      }      else      {	stream->insert_packet(pointer, 0, stream_timestamp);	errorstream = true;	pointer = read_buffer + read_size;      }      return(stream_id);  }}void MPEGsystem::Skip(double time){  if (skip_timestamp < timestamp)    skip_timestamp = timestamp;  skip_timestamp += time;} Uint32 MPEGsystem::Tell(){  register Uint32 t;  register int i;  /* Sum all stream positions */  for(i = 0, t = 0; stream_list[i]; i++)    t += stream_list[i]->pos;  if(t > TotalSize())    return(TotalSize());  else    return(t);}Uint32 MPEGsystem::TotalSize(){  off_t size;  off_t pos;  /* Lock to avoid concurrent access to the stream */  SDL_mutexP(system_mutex);  /* I made it this way (instead of fstat) to avoid #ifdef WIN32 everywhere */  /* in case 'in some weird perversion of nature' someone wants to port this to Win32 :-) */  if((pos = SDL_RWtell(source)) < 0)  {    if(errno != ESPIPE)    {      errorstream = true;      SetError(strerror(errno));    }    SDL_mutexV(system_mutex);    return(0);  }  if((size = SDL_RWseek(source, 0, SEEK_END)) < 0)  {    if(errno != ESPIPE)    {      errorstream = true;      SetError(strerror(errno));      }    SDL_mutexV(system_mutex);    return(0);  }    if((pos = SDL_RWseek(source, pos, SEEK_SET)) < 0)  {    if(errno != ESPIPE)    {      errorstream = true;      SetError(strerror(errno));      }    SDL_mutexV(system_mutex);    return(0);  }  SDL_mutexV(system_mutex);  return(size);}double MPEGsystem::TotalTime(){  off_t size, pos;  off_t file_ptr;  Uint8 * buffer, * p;  double time;  /* Lock to avoid concurrent access to the stream */  SDL_mutexP(system_mutex);  /* Save current position */  if((pos = SDL_RWtell(source)) < 0)  {    if(errno != ESPIPE)    {      errorstream = true;      SetError(strerror(errno));    }    SDL_mutexV(system_mutex);    return(false);  }  file_ptr = 0;  buffer = new Uint8[MPEG_BUFFER_SIZE];  time = 0;  /* If audio, compute total time according to bitrate of the first header and total size */  /* Note: this doesn't work on variable bitrate streams */  if(stream_list[0]->streamid == AUDIO_STREAMID)  {    do    {      if((size = SDL_RWseek(source, file_ptr, SEEK_SET)) < 0)      {

⌨️ 快捷键说明

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