[FFmpeg-devel] [PATCH 23/26] lavc/cbs: Add JPEG support
James Almer
jamrial at gmail.com
Thu Apr 26 01:23:19 EEST 2018
On 4/25/2018 6:31 PM, Mark Thompson wrote:
> +static int cbs_jpeg_split_fragment(CodedBitstreamContext *ctx,
> + CodedBitstreamFragment *frag,
> + int header)
> +{
> + AVBufferRef *data_ref;
> + uint8_t *data;
> + size_t data_size;
> + int unit, start, end, marker, next_start, next_marker;
> + int err, i, j, length;
> +
> + if (frag->data_size < 4) {
> + // Definitely too short to be meaningful.
> + return AVERROR_INVALIDDATA;
> + }
> +
> + for (i = 0; i + 1 < frag->data_size && frag->data[i] != 0xff; i++);
> + if (i > 0) {
> + av_log(ctx->log_ctx, AV_LOG_WARNING, "Discarding %d bytes at "
> + "beginning of image.\n", i);
> + }
> + for (++i; i + 1 < frag->data_size && frag->data[i] == 0xff; i++);
> + if (i + 1 >= frag->data_size && frag->data[i]) {
> + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: "
> + "no SOI marker found.\n");
> + return AVERROR_INVALIDDATA;
> + }
> + marker = frag->data[i];
> + if (marker != JPEG_MARKER_SOI) {
> + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: first "
> + "marker is %02x, should be SOI.\n", marker);
> + return AVERROR_INVALIDDATA;
> + }
> + for (++i; i + 1 < frag->data_size && frag->data[i] == 0xff; i++);
> + if (i + 1 >= frag->data_size) {
> + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: "
> + "no image content found.\n");
> + return AVERROR_INVALIDDATA;
> + }
> + marker = frag->data[i];
> + start = i + 1;
> +
> + for (unit = 0;; unit++) {
> + if (marker == JPEG_MARKER_EOI) {
> + break;
> + } else if (marker == JPEG_MARKER_SOS) {
> + for (i = start; i + 1 < frag->data_size; i++) {
> + if (frag->data[i] != 0xff)
> + continue;
> + end = i;
> + for (++i; i + 1 < frag->data_size &&
> + frag->data[i] == 0xff; i++);
> + if (i + 1 >= frag->data_size) {
> + next_marker = -1;
> + } else {
> + if (frag->data[i] == 0x00)
> + continue;
> + next_marker = frag->data[i];
> + next_start = i + 1;
> + }
> + break;
> + }
> + } else {
> + i = start;
> + if (i + 2 > frag->data_size) {
> + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: "
> + "truncated at %02x marker.\n", marker);
> + return AVERROR_INVALIDDATA;
> + }
> + length = AV_RB16(frag->data + i);
> + if (i + length > frag->data_size) {
> + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: "
> + "truncated at %02x marker segment.\n", marker);
> + return AVERROR_INVALIDDATA;
> + }
> + end = start + length;
> +
> + i = end;
> + if (frag->data[i] != 0xff) {
> + next_marker = -1;
> + } else {
> + for (++i; i + 1 < frag->data_size &&
> + frag->data[i] == 0xff; i++);
> + if (i + 1 >= frag->data_size) {
> + next_marker = -1;
> + } else {
> + next_marker = frag->data[i];
> + next_start = i + 1;
> + }
> + }
> + }
> +
> + if (marker == JPEG_MARKER_SOS) {
> + length = AV_RB16(frag->data + start);
> +
> + data_ref = av_buffer_alloc(end - start +
> + AV_INPUT_BUFFER_PADDING_SIZE);
Allocating an AVBufferRef here, letting ff_cbs_insert_unit_data()
generate a new reference to it, then unreffing the first one seems
wasteful/redundant.
Use av_malloc(), set data_ref to NULL, and let ff_cbs_insert_unit_data()
create the AVBufferRef by taking ownership of the malloc'd data array
instead. You'd then only need to free said data array if
ff_cbs_insert_unit_data() fails.
> + if (!data_ref)
> + return AVERROR(ENOMEM);
> + data = data_ref->data;
> +
> + memcpy(data, frag->data + start, length);
> + for (i = start + length, j = length; i < end; i++, j++) {
> + if (frag->data[i] == 0xff) {
> + while (frag->data[i] == 0xff)
> + ++i;
> + data[j] = 0xff;
> + } else {
> + data[j] = frag->data[i];
> + }
> + }
> + data_size = j;
> +
> + memset(data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
> +
> + } else {
> + data = frag->data + start;
> + data_size = end - start;
> + data_ref = frag->data_ref;
> + }
> +
> + err = ff_cbs_insert_unit_data(ctx, frag, unit, marker,
> + data, data_size, data_ref);
> + if (marker == JPEG_MARKER_SOS)
> + av_buffer_unref(&data_ref);
> + if (err < 0)
> + return err;
> +
> + if (next_marker == -1)
> + break;
> + marker = next_marker;
> + start = next_start;
> + }
> +
> + return 0;
> +}
More information about the ffmpeg-devel
mailing list