mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-18 04:50:11 +01:00
lavc: Add coded bitstream read/write API
This commit is contained in:
1
configure
vendored
1
configure
vendored
@@ -1739,6 +1739,7 @@ CONFIG_EXTRA="
|
|||||||
blockdsp
|
blockdsp
|
||||||
bswapdsp
|
bswapdsp
|
||||||
cabac
|
cabac
|
||||||
|
cbs
|
||||||
dirac_parse
|
dirac_parse
|
||||||
dvprofile
|
dvprofile
|
||||||
faandct
|
faandct
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ OBJS-$(CONFIG_AUDIODSP) += audiodsp.o
|
|||||||
OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o
|
OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o
|
||||||
OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
|
OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
|
||||||
OBJS-$(CONFIG_CABAC) += cabac.o
|
OBJS-$(CONFIG_CABAC) += cabac.o
|
||||||
|
OBJS-$(CONFIG_CBS) += cbs.o
|
||||||
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
|
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
|
||||||
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
|
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
|
||||||
OBJS-$(CONFIG_FAANDCT) += faandct.o
|
OBJS-$(CONFIG_FAANDCT) += faandct.o
|
||||||
|
|||||||
460
libavcodec/cbs.c
Normal file
460
libavcodec/cbs.c
Normal file
@@ -0,0 +1,460 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Libav.
|
||||||
|
*
|
||||||
|
* Libav is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Libav is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with Libav; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "libavutil/avassert.h"
|
||||||
|
#include "libavutil/common.h"
|
||||||
|
|
||||||
|
#include "cbs.h"
|
||||||
|
#include "cbs_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const CodedBitstreamType *cbs_type_table[] = {
|
||||||
|
};
|
||||||
|
|
||||||
|
int ff_cbs_init(CodedBitstreamContext *ctx,
|
||||||
|
enum AVCodecID codec_id, void *log_ctx)
|
||||||
|
{
|
||||||
|
const CodedBitstreamType *type;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
type = NULL;
|
||||||
|
for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
|
||||||
|
if (cbs_type_table[i]->codec_id == codec_id) {
|
||||||
|
type = cbs_type_table[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!type)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
ctx->log_ctx = log_ctx;
|
||||||
|
ctx->codec = type;
|
||||||
|
|
||||||
|
ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
|
||||||
|
if (!ctx->priv_data)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
ctx->decompose_unit_types = NULL;
|
||||||
|
|
||||||
|
ctx->trace_enable = 0;
|
||||||
|
ctx->trace_level = AV_LOG_TRACE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ff_cbs_close(CodedBitstreamContext *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->codec && ctx->codec->close)
|
||||||
|
ctx->codec->close(ctx);
|
||||||
|
|
||||||
|
av_freep(&ctx->priv_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cbs_unit_uninit(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit)
|
||||||
|
{
|
||||||
|
if (ctx->codec->free_unit && unit->content && !unit->content_external)
|
||||||
|
ctx->codec->free_unit(unit);
|
||||||
|
|
||||||
|
av_freep(&unit->data);
|
||||||
|
unit->data_size = 0;
|
||||||
|
unit->data_bit_padding = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < frag->nb_units; i++)
|
||||||
|
cbs_unit_uninit(ctx, &frag->units[i]);
|
||||||
|
av_freep(&frag->units);
|
||||||
|
frag->nb_units = 0;
|
||||||
|
|
||||||
|
av_freep(&frag->data);
|
||||||
|
frag->data_size = 0;
|
||||||
|
frag->data_bit_padding = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag)
|
||||||
|
{
|
||||||
|
int err, i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < frag->nb_units; i++) {
|
||||||
|
if (ctx->decompose_unit_types) {
|
||||||
|
for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
|
||||||
|
if (ctx->decompose_unit_types[j] == frag->units[i].type)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j >= ctx->nb_decompose_unit_types)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctx->codec->read_unit(ctx, &frag->units[i]);
|
||||||
|
if (err == AVERROR(ENOSYS)) {
|
||||||
|
av_log(ctx->log_ctx, AV_LOG_WARNING,
|
||||||
|
"Decomposition unimplemented for unit %d "
|
||||||
|
"(type %d).\n", i, frag->units[i].type);
|
||||||
|
} else if (err < 0) {
|
||||||
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
|
||||||
|
"(type %d).\n", i, frag->units[i].type);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const AVCodecParameters *par)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(frag, 0, sizeof(*frag));
|
||||||
|
|
||||||
|
frag->data = par->extradata;
|
||||||
|
frag->data_size = par->extradata_size;
|
||||||
|
|
||||||
|
err = ctx->codec->split_fragment(ctx, frag, 1);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
frag->data = NULL;
|
||||||
|
frag->data_size = 0;
|
||||||
|
|
||||||
|
return cbs_read_fragment_content(ctx, frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const AVPacket *pkt)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(frag, 0, sizeof(*frag));
|
||||||
|
|
||||||
|
frag->data = pkt->data;
|
||||||
|
frag->data_size = pkt->size;
|
||||||
|
|
||||||
|
err = ctx->codec->split_fragment(ctx, frag, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
frag->data = NULL;
|
||||||
|
frag->data_size = 0;
|
||||||
|
|
||||||
|
return cbs_read_fragment_content(ctx, frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_read(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(frag, 0, sizeof(*frag));
|
||||||
|
|
||||||
|
// (We won't write to this during split.)
|
||||||
|
frag->data = (uint8_t*)data;
|
||||||
|
frag->data_size = size;
|
||||||
|
|
||||||
|
err = ctx->codec->split_fragment(ctx, frag, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
frag->data = NULL;
|
||||||
|
frag->data_size = 0;
|
||||||
|
|
||||||
|
return cbs_read_fragment_content(ctx, frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag)
|
||||||
|
{
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
for (i = 0; i < frag->nb_units; i++) {
|
||||||
|
if (!frag->units[i].content)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
err = ctx->codec->write_unit(ctx, &frag->units[i]);
|
||||||
|
if (err < 0) {
|
||||||
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
|
||||||
|
"(type %d).\n", i, frag->units[i].type);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctx->codec->assemble_fragment(ctx, frag);
|
||||||
|
if (err < 0) {
|
||||||
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
|
||||||
|
AVCodecParameters *par,
|
||||||
|
CodedBitstreamFragment *frag)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = ff_cbs_write_fragment_data(ctx, frag);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
av_freep(&par->extradata);
|
||||||
|
|
||||||
|
par->extradata = av_malloc(frag->data_size +
|
||||||
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (!par->extradata)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
memcpy(par->extradata, frag->data, frag->data_size);
|
||||||
|
memset(par->extradata + frag->data_size, 0,
|
||||||
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
par->extradata_size = frag->data_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_write_packet(CodedBitstreamContext *ctx,
|
||||||
|
AVPacket *pkt,
|
||||||
|
CodedBitstreamFragment *frag)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = ff_cbs_write_fragment_data(ctx, frag);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
av_new_packet(pkt, frag->data_size);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
memcpy(pkt->data, frag->data, frag->data_size);
|
||||||
|
pkt->size = frag->data_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ff_cbs_trace_header(CodedBitstreamContext *ctx,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
if (!ctx->trace_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
|
||||||
|
const char *name, const char *bits,
|
||||||
|
int64_t value)
|
||||||
|
{
|
||||||
|
size_t name_len, bits_len;
|
||||||
|
int pad;
|
||||||
|
|
||||||
|
if (!ctx->trace_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
av_assert0(value >= INT_MIN && value <= UINT32_MAX);
|
||||||
|
|
||||||
|
name_len = strlen(name);
|
||||||
|
bits_len = strlen(bits);
|
||||||
|
|
||||||
|
if (name_len + bits_len > 60)
|
||||||
|
pad = bits_len + 2;
|
||||||
|
else
|
||||||
|
pad = 61 - name_len;
|
||||||
|
|
||||||
|
av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
|
||||||
|
position, name, pad, bits, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc,
|
||||||
|
int width, const char *name, uint32_t *write_to,
|
||||||
|
uint32_t range_min, uint32_t range_max)
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
int position;
|
||||||
|
|
||||||
|
av_assert0(width <= 32);
|
||||||
|
|
||||||
|
if (ctx->trace_enable)
|
||||||
|
position = bitstream_tell(bc);
|
||||||
|
|
||||||
|
value = bitstream_read(bc, width);
|
||||||
|
|
||||||
|
if (ctx->trace_enable) {
|
||||||
|
char bits[33];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < width; i++)
|
||||||
|
bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
|
||||||
|
bits[i] = 0;
|
||||||
|
|
||||||
|
ff_cbs_trace_syntax_element(ctx, position, name, bits, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < range_min || value > range_max) {
|
||||||
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
|
||||||
|
"%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
|
||||||
|
name, value, range_min, range_max);
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
*write_to = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
|
||||||
|
int width, const char *name, uint32_t value,
|
||||||
|
uint32_t range_min, uint32_t range_max)
|
||||||
|
{
|
||||||
|
av_assert0(width <= 32);
|
||||||
|
|
||||||
|
if (value < range_min || value > range_max) {
|
||||||
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
|
||||||
|
"%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
|
||||||
|
name, value, range_min, range_max);
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (put_bits_left(pbc) < width)
|
||||||
|
return AVERROR(ENOSPC);
|
||||||
|
|
||||||
|
if (ctx->trace_enable) {
|
||||||
|
char bits[33];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < width; i++)
|
||||||
|
bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
|
||||||
|
bits[i] = 0;
|
||||||
|
|
||||||
|
ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width < 32)
|
||||||
|
put_bits(pbc, width, value);
|
||||||
|
else
|
||||||
|
put_bits32(pbc, value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cbs_insert_unit(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position)
|
||||||
|
{
|
||||||
|
CodedBitstreamUnit *units;
|
||||||
|
|
||||||
|
units = av_malloc_array(frag->nb_units + 1, sizeof(*units));
|
||||||
|
if (!units)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
if (position > 0)
|
||||||
|
memcpy(units, frag->units, position * sizeof(*units));
|
||||||
|
if (position < frag->nb_units)
|
||||||
|
memcpy(units + position + 1, frag->units + position,
|
||||||
|
(frag->nb_units - position) * sizeof(*units));
|
||||||
|
|
||||||
|
memset(units + position, 0, sizeof(*units));
|
||||||
|
|
||||||
|
av_freep(&frag->units);
|
||||||
|
frag->units = units;
|
||||||
|
++frag->nb_units;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position, uint32_t type,
|
||||||
|
void *content)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (position == -1)
|
||||||
|
position = frag->nb_units;
|
||||||
|
av_assert0(position >= 0 && position <= frag->nb_units);
|
||||||
|
|
||||||
|
err = cbs_insert_unit(ctx, frag, position);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
frag->units[position].type = type;
|
||||||
|
frag->units[position].content = content;
|
||||||
|
frag->units[position].content_external = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position, uint32_t type,
|
||||||
|
uint8_t *data, size_t data_size)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (position == -1)
|
||||||
|
position = frag->nb_units;
|
||||||
|
av_assert0(position >= 0 && position <= frag->nb_units);
|
||||||
|
|
||||||
|
err = cbs_insert_unit(ctx, frag, position);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
frag->units[position].type = type;
|
||||||
|
frag->units[position].data = data;
|
||||||
|
frag->units[position].data_size = data_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position)
|
||||||
|
{
|
||||||
|
if (position < 0 || position >= frag->nb_units)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
cbs_unit_uninit(ctx, &frag->units[position]);
|
||||||
|
|
||||||
|
--frag->nb_units;
|
||||||
|
|
||||||
|
if (frag->nb_units == 0) {
|
||||||
|
av_freep(&frag->units);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
memmove(frag->units + position,
|
||||||
|
frag->units + position + 1,
|
||||||
|
(frag->nb_units - position) * sizeof(*frag->units));
|
||||||
|
|
||||||
|
// Don't bother reallocating the unit array.
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
274
libavcodec/cbs.h
Normal file
274
libavcodec/cbs.h
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Libav.
|
||||||
|
*
|
||||||
|
* Libav is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Libav is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with Libav; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_CBS_H
|
||||||
|
#define AVCODEC_CBS_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct CodedBitstreamType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coded bitstream unit structure.
|
||||||
|
*
|
||||||
|
* A bitstream unit the the smallest element of a bitstream which
|
||||||
|
* is meaningful on its own. For example, an H.264 NAL unit.
|
||||||
|
*
|
||||||
|
* See the codec-specific header for the meaning of this for any
|
||||||
|
* particular codec.
|
||||||
|
*/
|
||||||
|
typedef struct CodedBitstreamUnit {
|
||||||
|
/**
|
||||||
|
* Codec-specific type of this unit.
|
||||||
|
*/
|
||||||
|
uint32_t type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the bitstream form of this unit.
|
||||||
|
*
|
||||||
|
* May be NULL if the unit currently only exists in decomposed form.
|
||||||
|
*/
|
||||||
|
uint8_t *data;
|
||||||
|
/**
|
||||||
|
* The number of bytes in the bitstream (including any padding bits
|
||||||
|
* in the final byte).
|
||||||
|
*/
|
||||||
|
size_t data_size;
|
||||||
|
/**
|
||||||
|
* The number of bits which should be ignored in the final byte.
|
||||||
|
*
|
||||||
|
* This supports non-byte-aligned bitstreams.
|
||||||
|
*/
|
||||||
|
size_t data_bit_padding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to the decomposed form of this unit.
|
||||||
|
*
|
||||||
|
* The type of this structure depends on both the codec and the
|
||||||
|
* type of this unit. May be NULL if the unit only exists in
|
||||||
|
* bitstream form.
|
||||||
|
*/
|
||||||
|
void *content;
|
||||||
|
/**
|
||||||
|
* Whether the content was supplied externally.
|
||||||
|
*
|
||||||
|
* If so, it should not be freed when freeing the unit.
|
||||||
|
*/
|
||||||
|
int content_external;
|
||||||
|
} CodedBitstreamUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coded bitstream fragment structure, combining one or more units.
|
||||||
|
*
|
||||||
|
* This is any sequence of units. It need not form some greater whole,
|
||||||
|
* though in many cases it will. For example, an H.264 access unit,
|
||||||
|
* which is composed of a sequence of H.264 NAL units.
|
||||||
|
*/
|
||||||
|
typedef struct CodedBitstreamFragment {
|
||||||
|
/**
|
||||||
|
* Pointer to the bitstream form of this fragment.
|
||||||
|
*
|
||||||
|
* May be NULL if the fragment only exists as component units.
|
||||||
|
*/
|
||||||
|
uint8_t *data;
|
||||||
|
/**
|
||||||
|
* The number of bytes in the bitstream.
|
||||||
|
*
|
||||||
|
* The number of bytes in the bitstream (including any padding bits
|
||||||
|
* in the final byte).
|
||||||
|
*/
|
||||||
|
size_t data_size;
|
||||||
|
/**
|
||||||
|
* The number of bits which should be ignored in the final byte.
|
||||||
|
*/
|
||||||
|
size_t data_bit_padding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of units in this fragment.
|
||||||
|
*
|
||||||
|
* This may be zero if the fragment only exists in bistream form
|
||||||
|
* and has not been decomposed.
|
||||||
|
*/
|
||||||
|
int nb_units;
|
||||||
|
/**
|
||||||
|
* Pointer to an array of units of length nb_units.
|
||||||
|
*
|
||||||
|
* Must be NULL if nb_units is zero.
|
||||||
|
*/
|
||||||
|
CodedBitstreamUnit *units;
|
||||||
|
} CodedBitstreamFragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context structure for coded bitstream operations.
|
||||||
|
*/
|
||||||
|
typedef struct CodedBitstreamContext {
|
||||||
|
/**
|
||||||
|
* Logging context to be passed to all av_log() calls associated
|
||||||
|
* with this context.
|
||||||
|
*/
|
||||||
|
void *log_ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal codec-specific hooks.
|
||||||
|
*/
|
||||||
|
const struct CodedBitstreamType *codec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal codec-specific data.
|
||||||
|
*
|
||||||
|
* This contains any information needed when reading/writing
|
||||||
|
* bitsteams which will not necessarily be present in a fragment.
|
||||||
|
* For example, for H.264 it contains all currently visible
|
||||||
|
* parameter sets - they are required to determine the bitstream
|
||||||
|
* syntax but need not be present in every access unit.
|
||||||
|
*/
|
||||||
|
void *priv_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of unit types which should be decomposed when reading.
|
||||||
|
*
|
||||||
|
* Types not in this list will be available in bitstream form only.
|
||||||
|
* If NULL, all supported types will be decomposed.
|
||||||
|
*/
|
||||||
|
uint32_t *decompose_unit_types;
|
||||||
|
/**
|
||||||
|
* Length of the decompose_unit_types array.
|
||||||
|
*/
|
||||||
|
int nb_decompose_unit_types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable trace output during read/write operations.
|
||||||
|
*/
|
||||||
|
int trace_enable;
|
||||||
|
/**
|
||||||
|
* Log level to use for trace output.
|
||||||
|
*
|
||||||
|
* From AV_LOG_*; defaults to AV_LOG_TRACE.
|
||||||
|
*/
|
||||||
|
int trace_level;
|
||||||
|
} CodedBitstreamContext;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise a new context for the given codec.
|
||||||
|
*/
|
||||||
|
int ff_cbs_init(CodedBitstreamContext *ctx,
|
||||||
|
enum AVCodecID codec_id, void *log_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a context and free all internal state.
|
||||||
|
*/
|
||||||
|
void ff_cbs_close(CodedBitstreamContext *ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the extradata bitstream found in codec parameters into a
|
||||||
|
* fragment, then split into units and decompose.
|
||||||
|
*
|
||||||
|
* This also updates the internal state, so will need to be called for
|
||||||
|
* codecs with extradata to read parameter sets necessary for further
|
||||||
|
* parsing even if the fragment itself is not desired.
|
||||||
|
*/
|
||||||
|
int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const AVCodecParameters *par);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the data bitstream from a packet into a fragment, then
|
||||||
|
* split into units and decompose.
|
||||||
|
*/
|
||||||
|
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const AVPacket *pkt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a bitstream from a memory region into a fragment, then
|
||||||
|
* split into units and decompose.
|
||||||
|
*/
|
||||||
|
int ff_cbs_read(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const uint8_t *data, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the content of the fragment to its own internal buffer.
|
||||||
|
*
|
||||||
|
* Writes the content of all units and then assembles them into a new
|
||||||
|
* data buffer. When modifying the content of decomposed units, this
|
||||||
|
* can be used to regenerate the bitstream form of units or the whole
|
||||||
|
* fragment so that it can be extracted for other use.
|
||||||
|
*/
|
||||||
|
int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the bitstream of a fragment to the extradata in codec parameters.
|
||||||
|
*/
|
||||||
|
int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
|
||||||
|
AVCodecParameters *par,
|
||||||
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the bitstream of a fragment to a packet.
|
||||||
|
*/
|
||||||
|
int ff_cbs_write_packet(CodedBitstreamContext *ctx,
|
||||||
|
AVPacket *pkt,
|
||||||
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free all allocated memory in a fragment.
|
||||||
|
*/
|
||||||
|
void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new unit into a fragment with the given content.
|
||||||
|
*
|
||||||
|
* The content structure continues to be owned by the caller, and
|
||||||
|
* will not be freed when the unit is.
|
||||||
|
*/
|
||||||
|
int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position, uint32_t type,
|
||||||
|
void *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new unit into a fragment with the given data bitstream.
|
||||||
|
*
|
||||||
|
* The data buffer will be owned by the unit after this operation.
|
||||||
|
*/
|
||||||
|
int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position, uint32_t type,
|
||||||
|
uint8_t *data, size_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a unit from a fragment and free all memory it uses.
|
||||||
|
*/
|
||||||
|
int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int position);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* AVCODEC_CBS_H */
|
||||||
83
libavcodec/cbs_internal.h
Normal file
83
libavcodec/cbs_internal.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Libav.
|
||||||
|
*
|
||||||
|
* Libav is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Libav is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with Libav; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_CBS_INTERNAL_H
|
||||||
|
#define AVCODEC_CBS_INTERNAL_H
|
||||||
|
|
||||||
|
#include "avcodec.h"
|
||||||
|
#include "bitstream.h"
|
||||||
|
#include "cbs.h"
|
||||||
|
#include "put_bits.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct CodedBitstreamType {
|
||||||
|
enum AVCodecID codec_id;
|
||||||
|
|
||||||
|
size_t priv_data_size;
|
||||||
|
|
||||||
|
// Split frag->data into coded bitstream units, creating the
|
||||||
|
// frag->units array. Fill data but not content on each unit.
|
||||||
|
int (*split_fragment)(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
int header);
|
||||||
|
|
||||||
|
// Read the unit->data bitstream and decompose it, creating
|
||||||
|
// unit->content.
|
||||||
|
int (*read_unit)(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit);
|
||||||
|
|
||||||
|
// Write the unit->data bitstream from unit->content.
|
||||||
|
int (*write_unit)(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit);
|
||||||
|
|
||||||
|
// Read the data from all of frag->units and assemble it into
|
||||||
|
// a bitstream for the whole fragment.
|
||||||
|
int (*assemble_fragment)(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
|
// Free the content and data of a single unit.
|
||||||
|
void (*free_unit)(CodedBitstreamUnit *unit);
|
||||||
|
|
||||||
|
// Free the codec internal state.
|
||||||
|
void (*close)(CodedBitstreamContext *ctx);
|
||||||
|
} CodedBitstreamType;
|
||||||
|
|
||||||
|
|
||||||
|
// Helper functions for trace output.
|
||||||
|
|
||||||
|
void ff_cbs_trace_header(CodedBitstreamContext *ctx,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx,
|
||||||
|
int position, const char *name,
|
||||||
|
const char *bitstring, int64_t value);
|
||||||
|
|
||||||
|
|
||||||
|
// Helper functions for read/write of common bitstream elements, including
|
||||||
|
// generation of trace output.
|
||||||
|
|
||||||
|
int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, BitstreamContext *bc,
|
||||||
|
int width, const char *name, uint32_t *write_to,
|
||||||
|
uint32_t range_min, uint32_t range_max);
|
||||||
|
|
||||||
|
int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
|
||||||
|
int width, const char *name, uint32_t value,
|
||||||
|
uint32_t range_min, uint32_t range_max);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* AVCODEC_CBS_INTERNAL_H */
|
||||||
Reference in New Issue
Block a user