📄 video_x264.cpp
字号:
m_pic_input.i_type = X264_TYPE_AUTO; m_pic_input.i_qpplus1 = 0; m_pic_input.img.i_csp = X264_CSP_I420;#else x264_picture_alloc(&m_pic_input, X264_CSP_I420, Profile()->m_videoWidth, Profile()->m_videoHeight);#endif m_count = 0; return true;}bool CX264VideoEncoder::EncodeImage( const u_int8_t* pY, const u_int8_t* pU, const u_int8_t* pV, u_int32_t yStride, u_int32_t uvStride, bool wantKeyFrame, Duration elapsedDuration, Timestamp srcFrameTimestamp){ //debug_message("encoding at "U64, srcFrameTimestamp); m_push->Push(srcFrameTimestamp); if (m_vopBuffer == NULL) { m_vopBuffer = (u_int8_t*)malloc(Profile()->m_videoMaxVopSize); if (m_vopBuffer == NULL) { error_message("Cannot malloc vop size"); return false; } } m_count++; if (m_count >= m_key_frame_count) { wantKeyFrame = true; m_count = 0; }#ifdef USE_OUR_YUV m_pic_input.img.plane[0] = (uint8_t *)pY; m_pic_input.img.i_stride[0] = yStride; m_pic_input.img.plane[1] = (uint8_t *)pU; m_pic_input.img.i_stride[1] = uvStride; m_pic_input.img.plane[2] = (uint8_t *)pV; m_pic_input.img.i_stride[2] = uvStride;#else CopyYuv(pY, pU, pV, yStride, uvStride, uvStride, m_pic_input.img.plane[0],m_pic_input.img.plane[1],m_pic_input.img.plane[2], m_pic_input.img.i_stride[0],m_pic_input.img.i_stride[1],m_pic_input.img.i_stride[2], Profile()->m_videoWidth, Profile()->m_videoHeight);#endif m_pic_input.i_type = wantKeyFrame ? X264_TYPE_IDR : X264_TYPE_AUTO; m_pic_input.i_pts = srcFrameTimestamp; x264_nal_t *nal; int i_nal; if (x264_encoder_encode(m_h, &nal, &i_nal, &m_pic_input, &m_pic_output) < 0) { error_message("x264_encoder_encode failed"); return false; } CHECK_AND_FREE(m_nal_info); m_nal_info = (h264_nal_buf_t *)malloc(i_nal * sizeof(h264_nal_buf_t)); uint8_t *vopBuffer = m_vopBuffer; int vopBufferLen = m_vopBufferLength; uint32_t loaded = 0; uint32_t nal_on = 0; // read the nals out of the encoder. Nice... for (int ix = 0; ix < i_nal; ix++) { int i_size; bool skip = false; i_size = x264_nal_encode(vopBuffer, &vopBufferLen, 1, &nal[ix]); if (i_size > 0) { m_nal_info[nal_on].nal_length = i_size; m_nal_info[nal_on].nal_offset = loaded; m_nal_info[nal_on].nal_type = nal[ix].i_type; m_nal_info[nal_on].unique = false; uint32_t header = 0; if (h264_is_start_code(vopBuffer)) { header = vopBuffer[2] == 1 ? 3 : 4; } m_nal_info[nal_on].nal_length -= header; m_nal_info[nal_on].nal_offset += header; // we will send picture or sequence header through - let the // sinks decide to send or not if (skip == false) {#ifdef DEBUG_H264 uint8_t nal_type = nal[ix].i_type; if (h264_nal_unit_type_is_slice(nal_type)) { uint8_t stype; h264_find_slice_type(vopBuffer, i_size, &stype, true); debug_message("nal %d - type %u slice type %u %d", ix, nal_type, stype, i_size); } else { debug_message("nal %d - type %u %d", ix, nal_type, i_size); }#endif nal_on++; loaded += i_size; vopBufferLen -= i_size; vopBuffer += i_size; } else {#ifdef DEBUG_H264 debug_message("skipped nal %u", nal[ix].i_type);#endif } } else { error_message("Need to increase vop buffer size by %d", -i_size); } } m_nal_num = nal_on; m_vopBufferLength = loaded;#ifdef DEBUG_H264 debug_message("x264 loaded %d nals, %u len", i_nal, loaded);#endif#ifdef OUTPUT_RAW if (m_vopBufferLength) { fwrite(m_vopBuffer, m_vopBufferLength, 1, m_outfile); }#endif return true;}static void free_x264_frame (void *ifptr){ h264_media_frame_t *mf = (h264_media_frame_t *)ifptr; if (mf != NULL) { CHECK_AND_FREE(mf->buffer); CHECK_AND_FREE(mf->nal_bufs); free(mf); }}media_free_f CX264VideoEncoder::GetMediaFreeFunction (void){ return free_x264_frame;}bool CX264VideoEncoder::GetEncodedImage( u_int8_t** ppBuffer, u_int32_t* pBufferLength, Timestamp *dts, Timestamp *pts){ if (m_vopBufferLength == 0) return false; h264_media_frame_t *mf = MALLOC_STRUCTURE(h264_media_frame_t); if (mf == NULL) { CHECK_AND_FREE(m_vopBuffer); m_vopBufferLength = 0; return false; } mf->buffer = m_vopBuffer; mf->buffer_len = m_vopBufferLength; mf->nal_number = m_nal_num; mf->nal_bufs = m_nal_info; m_nal_info = NULL; m_vopBuffer = NULL; *ppBuffer = (uint8_t *)mf; *pBufferLength = 0;#if 1 Timestamp pts_try = m_pic_output.i_pts + m_pts_add; Timestamp closest_on_stack = m_push->Closest(pts_try, m_frame_time); if (closest_on_stack != 0) { *pts = closest_on_stack; } else { *pts = pts_try; } // debug_message("try "U64" closest "U64, pts_try, closest_on_stack);#else *pts = m_pic_output.i_pts + m_pts_add;#endif *dts = m_push->Pop(); // debug_message("dts "U64" pts "U64" "D64" type %u ", *dts, *pts, *pts - *dts, m_pic_output.i_type); if (*dts > *pts) *pts = *dts; else if (*pts - *dts < 6) *pts = *dts;#if 0 if (*dts != *pts) { debug_message("PTS "U64" not DTS "U64, *pts, *dts); }#endif m_vopBuffer = NULL; m_vopBufferLength = 0; return true;}bool CX264VideoEncoder::GetReconstructedImage( u_int8_t* pY, u_int8_t* pU, u_int8_t* pV){ uint32_t w = Profile()->m_videoWidth; uint32_t uvw = w / 2; CopyYuv(m_pic_input.img.plane[0], m_pic_input.img.plane[1], m_pic_input.img.plane[2], m_pic_input.img.i_stride[0], m_pic_input.img.i_stride[1], m_pic_input.img.i_stride[2], pY, pU, pV, w, uvw, uvw, w, Profile()->m_videoHeight); return true;}void CX264VideoEncoder::StopEncoder (void){#ifndef USE_OUR_YUV x264_picture_clean(&m_pic_input);#endif x264_encoder_close(m_h); CHECK_AND_FREE(m_vopBuffer); CHECK_AND_FREE(m_YUV); CHECK_AND_FREE(m_nal_info);#ifdef OUTPUT_RAW if (m_outfile) { fclose(m_outfile); }#endif if (m_push != NULL) { delete m_push; m_push = NULL; } }bool CX264VideoEncoder::GetEsConfig (uint8_t **ppEsConfig, uint32_t *pEsConfigLen){#ifdef DEBUG_H264 debug_message("Getting es config for x264");#endif CHECK_AND_FREE(Profile()->m_videoMpeg4Config); Profile()->m_videoMpeg4ConfigLength = 0; x264_nal_t *nal; int nal_num; if (x264_encoder_headers(m_h, &nal, &nal_num) != 0) { error_message("x264 - can't create headers"); StopEncoder(); return false; } uint8_t *seqptr = m_vopBuffer; uint8_t *picptr = m_vopBuffer; uint32_t seqlen = 0, piclen = 0; bool found_seq = false, found_pic = false; if (m_vopBuffer == NULL) { m_vopBuffer = (u_int8_t*)malloc(Profile()->m_videoMaxVopSize); } uint8_t *vopBuffer = m_vopBuffer; int vopBufferLen = Profile()->m_videoMaxVopSize; for (int ix = 0; ix < nal_num; ix++) { int i_size; i_size = x264_nal_encode(vopBuffer, &vopBufferLen, 1, &nal[ix]); if (i_size > 0) { bool useit = false; uint header_size = 0; if (h264_is_start_code(vopBuffer)) { header_size = vopBuffer[2] == 1 ? 3 : 4; } if (nal[ix].i_type == H264_NAL_TYPE_SEQ_PARAM) { found_seq = true; seqlen = i_size - header_size; seqptr = vopBuffer + header_size; useit = true; } else if (nal[ix].i_type == H264_NAL_TYPE_PIC_PARAM) { found_pic = true; piclen = i_size - header_size; picptr = vopBuffer + header_size; useit = true; } if (useit) { vopBuffer += i_size; vopBufferLen -= i_size; } } } if (found_seq == false) { error_message("Can't find seq pointer in x264 header"); StopEncoder(); return false; } if (found_pic == false) { error_message("Can't find pic pointer in x264 header"); StopEncoder(); return false; } uint8_t *p = seqptr; if (*p == 0 && p[1] == 0 && (p[2] == 1 || (p[2] == 0 && p[3] == 1))) { if (p[2] == 0) p += 4; else p += 3; } Profile()->m_videoMpeg4ProfileId = p[1] << 16 | p[2] << 8 | p[3]; debug_message("profile id %x", Profile()->m_videoMpeg4ProfileId); char *sprop = NULL; char *base64; base64 = MP4BinaryToBase64(seqptr, seqlen); sprop = strdup(base64); free(base64); base64 = MP4BinaryToBase64(picptr, piclen); sprop = (char *)realloc(sprop, strlen(sprop) + strlen(base64) + 1 + 1); strcat(sprop, ","); strcat(sprop, base64); free(base64); debug_message("sprop %s", sprop); Profile()->m_videoMpeg4Config = (uint8_t *)sprop; Profile()->m_videoMpeg4ConfigLength = strlen(sprop) + 1; StopEncoder(); return true;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -