📄 mpeg2ps.c
字号:
if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 4) { if (sptr->pes_buffer_size != sptr->pes_buffer_on) started_new_pes = true; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } while (MP4AV_Mpeg3FindNextStart(sptr->pes_buffer + sptr->pes_buffer_on, sptr->pes_buffer_size - sptr->pes_buffer_on, &offset, &scode) < 0 || (!IS_MPEG_START(scode & 0xff))) { if (sptr->pes_buffer_size > 3) sptr->pes_buffer_on = sptr->pes_buffer_size - 3; else { sptr->pes_buffer_on = sptr->pes_buffer_size; started_new_pes = true; } if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } sptr->pes_buffer_on += offset; if (offset == 0 && started_new_pes) { // nothing... we've copied the timestamp already. } else { // we found the new start, but we pulled in a new pes header before // starting. So, we want to use the header that we read. copy_next_pes_ts_to_frame_ts(sptr); //printf(" %u "U64"\n", sptr->frame_ts.have_dts, sptr->frame_ts.dts); }#if 0 printf("header %x at %d\n", scode, sptr->pes_buffer_on);#endif if (scode == MPEG3_PICTURE_START_CODE) { sptr->pict_header_offset = sptr->pes_buffer_on; have_pict = true; } else have_pict = false; start = 4 + sptr->pes_buffer_on; while (1) { if (MP4AV_Mpeg3FindNextStart(sptr->pes_buffer + start, sptr->pes_buffer_size - start, &offset, &scode) < 0) { start = sptr->pes_buffer_size - 3; start -= sptr->pes_buffer_on; sptr->pict_header_offset -= sptr->pes_buffer_on; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } start += sptr->pes_buffer_on; sptr->pict_header_offset += sptr->pes_buffer_on; } else {#if 0 printf("2header %x at %d\n", scode, start);#endif start += offset; if (have_pict == FALSE) { if (scode == MPEG3_PICTURE_START_CODE) { have_pict = true; sptr->pict_header_offset = start; } } else { if (IS_MPEG_START(scode & 0xff) || scode == MPEG3_SEQUENCE_END_START_CODE) { sptr->frame_len = start - sptr->pes_buffer_on; sptr->have_frame_loaded = true; return TRUE; } } start += 4; } } return FALSE;}static bool mpeg2ps_stream_find_h264_video_frame (mpeg2ps_stream_t *sptr){ uint32_t offset; bool have_pict; bool started_new_pes = false; uint32_t start; uint8_t nal_type; /* * First thing - determine if we have enough bytes to read the header. * if we do, we have the correct timestamp. If not, we read the new * pes, so we'd want to use the timestamp we read. */ sptr->frame_ts = sptr->next_pes_ts; if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 4) { if (sptr->pes_buffer_size != sptr->pes_buffer_on) started_new_pes = true; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } if (h264_is_start_code(sptr->pes_buffer + sptr->pes_buffer_on) == false) { do { uint32_t offset = h264_find_next_start_code(sptr->pes_buffer + sptr->pes_buffer_on, sptr->pes_buffer_size - sptr->pes_buffer_on); if (offset == 0) { if (sptr->pes_buffer_size > 3) sptr->pes_buffer_on = sptr->pes_buffer_size - 3; else { sptr->pes_buffer_on = sptr->pes_buffer_size; started_new_pes = true; } if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } else sptr->pes_buffer_on += offset; } while (h264_is_start_code(sptr->pes_buffer + sptr->pes_buffer_on) == false); } if (started_new_pes) { // nothing... we've copied the timestamp already. } else { // we found the new start, but we pulled in a new pes header before // starting. So, we want to use the header that we read. copy_next_pes_ts_to_frame_ts(sptr); }#if 0 printf("header %x at %d\n", scode, sptr->pes_buffer_on);#endif have_pict = false; start = 4 + sptr->pes_buffer_on; while (1) { if ((offset = h264_find_next_start_code(sptr->pes_buffer + start, sptr->pes_buffer_size - start)) == 0) { start = sptr->pes_buffer_size - 4; start -= sptr->pes_buffer_on; sptr->pict_header_offset -= sptr->pes_buffer_on; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } start += sptr->pes_buffer_on; sptr->pict_header_offset += sptr->pes_buffer_on; } else {#if 0 printf("2header %x at %d\n", scode, start);#endif start += offset; nal_type = h264_nal_unit_type(sptr->pes_buffer + start); if (have_pict == FALSE) { if (h264_nal_unit_type_is_slice(nal_type)) { have_pict = true; sptr->pict_header_offset = start; } } else { if (H264_NAL_TYPE_ACCESS_UNIT == nal_type) { sptr->frame_len = start - sptr->pes_buffer_on; sptr->have_frame_loaded = true; return TRUE; } } start += 4; } } return FALSE;}static bool mpeg2ps_stream_figure_out_video_type (mpeg2ps_stream_t *sptr) { bool started_new_pes = false; /* * First thing - determine if we have enough bytes to read the header. * if we do, we have the correct timestamp. If not, we read the new * pes, so we'd want to use the timestamp we read. */ sptr->frame_ts = sptr->next_pes_ts; if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 5) { if (sptr->pes_buffer_size != sptr->pes_buffer_on) started_new_pes = true; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } if (h264_is_start_code(sptr->pes_buffer + sptr->pes_buffer_on) && h264_nal_unit_type(sptr->pes_buffer + sptr->pes_buffer_on) == H264_NAL_TYPE_ACCESS_UNIT) { sptr->have_h264 = true; sptr->determined_type = true; return mpeg2ps_stream_find_h264_video_frame(sptr); } // figure it's mpeg2 sptr->have_h264 = false; sptr->determined_type = true; return mpeg2ps_stream_find_mpeg_video_frame(sptr);}static bool mpeg2ps_stream_find_lpcm_frame (mpeg2ps_stream_t *sptr){ uint8_t frames; uint32_t this_pes_byte_count; if (sptr->pes_buffer_size == sptr->pes_buffer_on) { if (mpeg2ps_stream_read_next_pes_buffer(sptr) == false) { return false; } } if (sptr->channels == 0) { // means we haven't read anything yet - we need to read for // frequency and channels. sptr->channels = 1 + (sptr->audio_private_stream_info[LPCM_INFO] & 0x7); sptr->freq = lpcm_freq_tab[(sptr->audio_private_stream_info[LPCM_INFO] >> 4) & 7]; } copy_next_pes_ts_to_frame_ts(sptr); if (sptr->lpcm_read_offset) { // we need to read bytes - 4 bytes. This should only occur when // we seek. Otherwise, we've already reall read the bytes when // we read the last pes uint32_t bytes_to_skip; bytes_to_skip = ntohs(*(uint16_t *)&sptr->audio_private_stream_info[LPCM_PES_OFFSET_MSB]); bytes_to_skip -= 4; while (bytes_to_skip > sptr->pes_buffer_size - sptr->pes_buffer_on) { if (mpeg2ps_stream_read_next_pes_buffer(sptr) == false) { return FALSE; } } sptr->pes_buffer_on += bytes_to_skip; sptr->lpcm_read_offset = false; } // calculate the number of bytes in this LPCM frame. There are // 150 PTS ticks per LPCM frame. We will read all the PCM frames // referenced by the header. frames = sptr->audio_private_stream_info[LPCM_FRAME_COUNT]; this_pes_byte_count = frames; this_pes_byte_count *= 150; this_pes_byte_count *= sptr->freq; this_pes_byte_count *= sptr->channels * sizeof(int16_t); this_pes_byte_count /= 90000; //printf("fcount %u bytes %u\n", frames, this_pes_byte_count); sptr->frame_len = this_pes_byte_count; while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) { if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } sptr->have_frame_loaded = true;#if 0 printf("lpcm size %u %u %u %u\n", sptr->pes_buffer_size - sptr->pes_buffer_on, sptr->frame_len, sptr->frame_ts.have_dts, sptr->frame_ts.have_pts);#endif return TRUE;}static bool mpeg2ps_stream_find_ac3_frame (mpeg2ps_stream_t *sptr){ const uint8_t *ret; uint32_t diff; bool started_new_pes = false; sptr->frame_ts = sptr->next_pes_ts; // set timestamp after searching if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 6) { if (sptr->pes_buffer_size != sptr->pes_buffer_on) started_new_pes = true; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } while (MP4AV_Ac3ParseHeader(sptr->pes_buffer + sptr->pes_buffer_on, sptr->pes_buffer_size - sptr->pes_buffer_on, &ret, NULL, NULL, &sptr->frame_len, NULL) <= 0) { // don't have frame if (sptr->pes_buffer_size > 6) { sptr->pes_buffer_on = sptr->pes_buffer_size - 6; started_new_pes = true; } else { sptr->pes_buffer_on = sptr->pes_buffer_size; }#if 0 printf("no frame - moving %u of %u\n", sptr->pes_buffer_on, sptr->pes_buffer_size);#endif if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } // have frame. diff = ret - (sptr->pes_buffer + sptr->pes_buffer_on); sptr->pes_buffer_on += diff; if (diff == 0 && started_new_pes) { // we might have a new PTS - but it's not here } else { copy_next_pes_ts_to_frame_ts(sptr); } while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) {#if 0 printf("don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, sptr->pes_buffer_size, sptr->pes_buffer_size - sptr->pes_buffer_on, sptr->frame_len);#endif if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } sptr->have_frame_loaded = true; return TRUE;}static bool mpeg2ps_stream_find_mp3_frame (mpeg2ps_stream_t *sptr){ const uint8_t *ret; uint32_t diff; bool started_new_pes = false; sptr->frame_ts = sptr->next_pes_ts; if (sptr->pes_buffer_size <= sptr->pes_buffer_on + 4) { if (sptr->pes_buffer_size != sptr->pes_buffer_on) started_new_pes = true; if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } while (MP4AV_Mp3GetNextFrame(sptr->pes_buffer + sptr->pes_buffer_on, sptr->pes_buffer_size - sptr->pes_buffer_on, &ret, &sptr->frame_len, TRUE, TRUE) == FALSE) { // don't have frame if (sptr->pes_buffer_size > 3) { if (sptr->pes_buffer_on != sptr->pes_buffer_size) { sptr->pes_buffer_on = sptr->pes_buffer_size - 3; } started_new_pes = true; // we have left over bytes... } else { sptr->pes_buffer_on = sptr->pes_buffer_size; }#if 0 printf("no frame - moving %u of %u\n", sptr->pes_buffer_on, sptr->pes_buffer_size);#endif if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } // have frame. diff = ret - (sptr->pes_buffer + sptr->pes_buffer_on); sptr->pes_buffer_on += diff; if (diff == 0 && started_new_pes) { } else { copy_next_pes_ts_to_frame_ts(sptr); } while (sptr->pes_buffer_size - sptr->pes_buffer_on < sptr->frame_len) {#if 0 printf("don't have enough - on %u size %u %u %u\n", sptr->pes_buffer_on, sptr->pes_buffer_size, sptr->pes_buffer_size - sptr->pes_buffer_on, sptr->frame_len);#endif if (mpeg2ps_stream_read_next_pes_buffer(sptr) == FALSE) { return FALSE; } } sptr->have_frame_loaded = true; return TRUE;}/* * mpeg2ps_stream_read_frame. read the correct frame based on stream type. * advance_pointers is false when we want to use the data */static bool mpeg2ps_stream_read_frame (mpeg2ps_stream_t *sptr, uint8_t **buffer, uint32_t *buflen, bool advance_pointers){ // bool done = FALSE; if (sptr->is_video) { if (sptr->determined_type == false) { if (mpeg2ps_stream_figure_out_video_type(sptr)) { *buffer = sptr->pes_buffer + sptr->pes_buffer_on; *buflen = sptr->frame_len; if (advance_pointers) { sptr->pes_buffer_on += sptr->frame_len; } return TRUE; } return FALSE; } else { if (sptr->have_h264) { if (mpeg2ps_stream_find_h264_video_frame(sptr)) { *buffer = sptr->pes_buffer + sptr->pes_buffer_on; *buflen = sptr->frame_len; if (advance_pointers) { sptr->pes_buffer_on += sptr->frame_len; } return TRUE; } } else { if (mpeg2ps_stream_find_mpeg_video_frame(sptr)) { *buffer = sptr->pes_buffer + sptr->pes_buffer_on; *buflen = sptr->frame_len; if (advance_pointers) { sptr->pes_buffer_on += sptr->frame_len; } return TRUE; } } return FALSE; } } else if (sptr->m_stream_id == 0xbd) { // would need to handle LPCM here if (sptr->m_substream_id >= 0xa0) { if (mpeg2ps_stream_find_lpcm_frame(sptr)) { *buffer = sptr->pes_buffer + sptr->pes_buffer_on; *buflen = sptr->frame_len; if (advance_pointers) { sptr->pes_buffer_on += sptr->frame_len; } return TRUE; } return FALSE; } if (mpeg2ps_stream_find_ac3_frame(sptr)) { *buffer = sptr->pes_buffer + sptr->pes_buffer_on; *buflen = sptr->frame_len; if (advance_pointers) sptr->pes_buffer_on += sptr->frame_len; return TRUE; } return FALSE; } else if (mpeg2ps_stream_find_mp3_frame(sptr)) { *buffer = sptr->pes_buffer + sptr->pes_buffer_on; *buflen = sptr->frame_len; if (advance_pointers) sptr->pes_buffer_on += sptr->frame_len; return TRUE; } return FALSE;}/* * get_info_from_frame - we have a frame, get the info from it. */static void get_info_from_frame (mpeg2ps_stream_t *sptr, uint8_t *buffer, uint32_t buflen){ if (sptr->is_video) { if (sptr->have_h264) { bool found_seq = false; do { if (h264_nal_unit_type(buffer) == H264_NAL_TYPE_SEQ_PARAM) { h264_decode_t dec; found_seq = true; if (h264_read_seq_info(buffer, buflen, &dec) >= 0) { sptr->video_profile = dec.profile; sptr->video_level = dec.level; sptr->w = dec.pic_width; sptr->h = dec.pic_height; } } else { uint32_t offset = h264_find_next_start_code(buffer, buflen); if (offset == 0) buflen = 0; else { buffer += offset; buflen -= offset; } } } while (found_seq == false && buflen > 0); mpeg2ps_message(LOG_ERR, "need to info h264"); sptr->ticks_per_frame = 90000 / 30; } else { if (MP4AV_Mpeg3ParseSeqHdr(buffer, buflen, &sptr->have_mpeg2, &sptr->h, &sptr->w, &sptr->frame_rate, &sptr->bit_rate, NULL, &sptr->video_profile) < 0) { mpeg2ps_message(LOG_ERR, "Can't parse sequence header in first frame - stream\n", sptr->m_stream_id); sptr->m_stream_id = 0; sptr->m_fd = FDNULL; } sptr->ticks_per_frame = (uint64_t)(90000.0 / sptr->frame_rate); mpeg2ps_message(LOG_INFO,"stream %x - %u x %u, %g at %g "U64, sptr->m_stream_id, sptr->w, sptr->h, sptr->bit_rate, sptr->frame_rate, sptr->ticks_per_frame); } return; } if (sptr->m_stream_id >= 0xc0) { // mpeg audio MP4AV_Mp3Header hdr = MP4AV_Mp3HeaderFromBytes(buffer); sptr->channels = MP4AV_Mp3GetChannels(hdr); sptr->freq = MP4AV_Mp3GetHdrSamplingRate(hdr); sptr->samples_per_frame = MP4AV_Mp3GetHdrSamplingWindow(hdr); sptr->bitrate = MP4AV_Mp3GetBitRate(hdr) * 1000; // give bps, not kbps sptr->layer = MP4AV_Mp3GetHdrLayer(hdr); sptr->version = MP4AV_Mp3GetHdrVersion(hdr); } else if (sptr->m_stream_id == 0xbd) { if (sptr->m_substream_id >= 0xa0) { // PCM - ??? sptr->samples_per_frame = 0; sptr->bitrate = sptr->freq * sptr->channels * sizeof(int16_t); } else if (sptr->m_substream_id >= 0x80) { // ac3 const uint8_t *temp; MP4AV_Ac3ParseHeader(buffer, buflen, &temp, &sptr->bitrate, &sptr->freq, NULL, &sptr->channels); sptr->samples_per_frame = 256 * 6; } else { mpeg2ps_message(LOG_ERR, "unknown audio private stream id %x %x",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -