📄 mpegsystem.cpp
字号:
}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, ×tamp)) != 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 + -