#include "aom-av1.h" #include "rtp-payload.h" #include "rtp-profile.h" #include #include #include #include enum { OBU_SEQUENCE_HEADER = 1, OBU_TEMPORAL_DELIMITER = 2, OBU_FRAME = 6, }; struct av1_rtp_test_t { struct aom_av1_t av1; void* encoder; void* decoder; uint32_t pts, dts; uint8_t* ptr; int bytes; int vcl; int keyframe; FILE* wfp; }; static uint8_t* file_read(const char* file, long* size) { FILE* fp = fopen(file, "rb"); if (fp) { fseek(fp, 0, SEEK_END); *size = ftell(fp); fseek(fp, 0, SEEK_SET); uint8_t* ptr = (uint8_t*)malloc(*size); fread(ptr, 1, *size, fp); fclose(fp); return ptr; } return NULL; } static void* rtp_alloc(void* /*param*/, int bytes) { static uint8_t buffer[2 * 1024 * 1024 + 4] = { 0, 0, 0, 1, }; assert(bytes <= sizeof(buffer) - 4); return buffer + 4; } static void rtp_free(void* /*param*/, void* /*packet*/) { } static int rtp_encode_packet(void* param, const void* packet, int bytes, uint32_t timestamp, int /*flags*/) { struct av1_rtp_test_t* ctx = (struct av1_rtp_test_t*)param; //int x = rand(); //if( (x % 100) < RTP_LOST_PERCENT ) //{ // printf("======== discard [%s] timestamp: %u ==============\n", ctx->av ? "V" : "A", (unsigned int)timestamp); // return 0; //} int r = rtp_payload_decode_input(ctx->decoder, packet, bytes); return r >= 0 ? 0 : r; } static int rtp_decode_packet(void* param, const void* packet, int bytes, uint32_t timestamp, int flags) { struct av1_rtp_test_t* ctx = (struct av1_rtp_test_t*)param; printf("RTP Decode: timestamp: %u, bytes: %d\n", (unsigned int)timestamp, bytes); static const uint8_t av1_temporal_delimiter[] = { 0x12, 0x00 }; assert(sizeof(av1_temporal_delimiter) == fwrite(av1_temporal_delimiter, 1, sizeof(av1_temporal_delimiter), ctx->wfp)); assert(bytes == fwrite(packet, 1, bytes, ctx->wfp)); return 0; } static int av1_handler(void* param, const uint8_t* obu, size_t bytes) { struct av1_rtp_test_t* ctx = (struct av1_rtp_test_t*)param; uint8_t obu_type = (obu[0] >> 3) & 0x0F; if (ctx->vcl > 0 && OBU_TEMPORAL_DELIMITER == obu_type) { printf("av1 frame: %u, bytes: %d\n", (unsigned int)ctx->dts, ctx->bytes); assert(0 == rtp_payload_encode_input(ctx->encoder, ctx->ptr, ctx->bytes, (unsigned int)ctx->dts)); ctx->dts += 40; // fps 25 ctx->bytes = 0; ctx->vcl = 0; ctx->keyframe = 0; } if (OBU_TEMPORAL_DELIMITER == obu_type) return 0; // ignore if (OBU_SEQUENCE_HEADER == obu_type) ctx->keyframe = 1; if (OBU_FRAME == obu_type) ++ctx->vcl; memcpy(ctx->ptr + ctx->bytes, obu, bytes); ctx->bytes += bytes; return 0; } void av1_rtp_test(const char* low_overhead_bitstream_format_obu) { struct av1_rtp_test_t ctx; memset(&ctx, 0, sizeof(ctx)); static uint8_t s_buffer[2 * 1024 * 1024]; snprintf((char*)s_buffer, sizeof(s_buffer), "%s.obu", low_overhead_bitstream_format_obu); ctx.wfp = fopen((const char*)s_buffer, "wb"); ctx.ptr = s_buffer; struct rtp_payload_t handler1; handler1.alloc = rtp_alloc; handler1.free = rtp_free; handler1.packet = rtp_decode_packet; ctx.decoder = rtp_payload_decode_create(97, "AV1", &handler1, &ctx); struct rtp_payload_t handler2; handler2.alloc = rtp_alloc; handler2.free = rtp_free; handler2.packet = rtp_encode_packet; ctx.encoder = rtp_payload_encode_create(97, "AV1", 0, 0, &handler2, &ctx); long bytes = 0; uint8_t* ptr = file_read(low_overhead_bitstream_format_obu, &bytes); if (NULL == ptr) return; aom_av1_obu_split(ptr, bytes, av1_handler, &ctx); free(ptr); fclose(ctx.wfp); }