lavc: Add coded bitstream read/write API
This commit is contained in:
parent
538e508751
commit
18f1706f33
1
configure
vendored
1
configure
vendored
@ -1739,6 +1739,7 @@ CONFIG_EXTRA="
|
||||
blockdsp
|
||||
bswapdsp
|
||||
cabac
|
||||
cbs
|
||||
dirac_parse
|
||||
dvprofile
|
||||
faandct
|
||||
|
@ -53,6 +53,7 @@ OBJS-$(CONFIG_AUDIODSP) += audiodsp.o
|
||||
OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o
|
||||
OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
|
||||
OBJS-$(CONFIG_CABAC) += cabac.o
|
||||
OBJS-$(CONFIG_CBS) += cbs.o
|
||||
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
|
||||
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.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 */
|
Loading…
x
Reference in New Issue
Block a user