diff --git a/include/h264_encoder.hh b/include/h264_encoder.hh index ffb27fa..76173f5 100644 --- a/include/h264_encoder.hh +++ b/include/h264_encoder.hh @@ -41,7 +41,7 @@ public: const unsigned int mtu_size = 1300; ISVCEncoder *encoder{}; - SEncParamExt encodeParams; + SEncParamBase encParamBase; SFrameBSInfo outputFrame{}; SSourcePicture inputFrame{}; }; diff --git a/src/h264_decoder.cc b/src/h264_decoder.cc index 84d6f02..ede7df9 100644 --- a/src/h264_decoder.cc +++ b/src/h264_decoder.cc @@ -2,12 +2,18 @@ #include #include #include +#include +#include #include // memcpy , strncat #include "h264_decoder.hh" using namespace neo_media; +using namespace std; + +FILE* video_input; +FILE* video_output; H264Decoder::H264Decoder(std::uint32_t video_pixel_format) { @@ -25,7 +31,6 @@ H264Decoder::H264Decoder(std::uint32_t video_pixel_format) dec_param.eEcActiveIdc = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE; dec_param.sVideoProperty.size = sizeof(SVideoProperty); dec_param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC; - // dec_param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_SVC; ret = decoder->Initialize(&dec_param); if (dsErrorFree != ret) @@ -35,6 +40,16 @@ H264Decoder::H264Decoder(std::uint32_t video_pixel_format) decoder = nullptr; assert(0); } + + video_input = fopen("video_input", "wb"); + if(!video_input){ + assert(0); + } + + video_output = fopen("video_output", "wb"); + if(!video_input){ + assert(0); + } } H264Decoder::~H264Decoder() @@ -44,6 +59,9 @@ H264Decoder::~H264Decoder() decoder->Uninitialize(); decoder = nullptr; } + + fclose(video_input); + fclose(video_output); } /** Wrap underlying async APIs to expose sync API to decode input bitstream to @@ -65,34 +83,69 @@ int H264Decoder::decode(const char *input_buffer, unsigned char *dst[3]; SBufferInfo dst_info; - auto ret = decoder->DecodeFrameNoDelay( + auto ret = decoder->DecodeFrame2( reinterpret_cast(input_buffer), input_length, dst, &dst_info); + if (dsErrorFree != ret) { - std::cerr << " 1st decode frame failed" << std::endl; + std::cerr << " H264 decode frame failed" << std::endl; // handle IDR request + } else { + std::cerr << "H264 Decode success " << std::endl; } if (dst_info.iBufferStatus == 1) { + width = dst_info.UsrData.sSystemBuffer.iWidth; + height = dst_info.UsrData.sSystemBuffer.iHeight; + + auto color_fmt = dst_info.UsrData.sSystemBuffer.iFormat; +#if 0 + std::cerr << "Decoded Width : " << width << std::endl; + std::cerr << "Decoded height : " << height << std::endl; + std::cerr << "Decoded Format : " << color_fmt << std::endl; + std::cerr << "Decoded Stride 0 : " << dst_info.UsrData.sSystemBuffer.iStride[0] << std::endl; + std::cerr << "Decoded Stride 1 : " << dst_info.UsrData.sSystemBuffer.iStride[1] << std::endl; +#endif + auto y_size = width * height; + auto uv_size = y_size >> 2; + + output_frame.resize(y_size + 2 * uv_size); + uint8_t *outp = output_frame.data(); + + size_t i = 0; + auto pPtr = dst[0]; + for(i = 0; i < height; i++) + { + memcpy(outp, pPtr, width); + outp += width; + pPtr += dst_info.UsrData.sSystemBuffer.iStride[0]; + } + + pPtr = dst[1]; + for(i = 0; i < height/2; i++) + { + memcpy(outp, pPtr, width/2); + outp += width/2; + pPtr += dst_info.UsrData.sSystemBuffer.iStride[1]; + } + + pPtr = dst[2]; + for(i = 0; i < height/2; i++) + { + memcpy(outp, pPtr, width/2); + outp += width/2; + pPtr += dst_info.UsrData.sSystemBuffer.iStride[1]; + } + + std::cerr << "Decoder wrote " << output_frame.size() << std::endl; } - width = dst_info.UsrData.sSystemBuffer.iWidth; - height = dst_info.UsrData.sSystemBuffer.iHeight; - - const int y_size = width * height; - const int uv_size = y_size >> 2; // YUV420 - output_frame.resize(y_size + 2 * uv_size); - uint8_t *outp = output_frame.data(); - // Copy Y plane - memcpy(outp, dst[0], y_size); - memcpy(outp + y_size, dst[1], uv_size); - memcpy(outp + y_size + uv_size, dst[2], uv_size); return 0; } diff --git a/src/h264_encoder.cc b/src/h264_encoder.cc index ef70763..02094a6 100644 --- a/src/h264_encoder.cc +++ b/src/h264_encoder.cc @@ -1,9 +1,10 @@ - #include #include #include #include // memcpy , strncat +#include +#include #include "h264_encoder.hh" @@ -22,28 +23,13 @@ H264Encoder::H264Encoder(unsigned int video_max_width, assert(0); // todo: throw exception? } - // Apply client app settings - encodeParams.eSpsPpsIdStrategy = INCREASING_ID; - // encodeParams.bPrefixNalAddingCtrl = 1; // codec_type SVC - encodeParams.bPrefixNalAddingCtrl = 0; // codec_type AVC - - encodeParams.iPicWidth = video_max_width; - encodeParams.iPicHeight = video_max_height; - encodeParams.fMaxFrameRate = video_max_frame_rate; - encodeParams.iTargetBitrate = video_max_bitrate; // bits/sec in base - encodeParams.bEnableFrameSkip = 1; - - encodeParams.bEnableDenoise = false; // disable denoise - encodeParams.bEnableSceneChangeDetect = 1; - encodeParams.bEnableBackgroundDetection = 1; - encodeParams.bEnableAdaptiveQuant = 0; - encodeParams.bEnableLongTermReference = 1; - encodeParams.iLtrMarkPeriod = 30; - encodeParams.iNumRefFrame = AUTO_REF_PIC_COUNT; + encParamBase.fMaxFrameRate = 30; + encParamBase.iPicHeight = video_max_height; + encParamBase.iPicWidth = video_max_width; + encParamBase.iTargetBitrate = video_max_bitrate; + encParamBase.iRCMode = RC_OFF_MODE; + encoder->Initialize(&encParamBase); - encoder->InitializeExt(&encodeParams); - - encoder->SetOption(ENCODER_OPTION_DATAFORMAT, &video_pixel_format); } H264Encoder::~H264Encoder() @@ -55,6 +41,32 @@ H264Encoder::~H264Encoder() } } +static std::string to_hex(const std::vector &data) +{ + std::stringstream hex(std::ios_base::out); + hex.flags(std::ios::hex); + int i = 0; + for (const auto &byte : data) + { + hex << std::setw(2) << std::setfill('0') << int(byte); + i++; + if (i > 25) + break; + } + return hex.str(); +} + +static std::string to_hex(unsigned char* data, int stop) +{ + std::stringstream hex(std::ios_base::out); + hex.flags(std::ios::hex); + for (int i = 0; i < stop; i++) + { + hex << std::setw(2) << std::setfill('0') << int(data[i]); + } + return hex.str(); +} + int H264Encoder::encode(const char *input_buffer, std::uint32_t input_length, std::uint32_t width, @@ -90,9 +102,16 @@ int H264Encoder::encode(const char *input_buffer, sourcePicture.iStride[1] = (int) stride_uv; sourcePicture.iStride[2] = (int) stride_uv; + //assert(0); int videoFormat = videoFormatI420; encoder->SetOption(ENCODER_OPTION_DATAFORMAT, &videoFormat); + if(genKeyFrame) { + auto ret = encoder->ForceIntraFrame(true); + std::cerr << "H264Enc: IDR Frame: " << ret << std::endl; + } + + memset(&outputFrame, 0, sizeof (SFrameBSInfo)); int ret = encoder->EncodeFrame(&sourcePicture, &outputFrame); if (ret == 0) { @@ -106,34 +125,31 @@ int H264Encoder::encode(const char *input_buffer, } } - // encode worked - auto a = outputFrame.iFrameSizeInBytes; - auto b = outputFrame.sLayerInfo->pNalLengthInByte; output_bitstream.resize(outputFrame.iFrameSizeInBytes); unsigned char *out_bits = output_bitstream.data(); - memcpy(out_bits, - outputFrame.sLayerInfo->pBsBuf, - outputFrame.iFrameSizeInBytes); + for(int i = 0; i < outputFrame.iLayerNum; i++) { + auto len = 0; + // pNalLengthInByte[0]+pNalLengthInByte[1]+…+pNalLengthInByte[iNalCount-1]. + for(int j =0; j < outputFrame.sLayerInfo[i].iNalCount; j++) { + len += outputFrame.sLayerInfo[i].pNalLengthInByte[j]; + } + + memcpy(out_bits, + outputFrame.sLayerInfo[i].pBsBuf, + len); + + auto stop = len; + if(len > 25) + stop = 25; + std::cerr << to_hex(out_bits, stop) << std::endl; + + out_bits += len; + } + total_bytes_encoded += output_bitstream.size(); total_frames_encoded++; - /* - // Debug log for frame number, type, avg time in usec, avg size in bytes - if (((total_frames_encoded-1) & 31) == 0) { // every 32 frames, ~1 sec - std::cerr << std::endl << height << "p " - << (format ? "I420" : "NV12") - << (encodeParams.request_key_frame ? " I " : " P ") - << "Frame#" << (total_frames_encoded-1) << " " - << bitstream.size() << " bytes " - << encode_time << " usec, avg " - << (total_bytes_encoded/total_frames_encoded) << " bytes " - << (total_time_encoded/total_frames_encoded) << " usec" << - std::endl; - //av1_encoder_stats_t stats = getStats(encoder); - //assert(0); // halt to check stats - } - */ // success - return 0; + return outputFrame.eFrameType == videoFrameTypeIDR ? 1 : 0; }