in S3_HLS_Pes.c [150:345]
int32_t S3_HLS_Pes_Write_Video_Frame(S3_HLS_BUFFER_CTX* buffer_ctx, S3_HLS_FRAME_PACK* pack) {
int32_t ret = S3_HLS_OK;
uint8_t random_access = S3_HLS_FALSE;
uint8_t has_pcr = S3_HLS_FALSE;
uint32_t content_length = 0;
if(0 == pack->item_count) {
PES_DEBUG("[Pes - Video] Invalid Packet Count!\n");
return S3_HLS_INVALID_PARAMETER;
}
if (0 != S3_HLS_Lock_Buffer(buffer_ctx)) {// lock failed
PES_DEBUG("[Pes - Video] Lock Buffer Failed!\n");
return S3_HLS_LOCK_FAILED;
}
if(first_call) {
PES_DEBUG("[Pes - Video] First Call Flush Buffer!\n");
S3_HLS_Flush_Buffer(buffer_ctx); // only update last timestamp
first_call = 0;
}
for(uint32_t cnt = 0; cnt < pack->item_count; cnt++) {
if(NULL == pack->items[cnt].first_part_start || (NULL == pack->items[cnt].second_part_start && pack->items[cnt].second_part_length != 0)) {
ret = S3_HLS_INVALID_PARAMETER;
goto l_exit;
}
S3_HLS_H264E_NALU_TYPE_E frame_type = S3_HLS_H264_Nalu_Type(&pack->items[cnt]);
if(seperate_nalu_type == frame_type) {
PES_DEBUG("[Pes - Video] Nalu: %d\n", frame_type);
if(seperate_count_interval == seperate_count) {
PES_DEBUG("[Pes - Video] Need Seperate\n");
has_error = 0;
ret = S3_HLS_Flush_Buffer(buffer_ctx);
if(0 > ret) {
PES_DEBUG("[Pes - Video] Flush Buffer Failed!\n");
goto l_exit;
}
seperate_count = 0;
pat_pmt_count = 0;
}
seperate_count++;
}
if(S3_HLS_H264E_NALU_IDR == frame_type) {
random_access = S3_HLS_TRUE;
}
content_length += pack->items[cnt].first_part_length + pack->items[cnt].second_part_length;
}
PES_DEBUG("[Pes - Video] Video Stream Length %d\n", content_length);
if(has_error) {
PES_DEBUG("[pes - Video] Prev error detected, skip until next sperate frame!\n");
goto l_exit;
}
content_length += sizeof(video_pes_header); // calculate total length
// decide whether write pat & pmt
if(0 == pat_pmt_count) {
ret = S3_HLS_H264_PAT_Write_To_Buffer(buffer_ctx);
if(0 > ret) {
has_error = 1;
PES_DEBUG("[Pes - Video] Write PAT Failed!\n");
goto l_exit;
}
ret = S3_HLS_H264_PMT_Write_To_Buffer(buffer_ctx);
if(0 > ret) {
has_error = 1;
PES_DEBUG("[Pes - Video] Write PAT Failed!\n");
goto l_exit;
}
}
// update counter
pat_pmt_count++;
if(pat_pmt_interval == pat_pmt_count) {
pat_pmt_count = 0;
}
if(0 == pcr_count) {
has_pcr = S3_HLS_TRUE;
pcr_count++;
if(pcr_count_interval == pcr_count) {
pcr_count = 0;
}
}
S3_HLS_TS_Set_Pid(S3_HLS_Video_PID);
S3_HLS_TS_Set_Payload_Start();
if(random_access) {
S3_HLS_TS_Set_Random_Access();
}
if(has_pcr) {
S3_HLS_TS_Set_PCR(pack->items[0].timestamp);
}
S3_HLS_TS_Fill_Remaining_Length(content_length);
PES_DEBUG("[Pes - Video] Write TS Header %d\n", content_length);
// write TS header
ret = S3_HLS_TS_Write_To_Buffer(buffer_ctx);
if(0 > ret) { // write error
has_error = 1;
goto l_exit;
}
uint32_t remaining = S3_HLS_TS_PACKET_SIZE - ret;
PES_DEBUG("[Pes - Video] Remaining Size %d\n", remaining);
// write PES info
ret = S3_HLS_Pes_Write_Video_Pes(buffer_ctx, pack->items[0].timestamp);
if(0 > ret) {
has_error = 1;
goto l_exit;
}
remaining -= ret;
content_length -= ret;
uint32_t packet_index = 0;
uint32_t packet_pos = 0;
while(content_length > 0) { // have data to send
PES_DEBUG("[Pes - Video] Remaining Size %d Content Length %d\n", remaining, content_length);
if(0 == remaining) { // start new ts header
PES_DEBUG("[Pes - Video] Start New TS Fragment\n");
S3_HLS_TS_Set_Pid(S3_HLS_Video_PID);
S3_HLS_TS_Fill_Remaining_Length(content_length);
ret = S3_HLS_TS_Write_To_Buffer(buffer_ctx);
PES_DEBUG("[Pes - Video] TS Header used %d\n", ret);
if(0 > ret) {
has_error = 1;
goto l_exit;
}
remaining = S3_HLS_TS_PACKET_SIZE - ret;
}
if(remaining > 0) {
// write data to buffer
uint8_t* start_pos;
uint32_t write_length;
if(packet_pos >= pack->items[packet_index].first_part_length) { // writing second part
// need to copy from second part
start_pos = pack->items[packet_index].second_part_start + (packet_pos - pack->items[packet_index].first_part_length);
write_length = remaining < (pack->items[packet_index].first_part_length + pack->items[packet_index].second_part_length - packet_pos) ? remaining : (pack->items[packet_index].first_part_length + pack->items[packet_index].second_part_length - packet_pos);
PES_DEBUG("Write From Second Part %d, %d, %d, %d, %d\n", remaining, write_length, pack->items[packet_index].first_part_length, pack->items[packet_index].second_part_length, packet_pos);
} else { // writing first part
start_pos = pack->items[packet_index].first_part_start + packet_pos;
write_length = remaining < (pack->items[packet_index].first_part_length - packet_pos) ? remaining : (pack->items[packet_index].first_part_length - packet_pos);
PES_DEBUG("Write From First Part %d, %d, %d, %d\n", remaining, write_length, pack->items[packet_index].first_part_length, packet_pos);
}
ret = S3_HLS_Put_To_Buffer(buffer_ctx, start_pos, write_length);
PES_DEBUG("Write Buffer Ret %d\n", ret);
if(0 > ret) {
has_error = 1;
goto l_exit;
}
content_length -= write_length;
remaining -= write_length;
packet_pos += write_length;
PES_DEBUG("[Pes - Video] After Put: Remaining Size %d Content Length %d Packet Pos %d\n", remaining, content_length, packet_pos);
if(packet_pos == pack->items[packet_index].first_part_length + pack->items[packet_index].second_part_length) {
PES_DEBUG("Goto Next Packet Remaining: %d\n", remaining);
packet_index++;
packet_pos = 0;
}
}
}
S3_HLS_Unlock_Buffer(buffer_ctx);
return S3_HLS_OK;
l_exit:
S3_HLS_Unlock_Buffer(buffer_ctx);
return ret;
}