On 4/22/2018 12:29 PM, Mark Thompson wrote: > +static int cbs_jpeg_split_fragment(CodedBitstreamContext *ctx, > + CodedBitstreamFragment *frag, > + int header) > +{ > + uint8_t *unit_data; > + size_t unit_size; > + int unit, start, end, marker, next_start, next_marker; > + int err, i, j; > + > + 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 { > + int length; > + i = start; > + if (i + 2 > frag->data_size) > + break; > + length = frag->data[i] << 8 | frag->data[i + 1]; > + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Length = %d (i = %d)\n", > length, i); > + if (i + length > frag->data_size) > + break; > + 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; > + } > + } > + } > + > + av_log(ctx->log_ctx, AV_LOG_DEBUG, "start = %d, end = %d, marker = > %02x\n", > + start, end, marker); > + > + unit_size = end - start; > + unit_data = av_malloc(unit_size + AV_INPUT_BUFFER_PADDING_SIZE); > + if (!unit_data) > + return AVERROR(ENOMEM); > + if (marker == JPEG_MARKER_SOS) { > + for (i = start, j = 0; i < end; i++, j++) { > + if (frag->data[i] == 0xff) { > + while (frag->data[i] == 0xff) > + ++i; > + unit_data[j] = 0xff; > + } else { > + unit_data[j] = frag->data[i]; > + } > + } > + unit_size = j; > + } else { > + memcpy(unit_data, frag->data + start, unit_size);
Create a new frag->data_ref reference instead in this case. There's no need to allocate a new buffer for these units. > + } > + memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); > + > + err = ff_cbs_insert_unit_data(ctx, frag, unit, marker, > + unit_data, unit_size, NULL); > + if (err < 0) { > + av_free(&unit_data); > + return err; > + } > + > + if (next_marker == -1) > + break; > + marker = next_marker; > + start = next_start; > + } > + > + return 0; > +} [...] > +static int cbs_jpeg_assemble_fragment(CodedBitstreamContext *ctx, > + CodedBitstreamFragment *frag) > +{ > + const CodedBitstreamUnit *unit; > + uint8_t *data; > + size_t size, dp, sp; > + int i; > + > + size = 4; // SOI + EOI. > + for (i = 0; i < frag->nb_units; i++) { > + unit = &frag->units[i]; > + size += 2 + unit->data_size; > + if (unit->type == JPEG_MARKER_SOS) { > + for (sp = 0; sp < unit->data_size; sp++) { > + if (unit->data[sp] == 0xff) > + ++size; > + } > + } > + } > + > + frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); > + if (!frag->data_ref) > + return AVERROR(ENOMEM); > + data = frag->data_ref->data; > + > + dp = 0; > + > + data[dp++] = 0xff; > + data[dp++] = JPEG_MARKER_SOI; > + > + for (i = 0; i < frag->nb_units; i++) { > + unit = &frag->units[i]; > + > + data[dp++] = 0xff; > + data[dp++] = unit->type; > + > + if (unit->type != JPEG_MARKER_SOS) { > + for (sp = 0; sp < unit->data_size; sp++) > + data[dp++] = unit->data[sp]; memcpy(data + dp, unit->data, unit->data_size); dp += unit->data_size; Will probably be faster on big units. > + } else { > + for (sp = 0; sp < unit->data_size; sp++) { > + if (unit->data[sp] == 0xff) { > + data[dp++] = 0xff; > + data[dp++] = 0x00; > + } else { > + data[dp++] = unit->data[sp]; > + } > + } > + } > + } > + > + data[dp++] = 0xff; > + data[dp++] = JPEG_MARKER_EOI; > + > + av_assert0(dp == size); > + > + memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); > + frag->data = data; > + frag->data_size = size; > + > + return 0; > +} _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel