| @@ -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 | ||||
| @@ -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 */ | |||||