📄 mpeg3.cpp
字号:
for (sid = 1; sid <= numSamples; sid++) { sampleSize = maxSampleSize; MP4Timestamp startTime; MP4Duration duration; MP4Duration renderingOffset; bool isSyncSample; bool rc = MP4ReadSample(mp4file, trackid, sid, &buffer, &sampleSize, &startTime, &duration, &renderingOffset, &isSyncSample);#ifdef DEBUG_MPEG3_HINT printf("sid %d - sample size %d\n", sid, sampleSize);#endif if (rc == false) { MP4DeleteTrack(mp4file, hintTrackId); return false; } // need to add rfc2250 header offset = 0; have_seq = 0; pbuffer = buffer; stop = false; do { uint32_t oldoffset; oldoffset = offset; if (MP4AV_Mpeg3FindNextStart(pbuffer + offset, sampleSize - offset, &offset, &scode) < 0) { // didn't find the start code#ifdef DEBUG_MPEG3_HINT printf("didn't find start code\n");#endif stop = true; } else { offset += oldoffset;#ifdef DEBUG_MPEG3_HINT printf("next sscode %x found at %d\n", scode, offset);#endif if (scode == MPEG3_SEQUENCE_START_CODE) have_seq = 1; offset += 4; // start with next value } } while (scode != MPEG3_PICTURE_START_CODE && stop == false); pstart = pbuffer + offset; // point to inside of picture start type = (pstart[1] >> 3) & 0x7; rfc2250[0] = (*pstart >> 6) & 0x3; rfc2250[1] = (pstart[0] << 2) | ((pstart[1] >> 6) & 0x3); // temporal ref rfc2250[2] = type; rfc2250_2 = rfc2250[2]; rfc2250[3] = 0; if (type == 2 || type == 3) { rfc2250[3] = pstart[3] << 5; if ((pstart[4] & 0x80) != 0) rfc2250[3] |= 0x10; if (type == 3) { rfc2250[3] |= (pstart[4] >> 3) & 0xf; } } if (MP4AddRtpVideoHint(mp4file, hintTrackId, type == 3, renderingOffset) == false) return false; // Find the next slice. Then we can add the header if the next // slice will be in the start. This lets us set the S bit in // rfc2250[2]. Then we need to loop to find the next slice that's // not in the buffer size - this should be in the while loop. prev_slice = 0; if (MP4AV_Mpeg3FindNextSliceStart(pbuffer, offset, sampleSize, &next_slice) < 0) { slice_at_begin = false; } else { slice_at_begin = true; }#ifdef DEBUG_MPEG3_HINT printf("starting slice at %d\n", next_slice);#endif offset = 0; bool nomoreslices = false; bool found_slice = slice_at_begin; bool onfirst = true; while (sampleSize > 0) { bool isLastPacket; uint32_t len_to_write; if (sampleSize <= maxPayloadSize) { // leave started_slice alone len_to_write = sampleSize; isLastPacket = true; prev_slice = 0; } else { found_slice = (onfirst == false) && (nomoreslices == false) && (next_slice <= maxPayloadSize); onfirst = false; isLastPacket = false; while (nomoreslices == false && next_slice <= maxPayloadSize) { prev_slice = next_slice; if (MP4AV_Mpeg3FindNextSliceStart(pbuffer, next_slice + 4, sampleSize, &next_slice) >= 0) {#ifdef DEBUG_MPEG3_HINT printf("prev_slice %u next slice %u %u\n", prev_slice, next_slice, offset + next_slice);#endif found_slice = true; } else { // at end nomoreslices = true; } } // prev_slice should have the end value. If it's not 0, we have // the end of the slice. if (found_slice) len_to_write = prev_slice; else len_to_write = MIN(maxPayloadSize, sampleSize); } rfc2250[2] = rfc2250_2; if (have_seq != 0) { rfc2250[2] |= 0x20; have_seq = 0; } if (slice_at_begin) { rfc2250[2] |= 0x10; // set b bit } if (found_slice || isLastPacket) { rfc2250[2] |= 0x08; // set end of slice bit slice_at_begin = true; // for next time } else { slice_at_begin = false; }#ifdef DEBUG_MPEG3_HINT printf("Adding packet, sid %u prev slice %u len_to_write %u\n", sid, prev_slice, len_to_write); printf("Next slice %u offset %u %x %x %x %x\n\n", next_slice, offset, rfc2250[0], rfc2250[1], rfc2250[2], rfc2250[3]);#endif // okay - we can now write out this packet. if (MP4AddRtpPacket(mp4file, hintTrackId, isLastPacket) == false || // add the 4 byte header MP4AddRtpImmediateData(mp4file, hintTrackId, rfc2250, sizeof(rfc2250)) == false || // add the immediate data MP4AddRtpSampleData(mp4file, hintTrackId, sid, offset, len_to_write) == false) { MP4DeleteTrack(mp4file, hintTrackId); return false; } offset += len_to_write; sampleSize -= len_to_write; prev_slice = 0; next_slice -= len_to_write; pbuffer += len_to_write; } if (MP4WriteRtpHint(mp4file, hintTrackId, duration, type == 1) == false) return false; } free(buffer); return true;}// mpeg3_find_dts_from_pts - given a pts, a frame type, and the// temporal reference from the frame type, calculate the dts// pts = presentation time stamp // dts = decode time stamp.int mpeg3_find_dts_from_pts (mpeg3_pts_to_dts_t *ptr, uint64_t pts_in_msec, int frame_type, uint16_t temp_ref, uint64_t *return_value){ uint64_t calc; double dcalc; double msec_per_frame = 1000.0 / ptr->frame_rate; int64_t diff; switch (frame_type) { case 1: // i frame // I frame calculation - take the temporal reference + 1, multiple it // times frame rate, subtract from pts to get dts. dcalc = (temp_ref + 1); dcalc *= msec_per_frame; calc = pts_in_msec - (uint64_t)dcalc; ptr->last_i_temp_ref = temp_ref; ptr->last_i_pts = pts_in_msec; ptr->last_i_dts = calc; *return_value = calc; break; case 2: // P frames suck. // see if the difference between temporal references in the last // frame is the difference between pts of the last I and this P frame // if they are, we most likely haven't lost a frame dcalc = (temp_ref - ptr->last_i_temp_ref); dcalc *= msec_per_frame; diff = pts_in_msec - ptr->last_i_pts; calc = (uint64_t)dcalc; diff -= calc; if (diff > TO_D64(10) || diff < TO_D64(-10)) { // out of range - we really can't guess // we could probably do more work here - record the number of // consectutive b frames, etc, but what it really means is that // we need to wait until the next I frame to display sanely. // We'll still decode, and may even display if B frames are // present, but we'll jerk a bit on these frames. // It all comes down to me being lazy... printf("pts out of range - diff "D64", temps %u %u\n", diff, temp_ref, ptr->last_i_temp_ref); printf("our pts "U64" last "U64"\n", pts_in_msec, ptr->last_i_pts); return -1; } if (ptr->last_i_temp_ref != 0) { // straight forward calculation *return_value = ptr->last_i_dts + calc; } else { // if the temp ref of the I frame was 0, there's no good calculation // of how to get to the P frame time. // a less straight forward calculation - just increment from the // last dts - there's no real way to calculate this accurately *return_value = ptr->last_dts + (uint64_t)msec_per_frame; } break; case 3: *return_value = pts_in_msec; break; } ptr->last_dts = *return_value; return 0;}uint8_t mpeg2_profile_to_mp4_track_type (uint8_t profile){ if (profile == 0) { return MP4_MPEG2_VIDEO_TYPE; } if ((profile & 0x80) == 0) { switch ((profile & 0x70) >> 4) { case 5: return MP4_MPEG2_SIMPLE_VIDEO_TYPE; case 4: return MP4_MPEG2_MAIN_VIDEO_TYPE; case 3: return MP4_MPEG2_SNR_VIDEO_TYPE; case 2: return MP4_MPEG2_SPATIAL_VIDEO_TYPE; case 1: return MP4_MPEG2_HIGH_VIDEO_TYPE; default: return MP4_MPEG2_VIDEO_TYPE; } } if (profile == 0x82 || profile == 0x85) { return MP4_MPEG2_442_VIDEO_TYPE; } return MP4_MPEG2_VIDEO_TYPE;}static const char *profile_names[] = { "Mpeg-2 High@<unk>", "Mpeg-2 High@High", "Mpeg-2 High@High 1440", "Mpeg-2 High@Main", "Mpeg-2 High@Low" "Mpeg-2 Spatially Scalable@<unk>", "Mpeg-2 Spatially Scalable@High", "Mpeg-2 Spatially Scalable@High 1440", "Mpeg-2 Spatially Scalable@Main", "Mpeg-2 Spatially Scalable@Low", "Mpeg-2 SNR Scalable@<unk>", "Mpeg-2 SNR Scalable@High", "Mpeg-2 SNR Scalable@High 1440", "Mpeg-2 SNR Scalable@Main", "Mpeg-2 SNR Scalable@Low", "Mpeg-2 Main@High<unk>", "Mpeg-2 Main@High", "Mpeg-2 Main@High 1440", "Mpeg-2 Main@Main", "Mpeg-2 Main@Low", "Mpeg-2 Simple@<unk>", "Mpeg-2 Simple@High", "Mpeg-2 Simple@High 1440", "Mpeg-2 Simple@Main", "Mpeg-2 Simple@Low", };const char *mpeg2_type (uint8_t profile) { if (profile == 0) { return "Mpeg-2"; } if ((profile & 0x80) == 0) { uint8_t index; index = ((profile & 0x70) >> 4); if (index == 0 || index > 5) { return "Mpeg-2 unknown profile"; } index--; index *= 5; uint8_t level = profile & 0xf; if ((level & 1) != 0 || (level > 0xb)) { // no change to index: return profile_names[index]; } level >>= 1; level -= 2; index += level; return profile_names[index]; } if (profile == 0x82) return "Mpeg-2 4:2:2@High"; if (profile == 0x85) { return "Mpeg-2 4:2:2@Main"; } if (profile == 0x8a) return "Mpeg-2 Multiview@High"; if (profile == 0x8b) return "Mpeg-2 Multiview@High 1440"; if (profile == 0x8d) return "Mpeg-2 Multiview@Main"; if (profile == 0x8e) return "Mpeg-2 Multiview@Low"; return "Mpeg-2 unknown escape profile";}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -