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 ...@@ -166,6 +166,10 @@ set(AOM_DECODER_APP_UTIL_SOURCES
"${AOM_ROOT}/video_reader.c" "${AOM_ROOT}/video_reader.c"
"${AOM_ROOT}/video_reader.h") "${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 set(AOM_ENCODER_APP_UTIL_SOURCES
"${AOM_ROOT}/ivfenc.c" "${AOM_ROOT}/ivfenc.c"
"${AOM_ROOT}/ivfenc.h" "${AOM_ROOT}/ivfenc.h"
......
...@@ -43,10 +43,15 @@ ...@@ -43,10 +43,15 @@
#include "./md5_utils.h" #include "./md5_utils.h"
#if CONFIG_OBU_NO_IVF
#include "./obudec.h"
#endif
#include "./tools_common.h" #include "./tools_common.h"
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO
#include "./webmdec.h" #include "./webmdec.h"
#endif #endif
#include "./y4menc.h" #include "./y4menc.h"
static const char *exec_name; static const char *exec_name;
...@@ -273,6 +278,11 @@ static int read_frame(struct AvxDecInputContext *input, uint8_t **buf, ...@@ -273,6 +278,11 @@ static int read_frame(struct AvxDecInputContext *input, uint8_t **buf,
case FILE_TYPE_IVF: case FILE_TYPE_IVF:
return ivf_read_frame(input->aom_input_ctx->file, buf, bytes_in_buffer, return ivf_read_frame(input->aom_input_ctx->file, buf, bytes_in_buffer,
buffer_size); 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; default: return 1;
} }
} }
...@@ -690,6 +700,10 @@ static int main_loop(int argc, const char **argv_) { ...@@ -690,6 +700,10 @@ static int main_loop(int argc, const char **argv_) {
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO
else if (file_is_webm(input.webm_ctx, input.aom_input_ctx)) else if (file_is_webm(input.webm_ctx, input.aom_input_ctx))
input.aom_input_ctx->file_type = FILE_TYPE_WEBM; 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 #endif
else if (file_is_raw(input.aom_input_ctx)) else if (file_is_raw(input.aom_input_ctx))
input.aom_input_ctx->file_type = FILE_TYPE_RAW; input.aom_input_ctx->file_type = FILE_TYPE_RAW;
......
...@@ -181,6 +181,9 @@ static const arg_def_t framerate = ...@@ -181,6 +181,9 @@ static const arg_def_t framerate =
static const arg_def_t use_webm = static const arg_def_t use_webm =
ARG_DEF(NULL, "webm", 0, "Output WebM (default when WebM IO is enabled)"); 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"); 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 = static const arg_def_t out_part =
ARG_DEF("P", "output-partitions", 0, ARG_DEF("P", "output-partitions", 0,
"Makes encoder output partitions. Requires IVF output!"); "Makes encoder output partitions. Requires IVF output!");
...@@ -224,6 +227,9 @@ static const arg_def_t *main_args[] = { &help, ...@@ -224,6 +227,9 @@ static const arg_def_t *main_args[] = { &help,
&psnrarg, &psnrarg,
&use_webm, &use_webm,
&use_ivf, &use_ivf,
#if CONFIG_OBU_NO_IVF
&use_obu,
#endif
&out_part, &out_part,
&q_hist_n, &q_hist_n,
&rate_hist_n, &rate_hist_n,
...@@ -746,6 +752,9 @@ struct stream_config { ...@@ -746,6 +752,9 @@ struct stream_config {
int arg_ctrls[ARG_CTRL_CNT_MAX][2]; int arg_ctrls[ARG_CTRL_CNT_MAX][2];
int arg_ctrl_cnt; int arg_ctrl_cnt;
int write_webm; int write_webm;
#if CONFIG_OBU_NO_IVF
int write_ivf;
#endif
// whether to use 16bit internal buffers // whether to use 16bit internal buffers
int use_16bit_internal; int use_16bit_internal;
}; };
...@@ -976,6 +985,9 @@ static struct stream_state *new_stream(struct AvxEncoderConfig *global, ...@@ -976,6 +985,9 @@ static struct stream_state *new_stream(struct AvxEncoderConfig *global,
/* Initialize remaining stream parameters */ /* Initialize remaining stream parameters */
stream->config.write_webm = 1; stream->config.write_webm = 1;
#if CONFIG_OBU_NO_IVF
stream->config.write_ivf = 0;
#endif
#if CONFIG_WEBM_IO #if CONFIG_WEBM_IO
stream->config.stereo_fmt = STEREO_FORMAT_MONO; stream->config.stereo_fmt = STEREO_FORMAT_MONO;
stream->webm_ctx.last_pts_ns = -1; stream->webm_ctx.last_pts_ns = -1;
...@@ -1036,7 +1048,17 @@ static int parse_stream_params(struct AvxEncoderConfig *global, ...@@ -1036,7 +1048,17 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
if (out_fn_len >= 4 && if (out_fn_len >= 4 &&
!strcmp(config->out_fn + out_fn_len - 4, ".ivf")) { !strcmp(config->out_fn + out_fn_len - 4, ".ivf")) {
config->write_webm = 0; 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)) { } else if (arg_match(&arg, &fpf_name, argi)) {
config->stats_fn = arg.val; config->stats_fn = arg.val;
...@@ -1053,6 +1075,14 @@ static int parse_stream_params(struct AvxEncoderConfig *global, ...@@ -1053,6 +1075,14 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
#endif #endif
} else if (arg_match(&arg, &use_ivf, argi)) { } else if (arg_match(&arg, &use_ivf, argi)) {
config->write_webm = 0; 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)) { } else if (arg_match(&arg, &threads, argi)) {
config->cfg.g_threads = arg_parse_uint(&arg); config->cfg.g_threads = arg_parse_uint(&arg);
} else if (arg_match(&arg, &profile, argi)) { } else if (arg_match(&arg, &profile, argi)) {
...@@ -1160,8 +1190,8 @@ static int parse_stream_params(struct AvxEncoderConfig *global, ...@@ -1160,8 +1190,8 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
match = 1; match = 1;
/* Point either to the next free element or the first /* 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++) for (j = 0; j < config->arg_ctrl_cnt; j++)
if (ctrl_args_map != NULL && if (ctrl_args_map != NULL &&
config->arg_ctrls[j][0] == ctrl_args_map[i]) config->arg_ctrls[j][0] == ctrl_args_map[i])
...@@ -1370,7 +1400,11 @@ static void open_output_file(struct stream_state *stream, ...@@ -1370,7 +1400,11 @@ static void open_output_file(struct stream_state *stream,
(void)pixel_aspect_ratio; (void)pixel_aspect_ratio;
#endif #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); ivf_write_file_header(stream->file, cfg, global->codec->fourcc, 0);
} }
} }
...@@ -1387,7 +1421,11 @@ static void close_output_file(struct stream_state *stream, ...@@ -1387,7 +1421,11 @@ static void close_output_file(struct stream_state *stream,
} }
#endif #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)) if (!fseek(stream->file, 0, SEEK_SET))
ivf_write_file_header(stream->file, &stream->config.cfg, fourcc, ivf_write_file_header(stream->file, &stream->config.cfg, fourcc,
stream->frames_out); stream->frames_out);
...@@ -1606,21 +1644,27 @@ static void get_cx_data(struct stream_state *stream, ...@@ -1606,21 +1644,27 @@ static void get_cx_data(struct stream_state *stream,
} }
#endif #endif
if (!stream->config.write_webm) { if (!stream->config.write_webm) {
if (pkt->data.frame.partition_id <= 0) { #if CONFIG_OBU_NO_IVF
ivf_header_pos = ftello(stream->file); if (stream->config.write_ivf) {
fsize = pkt->data.frame.sz; #endif
if (pkt->data.frame.partition_id <= 0) {
ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize); ivf_header_pos = ftello(stream->file);
} else { fsize = pkt->data.frame.sz;
fsize += pkt->data.frame.sz;
ivf_write_frame_header(stream->file, pkt->data.frame.pts, fsize);
if (!(pkt->data.frame.flags & AOM_FRAME_IS_FRAGMENT)) { } else {
const FileOffset currpos = ftello(stream->file); fsize += pkt->data.frame.sz;
fseeko(stream->file, ivf_header_pos, SEEK_SET);
ivf_write_frame_size(stream->file, fsize); if (!(pkt->data.frame.flags & AOM_FRAME_IS_FRAGMENT)) {
fseeko(stream->file, currpos, SEEK_SET); 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, (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
stream->file); stream->file);
...@@ -1971,9 +2015,16 @@ int main(int argc, const char **argv_) { ...@@ -1971,9 +2015,16 @@ int main(int argc, const char **argv_) {
FOREACH_STREAM(stream, streams) { FOREACH_STREAM(stream, streams) {
if (stream->config.write_webm) { if (stream->config.write_webm) {
stream->config.write_webm = 0; stream->config.write_webm = 0;
#if CONFIG_OBU_NO_IVF
stream->config.write_ivf = 0;
#endif
warn( warn(
"aomenc was compiled without WebM container support." "aomenc was compiled without WebM container support."
#if CONFIG_OBU_NO_IVF
"Producing OBU output");
#else
"Producing IVF output"); "Producing IVF output");
#endif
} }
} }
#endif #endif
......
...@@ -169,6 +169,7 @@ set(CONFIG_NCOBMC 0 CACHE NUMBER "AV1 experiment flag.") ...@@ -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_NEW_QUANT 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_NO_FRAME_CONTEXT_SIGNALING 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 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_OPT_REF_MV 0 CACHE NUMBER "AV1 experiment flag.")
set(CONFIG_PALETTE_DELTA_ENCODING 1 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.") set(CONFIG_PALETTE_THROUGHPUT 1 CACHE NUMBER "AV1 experiment flag.")
......
...@@ -333,6 +333,7 @@ EXPERIMENT_LIST=" ...@@ -333,6 +333,7 @@ EXPERIMENT_LIST="
mono_video mono_video
q_segmentation q_segmentation
segment_pred_last segment_pred_last
obu_no_ivf
" "
CONFIG_LIST=" CONFIG_LIST="
dependency_tracking dependency_tracking
......
...@@ -84,6 +84,9 @@ ifeq ($(CONFIG_WEBM_IO),yes) ...@@ -84,6 +84,9 @@ ifeq ($(CONFIG_WEBM_IO),yes)
aomdec.SRCS += $(LIBWEBM_PARSER_SRCS) aomdec.SRCS += $(LIBWEBM_PARSER_SRCS)
aomdec.SRCS += webmdec.cc webmdec.h aomdec.SRCS += webmdec.cc webmdec.h
endif endif
ifeq ($(CONFIG_OBU_NO_IVF),yes)
aomdec.SRCS += obudec.c obudec.h
endif
aomdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950 aomdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
aomdec.DESCRIPTION = Full featured decoder aomdec.DESCRIPTION = Full featured decoder
UTILS-$(CONFIG_AV1_ENCODER) += aomenc.c 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 */ ...@@ -69,6 +69,9 @@ typedef long FileOffset; /* NOLINT */
#define AV1_FOURCC 0x31305641 #define AV1_FOURCC 0x31305641
enum VideoFileType { enum VideoFileType {
#if CONFIG_OBU_NO_IVF
FILE_TYPE_OBU,
#endif
FILE_TYPE_RAW, FILE_TYPE_RAW,
FILE_TYPE_IVF, FILE_TYPE_IVF,
FILE_TYPE_Y4M, 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