Commit 6c788834 authored by Cyril Concolato's avatar Cyril Concolato

Enable encode/decode of OBU streams without IVF

Change-Id: Ieed4ecce63a2a3b2a74c40ccddabe91cb9386632
parent 60586676
......@@ -166,6 +166,10 @@ set(AOM_DECODER_APP_UTIL_SOURCES
"${AOM_ROOT}/video_reader.c"
"${AOM_ROOT}/video_reader.h")
if (CONFIG_OBU_NO_IVF)
list(APPEND AOM_DECODER_APP_UTIL_SOURCES "${AOM_ROOT}/obudec.c" "${AOM_ROOT}/obudec.h")
endif ()
set(AOM_ENCODER_APP_UTIL_SOURCES
"${AOM_ROOT}/ivfenc.c"
"${AOM_ROOT}/ivfenc.h"
......
......@@ -43,10 +43,15 @@
#include "./md5_utils.h"
#if CONFIG_OBU_NO_IVF
#include "./obudec.h"
#endif
#include "./tools_common.h"
#if CONFIG_WEBM_IO
#include "./webmdec.h"
#endif
#include "./y4menc.h"
static const char *exec_name;
......@@ -273,6 +278,11 @@ static int read_frame(struct AvxDecInputContext *input, uint8_t **buf,
case FILE_TYPE_IVF:
return ivf_read_frame(input->aom_input_ctx->file, buf, bytes_in_buffer,
buffer_size);
#if CONFIG_OBU_NO_IVF
case FILE_TYPE_OBU:
return obu_read_temporal_unit(input->aom_input_ctx->file, buf,
bytes_in_buffer, buffer_size);
#endif
default: return 1;
}
}
......@@ -690,6 +700,10 @@ static int main_loop(int argc, const char **argv_) {
#if CONFIG_WEBM_IO
else if (file_is_webm(input.webm_ctx, input.aom_input_ctx))
input.aom_input_ctx->file_type = FILE_TYPE_WEBM;
#endif
#if CONFIG_OBU_NO_IVF
else if (file_is_obu(input.aom_input_ctx))
input.aom_input_ctx->file_type = FILE_TYPE_OBU;
#endif
else if (file_is_raw(input.aom_input_ctx))
input.aom_input_ctx->file_type = FILE_TYPE_RAW;
......
......@@ -181,6 +181,9 @@ static const arg_def_t framerate =
static const arg_def_t use_webm =
ARG_DEF(NULL, "webm", 0, "Output WebM (default when WebM IO is enabled)");
static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0, "Output IVF");
#if CONFIG_OBU_NO_IVF
static const arg_def_t use_obu = ARG_DEF(NULL, "obu", 0, "Output OBU");
#endif
static const arg_def_t out_part =
ARG_DEF("P", "output-partitions", 0,
"Makes encoder output partitions. Requires IVF output!");
......@@ -224,6 +227,9 @@ static const arg_def_t *main_args[] = { &help,
&psnrarg,
&use_webm,
&use_ivf,
#if CONFIG_OBU_NO_IVF
&use_obu,
#endif
&out_part,
&q_hist_n,
&rate_hist_n,
......@@ -746,6 +752,9 @@ struct stream_config {
int arg_ctrls[ARG_CTRL_CNT_MAX][2];
int arg_ctrl_cnt;
int write_webm;
#if CONFIG_OBU_NO_IVF
int write_ivf;
#endif
// whether to use 16bit internal buffers
int use_16bit_internal;
};
......@@ -976,6 +985,9 @@ static struct stream_state *new_stream(struct AvxEncoderConfig *global,
/* Initialize remaining stream parameters */
stream->config.write_webm = 1;
#if CONFIG_OBU_NO_IVF
stream->config.write_ivf = 0;
#endif
#if CONFIG_WEBM_IO
stream->config.stereo_fmt = STEREO_FORMAT_MONO;
stream->webm_ctx.last_pts_ns = -1;
......@@ -1036,7 +1048,17 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
if (out_fn_len >= 4 &&
!strcmp(config->out_fn + out_fn_len - 4, ".ivf")) {
config->write_webm = 0;
#if CONFIG_OBU_NO_IVF
config->write_ivf = 1;
#endif
}
#if CONFIG_OBU_NO_IVF
else if (out_fn_len >= 4 &&
!strcmp(config->out_fn + out_fn_len - 4, ".obu")) {
config->write_webm = 0;
config->write_ivf = 0;
}
#endif
}
} else if (arg_match(&arg, &fpf_name, argi)) {
config->stats_fn = arg.val;
......@@ -1053,6 +1075,14 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
#endif
} else if (arg_match(&arg, &use_ivf, argi)) {
config->write_webm = 0;
#if CONFIG_OBU_NO_IVF
config->write_ivf = 1;
#endif
#if CONFIG_OBU_NO_IVF
} else if (arg_match(&arg, &use_obu, argi)) {
config->write_webm = 0;
config->write_ivf = 0;
#endif
} else if (arg_match(&arg, &threads, argi)) {
config->cfg.g_threads = arg_parse_uint(&arg);
} else if (arg_match(&arg, &profile, argi)) {
......@@ -1160,8 +1190,8 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
match = 1;
/* Point either to the next free element or the first
* instance of this control.
*/
* instance of this control.
*/
for (j = 0; j < config->arg_ctrl_cnt; j++)
if (ctrl_args_map != NULL &&
config->arg_ctrls[j][0] == ctrl_args_map[i])
......@@ -1370,7 +1400,11 @@ static void open_output_file(struct stream_state *stream,
(void)pixel_aspect_ratio;
#endif
if (!stream->config.write_webm) {
if (!stream->config.write_webm
#if CONFIG_OBU_NO_IVF
&& stream->config.write_ivf
#endif
) {
ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0);
}
}
......@@ -1387,7 +1421,11 @@ static void close_output_file(struct stream_state *stream,
}
#endif
if (!stream->config.write_webm) {
if (!stream->config.write_webm
#if CONFIG_OBU_NO_IVF
&& stream->config.write_ivf
#endif
) {
if (!fseek(stream->file, 0, SEEK_SET))
ivf_write_file_header(stream->file, &stream->config.cfg, fourcc,
stream->frames_out);
......@@ -1606,21 +1644,27 @@ static void get_cx_data(struct stream_state *stream,
}
#endif
if (!stream->config.write_webm) {
if (pkt->data.frame.partition_id <= 0) {
ivf_header_pos = ftello(stream->file);
fsize = pkt->data.frame.sz;
ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize);
} else {
fsize += pkt->data.frame.sz;
if (!(pkt->data.frame.flags & AOM_FRAME_IS_FRAGMENT)) {
const FileOffset currpos = ftello(stream->file);
fseeko(stream->file, ivf_header_pos, SEEK_SET);
ivf_write_frame_size(stream->file, fsize);
fseeko(stream->file, currpos, SEEK_SET);
#if CONFIG_OBU_NO_IVF
if (stream->config.write_ivf) {
#endif
if (pkt->data.frame.partition_id <= 0) {
ivf_header_pos = ftello(stream->file);
fsize = pkt->data.frame.sz;
ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize);
} else {
fsize += pkt->data.frame.sz;
if (!(pkt->data.frame.flags & AOM_FRAME_IS_FRAGMENT)) {
const FileOffset currpos = ftello(stream->file);
fseeko(stream->file, ivf_header_pos, SEEK_SET);
ivf_write_frame_size(stream->file, fsize);
fseeko(stream->file, currpos, SEEK_SET);
}
}
#if CONFIG_OBU_NO_IVF
}
#endif
(void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
stream->file);
......@@ -1971,9 +2015,16 @@ int main(int argc, const char **argv_) {
FOREACH_STREAM(stream, streams) {
if (stream->config.write_webm) {
stream->config.write_webm = 0;
#if CONFIG_OBU_NO_IVF
stream->config.write_ivf = 0;
#endif
warn(
"aomenc was compiled without WebM container support."
#if CONFIG_OBU_NO_IVF
"Producing OBU output");
#else
"Producing IVF output");
#endif
}
}
#endif
......
......@@ -169,6 +169,7 @@ set(CONFIG_NCOBMC 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_NEW_QUANT 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_NO_FRAME_CONTEXT_SIGNALING 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_OBU 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_OBU_NO_IVF 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_OPT_REF_MV 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_PALETTE_DELTA_ENCODING 1 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_PALETTE_THROUGHPUT 1 CACHE NUMBER "AV1 experiment flag.")
......
......@@ -333,6 +333,7 @@ EXPERIMENT_LIST="
mono_video
q_segmentation
segment_pred_last
obu_no_ivf
"
CONFIG_LIST="
dependency_tracking
......
......@@ -84,6 +84,9 @@ ifeq ($(CONFIG_WEBM_IO),yes)
aomdec.SRCS += $(LIBWEBM_PARSER_SRCS)
aomdec.SRCS += webmdec.cc webmdec.h
endif
ifeq ($(CONFIG_OBU_NO_IVF),yes)
aomdec.SRCS += obudec.c obudec.h
endif
aomdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
aomdec.DESCRIPTION = Full featured decoder
UTILS-$(CONFIG_AV1_ENCODER) += aomenc.c
......
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. 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 www.aomedia.org/license/patent.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./obudec.h"
#include "aom_ports/mem_ops.h"
#include "av1/common/common.h"
#define OBU_HEADER_SIZE_BYTES 1
#if CONFIG_OBU_NO_IVF
int obu_read_temporal_unit(FILE *infile, uint8_t **buffer, size_t *bytes_read,
size_t *buffer_size) {
size_t ret;
const size_t obu_length_header_size =
PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES;
uint32_t obu_size = 0;
uint8_t *data = NULL;
if (feof(infile)) {
return 1;
}
*buffer_size = 0;
*bytes_read = 0;
while (1) {
// augment the buffer to just contain the next size field
// and the first byte of the header
*buffer = realloc(*buffer, (*buffer_size) + obu_length_header_size);
data = *buffer + (*buffer_size);
*buffer_size += obu_length_header_size;
ret = fread(data, 1, obu_length_header_size, infile);
if (ret == 0) {
// fprintf(stderr, "Found end of stream, ending temporal unit\n");
break;
}
if (ret != obu_length_header_size) {
warn("Failed to read OBU Header\n");
return 1;
}
*bytes_read += obu_length_header_size;
if (((data[PRE_OBU_SIZE_BYTES] >> 3) & 0xF) == OBU_TEMPORAL_DELIMITER) {
// Stop when a temporal delimiter is found
// fprintf(stderr, "Found temporal delimiter, ending temporal unit\n");
// prevent decoder to start decoding another frame from this buffer
*bytes_read -= obu_length_header_size;
break;
}
// otherwise, read the OBU payload into memory
obu_size = mem_get_le32(data);
// fprintf(stderr, "Found OBU of type %d and size %d\n",
// ((data[PRE_OBU_SIZE_BYTES] >> 3) & 0xF), obu_size);
obu_size--; // removing the byte of the header already read
if (obu_size) {
*buffer = realloc(*buffer, (*buffer_size) + obu_size);
data = *buffer + (*buffer_size);
*buffer_size += obu_size;
ret = fread(data, 1, obu_size, infile);
if (ret != obu_size) {
warn("Failed to read OBU Payload\n");
return 1;
}
*bytes_read += obu_size;
}
}
return 0;
}
int file_is_obu(struct AvxInputContext *input_ctx) {
uint8_t obutd[PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES];
int size;
#if !CONFIG_ADD_4BYTES_OBUSIZE || !CONFIG_OBU
warn("obudec.c requires CONFIG_ADD_4BYTES_OBUSIZE and CONFIG_OBU");
return 0;
#endif
// Reading the first OBU TD to enable TU end detection at TD start.
fread(obutd, 1, PRE_OBU_SIZE_BYTES + OBU_HEADER_SIZE_BYTES, input_ctx->file);
size = mem_get_le32(obutd);
if (size != 1) {
warn("Expected first OBU size to be 1, got %d", size);
return 0;
}
if (((obutd[PRE_OBU_SIZE_BYTES] >> 3) & 0xF) != OBU_TEMPORAL_DELIMITER) {
warn("Expected OBU TD at file start, got %d\n", obutd[PRE_OBU_SIZE_BYTES]);
return 0;
}
// fprintf(stderr, "Starting to parse OBU stream\n");
return 1;
}
#endif
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. 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 www.aomedia.org/license/patent.
*/
#ifndef OBUDEC_H_
#define OBUDEC_H_
#include "./tools_common.h"
#ifdef __cplusplus
extern "C" {
#endif
int file_is_obu(struct AvxInputContext *input_ctx);
int obu_read_temporal_unit(FILE *infile, uint8_t **buffer, size_t *bytes_read,
size_t *buffer_size);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif // OBUDEC_H_
......@@ -69,6 +69,9 @@ typedef long FileOffset; /* NOLINT */
#define AV1_FOURCC 0x31305641
enum VideoFileType {
#if CONFIG_OBU_NO_IVF
FILE_TYPE_OBU,
#endif
FILE_TYPE_RAW,
FILE_TYPE_IVF,
FILE_TYPE_Y4M,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment