📄 mpeg1or2videostreamframer.cpp
字号:
};unsigned MPEG1or2VideoStreamParser::parseVideoSequenceHeader(Boolean haveSeenStartCode) {#ifdef DEBUG fprintf(stderr, "parsing video sequence header\n");#endif unsigned first4Bytes; if (!haveSeenStartCode) { while ((first4Bytes = test4Bytes()) != VIDEO_SEQUENCE_HEADER_START_CODE) {#ifdef DEBUG fprintf(stderr, "ignoring non video sequence header: 0x%08x\n", first4Bytes);#endif get1Byte(); setParseState(PARSING_VIDEO_SEQUENCE_HEADER); // ensures we progress over bad data } first4Bytes = get4Bytes(); } else { // We've already seen the start code first4Bytes = VIDEO_SEQUENCE_HEADER_START_CODE; } save4Bytes(first4Bytes); // Next, extract the size and rate parameters from the next 8 bytes unsigned paramWord1 = get4Bytes(); save4Bytes(paramWord1); unsigned next4Bytes = get4Bytes();#ifdef DEBUG unsigned short horizontal_size_value = (paramWord1&0xFFF00000)>>(32-12); unsigned short vertical_size_value = (paramWord1&0x000FFF00)>>8; unsigned char aspect_ratio_information = (paramWord1&0x000000F0)>>4;#endif unsigned char frame_rate_code = (paramWord1&0x0000000F); usingSource()->fFrameRate = frameRateFromCode[frame_rate_code];#ifdef DEBUG unsigned bit_rate_value = (next4Bytes&0xFFFFC000)>>(32-18); unsigned vbv_buffer_size_value = (next4Bytes&0x00001FF8)>>3; fprintf(stderr, "horizontal_size_value: %d, vertical_size_value: %d, aspect_ratio_information: %d, frame_rate_code: %d (=>%f fps), bit_rate_value: %d (=>%d bps), vbv_buffer_size_value: %d\n", horizontal_size_value, vertical_size_value, aspect_ratio_information, frame_rate_code, usingSource()->fFrameRate, bit_rate_value, bit_rate_value*400, vbv_buffer_size_value);#endif // Now, copy all bytes that we see, up until we reach a GROUP_START_CODE // or a PICTURE_START_CODE: do { saveToNextCode(next4Bytes); } while (next4Bytes != GROUP_START_CODE && next4Bytes != PICTURE_START_CODE); setParseState((next4Bytes == GROUP_START_CODE) ? PARSING_GOP_HEADER_SEEN_CODE : PARSING_PICTURE_HEADER); // Compute this frame's timestamp by noting how many pictures we've seen // since the last GOP header: usingSource()->computePresentationTime(fPicturesSinceLastGOP); // Save this video_sequence_header, in case we need to insert a copy // into the stream later: saveCurrentVSH(); return curFrameSize();}unsigned MPEG1or2VideoStreamParser::parseGOPHeader(Boolean haveSeenStartCode) { // First check whether we should insert a previously-saved // 'video_sequence_header' here: if (needToUseSavedVSH()) return useSavedVSH();#ifdef DEBUG fprintf(stderr, "parsing GOP header\n");#endif unsigned first4Bytes; if (!haveSeenStartCode) { while ((first4Bytes = test4Bytes()) != GROUP_START_CODE) {#ifdef DEBUG fprintf(stderr, "ignoring non GOP start code: 0x%08x\n", first4Bytes);#endif get1Byte(); setParseState(PARSING_GOP_HEADER); // ensures we progress over bad data } first4Bytes = get4Bytes(); } else { // We've already seen the GROUP_START_CODE first4Bytes = GROUP_START_CODE; } save4Bytes(first4Bytes); // Next, extract the (25-bit) time code from the next 4 bytes: unsigned next4Bytes = get4Bytes(); unsigned time_code = (next4Bytes&0xFFFFFF80)>>(32-25);#if defined(DEBUG) || defined(DEBUG_TIMESTAMPS) Boolean drop_frame_flag = (time_code&0x01000000) != 0;#endif unsigned time_code_hours = (time_code&0x00F80000)>>19; unsigned time_code_minutes = (time_code&0x0007E000)>>13; unsigned time_code_seconds = (time_code&0x00000FC0)>>6; unsigned time_code_pictures = (time_code&0x0000003F);#if defined(DEBUG) || defined(DEBUG_TIMESTAMPS) fprintf(stderr, "time_code: 0x%07x, drop_frame %d, hours %d, minutes %d, seconds %d, pictures %d\n", time_code, drop_frame_flag, time_code_hours, time_code_minutes, time_code_seconds, time_code_pictures);#endif#ifdef DEBUG Boolean closed_gop = (next4Bytes&0x00000040) != 0; Boolean broken_link = (next4Bytes&0x00000020) != 0; fprintf(stderr, "closed_gop: %d, broken_link: %d\n", closed_gop, broken_link);#endif // Now, copy all bytes that we see, up until we reach a PICTURE_START_CODE: do { saveToNextCode(next4Bytes); } while (next4Bytes != PICTURE_START_CODE); // Record the time code: usingSource()->setTimeCode(time_code_hours, time_code_minutes, time_code_seconds, time_code_pictures, fPicturesSinceLastGOP); fPicturesSinceLastGOP = 0; // Compute this frame's timestamp: usingSource()->computePresentationTime(0); setParseState(PARSING_PICTURE_HEADER); return curFrameSize();}inline Boolean isSliceStartCode(unsigned fourBytes) { if ((fourBytes&0xFFFFFF00) != 0x00000100) return False; unsigned char lastByte = fourBytes&0xFF; return lastByte <= 0xAF && lastByte >= 1;}unsigned MPEG1or2VideoStreamParser::parsePictureHeader() {#ifdef DEBUG fprintf(stderr, "parsing picture header\n");#endif // Note that we've already read the PICTURE_START_CODE // Next, extract the temporal reference from the next 4 bytes: unsigned next4Bytes = get4Bytes(); unsigned short temporal_reference = (next4Bytes&0xFFC00000)>>(32-10); unsigned char picture_coding_type = (next4Bytes&0x00380000)>>19;#ifdef DEBUG unsigned short vbv_delay = (next4Bytes&0x0007FFF8)>>3; fprintf(stderr, "temporal_reference: %d, picture_coding_type: %d, vbv_delay: %d\n", temporal_reference, picture_coding_type, vbv_delay);#endif fSkippingCurrentPicture = fIFramesOnly && picture_coding_type != 1; if (fSkippingCurrentPicture) { // Skip all bytes that we see, up until we reach a slice_start_code: do { skipToNextCode(next4Bytes); } while (!isSliceStartCode(next4Bytes)); } else { // Save the PICTURE_START_CODE that we've already read: save4Bytes(PICTURE_START_CODE); // Copy all bytes that we see, up until we reach a slice_start_code: do { saveToNextCode(next4Bytes); } while (!isSliceStartCode(next4Bytes)); } setParseState(PARSING_SLICE); fCurrentSliceNumber = next4Bytes&0xFF; // Record the temporal reference: fCurPicTemporalReference = temporal_reference; // Compute this frame's timestamp: usingSource()->computePresentationTime(fCurPicTemporalReference); if (fSkippingCurrentPicture) { return parse(); // try again, until we get a non-skipped frame } else { return curFrameSize(); }}unsigned MPEG1or2VideoStreamParser::parseSlice() { // Note that we've already read the slice_start_code: unsigned next4Bytes = PICTURE_START_CODE|fCurrentSliceNumber;#ifdef DEBUG_SLICE fprintf(stderr, "parsing slice: 0x%08x\n", next4Bytes);#endif if (fSkippingCurrentPicture) { // Skip all bytes that we see, up until we reach a code of some sort: skipToNextCode(next4Bytes); } else { // Copy all bytes that we see, up until we reach a code of some sort: saveToNextCode(next4Bytes); } // The next thing to parse depends on the code that we just saw: if (isSliceStartCode(next4Bytes)) { // common case setParseState(PARSING_SLICE); fCurrentSliceNumber = next4Bytes&0xFF; } else { // Because we don't see any more slices, we are assumed to have ended // the current picture: ++fPicturesSinceLastGOP; ++usingSource()->fPictureCount; usingSource()->fPictureEndMarker = True; // HACK ##### switch (next4Bytes) { case SEQUENCE_END_CODE: { setParseState(PARSING_VIDEO_SEQUENCE_HEADER); break; } case VIDEO_SEQUENCE_HEADER_START_CODE: { setParseState(PARSING_VIDEO_SEQUENCE_HEADER_SEEN_CODE); break; } case GROUP_START_CODE: { setParseState(PARSING_GOP_HEADER_SEEN_CODE); break; } case PICTURE_START_CODE: { setParseState(PARSING_PICTURE_HEADER); break; } default: { usingSource()->envir() << "MPEG1or2VideoStreamParser::parseSlice(): Saw unexpected code " << (void*)next4Bytes << "\n"; setParseState(PARSING_SLICE); // the safest way to recover... break; } } } // Compute this frame's timestamp: usingSource()->computePresentationTime(fCurPicTemporalReference); if (fSkippingCurrentPicture) { return parse(); // try again, until we get a non-skipped frame } else { return curFrameSize(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -