blob: d42a2ffed967a73706a61aba7b122e8f675a37f2 [file] [log] [blame] [edit]
/*
* Copyright (c) 2025, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* aomedia.org/license/patent-license/.
*/
#ifndef TOOLS_STREAM_MUX_H_
#define TOOLS_STREAM_MUX_H_
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <memory>
#include <string>
#include "config/aom_config.h"
#include "common/ivfdec.h"
#include "common/obudec.h"
#include "common/tools_common.h"
#include "common/webmdec.h"
#include "av1/common/obu_util.h"
#include "av1/common/blockd.h"
#include "aom_dsp/bitwriter_buffer.h"
#include "aom_dsp/bitreader_buffer.h"
#include "aom/aom_codec.h"
#include "av1/encoder/bitstream.h"
#define PRINT_TU_INFO 0
#define AOM_MAX_NUM_STREAMS 4
const size_t kInitialBufferSize = 100 * 1024;
// Basic OBU syntax
// 8 bits: Header
// 7,6,5,4
// type bits
// 3
// extension flag bit
// 2,1,0
// tlayer ID
const uint32_t kObuTypeBitsMask = 0x1F;
const uint32_t kObuTypeBitsShift = 2;
const uint32_t kObuExtensionFlagBitMask = 0x1;
const uint32_t kObuExtensionFlagBitShift = 7;
const uint32_t kObuExtTlayerIdBitsMask = 0x3;
const uint32_t kObuExtTlayerIdBitsShift = 0;
// When extension flag bit is set:
// 8 bits: extension header
// 7,6,5
// mlayer ID
// 4,3,2,1,0
// xlayer ID
const uint32_t kObuExtMlayerIdBitsMask = 0x7;
const uint32_t kObuExtMlayerIdBitsShift = 5;
const uint32_t kObuExtXlayerIdBitsMask = 0x1F;
const uint32_t kObuExtXlayerIdBitsShift = 0;
struct InputContext {
InputContext() = default;
~InputContext() { free(unit_buffer); }
void Init() {
memset(avx_ctx, 0, sizeof(*avx_ctx));
memset(obu_ctx, 0, sizeof(*obu_ctx));
obu_ctx->avx_ctx = avx_ctx;
#if CONFIG_WEBM_IO
memset(webm_ctx, 0, sizeof(*webm_ctx));
#endif
obu_ctx->is_annexb = 1;
}
AvxInputContext *avx_ctx = nullptr;
ObuDecInputContext *obu_ctx = nullptr;
#if CONFIG_WEBM_IO
WebmInputContext *webm_ctx = nullptr;
#endif
uint8_t *unit_buffer = nullptr;
size_t unit_buffer_size = 0;
};
VideoFileType GetFileType(InputContext *ctx) {
if (file_is_ivf(ctx->avx_ctx)) return FILE_TYPE_IVF;
if (file_is_obu(ctx->obu_ctx)) return FILE_TYPE_OBU;
#if CONFIG_WEBM_IO
if (file_is_webm(ctx->webm_ctx, ctx->avx_ctx)) return FILE_TYPE_WEBM;
#endif
return FILE_TYPE_RAW;
}
bool ReadTemporalUnit(InputContext *ctx, size_t *unit_size) {
const VideoFileType file_type = ctx->avx_ctx->file_type;
switch (file_type) {
case FILE_TYPE_IVF: {
if (ivf_read_frame(ctx->avx_ctx->file, &ctx->unit_buffer, unit_size,
&ctx->unit_buffer_size, NULL)) {
return false;
}
break;
}
case FILE_TYPE_OBU: {
if (obudec_read_temporal_unit(ctx->obu_ctx, &ctx->unit_buffer, unit_size,
&ctx->unit_buffer_size)) {
return false;
}
break;
}
#if CONFIG_WEBM_IO
case FILE_TYPE_WEBM: {
if (webm_read_frame(ctx->webm_ctx, &ctx->unit_buffer, unit_size,
&ctx->unit_buffer_size)) {
return false;
}
break;
}
#endif
default: fprintf(stderr, "Error: Unsupported file type.\n"); return false;
}
return true;
}
bool ValidObuType(int obu_type) {
switch (obu_type) {
case OBU_SEQUENCE_HEADER:
case OBU_TEMPORAL_DELIMITER:
#if CONFIG_MULTI_FRAME_HEADER
case OBU_MULTI_FRAME_HEADER:
#endif // CONFIG_MULTI_FRAME_HEADER
#if CONFIG_F106_OBU_TILEGROUP
#if CONFIG_F106_OBU_SWITCH
case OBU_SWITCH:
#endif // CONFIG_F106_OBU_SWITCH
#if CONFIG_F106_OBU_SEF
case OBU_SEF:
#endif // CONFIG_F106_OBU_SEF
#if CONFIG_F106_OBU_TIP
case OBU_TIP:
#endif // CONFIG_F106_OBU_TIP
case OBU_TILE_GROUP:
#else
case OBU_FRAME_HEADER:
case OBU_TILE_GROUP:
#endif // CONFIG_F106_OBU_TILEGROUP
case OBU_METADATA:
#if !CONFIG_F106_OBU_TILEGROUP
case OBU_FRAME:
#if !CONFIG_REMOVAL_REDUNDANT_FRAME_HEADER
case OBU_REDUNDANT_FRAME_HEADER:
#endif // !CONFIG_REMOVAL_REDUNDANT_FRAME_HEADER
#endif // CONFIG_F106_OBU_TILEGROUP
#if CONFIG_MULTILAYER_HLS
case OBU_LAYER_CONFIGURATION_RECORD:
case OBU_ATLAS_SEGMENT:
case OBU_OPERATING_POINT_SET:
#endif // CONFIG_MULTILAYER_HLS
#if CONFIG_MULTI_STREAM
case OBU_MSDO:
#endif // CONFIG_MULTI_STREAM
case OBU_PADDING: return true;
}
return false;
}
void PrintObuHeader(const ObuHeader *header) {
printf(
" OBU type: %s\n"
" obu_tlayer_id: %d\n"
" obu_mlayer_id: %d\n"
" obu_xlayer_id: %d\n",
aom_obu_type_to_string(static_cast<OBU_TYPE>(header->type)),
header->obu_tlayer_id, header->obu_mlayer_id, header->obu_xlayer_id);
}
// Initialize a read bit buffer
struct aom_read_bit_buffer *init_read_bit_buffer(struct aom_read_bit_buffer *rb,
const uint8_t *data,
const uint8_t *data_end) {
rb->bit_offset = 0;
rb->error_handler = NULL;
rb->error_handler_data = NULL;
rb->bit_buffer = data;
rb->bit_buffer_end = data_end;
return rb;
}
bool ParseAV2ObuHeader(uint8_t obu_header_byte, ObuHeader *obu_header) {
obu_header->type = static_cast<OBU_TYPE>(
(obu_header_byte >> kObuTypeBitsShift) & kObuTypeBitsMask);
if (!ValidObuType(obu_header->type)) {
fprintf(stderr, "Invalid OBU type: %d.\n", obu_header->type);
return false;
}
obu_header->obu_extension_flag =
(obu_header_byte >> kObuExtensionFlagBitShift) & kObuExtensionFlagBitMask;
obu_header->obu_tlayer_id =
(obu_header_byte >> kObuExtTlayerIdBitsShift) & kObuExtTlayerIdBitsMask;
return true;
}
bool ParseAV2ObuExtensionHeader(uint8_t ext_header_byte,
ObuHeader *obu_header) {
obu_header->obu_mlayer_id =
(ext_header_byte >> kObuExtMlayerIdBitsShift) & kObuExtMlayerIdBitsMask;
obu_header->obu_xlayer_id =
(ext_header_byte >> kObuExtXlayerIdBitsShift) & kObuExtXlayerIdBitsMask;
return true;
}
#endif // TOOLS_STREAM_MUX_H_