Implementation for FEC decoder module

This commit is contained in:
dijunkun
2023-11-15 22:01:05 -08:00
parent 31b5d7f2e3
commit b0bee226d1
12 changed files with 940 additions and 484 deletions

127
src/fec/fec_decoder.cpp Normal file
View File

@@ -0,0 +1,127 @@
#include "fec_decoder.h"
#include "log.h"
FecDecoder::FecDecoder() {}
FecDecoder::~FecDecoder() {}
int FecDecoder::Init() {
fec_codec_id_ = OF_CODEC_REED_SOLOMON_GF_2_M_STABLE;
fec_rs_params_ = (of_rs_2_m_parameters_t *)calloc(1, sizeof(*fec_params_));
if (nullptr == fec_rs_params_) {
LOG_ERROR("Create FEC decoder params failed");
return -1;
}
fec_rs_params_->m = 8;
fec_params_ = (of_parameters_t *)fec_rs_params_;
if (OF_STATUS_OK !=
of_create_codec_instance(&fec_session_, fec_codec_id_, OF_DECODER, 2)) {
LOG_ERROR("Create FEC decoder instance failed");
return -1;
}
return 0;
}
int FecDecoder::Release() {
if (!fec_session_) {
LOG_ERROR("Invalid FEC decoder instance");
return -1;
}
{
if (OF_STATUS_OK != of_release_codec_instance(fec_session_)) {
LOG_ERROR("Release FEC decoder instance failed");
return -1;
}
}
if (fec_rs_params_) {
free(fec_rs_params_);
}
return 0;
}
int FecDecoder::ResetParams(unsigned int source_symbol_num) {
if (!fec_session_) {
LOG_ERROR("Invalid FEC decoder instance");
return -1;
}
num_of_received_symbols_ = 0;
num_of_source_packets_ = source_symbol_num;
num_of_total_packets_ =
(unsigned int)floor((double)source_symbol_num / (double)code_rate_);
LOG_ERROR("Set s[{}] r[{}]", num_of_source_packets_,
num_of_total_packets_ - source_symbol_num);
fec_params_->nb_source_symbols = source_symbol_num;
fec_params_->nb_repair_symbols = num_of_total_packets_ - source_symbol_num;
fec_params_->encoding_symbol_length = max_size_of_packet_;
if (OF_STATUS_OK != of_set_fec_parameters(fec_session_, fec_params_)) {
LOG_ERROR("Set FEC params failed for codec_id {}", fec_codec_id_);
return -1;
}
return 0;
}
uint8_t **FecDecoder::DecodeWithNewSymbol(const char *fec_symbol,
unsigned int fec_symbol_id) {
if (!fec_session_) {
LOG_ERROR("Invalid FEC decoder instance");
return nullptr;
}
num_of_received_symbols_++;
if (OF_STATUS_ERROR == of_decode_with_new_symbol(
fec_session_, (char *)fec_symbol, fec_symbol_id)) {
LOG_ERROR("Decode wit new symbol failed");
return nullptr;
}
if ((num_of_received_symbols_ >= fec_params_->nb_source_symbols) &&
(true == of_is_decoding_complete(fec_session_))) {
uint8_t **source_packets =
(uint8_t **)calloc(num_of_total_packets_, sizeof(uint8_t *));
if (!source_packets) {
LOG_ERROR("Calloc failed for source_packets with size [{}])",
num_of_total_packets_);
}
if (OF_STATUS_OK !=
of_get_source_symbols_tab(fec_session_, (void **)source_packets)) {
LOG_ERROR("Get source symbols failed");
return nullptr;
}
return source_packets;
}
return nullptr;
}
int FecDecoder::ReleaseSourcePackets(uint8_t **source_packets) {
if (nullptr == source_packets) {
LOG_ERROR(
"Release source packets failed, due to source_packets is nullptr");
return -1;
}
// for (unsigned int index = 0; index < num_of_source_packets_; index++) {
// if (source_packets[index]) {
// LOG_ERROR("Free [{}]", index);
// free(source_packets[index]);
// }
// }
free(source_packets);
return 0;
}

50
src/fec/fec_decoder.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* @Author: DI JUNKUN
* @Date: 2023-11-15
* Copyright (c) 2023 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _FEC_DECODER_H_
#define _FEC_DECODER_H_
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "lib_common/of_openfec_api.h"
#ifdef __cplusplus
};
#endif
class FecDecoder {
public:
FecDecoder();
~FecDecoder();
public:
int Init();
int Release();
int ResetParams(unsigned int source_symbol_num);
uint8_t **DecodeWithNewSymbol(const char *fec_symbol,
unsigned int fec_symbol_id);
int ReleaseSourcePackets(uint8_t **source_packets);
private:
double code_rate_ = 0.667;
int max_size_of_packet_ = 1400;
private:
of_codec_id_t fec_codec_id_ = OF_CODEC_REED_SOLOMON_GF_2_M_STABLE;
of_session_t *fec_session_ = nullptr;
of_parameters_t *fec_params_ = nullptr;
of_rs_2_m_parameters_t *fec_rs_params_ = nullptr;
of_ldpc_parameters_t *fec_ldpc_params_ = nullptr;
unsigned int num_of_received_symbols_ = 0;
unsigned int num_of_source_packets_ = 0;
unsigned int num_of_total_packets_ = 0;
};
#endif

View File

@@ -40,6 +40,10 @@ int FecEncoder::Release() {
}
}
if (fec_rs_params_) {
free(fec_rs_params_);
}
return 0;
}

View File

@@ -38,7 +38,7 @@ class OpenH264Encoder : public VideoEncoder {
private:
int frame_width_ = 1280;
int frame_height_ = 720;
int key_frame_interval_ = 3000;
int key_frame_interval_ = 1;
int target_bitrate_ = 1000;
int max_bitrate_ = 500000;
int max_payload_size_ = 1400;

View File

@@ -425,7 +425,7 @@ int PeerConnection::SendVideoData(const char *data, size_t size) {
int ret = video_encoder_->Encode(
(uint8_t *)data, size, [this](char *encoded_frame, size_t size) -> int {
for (auto &ice_trans : ice_transmission_list_) {
// LOG_ERROR("H264 frame size: [{}]", size);
LOG_ERROR("H264 frame size: [{}]", size);
ice_trans.second->SendData(IceTransmission::DATA_TYPE::VIDEO,
encoded_frame, size);
}

View File

@@ -52,14 +52,14 @@ void RtpCodec::Encode(uint8_t* buffer, size_t size,
timestamp_ =
std::chrono::high_resolution_clock::now().time_since_epoch().count();
for (size_t index = 0; index < num_of_total_packets; index++) {
for (unsigned int index = 0; index < num_of_total_packets; index++) {
RtpPacket rtp_packet;
if (index < num_of_source_packets) {
rtp_packet.SetVerion(version_);
rtp_packet.SetHasPadding(has_padding_);
rtp_packet.SetHasExtension(has_extension_);
rtp_packet.SetMarker(index == num_of_source_packets - 1 ? 1 : 0);
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE::H264);
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE::H264_FEC_SOURCE);
rtp_packet.SetSequenceNumber(sequence_number_++);
rtp_packet.SetTimestamp(timestamp_);
rtp_packet.SetSsrc(ssrc_);
@@ -89,12 +89,16 @@ void RtpCodec::Encode(uint8_t* buffer, size_t size,
if (index == num_of_source_packets - 1) {
if (last_packet_size > 0) {
rtp_packet.EncodeH264Fua(fec_packets[index], last_packet_size);
rtp_packet.EncodeH264FecSource(fec_packets[index],
last_packet_size, index,
num_of_source_packets);
} else {
rtp_packet.EncodeH264Fua(fec_packets[index], MAX_NALU_LEN);
rtp_packet.EncodeH264FecSource(fec_packets[index], MAX_NALU_LEN,
index, num_of_source_packets);
}
} else {
rtp_packet.EncodeH264Fua(fec_packets[index], MAX_NALU_LEN);
rtp_packet.EncodeH264FecSource(fec_packets[index], MAX_NALU_LEN,
index, num_of_source_packets);
}
} else if (index >= num_of_source_packets &&
@@ -103,7 +107,7 @@ void RtpCodec::Encode(uint8_t* buffer, size_t size,
rtp_packet.SetHasPadding(has_padding_);
rtp_packet.SetHasExtension(has_extension_);
rtp_packet.SetMarker(index == num_of_total_packets - 1 ? 1 : 0);
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE::H264_FEC);
rtp_packet.SetPayloadType(RtpPacket::PAYLOAD_TYPE::H264_FEC_REPAIR);
rtp_packet.SetSequenceNumber(sequence_number_++);
rtp_packet.SetTimestamp(timestamp_);
rtp_packet.SetSsrc(ssrc_);
@@ -116,7 +120,8 @@ void RtpCodec::Encode(uint8_t* buffer, size_t size,
rtp_packet.SetExtensionProfile(extension_profile_);
rtp_packet.SetExtensionData(extension_data_, extension_len_);
}
rtp_packet.EncodeH264Fec(fec_packets[index], MAX_NALU_LEN);
rtp_packet.EncodeH264FecRepair(fec_packets[index], MAX_NALU_LEN,
index, num_of_source_packets);
}
packets.emplace_back(rtp_packet);
@@ -238,6 +243,7 @@ size_t RtpCodec::Decode(RtpPacket& packet, uint8_t* payload) {
// if ((packet.Buffer()[13] >> 7) & 0x01) {
// LOG_ERROR("Start bit!!!!!!!!!!!!!!!");
// }
auto nal_unit_type = packet.Buffer()[12] & 0x1F;
if (NALU == nal_unit_type) {

View File

@@ -12,8 +12,11 @@ void RtpPacket::TryToDecodeRtpPacket() {
} else if (NAL_UNIT_TYPE::FU_A == nal_unit_type_) {
DecodeH264Fua();
}
} else if (PAYLOAD_TYPE::H264_FEC == PAYLOAD_TYPE(buffer_[1] & 0x7F)) {
DecodeH264Fec();
} else if (PAYLOAD_TYPE::H264_FEC_SOURCE == PAYLOAD_TYPE(buffer_[1] & 0x7F)) {
nal_unit_type_ = NAL_UNIT_TYPE::FU_A;
DecodeH264FecSource();
} else if (PAYLOAD_TYPE::H264_FEC_REPAIR == PAYLOAD_TYPE(buffer_[1] & 0x7F)) {
DecodeH264FecRepair();
} else if (PAYLOAD_TYPE::DATA == PAYLOAD_TYPE(buffer_[1] & 0x7F)) {
DecodeData();
} else {
@@ -245,7 +248,9 @@ const uint8_t *RtpPacket::EncodeH264Fua(uint8_t *payload, size_t payload_size) {
return buffer_;
}
const uint8_t *RtpPacket::EncodeH264Fec(uint8_t *payload, size_t payload_size) {
const uint8_t *RtpPacket::EncodeH264FecSource(
uint8_t *payload, size_t payload_size, unsigned int fec_symbol_id,
unsigned int fec_source_symbol_num) {
buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) |
total_csrc_number_;
buffer_[1] = (marker_ << 7) | payload_type_;
@@ -279,10 +284,75 @@ const uint8_t *RtpPacket::EncodeH264Fec(uint8_t *payload, size_t payload_size) {
}
uint32_t fec_symbol_id_offset =
extension_offset + (has_extension_ && extension_data_ ? 4 : 0);
buffer_[12 + fec_symbol_id_offset] = fec_symbol_id_;
(has_extension_ && extension_data_ ? extension_len_ : 0) +
extension_offset;
uint32_t payload_offset = fec_symbol_id_offset + 1;
buffer_[12 + fec_symbol_id_offset] = fec_symbol_id;
uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1;
buffer_[12 + fec_source_symbol_num_offset] = fec_source_symbol_num;
uint32_t payload_offset = fec_source_symbol_num_offset + 1;
buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 |
fu_indicator_.nal_reference_idc << 6 |
fu_indicator_.nal_unit_type;
buffer_[13 + payload_offset] = fu_header_.start << 7 | fu_header_.end << 6 |
fu_header_.remain_bit << 1 |
fu_header_.nal_unit_type;
memcpy(buffer_ + 14 + payload_offset, payload, payload_size);
size_ = payload_size + (14 + payload_offset);
return buffer_;
}
const uint8_t *RtpPacket::EncodeH264FecRepair(
uint8_t *payload, size_t payload_size, unsigned int fec_symbol_id,
unsigned int fec_source_symbol_num) {
buffer_[0] = (version_ << 6) | (has_padding_ << 5) | (has_extension_ << 4) |
total_csrc_number_;
buffer_[1] = (marker_ << 7) | payload_type_;
buffer_[2] = (sequence_number_ >> 8) & 0xFF;
buffer_[3] = sequence_number_ & 0xFF;
buffer_[4] = (timestamp_ >> 24) & 0xFF;
buffer_[5] = (timestamp_ >> 16) & 0xFF;
buffer_[6] = (timestamp_ >> 8) & 0xFF;
buffer_[7] = timestamp_ & 0xFF;
buffer_[8] = (ssrc_ >> 24) & 0xFF;
buffer_[9] = (ssrc_ >> 16) & 0xFF;
buffer_[10] = (ssrc_ >> 8) & 0xFF;
buffer_[11] = ssrc_ & 0xFF;
for (uint32_t index = 0; index < total_csrc_number_ && !csrcs_.empty();
index++) {
buffer_[12 + index] = (csrcs_[index] >> 24) & 0xFF;
buffer_[13 + index] = (csrcs_[index] >> 16) & 0xFF;
buffer_[14 + index] = (csrcs_[index] >> 8) & 0xFF;
buffer_[15 + index] = csrcs_[index] & 0xFF;
}
uint32_t extension_offset =
total_csrc_number_ && !csrcs_.empty() ? total_csrc_number_ * 4 : 0;
if (has_extension_ && extension_data_) {
buffer_[12 + extension_offset] = extension_profile_ >> 8;
buffer_[13 + extension_offset] = extension_profile_ & 0xff;
buffer_[14 + extension_offset] = (extension_len_ >> 8) & 0xFF;
buffer_[15 + extension_offset] = extension_len_ & 0xFF;
memcpy(buffer_ + 16 + extension_offset, extension_data_, extension_len_);
}
uint32_t fec_symbol_id_offset =
(has_extension_ && extension_data_ ? extension_len_ : 0) +
extension_offset;
buffer_[12 + fec_symbol_id_offset] = fec_symbol_id;
uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1;
buffer_[12 + fec_source_symbol_num_offset] = fec_source_symbol_num;
uint32_t payload_offset = fec_source_symbol_num_offset + 1;
buffer_[12 + payload_offset] = fu_indicator_.forbidden_bit << 7 |
fu_indicator_.nal_reference_idc << 6 |
@@ -438,7 +508,7 @@ size_t RtpPacket::DecodeH264Fua(uint8_t *payload) {
return payload_size_;
}
size_t RtpPacket::DecodeH264Fec(uint8_t *payload) {
size_t RtpPacket::DecodeH264FecSource(uint8_t *payload) {
version_ = (buffer_[0] >> 6) & 0x03;
has_padding_ = (buffer_[0] >> 5) & 0x01;
has_extension_ = (buffer_[0] >> 4) & 0x01;
@@ -467,10 +537,69 @@ size_t RtpPacket::DecodeH264Fec(uint8_t *payload) {
extension_data_ = buffer_ + 16 + extension_offset;
}
uint32_t fec_symbol_id_offset = extension_offset + (has_extension_ ? 4 : 0);
uint32_t fec_symbol_id_offset =
extension_offset + (has_extension_ ? extension_len_ : 0);
fec_symbol_id_ = buffer_[12 + fec_symbol_id_offset];
uint32_t payload_offset = fec_symbol_id_offset + 1;
uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1;
fec_source_symbol_num_ = buffer_[12 + fec_source_symbol_num_offset];
uint32_t payload_offset = fec_source_symbol_num_offset + 1;
fu_indicator_.forbidden_bit = (buffer_[12 + payload_offset] >> 7) & 0x01;
fu_indicator_.nal_reference_idc = (buffer_[12 + payload_offset] >> 5) & 0x03;
fu_indicator_.nal_unit_type = buffer_[12 + payload_offset] & 0x1F;
fu_header_.start = (buffer_[13 + payload_offset] >> 7) & 0x01;
fu_header_.end = (buffer_[13 + payload_offset] >> 6) & 0x01;
fu_header_.remain_bit = (buffer_[13 + payload_offset] >> 5) & 0x01;
fu_header_.nal_unit_type = buffer_[13 + payload_offset] & 0x1F;
payload_size_ = size_ - (14 + payload_offset);
payload_ = buffer_ + 14 + payload_offset;
if (payload) {
memcpy(payload, payload_, payload_size_);
}
return payload_size_;
}
size_t RtpPacket::DecodeH264FecRepair(uint8_t *payload) {
version_ = (buffer_[0] >> 6) & 0x03;
has_padding_ = (buffer_[0] >> 5) & 0x01;
has_extension_ = (buffer_[0] >> 4) & 0x01;
total_csrc_number_ = buffer_[0] & 0x0f;
marker_ = (buffer_[1] >> 7) & 0x01;
payload_type_ = buffer_[1] & 0x7f;
sequence_number_ = (buffer_[2] << 8) | buffer_[3];
timestamp_ =
(buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | buffer_[7];
ssrc_ = (buffer_[8] << 24) | (buffer_[9] << 16) | (buffer_[10] << 8) |
buffer_[11];
for (uint32_t index = 0; index < total_csrc_number_; index++) {
uint32_t csrc = (buffer_[12 + index] << 24) | (buffer_[13 + index] << 16) |
(buffer_[14 + index] << 8) | buffer_[15 + index];
csrcs_.push_back(csrc);
}
uint32_t extension_offset = total_csrc_number_ * 4;
if (has_extension_) {
extension_profile_ =
(buffer_[12 + extension_offset] << 8) | buffer_[13 + extension_offset];
extension_len_ =
(buffer_[14 + extension_offset] << 8) | buffer_[15 + extension_offset];
extension_data_ = buffer_ + 16 + extension_offset;
}
uint32_t fec_symbol_id_offset =
extension_offset + (has_extension_ ? extension_len_ : 0);
fec_symbol_id_ = buffer_[12 + fec_symbol_id_offset];
uint32_t fec_source_symbol_num_offset = fec_symbol_id_offset + 1;
fec_source_symbol_num_ = buffer_[12 + fec_source_symbol_num_offset];
uint32_t payload_offset = fec_source_symbol_num_offset + 1;
payload_size_ = size_ - (14 + payload_offset);
payload_ = buffer_ + 14 + payload_offset;

View File

@@ -63,7 +63,7 @@
// |F|NRI| Type |S|E|R| Type |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// H264 FEC
// H264 FEC source symbol
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -81,7 +81,33 @@
// | Extensions |x
// | .... |x
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | FEC symbol id | |
// | FEC symbol id | src sym num | FU indicator | FU header |
// | |
// | FU Payload |
// | |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | padding | Padding size |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// H264 FEC repair symbol
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |V=2|P|X| CC |M| PT | sequence number |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | timestamp |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | synchronization source (SSRC) identifier |
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | Contributing source (CSRC) identifiers |x
// | .... |x
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | defined by profile | length |x
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Extensions |x
// | .... |x
// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// | FEC symbol id | src sym num | |
// | |
// | Fec Payload |
// | |
@@ -96,7 +122,8 @@ class RtpPacket {
public:
typedef enum {
H264 = 96,
H264_FEC = 97,
H264_FEC_SOURCE = 97,
H264_FEC_REPAIR = 98,
OPUS = 111,
DATA = 127
} PAYLOAD_TYPE;
@@ -171,11 +198,17 @@ class RtpPacket {
const uint8_t *Encode(uint8_t *payload, size_t payload_size);
const uint8_t *EncodeH264Nalu(uint8_t *payload, size_t payload_size);
const uint8_t *EncodeH264Fua(uint8_t *payload, size_t payload_size);
const uint8_t *EncodeH264Fec(uint8_t *payload, size_t payload_size);
const uint8_t *EncodeH264FecSource(uint8_t *payload, size_t payload_size,
unsigned int fec_symbol_id,
unsigned int fec_source_symbol_num);
const uint8_t *EncodeH264FecRepair(uint8_t *payload, size_t payload_size,
unsigned int fec_symbol_id,
unsigned int fec_source_symbol_num);
size_t DecodeData(uint8_t *payload = nullptr);
size_t DecodeH264Nalu(uint8_t *payload = nullptr);
size_t DecodeH264Fua(uint8_t *payload = nullptr);
size_t DecodeH264Fec(uint8_t *payload = nullptr);
size_t DecodeH264FecSource(uint8_t *payload = nullptr);
size_t DecodeH264FecRepair(uint8_t *payload = nullptr);
public:
// Get Header
@@ -226,6 +259,8 @@ class RtpPacket {
const uint8_t FecSymbolId() { return fec_symbol_id_; }
const uint8_t FecSourceSymbolNum() { return fec_source_symbol_num_; }
// Payload
const uint8_t *Payload() {
ParseRtpData();
@@ -277,6 +312,7 @@ class RtpPacket {
FU_INDICATOR fu_indicator_;
FU_HEADER fu_header_;
uint8_t fec_symbol_id_ = 0;
uint8_t fec_source_symbol_num_ = 0;
// Payload
uint8_t *payload_ = nullptr;

View File

@@ -48,9 +48,11 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
rtcp_rr.Encode();
SendRtcpRR(rtcp_rr);
// SendRtcpRR(rtcp_rr);
}
if (!fec_enable_) {
if (RtpPacket::PAYLOAD_TYPE::H264 == rtp_packet.PayloadType()) {
if (RtpPacket::NAL_UNIT_TYPE::NALU == rtp_packet.NalUnitType()) {
compelete_video_frame_queue_.push(
VideoFrame(rtp_packet.Payload(), rtp_packet.Size()));
@@ -59,6 +61,107 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
bool complete = CheckIsFrameCompleted(rtp_packet);
}
}
} else {
if (RtpPacket::PAYLOAD_TYPE::H264 == rtp_packet.PayloadType()) {
if (RtpPacket::NAL_UNIT_TYPE::NALU == rtp_packet.NalUnitType()) {
compelete_video_frame_queue_.push(
VideoFrame(rtp_packet.Payload(), rtp_packet.Size()));
} else if (RtpPacket::NAL_UNIT_TYPE::FU_A == rtp_packet.NalUnitType()) {
incomplete_frame_list_[rtp_packet.SequenceNumber()] = rtp_packet;
bool complete = CheckIsFrameCompleted(rtp_packet);
}
} else if (RtpPacket::PAYLOAD_TYPE::H264_FEC_SOURCE ==
rtp_packet.PayloadType()) {
if (last_packet_ts_ != rtp_packet.Timestamp()) {
fec_decoder_.Init();
fec_decoder_.ResetParams(rtp_packet.FecSourceSymbolNum());
last_packet_ts_ = rtp_packet.Timestamp();
}
incomplete_fec_packet_list_[rtp_packet.Timestamp()]
[rtp_packet.SequenceNumber()] = rtp_packet;
uint8_t** complete_frame = fec_decoder_.DecodeWithNewSymbol(
(const char*)incomplete_fec_packet_list_[rtp_packet.Timestamp()]
[rtp_packet.SequenceNumber()]
.Payload(),
rtp_packet.FecSymbolId());
if (nullptr != complete_frame) {
if (!nv12_data_) {
nv12_data_ = new uint8_t[NV12_BUFFER_SIZE];
}
size_t complete_frame_size = 0;
for (int index = 0; index < rtp_packet.FecSourceSymbolNum(); index++) {
if (nullptr == complete_frame[index]) {
LOG_ERROR("Invalid complete_frame[{}]", index);
}
memcpy(nv12_data_ + complete_frame_size, complete_frame[index], 1400);
complete_frame_size += 1400;
}
fec_decoder_.ReleaseSourcePackets(complete_frame);
fec_decoder_.Release();
LOG_ERROR("Release incomplete_fec_packet_list_");
incomplete_fec_packet_list_.erase(rtp_packet.Timestamp());
if (incomplete_fec_frame_list_.end() !=
incomplete_fec_frame_list_.find(rtp_packet.Timestamp())) {
incomplete_fec_frame_list_.erase(rtp_packet.Timestamp());
}
compelete_video_frame_queue_.push(
VideoFrame(nv12_data_, complete_frame_size));
} else {
incomplete_fec_frame_list_.insert(rtp_packet.Timestamp());
}
} else if (RtpPacket::PAYLOAD_TYPE::H264_FEC_REPAIR ==
rtp_packet.PayloadType()) {
if (incomplete_fec_frame_list_.end() ==
incomplete_fec_frame_list_.find(rtp_packet.Timestamp())) {
return;
}
if (last_packet_ts_ != rtp_packet.Timestamp()) {
fec_decoder_.Init();
fec_decoder_.ResetParams(rtp_packet.FecSourceSymbolNum());
last_packet_ts_ = rtp_packet.Timestamp();
}
incomplete_fec_packet_list_[rtp_packet.Timestamp()]
[rtp_packet.SequenceNumber()] = rtp_packet;
uint8_t** complete_frame = fec_decoder_.DecodeWithNewSymbol(
(const char*)incomplete_fec_packet_list_[rtp_packet.Timestamp()]
[rtp_packet.SequenceNumber()]
.Payload(),
rtp_packet.FecSymbolId());
if (nullptr != complete_frame) {
if (!nv12_data_) {
nv12_data_ = new uint8_t[NV12_BUFFER_SIZE];
}
size_t complete_frame_size = 0;
for (int index = 0; index < rtp_packet.FecSourceSymbolNum(); index++) {
if (nullptr == complete_frame[index]) {
LOG_ERROR("Invalid complete_frame[{}]", index);
}
memcpy(nv12_data_ + complete_frame_size, complete_frame[index], 1400);
complete_frame_size += 1400;
}
fec_decoder_.ReleaseSourcePackets(complete_frame);
fec_decoder_.Release();
incomplete_fec_packet_list_.erase(rtp_packet.Timestamp());
compelete_video_frame_queue_.push(
VideoFrame(nv12_data_, complete_frame_size));
}
}
}
}
bool RtpVideoReceiver::CheckIsFrameCompleted(RtpPacket& rtp_packet) {
if (rtp_packet.FuAEnd()) {

View File

@@ -4,7 +4,9 @@
#include <functional>
#include <map>
#include <queue>
#include <set>
#include "fec_decoder.h"
#include "frame.h"
#include "ringbuffer.h"
#include "rtcp_receiver_report.h"
@@ -46,6 +48,16 @@ class RtpVideoReceiver : public ThreadBase {
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
uint32_t last_send_rtcp_rr_packet_ts_ = 0;
std::function<int(const char*, size_t)> data_send_func_ = nullptr;
private:
bool fec_enable_ = true;
FecDecoder fec_decoder_;
uint32_t last_packet_ts_ = 0;
// std::map<uint16_t, RtpPacket> incomplete_fec_frame_list_;
// std::map<uint32_t, std::map<uint16_t, RtpPacket>> fec_source_symbol_list_;
// std::map<uint32_t, std::map<uint16_t, RtpPacket>> fec_repair_symbol_list_;
std::set<uint32_t> incomplete_fec_frame_list_;
std::map<uint32_t, std::map<uint16_t, RtpPacket>> incomplete_fec_packet_list_;
};
#endif

View File

@@ -313,7 +313,9 @@ uint8_t IceTransmission::CheckIsVideoPacket(const char *buffer, size_t size) {
}
uint8_t pt = buffer[1] & 0x7F;
if (RtpPacket::PAYLOAD_TYPE::H264 == pt) {
if (RtpPacket::PAYLOAD_TYPE::H264 == pt ||
RtpPacket::PAYLOAD_TYPE::H264_FEC_SOURCE == pt ||
RtpPacket::PAYLOAD_TYPE::H264_FEC_REPAIR == pt) {
return pt;
} else {
return 0;

View File

@@ -33,20 +33,17 @@
#include "of_reed-solomon_gf_2_m_includes.h"
#ifdef OF_USE_REED_SOLOMON_2_M_CODEC
of_status_t of_rs_2_m_create_codec_instance (of_rs_2_m_cb_t** of_cb)
{
of_status_t of_rs_2_m_create_codec_instance(of_rs_2_m_cb_t** of_cb) {
of_codec_type_t codec_type; /* temporary value */
of_rs_2_m_cb_t* cb;
OF_ENTER_FUNCTION
cb = (of_rs_2_m_cb_t*)of_realloc(*of_cb, sizeof(of_rs_2_m_cb_t));
*of_cb = cb;
/* realloc does not initialize the additional buffer space, so do that manually,
* then re-initialize a few parameters */
/* realloc does not initialize the additional buffer space, so do that
* manually, then re-initialize a few parameters */
codec_type = cb->codec_type;
memset(cb, 0, sizeof(*cb));
cb->codec_type = codec_type;
@@ -60,32 +57,35 @@ of_status_t of_rs_2_m_create_codec_instance (of_rs_2_m_cb_t** of_cb)
return OF_STATUS_OK;
}
of_status_t of_rs_2_m_release_codec_instance (of_rs_2_m_cb_t* ofcb)
{
of_status_t of_rs_2_m_release_codec_instance(of_rs_2_m_cb_t* ofcb) {
OF_ENTER_FUNCTION
of_rs_2m_release((of_galois_field_code_cb_t*)ofcb);
#ifdef OF_USE_DECODER
if (ofcb->available_symbols_tab != NULL)
{
if (ofcb->available_symbols_tab != NULL) {
of_free(ofcb->available_symbols_tab);
ofcb->available_symbols_tab = NULL;
}
#endif /* OF_USE_DECODER */
#ifdef OF_DEBUG /* { */
OF_TRACE_LVL(1, ("\tTo be added: Reed-Solomon GF(2^4): total of %ld bytes for precalculated tables (incl. %ld for the optimized mult table)\n",
sizeof(of_gf_2_4_log) + sizeof(of_gf_2_4_exp) + sizeof(of_gf_2_4_inv) + sizeof(of_gf_2_4_mul_table) + sizeof(of_gf_2_4_opt_mul_table), sizeof(of_gf_2_4_opt_mul_table)))
OF_TRACE_LVL(1, ("\tTo be added: Reed-Solomon GF(2^8): total of %ld bytes for precalculated tables (incl. %ld for mult table)\n",
sizeof(of_gf_2_8_log) + sizeof(of_gf_2_8_exp) + sizeof(of_gf_2_8_inv) + sizeof(of_gf_2_8_mul_table), sizeof(of_gf_2_8_mul_table)))
OF_TRACE_LVL(
1,
("\tTo be added: Reed-Solomon GF(2^4): total of %ld bytes for "
"precalculated tables (incl. %ld for the optimized mult table)\n",
sizeof(of_gf_2_4_log) + sizeof(of_gf_2_4_exp) + sizeof(of_gf_2_4_inv) +
sizeof(of_gf_2_4_mul_table) + sizeof(of_gf_2_4_opt_mul_table),
sizeof(of_gf_2_4_opt_mul_table)))
OF_TRACE_LVL(1, ("\tTo be added: Reed-Solomon GF(2^8): total of %ld bytes "
"for precalculated tables (incl. %ld for mult table)\n",
sizeof(of_gf_2_8_log) + sizeof(of_gf_2_8_exp) +
sizeof(of_gf_2_8_inv) + sizeof(of_gf_2_8_mul_table),
sizeof(of_gf_2_8_mul_table)))
#endif /* } OF_DEBUG */
OF_EXIT_FUNCTION
return OF_STATUS_OK;
}
of_status_t of_rs_2_m_set_fec_parameters(of_rs_2_m_cb_t* ofcb,
of_rs_2_m_parameters_t* params)
{
of_rs_2_m_parameters_t* params) {
OF_ENTER_FUNCTION
ofcb->m = params->m;
if ((ofcb->m != 4) && (ofcb->m != 8)) {
@@ -93,9 +93,12 @@ of_status_t of_rs_2_m_set_fec_parameters (of_rs_2_m_cb_t* ofcb,
goto error;
}
ofcb->field_size = (1 << ofcb->m) - 1;
ofcb->max_nb_encoding_symbols = ofcb->max_nb_source_symbols = ofcb->field_size;
if ((ofcb->nb_source_symbols = params->nb_source_symbols) > ofcb->max_nb_source_symbols) {
OF_PRINT_ERROR(("ERROR: invalid nb_source_symbols parameter (got %d, maximum is %d)",
ofcb->max_nb_encoding_symbols = ofcb->max_nb_source_symbols =
ofcb->field_size;
if ((ofcb->nb_source_symbols = params->nb_source_symbols) >
ofcb->max_nb_source_symbols) {
OF_PRINT_ERROR(
("ERROR: invalid nb_source_symbols parameter (got %d, maximum is %d)",
ofcb->nb_source_symbols, ofcb->max_nb_source_symbols))
goto error;
}
@@ -104,7 +107,8 @@ of_status_t of_rs_2_m_set_fec_parameters (of_rs_2_m_cb_t* ofcb,
ofcb->encoding_symbol_length = params->encoding_symbol_length;
ofcb->nb_encoding_symbols = ofcb->nb_source_symbols + ofcb->nb_repair_symbols;
#ifdef OF_USE_DECODER
ofcb->available_symbols_tab = (void**) of_calloc (ofcb->nb_encoding_symbols, sizeof (void*));
ofcb->available_symbols_tab =
(void**)of_calloc(ofcb->nb_encoding_symbols, sizeof(void*));
ofcb->nb_available_symbols = 0;
ofcb->nb_available_source_symbols = 0;
#endif /* OF_USE_DECODER */
@@ -116,59 +120,56 @@ error:
return OF_STATUS_FATAL_ERROR;
}
of_status_t of_rs_2_m_set_callback_functions (of_rs_2_m_cb_t* ofcb,
void* (*decoded_source_symbol_callback) (void *context,
_UINT32 size, /* size of decoded source symbol */
of_status_t of_rs_2_m_set_callback_functions(
of_rs_2_m_cb_t* ofcb,
void* (*decoded_source_symbol_callback)(
void* context, _UINT32 size, /* size of decoded source symbol */
_UINT32 esi), /* encoding symbol ID in {0..k-1} */
void* (*decoded_repair_symbol_callback) (void *context,
_UINT32 size, /* size of decoded repair symbol */
void* (*decoded_repair_symbol_callback)(
void* context, _UINT32 size, /* size of decoded repair symbol */
_UINT32 esi), /* encoding symbol ID in {0..k-1} */
void* context_4_callback)
{
void* context_4_callback) {
ofcb->decoded_source_symbol_callback = decoded_source_symbol_callback;
ofcb->decoded_repair_symbol_callback = decoded_repair_symbol_callback;
ofcb->context_4_callback = context_4_callback;
if (ofcb->decoded_repair_symbol_callback != NULL)
{
OF_PRINT_ERROR(("WARNING, the decoded repair symbol callback is never called with Reed-Solomon codes, since those repair symbols are never decoded\n"))
if (ofcb->decoded_repair_symbol_callback != NULL) {
OF_PRINT_ERROR(
("WARNING, the decoded repair symbol callback is never called with "
"Reed-Solomon codes, since those repair symbols are never decoded\n"))
}
return OF_STATUS_OK;
}
#ifdef OF_USE_ENCODER
of_status_t of_rs_2_m_build_repair_symbol(of_rs_2_m_cb_t* ofcb,
void* encoding_symbols_tab[],
_UINT32 esi_of_symbol_to_build)
{
_UINT32 esi_of_symbol_to_build) {
OF_ENTER_FUNCTION
if (esi_of_symbol_to_build < ofcb->nb_source_symbols || esi_of_symbol_to_build >= ofcb->nb_encoding_symbols)
{
OF_PRINT_ERROR(("ERROR: bad esi of encoding symbol (%d)\n", esi_of_symbol_to_build))
if (esi_of_symbol_to_build < ofcb->nb_source_symbols ||
esi_of_symbol_to_build >= ofcb->nb_encoding_symbols) {
OF_PRINT_ERROR(
("ERROR: bad esi of encoding symbol (%d)\n", esi_of_symbol_to_build))
goto error;
}
if (encoding_symbols_tab[esi_of_symbol_to_build] == NULL)
{
if ((encoding_symbols_tab[esi_of_symbol_to_build] = of_calloc (1, ofcb->encoding_symbol_length)) == NULL)
{
if (encoding_symbols_tab[esi_of_symbol_to_build] == NULL) {
if ((encoding_symbols_tab[esi_of_symbol_to_build] =
of_calloc(1, ofcb->encoding_symbol_length)) == NULL) {
OF_PRINT_ERROR(("ERROR: no memory\n"))
goto error;
}
}
if (ofcb->enc_matrix == NULL)
{
if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) != OF_STATUS_OK)
{
if (ofcb->enc_matrix == NULL) {
if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) !=
OF_STATUS_OK) {
OF_PRINT_ERROR(("ERROR: creating encoding matrix failed\n"))
goto error;
}
}
if (of_rs_2m_encode((of_galois_field_code_cb_t*) ofcb, (gf**)encoding_symbols_tab,
if (of_rs_2m_encode(
(of_galois_field_code_cb_t*)ofcb, (gf**)encoding_symbols_tab,
encoding_symbols_tab[esi_of_symbol_to_build], esi_of_symbol_to_build,
ofcb->encoding_symbol_length) != OF_STATUS_OK)
{
ofcb->encoding_symbol_length) != OF_STATUS_OK) {
OF_PRINT_ERROR(("ERROR: of_rs_encode failed\n"))
goto error;
}
@@ -181,45 +182,39 @@ error:
}
#endif // OF_USE_ENCODER
#ifdef OF_USE_DECODER
of_status_t of_rs_2_m_decode_with_new_symbol(of_rs_2_m_cb_t* ofcb,
void* new_symbol,
_UINT32 new_symbol_esi)
{
_UINT32 new_symbol_esi) {
OF_ENTER_FUNCTION
if (ofcb->decoding_finished)
{
if (ofcb->decoding_finished) {
OF_TRACE_LVL(2, ("%s: decoding already done\n", __FUNCTION__));
return OF_STATUS_OK;
}
if (ofcb->available_symbols_tab[new_symbol_esi] != NULL)
{
if (ofcb->available_symbols_tab[new_symbol_esi] != NULL) {
/* duplicated symbol, ignore */
OF_TRACE_LVL(2, ("%s: symbol (esi=%d) duplicated\n", __FUNCTION__, new_symbol_esi));
OF_TRACE_LVL(
2, ("%s: symbol (esi=%d) duplicated\n", __FUNCTION__, new_symbol_esi));
goto end;
}
ofcb->available_symbols_tab[new_symbol_esi] = new_symbol;
ofcb->nb_available_symbols++;
if (new_symbol_esi < ofcb->nb_source_symbols)
{
if (new_symbol_esi < ofcb->nb_source_symbols) {
/* remember a new source symbol is available */
ofcb->nb_available_source_symbols++;
}
if (ofcb->nb_available_source_symbols == ofcb->nb_source_symbols)
{
if (ofcb->nb_available_source_symbols == ofcb->nb_source_symbols) {
/* we received all the k source symbols, so it's finished */
ofcb->decoding_finished = true;
OF_TRACE_LVL(2, ("%s: done, all source symbols have been received\n", __FUNCTION__));
OF_TRACE_LVL(
2, ("%s: done, all source symbols have been received\n", __FUNCTION__));
OF_EXIT_FUNCTION
return OF_STATUS_OK;
}
if (ofcb->nb_available_symbols >= ofcb->nb_source_symbols)
{
if (ofcb->nb_available_symbols >= ofcb->nb_source_symbols) {
/* we received a sufficient number of symbols, so let's decode */
if (of_rs_2_m_finish_decoding(ofcb) != OF_STATUS_OK)
{
if (of_rs_2_m_finish_decoding(ofcb) != OF_STATUS_OK) {
OF_PRINT_ERROR(("ERROR: of_rs_decode failure\n"))
goto error;
}
@@ -237,23 +232,18 @@ error:
return OF_STATUS_ERROR;
}
of_status_t of_rs_2_m_set_available_symbols (of_rs_2_m_cb_t* ofcb,
void* const encoding_symbols_tab[])
{
of_status_t of_rs_2_m_set_available_symbols(
of_rs_2_m_cb_t* ofcb, void* const encoding_symbols_tab[]) {
_UINT32 i;
OF_ENTER_FUNCTION
ofcb->nb_available_symbols = 0;
ofcb->nb_available_source_symbols = 0;
for (i = 0; i < ofcb->nb_encoding_symbols; i++)
{
if ((ofcb->available_symbols_tab[i] = encoding_symbols_tab[i]) == NULL)
{
for (i = 0; i < ofcb->nb_encoding_symbols; i++) {
if ((ofcb->available_symbols_tab[i] = encoding_symbols_tab[i]) == NULL) {
continue;
}
if (i < ofcb->nb_source_symbols)
{
if (i < ofcb->nb_source_symbols) {
ofcb->nb_available_source_symbols++;
}
ofcb->nb_available_symbols++;
@@ -262,7 +252,6 @@ of_status_t of_rs_2_m_set_available_symbols (of_rs_2_m_cb_t* ofcb,
return OF_STATUS_OK;
}
#if 0 /* new */
of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
{
@@ -370,26 +359,29 @@ error:
#else /* old follows */
of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
{
of_status_t of_rs_2_m_finish_decoding(of_rs_2_m_cb_t* ofcb) {
_UINT32 k;
_UINT32 n;
// char *tmp_buf[ofcb->nb_source_symbols];/* keep available source/repair symbol buffers here... */
// int tmp_esi[ofcb->nb_source_symbols]; /* ...and their esi here. In fact we only need k entries
// char *tmp_buf[ofcb->nb_source_symbols];/* keep available
// source/repair symbol buffers here... */ int
// tmp_esi[ofcb->nb_source_symbols]; /* ...and their esi here. In fact we only
// need k entries
// * in these tables, but in order to avoid using malloc (time
// * consumming), we use an automatic table of maximum size for
// * both tmp_buf[] and tmp_esi[]. */
_INT32 tmp_idx; /* index in tmp_buf[] and tmp_esi[] tabs */
char *large_buf = NULL; /* single large buffer where to copy all source/repair symbols */
char* large_buf =
NULL; /* single large buffer where to copy all source/repair symbols */
_UINT32 off; /* offset, in unit of characters, in large_buf */
void **ass_buf; /* tmp pointer to the current available source symbol entry in available_symbols_tab[] */
void** ass_buf; /* tmp pointer to the current available source symbol entry in
available_symbols_tab[] */
_UINT32 ass_esi; /* corresponding available source symbol ESI */
void **ars_buf; /* tmp pointer to the current available repair symbol entry in available_symbols_tab[] */
void** ars_buf; /* tmp pointer to the current available repair symbol entry in
available_symbols_tab[] */
_UINT32 ars_esi; /* corresponding available repair symbol ESI */
OF_ENTER_FUNCTION
if (ofcb->decoding_finished)
{
if (ofcb->decoding_finished) {
return OF_STATUS_OK;
}
k = ofcb->nb_source_symbols;
@@ -399,14 +391,12 @@ of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
for (int i = 0; i < n; i++) {
tmp_buf[i] = NULL;
}
if (ofcb->nb_available_symbols < k)
{
if (ofcb->nb_available_symbols < k) {
OF_PRINT_ERROR(("ERROR: nb received symbols < nb source symbols\n"))
OF_EXIT_FUNCTION
return OF_STATUS_FAILURE;
}
if (ofcb->nb_available_source_symbols == k)
{
if (ofcb->nb_available_source_symbols == k) {
/* we received all the k source symbols, so it's finished */
ofcb->decoding_finished = true;
OF_EXIT_FUNCTION
@@ -418,46 +408,43 @@ of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
* the tmp_buf buffers!!!
*/
large_buf = (char*)of_malloc(k * ofcb->encoding_symbol_length);
if (large_buf == NULL)
{
if (large_buf == NULL) {
goto no_mem;
}
/* Then remember the location of each symbol buffer */
for (tmp_idx = 0, off = 0; tmp_idx < k; tmp_idx++, off += ofcb->encoding_symbol_length) {
for (tmp_idx = 0, off = 0; tmp_idx < k;
tmp_idx++, off += ofcb->encoding_symbol_length) {
tmp_buf[tmp_idx] = large_buf + off;
}
tmp_idx = 0; /* index in tmp_buf and tmp_esi tables */
/*
* Copy all the available source symbols (it's essential for decoding speed purposes) and
* a sufficient number of repair symbols to the tmp_buf array. Copy data as well in the
* large_buf buffer.
* Because of of_rs_decode internal details, we put source symbols at their right location
* and fill in the gaps (i.e. erased source symbols) with repair symbols.
* Copy all the available source symbols (it's essential for decoding speed
* purposes) and a sufficient number of repair symbols to the tmp_buf array.
* Copy data as well in the large_buf buffer. Because of of_rs_decode internal
* details, we put source symbols at their right location and fill in the gaps
* (i.e. erased source symbols) with repair symbols.
*/
ass_esi = 0;
ars_esi = k;
ass_buf = ofcb->available_symbols_tab;
ars_buf = ofcb->available_symbols_tab + k;
for (tmp_idx = 0; tmp_idx < k; tmp_idx++)
{
if (*ass_buf == NULL)
{
for (tmp_idx = 0; tmp_idx < k; tmp_idx++) {
if (*ass_buf == NULL) {
/* this source symbol is not available, replace it with a repair */
while (*ars_buf == NULL)
{
while (*ars_buf == NULL) {
ars_esi++;
ars_buf++;
}
OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy repair with esi=%d in tmp_buf[%d]\n",
OF_TRACE_LVL(
2, ("of_rs_finish_decoding: copy repair with esi=%d in tmp_buf[%d]\n",
ars_esi, tmp_idx))
memcpy(tmp_buf[tmp_idx], *ars_buf, ofcb->encoding_symbol_length);
tmp_esi[tmp_idx] = ars_esi;
ars_esi++;
ars_buf++;
}
else
{
OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy source with esi=%d in tmp_buf[%d]\n",
} else {
OF_TRACE_LVL(
2, ("of_rs_finish_decoding: copy source with esi=%d in tmp_buf[%d]\n",
ars_esi, tmp_idx))
int i;
@@ -475,16 +462,16 @@ of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
OF_TRACE_LVL(2, ("Before of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx))
}
#endif
if (ofcb->enc_matrix == NULL)
{
if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) != OF_STATUS_OK)
{
if (ofcb->enc_matrix == NULL) {
if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) !=
OF_STATUS_OK) {
OF_PRINT_ERROR(("ERROR: creating encoding matrix failed\n"))
goto error;
}
}
if (of_rs_2m_decode ((of_galois_field_code_cb_t*)ofcb, (gf**)tmp_buf, (int*)tmp_esi, ofcb->encoding_symbol_length) != OF_STATUS_OK)
{
if (of_rs_2m_decode((of_galois_field_code_cb_t*)ofcb, (gf**)tmp_buf,
(int*)tmp_esi,
ofcb->encoding_symbol_length) != OF_STATUS_OK) {
OF_PRINT_ERROR(("ERROR: of_rs_decode failure\n"))
goto error;
}
@@ -496,14 +483,13 @@ of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
}
#endif
/*
* finally update the source_symbols_tab table with the decoded source symbols.
* finally update the source_symbols_tab table with the decoded source
* symbols.
*/
for (tmp_idx = 0; tmp_idx < k; tmp_idx++)
{
for (tmp_idx = 0; tmp_idx < k; tmp_idx++) {
ASSERT(tmp_idx < k);
ass_buf = &(ofcb->available_symbols_tab[tmp_idx]);
if (*ass_buf != NULL)
{
if (*ass_buf != NULL) {
/* nothing to do, this source symbol has already been received. */
continue;
}
@@ -513,58 +499,48 @@ of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb)
* Call either the associated callback or allocate memory, and then
* copy the symbol content in it.
*/
if (ofcb->decoded_source_symbol_callback != NULL)
{
*ass_buf = ofcb->decoded_source_symbol_callback (ofcb->context_4_callback,
ofcb->encoding_symbol_length, tmp_idx);
}
else
{
if (ofcb->decoded_source_symbol_callback != NULL) {
*ass_buf = ofcb->decoded_source_symbol_callback(
ofcb->context_4_callback, ofcb->encoding_symbol_length, tmp_idx);
} else {
*ass_buf = (void*)of_malloc(ofcb->encoding_symbol_length);
}
if (*ass_buf == NULL)
{
if (*ass_buf == NULL) {
goto no_mem;
}
memcpy(*ass_buf, tmp_buf[tmp_idx], ofcb->encoding_symbol_length);
OF_TRACE_LVL(2, ("of_rs_finish_decoding: decoded source symbol esi=%d from tmp_buf[%d]\n",
OF_TRACE_LVL(2, ("of_rs_finish_decoding: decoded source symbol esi=%d from "
"tmp_buf[%d]\n",
tmp_idx, tmp_idx))
}
of_free(large_buf);
free(tmp_esi);
for(int i=0;i<n;i++){
free(tmp_buf[i]);
}
free(tmp_buf);
OF_EXIT_FUNCTION
return OF_STATUS_OK;
no_mem:
OF_PRINT_ERROR(("ERROR: out of memory.\n"))
free(tmp_esi);
for(int i=0;i<n;i++){
free(tmp_buf[i]);
}
free(tmp_buf);
error:
OF_EXIT_FUNCTION
return OF_STATUS_ERROR;
}
#endif
bool of_rs_2_m_is_decoding_complete (of_rs_2_m_cb_t* ofcb)
{
bool of_rs_2_m_is_decoding_complete(of_rs_2_m_cb_t* ofcb) {
OF_ENTER_FUNCTION
OF_EXIT_FUNCTION
return ofcb->decoding_finished;
}
of_status_t of_rs_2_m_get_source_symbols_tab(of_rs_2_m_cb_t* ofcb,
void* source_symbols_tab[])
{
void* source_symbols_tab[]) {
OF_ENTER_FUNCTION
if (of_rs_2_m_is_decoding_complete(ofcb) == false)
{
if (of_rs_2_m_is_decoding_complete(ofcb) == false) {
OF_PRINT_ERROR(("ERROR: decoding not complete.\n"))
OF_EXIT_FUNCTION
return OF_STATUS_ERROR;
@@ -579,27 +555,27 @@ of_status_t of_rs_2_m_get_source_symbols_tab (of_rs_2_m_cb_t* ofcb,
}
}
#else
memcpy(source_symbols_tab, ofcb->available_symbols_tab, ofcb->nb_source_symbols * sizeof(void*));
memcpy(source_symbols_tab, ofcb->available_symbols_tab,
ofcb->nb_source_symbols * sizeof(void*));
#endif
OF_EXIT_FUNCTION
return OF_STATUS_OK;
}
#endif // OF_USE_DECODER
of_status_t of_rs_2_m_set_control_parameter (of_rs_2_m_cb_t* ofcb,
_UINT32 type,
void* value,
_UINT32 length)
{
of_status_t of_rs_2_m_set_control_parameter(of_rs_2_m_cb_t* ofcb, _UINT32 type,
void* value, _UINT32 length) {
_UINT16 m;
OF_ENTER_FUNCTION
switch (type) {
case OF_RS_CTRL_SET_FIELD_SIZE:
if (value == NULL || length != sizeof(_UINT16)) {
OF_PRINT_ERROR(("OF_CTRL_SET_FIELD_SIZE ERROR: null value or bad length (got %d, expected %zu)\n", length, sizeof(_UINT16)))
OF_PRINT_ERROR(
("OF_CTRL_SET_FIELD_SIZE ERROR: null value or bad length (got %d, "
"expected %zu)\n",
length, sizeof(_UINT16)))
goto error;
}
m = *(_UINT16*)value;
@@ -609,7 +585,8 @@ of_status_t of_rs_2_m_set_control_parameter (of_rs_2_m_cb_t* ofcb,
}
ofcb->m = m;
ofcb->field_size = (1 << ofcb->m) - 1;
ofcb->max_nb_encoding_symbols = ofcb->max_nb_source_symbols = ofcb->field_size;
ofcb->max_nb_encoding_symbols = ofcb->max_nb_source_symbols =
ofcb->field_size;
break;
default:
@@ -624,38 +601,48 @@ error:
return OF_STATUS_ERROR;
}
of_status_t of_rs_2_m_get_control_parameter (of_rs_2_m_cb_t* ofcb,
_UINT32 type,
void* value,
_UINT32 length)
{
of_status_t of_rs_2_m_get_control_parameter(of_rs_2_m_cb_t* ofcb, _UINT32 type,
void* value, _UINT32 length) {
OF_ENTER_FUNCTION
switch (type) {
case OF_CTRL_GET_MAX_K:
if (value == NULL || length != sizeof(_UINT32)) {
OF_PRINT_ERROR(("OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, expected %zu)\n", length, sizeof(_UINT32)))
OF_PRINT_ERROR(
("OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, "
"expected %zu)\n",
length, sizeof(_UINT32)))
goto error;
}
if (ofcb->max_nb_source_symbols == 0) {
OF_PRINT_ERROR(("OF_CTRL_GET_MAX_K ERROR: this parameter is not initialized. Use the of_rs_2_m_set_fec_parameters function to initialize it or of_rs_2_m_set_control_parameter.\n"))
OF_PRINT_ERROR(
("OF_CTRL_GET_MAX_K ERROR: this parameter is not initialized. Use "
"the of_rs_2_m_set_fec_parameters function to initialize it or "
"of_rs_2_m_set_control_parameter.\n"))
goto error;
}
*(_UINT32*)value = ofcb->max_nb_source_symbols;
OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(_UINT32*)value))
OF_TRACE_LVL(
1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(_UINT32*)value))
break;
case OF_CTRL_GET_MAX_N:
if (value == NULL || length != sizeof(_UINT32)) {
OF_PRINT_ERROR(("OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, expected %zu)\n", length, sizeof(_UINT32)))
OF_PRINT_ERROR(
("OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, "
"expected %zu)\n",
length, sizeof(_UINT32)))
goto error;
}
if (ofcb->max_nb_encoding_symbols == 0) {
OF_PRINT_ERROR(("OF_CTRL_GET_MAX_N ERROR: this parameter is not initialized. Use the of_rs_2_m_set_fec_parameters function to initialize it or of_rs_2_m_set_control_parameter.\n"))
OF_PRINT_ERROR(
("OF_CTRL_GET_MAX_N ERROR: this parameter is not initialized. Use "
"the of_rs_2_m_set_fec_parameters function to initialize it or "
"of_rs_2_m_set_control_parameter.\n"))
goto error;
}
*(_UINT32*)value = ofcb->max_nb_encoding_symbols;
OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(_UINT32*)value))
OF_TRACE_LVL(
1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(_UINT32*)value))
break;
default: