uint8_t * get_nal(uint32_t *len, uint8_t **offset, uint8_t *start, uint32_t total) { uint32_t info; uint8_t *q ; uint8_t *p = *offset; *len = 0; while(1) { info = find_start_code(p, 3); if (info == 1) break; p++; if ((p - start) >= total) return NULL; } q = p + 4; p = q; while(1) { info = find_start_code(p, 3); if (info == 1) break; p++; if ((p - start) >= total) return NULL; } *len = (p - q); *offset = p; return q; }
uint32_t handle_mpeg4AVC(uint8_t* data, uint32_t *input_size){ uint32_t slice_type,nal_size,inp_size; uint8_t *nal_data; int nal_type,sc_type; inp_size=*input_size; /**/ sc_type = find_start_code(data); data+=sc_type; *input_size=(*input_size)+sc_type; nal_size = get_nal_mem(data, 188-(*input_size)); nal_data = data; data+=nal_size; *input_size=(*input_size)+nal_size; nal_type = get_nal_type(nal_data, nal_size); switch(nal_type){ case AVC_NALU_IDR_SLICE: slice_type= 1; break; case AVC_NALU_NON_IDR_SLICE: slice_type= 2; break; default: slice_type= 0; break; } return slice_type; }
size_t mpeg_bitstream_parse(mpeg_bitstream_t* packet, caption_frame_t* frame, const uint8_t* data, size_t size, unsigned stream_type, double dts, double cts) { if (MAX_NALU_SIZE <= packet->size) { packet->status = LIBCAPTION_ERROR; // fprintf(stderr, "LIBCAPTION_ERROR\n"); return 0; } // consume upto MAX_NALU_SIZE bytes if (MAX_NALU_SIZE <= packet->size + size) { size = MAX_NALU_SIZE - packet->size; } sei_t sei; size_t header_size, scpos; packet->status = LIBCAPTION_OK; memcpy(&packet->data[packet->size], data, size); packet->size += size; while (packet->status == LIBCAPTION_OK && 0 < (scpos = find_start_code(&packet->data[0], packet->size))) { switch (mpeg_bitstream_packet_type(packet, stream_type)) { default: break; case H262_SEI_PACKET: header_size = 4; if (STREAM_TYPE_H262 == stream_type && scpos > header_size) { cea708_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts); packet->status = libcaption_status_update(packet->status, cea708_parse_h262(&packet->data[header_size], scpos - header_size, cea708)); _mpeg_bitstream_cea708_sort_flush(packet, frame, dts); } break; case H264_SEI_PACKET: case H265_SEI_PACKET: header_size = STREAM_TYPE_H264 == stream_type ? 4 : STREAM_TYPE_H265 == stream_type ? 5 : 0; if (header_size && scpos > header_size) { packet->status = libcaption_status_update(packet->status, sei_parse(&sei, &packet->data[header_size], scpos - header_size, dts + cts)); for (sei_message_t* msg = sei_message_head(&sei); msg; msg = sei_message_next(msg)) { if (sei_type_user_data_registered_itu_t_t35 == sei_message_type(msg)) { cea708_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts); packet->status = libcaption_status_update(packet->status, cea708_parse_h264(sei_message_data(msg), sei_message_size(msg), cea708)); _mpeg_bitstream_cea708_sort_flush(packet, frame, dts); } } sei_free(&sei); } break; } packet->size -= scpos; memmove(&packet->data[0], &packet->data[scpos], packet->size); } return size; }
inline void send_data_for_channel(int chn, const FHADV_VIDEO_FRM_INFO_t *info, const FH_ADDR data, const FH_SINT32 len) { int i = 0; unsigned char *pos = data; unsigned char *end = data + len; int rest = len; unsigned char *next_start; #ifdef FH_USING_RTSP struct rtsp_server_context *server = g_rtsp_servers[chn]; #else struct vlcview_enc_stream_element stream_element; stream_element.frame_type = info->key_frame ? VLCVIEW_ENC_H264_I_FRAME : VLCVIEW_ENC_H264_P_FRAME; stream_element.frame_len = len; stream_element.time_stamp = info->ts; stream_element.nalu_count = 0; #endif do { next_start = find_start_code(pos + 4, rest - 4); if (next_start) { #ifdef FH_USING_RTSP rtp_push_data(server, pos, next_start - pos, info->ts); #else stream_element.nalu[i].start = pos; stream_element.nalu[i].len = next_start - pos; stream_element.nalu_count++; #endif i++; rest = rest - (next_start - pos); pos = next_start; } else { /* reach the end of data */ #ifdef FH_USING_RTSP rtp_push_data(server, pos, end - pos, info->ts); #else stream_element.nalu[i].start = pos; stream_element.nalu[i].len = end - pos; stream_element.nalu_count++; #endif } } while (next_start != NULL); #ifndef FH_USING_RTSP vlcview_pes_stream_pack(chn, stream_element); #endif }
static bool looksLikeMPEG( unsigned char const *inData, unsigned long inSize ) { unsigned long state = 0xFF ; if( find_start_code( inData, inSize, state ) ) { return ( state == PACK_START_CODE || state == SYSTEM_HEADER_START_CODE || (state >= 0x1e0 && state <= 0x1ef) || (state >= 0x1c0 && state <= 0x1df) || state == PRIVATE_STREAM_2 || state == PROGRAM_STREAM_MAP || state == PRIVATE_STREAM_1 || state == PADDING_STREAM ); } else return false ; }
bool CVC1BitstreamParser::vc1_parse_frame(const uint8_t *buf, const uint8_t *buf_end, bool sequence_only) { uint32_t state = -1; for (;;) { buf = find_start_code(buf, buf_end, &state); if (buf >= buf_end) break; if (buf[-1] == VC1_SEQUENCE) { if (m_Profile != VC1_PROFILE_NOPROFILE) return false; CBitstreamReader br(buf, buf_end - buf); // Read the profile m_Profile = static_cast<uint8_t>(br.ReadBits(2)); if (m_Profile == VC1_PROFILE_ADVANCED) { br.SkipBits(39); m_AdvInterlace = br.ReadBits(1); } else { br.SkipBits(22); m_SimpleSkipBits = 2; if (br.ReadBits(1)) //rangered ++m_SimpleSkipBits; m_MaxBFrames = br.ReadBits(3); br.SkipBits(2); // quantizer if (br.ReadBits(1)) //finterpflag ++m_SimpleSkipBits; } if (sequence_only) return true; } else if (buf[-1] == VC1_FRAME) { CBitstreamReader br(buf, buf_end - buf); if (sequence_only) return false; if (m_Profile == VC1_PROFILE_ADVANCED) { uint8_t fcm; if (m_AdvInterlace) { fcm = br.ReadBits(1); if (fcm) fcm = br.ReadBits(1) + 1; } else fcm = VC1_FRAME_PROGRESSIVE; if (fcm == VC1_FIELD_INTERLACE) { uint8_t pic = br.ReadBits(3); return pic == 0x00 || pic == 0x01; } else { uint8_t pic(0); while (pic < 4 && br.ReadBits(1))++pic; return pic == 2; } return false; } else if (m_Profile != VC1_PROFILE_NOPROFILE) { br.SkipBits(m_SimpleSkipBits); // quantizer uint8_t pic(br.ReadBits(1)); if (m_MaxBFrames) { if (!pic) { pic = br.ReadBits(1); return pic != 0; } else return false; } else return pic != 0; } else break; } } return false; }
static int vdec_h264_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs, struct vdec_fb *fb, bool *res_chg) { struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec; struct vdec_vpu_inst *vpu = &inst->vpu; int nal_start_idx = 0; int err = 0; unsigned int nal_start; unsigned int nal_type; unsigned char *buf; unsigned int buf_sz; unsigned int data[2]; uint64_t vdec_fb_va = (u64)(uintptr_t)fb; uint64_t y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0; uint64_t c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0; mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p", ++inst->num_nalu, y_fb_dma, c_fb_dma, fb); /* bs NULL means flush decoder */ if (bs == NULL) return vpu_dec_reset(vpu); buf = (unsigned char *)bs->va; buf_sz = bs->size; nal_start_idx = find_start_code(buf, buf_sz); if (nal_start_idx < 0) goto err_free_fb_out; nal_start = buf[nal_start_idx]; nal_type = NAL_TYPE(buf[nal_start_idx]); mtk_vcodec_debug(inst, "\n + NALU[%d] type %d +\n", inst->num_nalu, nal_type); if (nal_type == NAL_H264_PPS) { buf_sz -= nal_start_idx; if (buf_sz > HDR_PARSING_BUF_SZ) { err = -EILSEQ; goto err_free_fb_out; } memcpy(inst->vsi->hdr_buf, buf + nal_start_idx, buf_sz); } inst->vsi->dec.bs_dma = (uint64_t)bs->dma_addr; inst->vsi->dec.y_fb_dma = y_fb_dma; inst->vsi->dec.c_fb_dma = c_fb_dma; inst->vsi->dec.vdec_fb_va = vdec_fb_va; data[0] = buf_sz; data[1] = nal_start; err = vpu_dec_start(vpu, data, 2); if (err) goto err_free_fb_out; *res_chg = inst->vsi->dec.resolution_changed; if (*res_chg) { struct vdec_pic_info pic; mtk_vcodec_debug(inst, "- resolution changed -"); get_pic_info(inst, &pic); if (inst->vsi->dec.realloc_mv_buf) { err = alloc_mv_buf(inst, &pic); if (err) goto err_free_fb_out; } } if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) { /* wait decoder done interrupt */ err = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED, WAIT_INTR_TIMEOUT_MS); if (err) goto err_free_fb_out; vpu_dec_end(vpu); } mtk_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu, nal_type); return 0; err_free_fb_out: put_fb_to_free(inst, fb); mtk_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err); return err; }