📄 mpegsystem.cpp
字号:
if(errno != ESPIPE) { errorstream = true; SetError(strerror(errno)); } SDL_mutexV(system_mutex); return(false); } if(SDL_RWread(source, buffer, 1, MPEG_BUFFER_SIZE) < 0) break; /* Search for a valid audio header */ for(p = buffer; p < buffer + MPEG_BUFFER_SIZE; p++) if(audio_aligned(p, buffer + MPEG_BUFFER_SIZE - p)) break; file_ptr += MPEG_BUFFER_SIZE; } while(p >= MPEG_BUFFER_SIZE + buffer); /* Extract time info from the first header */ Uint32 framesize; double frametime; Uint32 totalsize; audio_header(p, &framesize, &frametime); totalsize = TotalSize(); if(framesize) time = frametime * totalsize / framesize; } else { bool last_chance = false; do { /* Otherwise search the stream backwards for a valid header */ file_ptr -= MPEG_BUFFER_SIZE; if ( file_ptr < -(Sint32)TotalSize() ) { last_chance = true; file_ptr = -(Sint32)TotalSize(); } if((size = SDL_RWseek(source, file_ptr, SEEK_END)) < 0) { if(errno != ESPIPE) { errorstream = true; SetError(strerror(errno)); } SDL_mutexV(system_mutex); return(false); } if(SDL_RWread(source, buffer, 1, MPEG_BUFFER_SIZE) < 0) break; if(stream_list[0]->streamid == SYSTEM_STREAMID) for(p = buffer + MPEG_BUFFER_SIZE - 1; p >= buffer;) { if(*p-- != 0xba) continue; // Packet header if(*p-- != 1) continue; if(*p-- != 0) continue; if(*p-- != 0) continue; ++p; break; } if(stream_list[0]->streamid == VIDEO_STREAMID) for(p = buffer + MPEG_BUFFER_SIZE - 1; p >= buffer;) { if(*p-- != 0xb8) continue; // GOP header if(*p-- != 1) continue; if(*p-- != 0) continue; if(*p-- != 0) continue; ++p; break; } } while( !last_chance && (p < buffer) ); if ( p >= buffer ) { /* Extract time info from the last header */ if(stream_list[0]->streamid == SYSTEM_STREAMID) packet_header(p, buffer + MPEG_BUFFER_SIZE - p, &time); if(stream_list[0]->streamid == VIDEO_STREAMID) gop_header(p, buffer + MPEG_BUFFER_SIZE - p, &time); } } delete[] buffer; /* Get back to saved position */ if((pos = SDL_RWseek(source, pos, SEEK_SET)) < 0) { if(errno != ESPIPE) { errorstream = true; SetError(strerror(errno)); } time = 0; } SDL_mutexV(system_mutex); return(time);}double MPEGsystem::TimeElapsedAudio(int atByte){ off_t size, pos; off_t file_ptr; Uint8 * buffer, * p; double time; if (atByte < 0) { return -1; } /* 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]; /* 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) { if(errno != ESPIPE) { errorstream = true; SetError(strerror(errno)); } SDL_mutexV(system_mutex); return(false); } if(SDL_RWread(source, buffer, 1, MPEG_BUFFER_SIZE) < 0) break; /* Search for a valid audio header */ for(p = buffer; p < buffer + MPEG_BUFFER_SIZE; p++) if(audio_aligned(p, buffer + MPEG_BUFFER_SIZE - p)) break; file_ptr += MPEG_BUFFER_SIZE; } while(p >= MPEG_BUFFER_SIZE + buffer); /* Extract time info from the first header */ Uint32 framesize; double frametime; Uint32 totalsize; audio_header(p, &framesize, &frametime); totalsize = TotalSize(); if(framesize) //is there a better way to do this? time = (frametime * (atByte ? atByte:totalsize)) / framesize; else time = 0; } else //This is not a purely audio stream. This doesn't make sense! { time = -1; } delete buffer; /* Get back to saved position */ 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(time);}void MPEGsystem::Rewind(){ Seek(0);}bool MPEGsystem::Seek(int length){ /* Stop the system thread */ Stop(); /* Lock to avoid concurrent access to the stream */ SDL_mutexP(system_mutex); /* Get into the stream */ if(SDL_RWseek(source, length, SEEK_SET) < 0) { if(errno != ESPIPE) { errorstream = true; SetError(strerror(errno)); } return(false); } /* Reinitialize the read buffer */ pointer = read_buffer; read_size = 0; read_total = length; stream_list[0]->pos += length; packet_total = 0; endofstream = false; errorstream = false; timestamp = 0.0; skip_timestamp = -1; SDL_mutexV(system_mutex); /* Restart the system thread */ Start(); return(true);}void MPEGsystem::Loop(bool toggle){ looping = toggle; loop_all_streams(looping);}void MPEGsystem::RequestBuffer(){ SDL_SemPost(request_wait);}void MPEGsystem::Start(){ if(system_thread_running) return; /* Get the next header */ if(!seek_next_header()) { if(!Eof()) { errorstream = true; SetError("Could not find the beginning of MPEG data\n"); } } #ifdef USE_SYSTEM_THREAD /* Start the system thread */ system_thread = SDL_CreateThread(SystemThread, this); /* Wait for the thread to start */ while(!system_thread_running && !Eof()) SDL_Delay(1);#else system_thread_running = true;#endif}void MPEGsystem::Stop(){ if(!system_thread_running) return; /* Force the system thread to die */ system_thread_running = false;#ifdef USE_SYSTEM_THREAD SDL_SemPost(request_wait); SDL_WaitThread(system_thread, NULL);#endif /* Reset the streams */ reset_all_streams();}bool MPEGsystem::Wait(){ if ( ! errorstream ) { while(SDL_SemValue(request_wait) != 0)#ifdef USE_SYSTEM_THREAD SDL_Delay(1);#else if ( ! SystemLoop(this) ) break;#endif } return(!errorstream);}bool MPEGsystem::Eof() const{ return(errorstream || endofstream);}bool MPEGsystem::SystemLoop(MPEGsystem *system){ /* Check for end of file */ if(system->Eof()) { /* Set the eof mark on all streams */ system->end_all_streams(); /* Get back to the beginning of the stream if possible */ if(SDL_RWseek(system->source, 0, SEEK_SET) < 0) { if(errno != ESPIPE) { system->errorstream = true; system->SetError(strerror(errno)); } return(false); } /* Reinitialize the read buffer */ system->pointer = system->read_buffer; system->read_size = 0; system->read_total = 0; system->packet_total = 0; system->endofstream = false; system->errorstream = false; /* Get the first header */ if(!system->seek_first_header()) { system->errorstream = true; system->SetError("Could not find the beginning of MPEG data\n"); return(false); } } /* Wait for a buffer request */ SDL_SemWait(system->request_wait); /* Read the buffer */ system->FillBuffer(); return(true);}int MPEGsystem::SystemThread(void * udata){ MPEGsystem * system = (MPEGsystem *) udata; system->system_thread_running = true; while(system->system_thread_running) { if ( ! SystemLoop(system) ) { system->system_thread_running = false; } } return(true);}void MPEGsystem::add_stream(MPEGstream * stream){ register int i; /* Go to the end of the list */ for(i = 0; stream_list[i]; i++); /* Resize list */ stream_list = (MPEGstream **) realloc(stream_list, (i+2)*sizeof(MPEGstream *)); /* Write the stream */ stream_list[i] = stream; /* Set the looping flag for that stream */ stream->loop(looping); /* Put the end marker (null) */ stream_list[i+1] = 0;}MPEGstream * MPEGsystem::get_stream(Uint8 stream_id){ register int i; for(i = 0; stream_list[i]; i++) if(stream_list[i]->streamid == stream_id) break; return(stream_list[i]);}Uint8 MPEGsystem::exist_stream(Uint8 stream_id, Uint8 mask){ register int i; for(i = 0; stream_list[i]; i++) if(((stream_list[i]->streamid) & mask) == (stream_id & mask)) return(stream_list[i]->streamid); return(0);}void MPEGsystem::reset_all_streams(){ register int i; /* Reset the streams */ for(i = 0; stream_list[i]; i++) stream_list[i]->reset_stream();}void MPEGsystem::end_all_streams(){ register int i; /* End the streams */ /* We use a null buffer as the end of stream marker */ for(i = 0; stream_list[i]; i++) stream_list[i]->insert_packet(0, 0);}void MPEGsystem::loop_all_streams(bool toggle){ register int i; /* Set loop flag on all streams */ for(i = 0; stream_list[i]; i++) stream_list[i]->loop(toggle);}bool MPEGsystem::seek_first_header(){ Read(); if(Eof()) return(false); while(!(audio_aligned(pointer, read_buffer + read_size - pointer) || system_aligned(pointer, read_buffer + read_size - pointer) || Match4(pointer, VIDEO_CODE, VIDEO_MASK))) { ++pointer; stream_list[0]->pos++; /* Make sure buffer is always full */ Read(); if(Eof()) return(false); } return(true);}bool MPEGsystem::seek_next_header(){ Read(); if(Eof()) return(false); while(!( (stream_list[0]->streamid == AUDIO_STREAMID && audio_aligned(pointer, read_buffer + read_size - pointer)) || (stream_list[0]->streamid == SYSTEM_STREAMID && system_aligned(pointer, read_buffer + read_size - pointer)) || (stream_list[0]->streamid == VIDEO_STREAMID && Match4(pointer, GOP_CODE, GOP_MASK)) ) ) { ++pointer; stream_list[0]->pos++; /* Make sure buffer is always full */ Read(); if(Eof()) return(false); } return(true);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -