Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

h264 2-way video work, but no color #5

Merged
merged 1 commit into from
Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/h264_encoder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public:
const unsigned int mtu_size = 1300;

ISVCEncoder *encoder{};
SEncParamExt encodeParams;
SEncParamBase encParamBase;
SFrameBSInfo outputFrame{};
SSourcePicture inputFrame{};
};
Expand Down
81 changes: 67 additions & 14 deletions src/h264_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
#include <iostream>
#include <vector>
#include <cassert>
#include <fstream>
#include <stdio.h>

#include <string.h> // 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)
{
Expand All @@ -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)
Expand All @@ -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()
Expand All @@ -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
Expand All @@ -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<const unsigned char *>(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;
}
106 changes: 61 additions & 45 deletions src/h264_encoder.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@

#include <iostream>
#include <vector>
#include <cassert>

#include <string.h> // memcpy , strncat
#include <sstream>
#include <iomanip>

#include "h264_encoder.hh"

Expand All @@ -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()
Expand All @@ -55,6 +41,32 @@ H264Encoder::~H264Encoder()
}
}

static std::string to_hex(const std::vector<uint8_t> &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,
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
}