mirror of https://github.com/FFmpeg/FFmpeg.git
parent
538e508751
commit
18f1706f33
5 changed files with 819 additions and 0 deletions
@ -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; |
||||
} |
@ -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 */ |
@ -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…
Reference in new issue