1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "cbs.h" 20cabdff1aSopenharmony_ci#include "cbs_internal.h" 21cabdff1aSopenharmony_ci#include "cbs_jpeg.h" 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#define HEADER(name) do { \ 25cabdff1aSopenharmony_ci ff_cbs_trace_header(ctx, name); \ 26cabdff1aSopenharmony_ci } while (0) 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#define CHECK(call) do { \ 29cabdff1aSopenharmony_ci err = (call); \ 30cabdff1aSopenharmony_ci if (err < 0) \ 31cabdff1aSopenharmony_ci return err; \ 32cabdff1aSopenharmony_ci } while (0) 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#define u(width, name, range_min, range_max) \ 37cabdff1aSopenharmony_ci xu(width, name, range_min, range_max, 0, ) 38cabdff1aSopenharmony_ci#define us(width, name, sub, range_min, range_max) \ 39cabdff1aSopenharmony_ci xu(width, name, range_min, range_max, 1, sub) 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#define READ 43cabdff1aSopenharmony_ci#define READWRITE read 44cabdff1aSopenharmony_ci#define RWContext GetBitContext 45cabdff1aSopenharmony_ci#define FUNC(name) cbs_jpeg_read_ ## name 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci#define xu(width, name, range_min, range_max, subs, ...) do { \ 48cabdff1aSopenharmony_ci uint32_t value; \ 49cabdff1aSopenharmony_ci CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ 50cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), \ 51cabdff1aSopenharmony_ci &value, range_min, range_max)); \ 52cabdff1aSopenharmony_ci current->name = value; \ 53cabdff1aSopenharmony_ci } while (0) 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci#include "cbs_jpeg_syntax_template.c" 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci#undef READ 58cabdff1aSopenharmony_ci#undef READWRITE 59cabdff1aSopenharmony_ci#undef RWContext 60cabdff1aSopenharmony_ci#undef FUNC 61cabdff1aSopenharmony_ci#undef xu 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci#define WRITE 64cabdff1aSopenharmony_ci#define READWRITE write 65cabdff1aSopenharmony_ci#define RWContext PutBitContext 66cabdff1aSopenharmony_ci#define FUNC(name) cbs_jpeg_write_ ## name 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci#define xu(width, name, range_min, range_max, subs, ...) do { \ 69cabdff1aSopenharmony_ci uint32_t value = current->name; \ 70cabdff1aSopenharmony_ci CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ 71cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), \ 72cabdff1aSopenharmony_ci value, range_min, range_max)); \ 73cabdff1aSopenharmony_ci } while (0) 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci#include "cbs_jpeg_syntax_template.c" 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci#undef WRITE 79cabdff1aSopenharmony_ci#undef READWRITE 80cabdff1aSopenharmony_ci#undef RWContext 81cabdff1aSopenharmony_ci#undef FUNC 82cabdff1aSopenharmony_ci#undef xu 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_cistatic void cbs_jpeg_free_application_data(void *opaque, uint8_t *content) 86cabdff1aSopenharmony_ci{ 87cabdff1aSopenharmony_ci JPEGRawApplicationData *ad = (JPEGRawApplicationData*)content; 88cabdff1aSopenharmony_ci av_buffer_unref(&ad->Ap_ref); 89cabdff1aSopenharmony_ci av_freep(&content); 90cabdff1aSopenharmony_ci} 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_cistatic void cbs_jpeg_free_comment(void *opaque, uint8_t *content) 93cabdff1aSopenharmony_ci{ 94cabdff1aSopenharmony_ci JPEGRawComment *comment = (JPEGRawComment*)content; 95cabdff1aSopenharmony_ci av_buffer_unref(&comment->Cm_ref); 96cabdff1aSopenharmony_ci av_freep(&content); 97cabdff1aSopenharmony_ci} 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_cistatic void cbs_jpeg_free_scan(void *opaque, uint8_t *content) 100cabdff1aSopenharmony_ci{ 101cabdff1aSopenharmony_ci JPEGRawScan *scan = (JPEGRawScan*)content; 102cabdff1aSopenharmony_ci av_buffer_unref(&scan->data_ref); 103cabdff1aSopenharmony_ci av_freep(&content); 104cabdff1aSopenharmony_ci} 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_cistatic int cbs_jpeg_split_fragment(CodedBitstreamContext *ctx, 107cabdff1aSopenharmony_ci CodedBitstreamFragment *frag, 108cabdff1aSopenharmony_ci int header) 109cabdff1aSopenharmony_ci{ 110cabdff1aSopenharmony_ci AVBufferRef *data_ref; 111cabdff1aSopenharmony_ci uint8_t *data; 112cabdff1aSopenharmony_ci size_t data_size; 113cabdff1aSopenharmony_ci int start, end, marker, next_start, next_marker; 114cabdff1aSopenharmony_ci int err, i, j, length; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci if (frag->data_size < 4) { 117cabdff1aSopenharmony_ci // Definitely too short to be meaningful. 118cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 119cabdff1aSopenharmony_ci } 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci for (i = 0; i + 1 < frag->data_size && frag->data[i] != 0xff; i++); 122cabdff1aSopenharmony_ci if (i > 0) { 123cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_WARNING, "Discarding %d bytes at " 124cabdff1aSopenharmony_ci "beginning of image.\n", i); 125cabdff1aSopenharmony_ci } 126cabdff1aSopenharmony_ci for (++i; i + 1 < frag->data_size && frag->data[i] == 0xff; i++); 127cabdff1aSopenharmony_ci if (i + 1 >= frag->data_size && frag->data[i]) { 128cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: " 129cabdff1aSopenharmony_ci "no SOI marker found.\n"); 130cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 131cabdff1aSopenharmony_ci } 132cabdff1aSopenharmony_ci marker = frag->data[i]; 133cabdff1aSopenharmony_ci if (marker != JPEG_MARKER_SOI) { 134cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: first " 135cabdff1aSopenharmony_ci "marker is %02x, should be SOI.\n", marker); 136cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 137cabdff1aSopenharmony_ci } 138cabdff1aSopenharmony_ci for (++i; i + 1 < frag->data_size && frag->data[i] == 0xff; i++); 139cabdff1aSopenharmony_ci if (i + 1 >= frag->data_size) { 140cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: " 141cabdff1aSopenharmony_ci "no image content found.\n"); 142cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci marker = frag->data[i]; 145cabdff1aSopenharmony_ci start = i + 1; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci do { 148cabdff1aSopenharmony_ci if (marker == JPEG_MARKER_EOI) { 149cabdff1aSopenharmony_ci break; 150cabdff1aSopenharmony_ci } else if (marker == JPEG_MARKER_SOS) { 151cabdff1aSopenharmony_ci next_marker = -1; 152cabdff1aSopenharmony_ci end = start; 153cabdff1aSopenharmony_ci for (i = start; i + 1 < frag->data_size; i++) { 154cabdff1aSopenharmony_ci if (frag->data[i] != 0xff) 155cabdff1aSopenharmony_ci continue; 156cabdff1aSopenharmony_ci end = i; 157cabdff1aSopenharmony_ci for (++i; i + 1 < frag->data_size && 158cabdff1aSopenharmony_ci frag->data[i] == 0xff; i++); 159cabdff1aSopenharmony_ci if (i + 1 < frag->data_size) { 160cabdff1aSopenharmony_ci if (frag->data[i] == 0x00) 161cabdff1aSopenharmony_ci continue; 162cabdff1aSopenharmony_ci next_marker = frag->data[i]; 163cabdff1aSopenharmony_ci next_start = i + 1; 164cabdff1aSopenharmony_ci } 165cabdff1aSopenharmony_ci break; 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci } else { 168cabdff1aSopenharmony_ci i = start; 169cabdff1aSopenharmony_ci if (i + 2 > frag->data_size) { 170cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: " 171cabdff1aSopenharmony_ci "truncated at %02x marker.\n", marker); 172cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci length = AV_RB16(frag->data + i); 175cabdff1aSopenharmony_ci if (i + length > frag->data_size) { 176cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid JPEG image: " 177cabdff1aSopenharmony_ci "truncated at %02x marker segment.\n", marker); 178cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 179cabdff1aSopenharmony_ci } 180cabdff1aSopenharmony_ci end = start + length; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci i = end; 183cabdff1aSopenharmony_ci if (frag->data[i] != 0xff) { 184cabdff1aSopenharmony_ci next_marker = -1; 185cabdff1aSopenharmony_ci } else { 186cabdff1aSopenharmony_ci for (++i; i + 1 < frag->data_size && 187cabdff1aSopenharmony_ci frag->data[i] == 0xff; i++); 188cabdff1aSopenharmony_ci if (i + 1 >= frag->data_size) { 189cabdff1aSopenharmony_ci next_marker = -1; 190cabdff1aSopenharmony_ci } else { 191cabdff1aSopenharmony_ci next_marker = frag->data[i]; 192cabdff1aSopenharmony_ci next_start = i + 1; 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci } 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci if (marker == JPEG_MARKER_SOS) { 198cabdff1aSopenharmony_ci length = AV_RB16(frag->data + start); 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci if (length > end - start) 201cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci data_ref = NULL; 204cabdff1aSopenharmony_ci data = av_malloc(end - start + 205cabdff1aSopenharmony_ci AV_INPUT_BUFFER_PADDING_SIZE); 206cabdff1aSopenharmony_ci if (!data) 207cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci memcpy(data, frag->data + start, length); 210cabdff1aSopenharmony_ci for (i = start + length, j = length; i < end; i++, j++) { 211cabdff1aSopenharmony_ci if (frag->data[i] == 0xff) { 212cabdff1aSopenharmony_ci while (frag->data[i] == 0xff) 213cabdff1aSopenharmony_ci ++i; 214cabdff1aSopenharmony_ci data[j] = 0xff; 215cabdff1aSopenharmony_ci } else { 216cabdff1aSopenharmony_ci data[j] = frag->data[i]; 217cabdff1aSopenharmony_ci } 218cabdff1aSopenharmony_ci } 219cabdff1aSopenharmony_ci data_size = j; 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci memset(data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci } else { 224cabdff1aSopenharmony_ci data = frag->data + start; 225cabdff1aSopenharmony_ci data_size = end - start; 226cabdff1aSopenharmony_ci data_ref = frag->data_ref; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci err = ff_cbs_append_unit_data(frag, marker, 230cabdff1aSopenharmony_ci data, data_size, data_ref); 231cabdff1aSopenharmony_ci if (err < 0) 232cabdff1aSopenharmony_ci return err; 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci marker = next_marker; 235cabdff1aSopenharmony_ci start = next_start; 236cabdff1aSopenharmony_ci } while (next_marker != -1); 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci return 0; 239cabdff1aSopenharmony_ci} 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_cistatic int cbs_jpeg_read_unit(CodedBitstreamContext *ctx, 242cabdff1aSopenharmony_ci CodedBitstreamUnit *unit) 243cabdff1aSopenharmony_ci{ 244cabdff1aSopenharmony_ci GetBitContext gbc; 245cabdff1aSopenharmony_ci int err; 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); 248cabdff1aSopenharmony_ci if (err < 0) 249cabdff1aSopenharmony_ci return err; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci if (unit->type >= JPEG_MARKER_SOF0 && 252cabdff1aSopenharmony_ci unit->type <= JPEG_MARKER_SOF3) { 253cabdff1aSopenharmony_ci err = ff_cbs_alloc_unit_content(unit, 254cabdff1aSopenharmony_ci sizeof(JPEGRawFrameHeader), 255cabdff1aSopenharmony_ci NULL); 256cabdff1aSopenharmony_ci if (err < 0) 257cabdff1aSopenharmony_ci return err; 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci err = cbs_jpeg_read_frame_header(ctx, &gbc, unit->content); 260cabdff1aSopenharmony_ci if (err < 0) 261cabdff1aSopenharmony_ci return err; 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci } else if (unit->type >= JPEG_MARKER_APPN && 264cabdff1aSopenharmony_ci unit->type <= JPEG_MARKER_APPN + 15) { 265cabdff1aSopenharmony_ci err = ff_cbs_alloc_unit_content(unit, 266cabdff1aSopenharmony_ci sizeof(JPEGRawApplicationData), 267cabdff1aSopenharmony_ci &cbs_jpeg_free_application_data); 268cabdff1aSopenharmony_ci if (err < 0) 269cabdff1aSopenharmony_ci return err; 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci err = cbs_jpeg_read_application_data(ctx, &gbc, unit->content); 272cabdff1aSopenharmony_ci if (err < 0) 273cabdff1aSopenharmony_ci return err; 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci } else if (unit->type == JPEG_MARKER_SOS) { 276cabdff1aSopenharmony_ci JPEGRawScan *scan; 277cabdff1aSopenharmony_ci int pos; 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_ci err = ff_cbs_alloc_unit_content(unit, 280cabdff1aSopenharmony_ci sizeof(JPEGRawScan), 281cabdff1aSopenharmony_ci &cbs_jpeg_free_scan); 282cabdff1aSopenharmony_ci if (err < 0) 283cabdff1aSopenharmony_ci return err; 284cabdff1aSopenharmony_ci scan = unit->content; 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ci err = cbs_jpeg_read_scan_header(ctx, &gbc, &scan->header); 287cabdff1aSopenharmony_ci if (err < 0) 288cabdff1aSopenharmony_ci return err; 289cabdff1aSopenharmony_ci 290cabdff1aSopenharmony_ci pos = get_bits_count(&gbc); 291cabdff1aSopenharmony_ci av_assert0(pos % 8 == 0); 292cabdff1aSopenharmony_ci if (pos > 0) { 293cabdff1aSopenharmony_ci scan->data_size = unit->data_size - pos / 8; 294cabdff1aSopenharmony_ci scan->data_ref = av_buffer_ref(unit->data_ref); 295cabdff1aSopenharmony_ci if (!scan->data_ref) 296cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 297cabdff1aSopenharmony_ci scan->data = unit->data + pos / 8; 298cabdff1aSopenharmony_ci } 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci } else { 301cabdff1aSopenharmony_ci switch (unit->type) { 302cabdff1aSopenharmony_ci#define SEGMENT(marker, type, func, free) \ 303cabdff1aSopenharmony_ci case JPEG_MARKER_ ## marker: \ 304cabdff1aSopenharmony_ci { \ 305cabdff1aSopenharmony_ci err = ff_cbs_alloc_unit_content(unit, \ 306cabdff1aSopenharmony_ci sizeof(type), free); \ 307cabdff1aSopenharmony_ci if (err < 0) \ 308cabdff1aSopenharmony_ci return err; \ 309cabdff1aSopenharmony_ci err = cbs_jpeg_read_ ## func(ctx, &gbc, unit->content); \ 310cabdff1aSopenharmony_ci if (err < 0) \ 311cabdff1aSopenharmony_ci return err; \ 312cabdff1aSopenharmony_ci } \ 313cabdff1aSopenharmony_ci break 314cabdff1aSopenharmony_ci SEGMENT(DQT, JPEGRawQuantisationTableSpecification, dqt, NULL); 315cabdff1aSopenharmony_ci SEGMENT(DHT, JPEGRawHuffmanTableSpecification, dht, NULL); 316cabdff1aSopenharmony_ci SEGMENT(COM, JPEGRawComment, comment, &cbs_jpeg_free_comment); 317cabdff1aSopenharmony_ci#undef SEGMENT 318cabdff1aSopenharmony_ci default: 319cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 320cabdff1aSopenharmony_ci } 321cabdff1aSopenharmony_ci } 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci return 0; 324cabdff1aSopenharmony_ci} 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_cistatic int cbs_jpeg_write_scan(CodedBitstreamContext *ctx, 327cabdff1aSopenharmony_ci CodedBitstreamUnit *unit, 328cabdff1aSopenharmony_ci PutBitContext *pbc) 329cabdff1aSopenharmony_ci{ 330cabdff1aSopenharmony_ci JPEGRawScan *scan = unit->content; 331cabdff1aSopenharmony_ci int err; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci err = cbs_jpeg_write_scan_header(ctx, pbc, &scan->header); 334cabdff1aSopenharmony_ci if (err < 0) 335cabdff1aSopenharmony_ci return err; 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci if (scan->data) { 338cabdff1aSopenharmony_ci if (scan->data_size * 8 > put_bits_left(pbc)) 339cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci av_assert0(put_bits_count(pbc) % 8 == 0); 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci flush_put_bits(pbc); 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_ci memcpy(put_bits_ptr(pbc), scan->data, scan->data_size); 346cabdff1aSopenharmony_ci skip_put_bytes(pbc, scan->data_size); 347cabdff1aSopenharmony_ci } 348cabdff1aSopenharmony_ci 349cabdff1aSopenharmony_ci return 0; 350cabdff1aSopenharmony_ci} 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_cistatic int cbs_jpeg_write_segment(CodedBitstreamContext *ctx, 353cabdff1aSopenharmony_ci CodedBitstreamUnit *unit, 354cabdff1aSopenharmony_ci PutBitContext *pbc) 355cabdff1aSopenharmony_ci{ 356cabdff1aSopenharmony_ci int err; 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci if (unit->type >= JPEG_MARKER_SOF0 && 359cabdff1aSopenharmony_ci unit->type <= JPEG_MARKER_SOF3) { 360cabdff1aSopenharmony_ci err = cbs_jpeg_write_frame_header(ctx, pbc, unit->content); 361cabdff1aSopenharmony_ci } else if (unit->type >= JPEG_MARKER_APPN && 362cabdff1aSopenharmony_ci unit->type <= JPEG_MARKER_APPN + 15) { 363cabdff1aSopenharmony_ci err = cbs_jpeg_write_application_data(ctx, pbc, unit->content); 364cabdff1aSopenharmony_ci } else { 365cabdff1aSopenharmony_ci switch (unit->type) { 366cabdff1aSopenharmony_ci#define SEGMENT(marker, func) \ 367cabdff1aSopenharmony_ci case JPEG_MARKER_ ## marker: \ 368cabdff1aSopenharmony_ci err = cbs_jpeg_write_ ## func(ctx, pbc, unit->content); \ 369cabdff1aSopenharmony_ci break; 370cabdff1aSopenharmony_ci SEGMENT(DQT, dqt); 371cabdff1aSopenharmony_ci SEGMENT(DHT, dht); 372cabdff1aSopenharmony_ci SEGMENT(COM, comment); 373cabdff1aSopenharmony_ci default: 374cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 375cabdff1aSopenharmony_ci } 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci return err; 379cabdff1aSopenharmony_ci} 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_cistatic int cbs_jpeg_write_unit(CodedBitstreamContext *ctx, 382cabdff1aSopenharmony_ci CodedBitstreamUnit *unit, 383cabdff1aSopenharmony_ci PutBitContext *pbc) 384cabdff1aSopenharmony_ci{ 385cabdff1aSopenharmony_ci if (unit->type == JPEG_MARKER_SOS) 386cabdff1aSopenharmony_ci return cbs_jpeg_write_scan (ctx, unit, pbc); 387cabdff1aSopenharmony_ci else 388cabdff1aSopenharmony_ci return cbs_jpeg_write_segment(ctx, unit, pbc); 389cabdff1aSopenharmony_ci} 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_cistatic int cbs_jpeg_assemble_fragment(CodedBitstreamContext *ctx, 392cabdff1aSopenharmony_ci CodedBitstreamFragment *frag) 393cabdff1aSopenharmony_ci{ 394cabdff1aSopenharmony_ci const CodedBitstreamUnit *unit; 395cabdff1aSopenharmony_ci uint8_t *data; 396cabdff1aSopenharmony_ci size_t size, dp, sp; 397cabdff1aSopenharmony_ci int i; 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_ci size = 4; // SOI + EOI. 400cabdff1aSopenharmony_ci for (i = 0; i < frag->nb_units; i++) { 401cabdff1aSopenharmony_ci unit = &frag->units[i]; 402cabdff1aSopenharmony_ci size += 2 + unit->data_size; 403cabdff1aSopenharmony_ci if (unit->type == JPEG_MARKER_SOS) { 404cabdff1aSopenharmony_ci for (sp = 0; sp < unit->data_size; sp++) { 405cabdff1aSopenharmony_ci if (unit->data[sp] == 0xff) 406cabdff1aSopenharmony_ci ++size; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci } 409cabdff1aSopenharmony_ci } 410cabdff1aSopenharmony_ci 411cabdff1aSopenharmony_ci frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); 412cabdff1aSopenharmony_ci if (!frag->data_ref) 413cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 414cabdff1aSopenharmony_ci data = frag->data_ref->data; 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci dp = 0; 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci data[dp++] = 0xff; 419cabdff1aSopenharmony_ci data[dp++] = JPEG_MARKER_SOI; 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_ci for (i = 0; i < frag->nb_units; i++) { 422cabdff1aSopenharmony_ci unit = &frag->units[i]; 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci data[dp++] = 0xff; 425cabdff1aSopenharmony_ci data[dp++] = unit->type; 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_ci if (unit->type != JPEG_MARKER_SOS) { 428cabdff1aSopenharmony_ci memcpy(data + dp, unit->data, unit->data_size); 429cabdff1aSopenharmony_ci dp += unit->data_size; 430cabdff1aSopenharmony_ci } else { 431cabdff1aSopenharmony_ci sp = AV_RB16(unit->data); 432cabdff1aSopenharmony_ci av_assert0(sp <= unit->data_size); 433cabdff1aSopenharmony_ci memcpy(data + dp, unit->data, sp); 434cabdff1aSopenharmony_ci dp += sp; 435cabdff1aSopenharmony_ci 436cabdff1aSopenharmony_ci for (; sp < unit->data_size; sp++) { 437cabdff1aSopenharmony_ci if (unit->data[sp] == 0xff) { 438cabdff1aSopenharmony_ci data[dp++] = 0xff; 439cabdff1aSopenharmony_ci data[dp++] = 0x00; 440cabdff1aSopenharmony_ci } else { 441cabdff1aSopenharmony_ci data[dp++] = unit->data[sp]; 442cabdff1aSopenharmony_ci } 443cabdff1aSopenharmony_ci } 444cabdff1aSopenharmony_ci } 445cabdff1aSopenharmony_ci } 446cabdff1aSopenharmony_ci 447cabdff1aSopenharmony_ci data[dp++] = 0xff; 448cabdff1aSopenharmony_ci data[dp++] = JPEG_MARKER_EOI; 449cabdff1aSopenharmony_ci 450cabdff1aSopenharmony_ci av_assert0(dp == size); 451cabdff1aSopenharmony_ci 452cabdff1aSopenharmony_ci memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); 453cabdff1aSopenharmony_ci frag->data = data; 454cabdff1aSopenharmony_ci frag->data_size = size; 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci return 0; 457cabdff1aSopenharmony_ci} 458cabdff1aSopenharmony_ci 459cabdff1aSopenharmony_ciconst CodedBitstreamType ff_cbs_type_jpeg = { 460cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_MJPEG, 461cabdff1aSopenharmony_ci 462cabdff1aSopenharmony_ci .split_fragment = &cbs_jpeg_split_fragment, 463cabdff1aSopenharmony_ci .read_unit = &cbs_jpeg_read_unit, 464cabdff1aSopenharmony_ci .write_unit = &cbs_jpeg_write_unit, 465cabdff1aSopenharmony_ci .assemble_fragment = &cbs_jpeg_assemble_fragment, 466cabdff1aSopenharmony_ci}; 467