static int dxv_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { DXVContext *ctx = avctx->priv_data; ThreadFrame tframe; GetByteContext *gbc = &ctx->gbc; int (*decompress_tex)(AVCodecContext *avctx); const char *msgcomp, *msgtext; uint32_t tag; int version_major, version_minor = 0; int size = 0, old_type = 0; int ret; bytestream2_init(gbc, avpkt->data, avpkt->size); tag = bytestream2_get_le32(gbc); switch (tag) { case MKBETAG('D', 'X', 'T', '1'): decompress_tex = dxv_decompress_dxt1; ctx->tex_funct = ctx->texdsp.dxt1_block; ctx->tex_rat = 8; ctx->tex_step = 8; msgcomp = "DXTR1"; msgtext = "DXT1"; break; case MKBETAG('D', 'X', 'T', '5'): decompress_tex = dxv_decompress_dxt5; ctx->tex_funct = ctx->texdsp.dxt5_block; ctx->tex_rat = 4; ctx->tex_step = 16; msgcomp = "DXTR5"; msgtext = "DXT5"; break; case MKBETAG('Y', 'C', 'G', '6'): case MKBETAG('Y', 'G', '1', '0'): avpriv_report_missing_feature(avctx, "Tag 0x%08X", tag); return AVERROR_PATCHWELCOME; default: /* Old version does not have a real header, just size and type. */ size = tag & 0x00FFFFFF; old_type = tag >> 24; version_major = (old_type & 0x0F) - 1; if (old_type & 0x80) { msgcomp = "RAW"; decompress_tex = dxv_decompress_raw; } else { msgcomp = "LZF"; decompress_tex = dxv_decompress_lzf; } if (old_type & 0x40) { msgtext = "DXT5"; ctx->tex_funct = ctx->texdsp.dxt5_block; ctx->tex_step = 16; } else if (old_type & 0x20 || version_major == 1) { msgtext = "DXT1"; ctx->tex_funct = ctx->texdsp.dxt1_block; ctx->tex_step = 8; } else { av_log(avctx, AV_LOG_ERROR, "Unsupported header (0x%08X)\n.", tag); return AVERROR_INVALIDDATA; } ctx->tex_rat = 1; break; } /* New header is 12 bytes long. */ if (!old_type) { version_major = bytestream2_get_byte(gbc) - 1; version_minor = bytestream2_get_byte(gbc); /* Encoder copies texture data when compression is not advantageous. */ if (bytestream2_get_byte(gbc)) { msgcomp = "RAW"; ctx->tex_rat = 1; decompress_tex = dxv_decompress_raw; } bytestream2_skip(gbc, 1); // unknown size = bytestream2_get_le32(gbc); } av_log(avctx, AV_LOG_DEBUG, "%s compression with %s texture (version %d.%d)\n", msgcomp, msgtext, version_major, version_minor); if (size != bytestream2_get_bytes_left(gbc)) { av_log(avctx, AV_LOG_ERROR, "Incomplete or invalid file (header %d, left %d).\n", size, bytestream2_get_bytes_left(gbc)); return AVERROR_INVALIDDATA; } ctx->tex_size = avctx->coded_width * avctx->coded_height * 4 / ctx->tex_rat; ret = av_reallocp(&ctx->tex_data, ctx->tex_size); if (ret < 0) return ret; /* Decompress texture out of the intermediate compression. */ ret = decompress_tex(avctx); if (ret < 0) return ret; tframe.f = data; ret = ff_thread_get_buffer(avctx, &tframe, 0); if (ret < 0) return ret; ff_thread_finish_setup(avctx); /* Now decompress the texture with the standard functions. */ avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); /* Frame is ready to be output. */ tframe.f->pict_type = AV_PICTURE_TYPE_I; tframe.f->key_frame = 1; *got_frame = 1; return avpkt->size; }
static int dxv_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { DXVContext *ctx = avctx->priv_data; ThreadFrame tframe; GetByteContext *gbc = &ctx->gbc; int (*decompress_tex)(AVCodecContext *avctx); uint32_t tag; int channels, size = 0, old_type = 0; int ret; bytestream2_init(gbc, avpkt->data, avpkt->size); tag = bytestream2_get_le32(gbc); switch (tag) { case MKBETAG('D', 'X', 'T', '1'): decompress_tex = dxv_decompress_dxt1; ctx->tex_funct = ctx->texdsp.dxt1_block; ctx->tex_rat = 8; ctx->tex_step = 8; av_log(avctx, AV_LOG_DEBUG, "DXTR1 compression and DXT1 texture "); break; case MKBETAG('D', 'X', 'T', '5'): decompress_tex = dxv_decompress_dxt5; ctx->tex_funct = ctx->texdsp.dxt5_block; ctx->tex_rat = 4; ctx->tex_step = 16; av_log(avctx, AV_LOG_DEBUG, "DXTR5 compression and DXT5 texture "); break; case MKBETAG('Y', 'C', 'G', '6'): case MKBETAG('Y', 'G', '1', '0'): avpriv_report_missing_feature(avctx, "Tag 0x%08X", tag); return AVERROR_PATCHWELCOME; default: /* Old version does not have a real header, just size and type. */ size = tag & 0x00FFFFFF; old_type = tag >> 24; channels = old_type & 0x0F; if (old_type & 0x40) { av_log(avctx, AV_LOG_DEBUG, "LZF compression and DXT5 texture "); ctx->tex_funct = ctx->texdsp.dxt5_block; ctx->tex_step = 16; } else if (old_type & 0x20) { av_log(avctx, AV_LOG_DEBUG, "LZF compression and DXT1 texture "); ctx->tex_funct = ctx->texdsp.dxt1_block; ctx->tex_step = 8; } else { av_log(avctx, AV_LOG_ERROR, "Unsupported header (0x%08X)\n.", tag); return AVERROR_INVALIDDATA; } decompress_tex = dxv_decompress_lzf; ctx->tex_rat = 1; break; } /* New header is 12 bytes long. */ if (!old_type) { channels = bytestream2_get_byte(gbc); bytestream2_skip(gbc, 3); // unknown size = bytestream2_get_le32(gbc); } av_log(avctx, AV_LOG_DEBUG, "(%d channels)\n", channels); if (size != bytestream2_get_bytes_left(gbc)) { av_log(avctx, AV_LOG_ERROR, "Incomplete or invalid file (%u > %u)\n.", size, bytestream2_get_bytes_left(gbc)); return AVERROR_INVALIDDATA; } ctx->tex_size = avctx->coded_width * avctx->coded_height * 4 / ctx->tex_rat; ret = av_reallocp(&ctx->tex_data, ctx->tex_size); if (ret < 0) return ret; /* Decompress texture out of the intermediate compression. */ ret = decompress_tex(avctx); if (ret < 0) return ret; tframe.f = data; ret = ff_thread_get_buffer(avctx, &tframe, 0); if (ret < 0) return ret; ff_thread_finish_setup(avctx); /* Now decompress the texture with the standard functions. */ avctx->execute2(avctx, decompress_texture_thread, tframe.f, NULL, ctx->slice_count); /* Frame is ready to be output. */ tframe.f->pict_type = AV_PICTURE_TYPE_I; tframe.f->key_frame = 1; *got_frame = 1; return avpkt->size; }