147 lines
3.5 KiB
C++
147 lines
3.5 KiB
C++
#include "aom-av1.h"
|
|
#include "rtp-payload.h"
|
|
#include "rtp-profile.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
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);
|
|
}
|