int32_t S3_HLS_Pes_Write_Video_Frame()

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;
}