mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
lavc: Add coded bitstream read/write API
(cherry picked from commit18f1706f33
) (cherry picked from commit44cde38c8a
)
This commit is contained in:
parent
b1374e925c
commit
6734eef6b8
1
configure
vendored
1
configure
vendored
@ -2150,6 +2150,7 @@ CONFIG_EXTRA="
|
||||
blockdsp
|
||||
bswapdsp
|
||||
cabac
|
||||
cbs
|
||||
dirac_parse
|
||||
dvprofile
|
||||
exif
|
||||
|
@ -59,6 +59,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_CRYSTALHD) += crystalhd.o
|
||||
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
|
||||
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
|
||||
|
482
libavcodec/cbs.c
Normal file
482
libavcodec/cbs.c
Normal file
@ -0,0 +1,482 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg 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.
|
||||
*
|
||||
* FFmpeg 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 FFmpeg; 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_ptr,
|
||||
enum AVCodecID codec_id, void *log_ctx)
|
||||
{
|
||||
CodedBitstreamContext *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 = av_mallocz(sizeof(*ctx));
|
||||
if (!ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ctx->log_ctx = log_ctx;
|
||||
ctx->codec = type;
|
||||
|
||||
ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
|
||||
if (!ctx->priv_data) {
|
||||
av_freep(&ctx);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
ctx->decompose_unit_types = NULL;
|
||||
|
||||
ctx->trace_enable = 0;
|
||||
ctx->trace_level = AV_LOG_TRACE;
|
||||
|
||||
*ctx_ptr = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
|
||||
{
|
||||
CodedBitstreamContext *ctx = *ctx_ptr;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->codec && ctx->codec->close)
|
||||
ctx->codec->close(ctx);
|
||||
|
||||
av_freep(&ctx->priv_data);
|
||||
av_freep(ctx_ptr);
|
||||
}
|
||||
|
||||
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 %"PRIu32").\n", i, frag->units[i].type);
|
||||
} else if (err < 0) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
|
||||
"(type %"PRIu32").\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 %"PRIu32").\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;
|
||||
|
||||
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, GetBitContext *gbc,
|
||||
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 > 0 && width <= 32);
|
||||
|
||||
if (get_bits_left(gbc) < width) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
|
||||
"%s: bitstream ended.\n", name);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (ctx->trace_enable)
|
||||
position = get_bits_count(gbc);
|
||||
|
||||
value = get_bits_long(gbc, 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 > 0 && 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,
|
||||
CodedBitstreamUnitType 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,
|
||||
CodedBitstreamUnitType 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;
|
||||
}
|
308
libavcodec/cbs.h
Normal file
308
libavcodec/cbs.h
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg 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.
|
||||
*
|
||||
* FFmpeg 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 FFmpeg; 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"
|
||||
|
||||
|
||||
/*
|
||||
* This defines a framework for converting between a coded bitstream
|
||||
* and structures defining all individual syntax elements found in
|
||||
* such a stream.
|
||||
*
|
||||
* Conversion in both directions is possible. Given a coded bitstream
|
||||
* (any meaningful fragment), it can be parsed and decomposed into
|
||||
* syntax elements stored in a set of codec-specific structures.
|
||||
* Similarly, given a set of those same codec-specific structures the
|
||||
* syntax elements can be serialised and combined to create a coded
|
||||
* bitstream.
|
||||
*/
|
||||
|
||||
struct CodedBitstreamType;
|
||||
|
||||
/**
|
||||
* The codec-specific type of a bitstream unit.
|
||||
*/
|
||||
typedef uint32_t CodedBitstreamUnitType;
|
||||
|
||||
/**
|
||||
* Coded bitstream unit structure.
|
||||
*
|
||||
* A bitstream unit 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.
|
||||
*/
|
||||
CodedBitstreamUnitType type;
|
||||
|
||||
/**
|
||||
* Pointer to the directly-parsable 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 bitstream 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.
|
||||
*/
|
||||
CodedBitstreamUnitType *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;
|
||||
|
||||
|
||||
/**
|
||||
* Create and 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.
|
||||
*
|
||||
* This also updates the internal state of the coded bitstream context
|
||||
* with any persistent data from the fragment which may be required to
|
||||
* read following fragments (e.g. parameter sets).
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This also updates the internal state of the coded bitstream context
|
||||
* with any persistent data from the fragment which may be required to
|
||||
* read following fragments (e.g. parameter sets).
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This also updates the internal state of the coded bitstream context
|
||||
* with any persistent data from the fragment which may be required to
|
||||
* write following fragments (e.g. parameter sets).
|
||||
*/
|
||||
int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag);
|
||||
|
||||
/**
|
||||
* Write the bitstream of a fragment to the extradata in codec parameters.
|
||||
*
|
||||
* This replaces any existing extradata in the structure.
|
||||
*/
|
||||
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,
|
||||
CodedBitstreamUnitType 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,
|
||||
CodedBitstreamUnitType 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 */
|
86
libavcodec/cbs_internal.h
Normal file
86
libavcodec/cbs_internal.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg 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.
|
||||
*
|
||||
* FFmpeg 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 FFmpeg; 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 "cbs.h"
|
||||
#include "get_bits.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.
|
||||
// header is set if the fragment came from a header block, which
|
||||
// may require different parsing for some codecs (e.g. the AVCC
|
||||
// header in H.264).
|
||||
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, GetBitContext *gbc,
|
||||
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…
Reference in New Issue
Block a user