static int read_header(FFV1Context *f) { uint8_t state[CONTEXT_SIZE]; int i, j, context_count = -1; //-1 to avoid warning RangeCoder *const c = &f->slice_context[0]->c; memset(state, 128, sizeof(state)); if (f->version < 2) { int chroma_planes, chroma_h_shift, chroma_v_shift, transparency, colorspace, bits_per_raw_sample; unsigned v= get_symbol(c, state, 0); if (v >= 2) { av_log(f->avctx, AV_LOG_ERROR, "invalid version %d in ver01 header\n", v); return AVERROR_INVALIDDATA; } f->version = v; f->ac = f->avctx->coder_type = get_symbol(c, state, 0); if (f->ac > 1) { for (i = 1; i < 256; i++) f->state_transition[i] = get_symbol(c, state, 1) + c->one_state[i]; } colorspace = get_symbol(c, state, 0); //YUV cs type bits_per_raw_sample = f->version > 0 ? get_symbol(c, state, 0) : f->avctx->bits_per_raw_sample; chroma_planes = get_rac(c, state); chroma_h_shift = get_symbol(c, state, 0); chroma_v_shift = get_symbol(c, state, 0); transparency = get_rac(c, state); if (f->plane_count) { if ( colorspace != f->colorspace || bits_per_raw_sample != f->avctx->bits_per_raw_sample || chroma_planes != f->chroma_planes || chroma_h_shift!= f->chroma_h_shift || chroma_v_shift!= f->chroma_v_shift || transparency != f->transparency) { av_log(f->avctx, AV_LOG_ERROR, "Invalid change of global parameters\n"); return AVERROR_INVALIDDATA; } } f->colorspace = colorspace; f->avctx->bits_per_raw_sample = bits_per_raw_sample; f->chroma_planes = chroma_planes; f->chroma_h_shift = chroma_h_shift; f->chroma_v_shift = chroma_v_shift; f->transparency = transparency; f->plane_count = 2 + f->transparency; } if (f->colorspace == 0) { if (!f->transparency && !f->chroma_planes) { if (f->avctx->bits_per_raw_sample <= 8) f->avctx->pix_fmt = AV_PIX_FMT_GRAY8; else f->avctx->pix_fmt = AV_PIX_FMT_GRAY16; } else if (f->avctx->bits_per_raw_sample<=8 && !f->transparency) { switch(16 * f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P; break; case 0x01: f->avctx->pix_fmt = AV_PIX_FMT_YUV440P; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P; break; case 0x20: f->avctx->pix_fmt = AV_PIX_FMT_YUV411P; break; case 0x22: f->avctx->pix_fmt = AV_PIX_FMT_YUV410P; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return AVERROR(ENOSYS); } } else if (f->avctx->bits_per_raw_sample <= 8 && f->transparency) { switch(16*f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUVA444P; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUVA422P; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUVA420P; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return AVERROR(ENOSYS); } } else if (f->avctx->bits_per_raw_sample == 9) { f->packed_at_lsb = 1; switch(16 * f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P9; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P9; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P9; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return AVERROR(ENOSYS); } } else if (f->avctx->bits_per_raw_sample == 10) { f->packed_at_lsb = 1; switch(16 * f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P10; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P10; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return AVERROR(ENOSYS); } } else { switch(16 * f->chroma_h_shift + f->chroma_v_shift) { case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P16; break; case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P16; break; case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P16; break; default: av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); return AVERROR(ENOSYS); } } } else if (f->colorspace == 1) { if (f->chroma_h_shift || f->chroma_v_shift) { av_log(f->avctx, AV_LOG_ERROR, "chroma subsampling not supported in this colorspace\n"); return AVERROR(ENOSYS); } if ( f->avctx->bits_per_raw_sample == 9) f->avctx->pix_fmt = AV_PIX_FMT_GBRP9; else if (f->avctx->bits_per_raw_sample == 10) f->avctx->pix_fmt = AV_PIX_FMT_GBRP10; else if (f->avctx->bits_per_raw_sample == 12) f->avctx->pix_fmt = AV_PIX_FMT_GBRP12; else if (f->avctx->bits_per_raw_sample == 14) f->avctx->pix_fmt = AV_PIX_FMT_GBRP14; else if (f->transparency) f->avctx->pix_fmt = AV_PIX_FMT_RGB32; else f->avctx->pix_fmt = AV_PIX_FMT_0RGB32; } else { av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n"); return AVERROR(ENOSYS); } av_dlog(f->avctx, "%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift, f->avctx->pix_fmt); if (f->version < 2) { context_count = read_quant_tables(c, f->quant_table); if (context_count < 0) { av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n"); return AVERROR_INVALIDDATA; } } else if (f->version < 3) { f->slice_count = get_symbol(c, state, 0); } else { const uint8_t *p = c->bytestream_end; for (f->slice_count = 0; f->slice_count < MAX_SLICES && 3 < p - c->bytestream_start; f->slice_count++) { int trailer = 3 + 5*!!f->ec; int size = AV_RB24(p-trailer); if (size + trailer > p - c->bytestream_start) break; p -= size + trailer; } } if (f->slice_count > (unsigned)MAX_SLICES || f->slice_count <= 0) { av_log(f->avctx, AV_LOG_ERROR, "slice count %d is invalid\n", f->slice_count); return AVERROR_INVALIDDATA; } for (j = 0; j < f->slice_count; j++) { FFV1Context *fs = f->slice_context[j]; fs->ac = f->ac; fs->packed_at_lsb = f->packed_at_lsb; fs->slice_damaged = 0; if (f->version == 2) { fs->slice_x = get_symbol(c, state, 0) * f->width ; fs->slice_y = get_symbol(c, state, 0) * f->height; fs->slice_width = (get_symbol(c, state, 0) + 1) * f->width + fs->slice_x; fs->slice_height = (get_symbol(c, state, 0) + 1) * f->height + fs->slice_y; fs->slice_x /= f->num_h_slices; fs->slice_y /= f->num_v_slices; fs->slice_width = fs->slice_width / f->num_h_slices - fs->slice_x; fs->slice_height = fs->slice_height / f->num_v_slices - fs->slice_y; if ((unsigned)fs->slice_width > f->width || (unsigned)fs->slice_height > f->height) return AVERROR_INVALIDDATA; if ( (unsigned)fs->slice_x + (uint64_t)fs->slice_width > f->width || (unsigned)fs->slice_y + (uint64_t)fs->slice_height > f->height) return AVERROR_INVALIDDATA; } for (i = 0; i < f->plane_count; i++) { PlaneContext *const p = &fs->plane[i]; if (f->version == 2) { int idx = get_symbol(c, state, 0); if (idx > (unsigned)f->quant_table_count) { av_log(f->avctx, AV_LOG_ERROR, "quant_table_index out of range\n"); return AVERROR_INVALIDDATA; } p->quant_table_index = idx; memcpy(p->quant_table, f->quant_tables[idx], sizeof(p->quant_table)); context_count = f->context_count[idx]; } else { memcpy(p->quant_table, f->quant_table, sizeof(p->quant_table)); } if (f->version <= 2) { av_assert0(context_count >= 0); if (p->context_count < context_count) { av_freep(&p->state); av_freep(&p->vlc_state); } p->context_count = context_count; } } } return 0; }