00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <zlib.h>
00020
00021 #include "avcodec.h"
00022 #include "internal.h"
00023 #include "libavutil/common.h"
00024
00025 typedef struct {
00026 AVFrame previous_frame;
00027 z_stream zstream;
00028 int size;
00029 } ZeroCodecContext;
00030
00031 static int zerocodec_decode_frame(AVCodecContext *avctx, void *data,
00032 int *got_frame, AVPacket *avpkt)
00033 {
00034 ZeroCodecContext *zc = avctx->priv_data;
00035 AVFrame *pic = avctx->coded_frame;
00036 AVFrame *prev_pic = &zc->previous_frame;
00037 z_stream *zstream = &zc->zstream;
00038 uint8_t *prev = prev_pic->data[0];
00039 uint8_t *dst;
00040 int i, j, zret;
00041
00042 pic->reference = 3;
00043
00044 if (avpkt->flags & AV_PKT_FLAG_KEY) {
00045 pic->key_frame = 1;
00046 pic->pict_type = AV_PICTURE_TYPE_I;
00047 } else {
00048 if (!prev) {
00049 av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
00050 return AVERROR_INVALIDDATA;
00051 }
00052
00053 prev += (avctx->height - 1) * prev_pic->linesize[0];
00054
00055 pic->key_frame = 0;
00056 pic->pict_type = AV_PICTURE_TYPE_P;
00057 }
00058
00059 zret = inflateReset(zstream);
00060 if (zret != Z_OK) {
00061 av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret);
00062 return AVERROR_INVALIDDATA;
00063 }
00064
00065 if (ff_get_buffer(avctx, pic) < 0) {
00066 av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
00067 return AVERROR(ENOMEM);
00068 }
00069
00070 zstream->next_in = avpkt->data;
00071 zstream->avail_in = avpkt->size;
00072
00073 dst = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
00074
00080 for (i = 0; i < avctx->height; i++) {
00081 zstream->next_out = dst;
00082 zstream->avail_out = avctx->width << 1;
00083
00084 zret = inflate(zstream, Z_SYNC_FLUSH);
00085 if (zret != Z_OK && zret != Z_STREAM_END) {
00086 avctx->release_buffer(avctx, pic);
00087 av_log(avctx, AV_LOG_ERROR,
00088 "Inflate failed with return code: %d.\n", zret);
00089 return AVERROR_INVALIDDATA;
00090 }
00091
00092 if (!(avpkt->flags & AV_PKT_FLAG_KEY))
00093 for (j = 0; j < avctx->width << 1; j++)
00094 dst[j] += prev[j] & -!dst[j];
00095
00096 prev -= prev_pic->linesize[0];
00097 dst -= pic->linesize[0];
00098 }
00099
00100
00101 if (prev_pic->data[0])
00102 avctx->release_buffer(avctx, prev_pic);
00103
00104 *got_frame = 1;
00105 *(AVFrame *)data = *pic;
00106
00107
00108
00109 FFSWAP(AVFrame, *pic, *prev_pic);
00110
00111 return avpkt->size;
00112 }
00113
00114 static av_cold int zerocodec_decode_close(AVCodecContext *avctx)
00115 {
00116 ZeroCodecContext *zc = avctx->priv_data;
00117 AVFrame *prev_pic = &zc->previous_frame;
00118
00119 inflateEnd(&zc->zstream);
00120
00121
00122 if (prev_pic->data[0])
00123 avctx->release_buffer(avctx, prev_pic);
00124
00125 av_freep(&avctx->coded_frame);
00126
00127 return 0;
00128 }
00129
00130 static av_cold int zerocodec_decode_init(AVCodecContext *avctx)
00131 {
00132 ZeroCodecContext *zc = avctx->priv_data;
00133 z_stream *zstream = &zc->zstream;
00134 int zret;
00135
00136 avctx->pix_fmt = AV_PIX_FMT_UYVY422;
00137 avctx->bits_per_raw_sample = 8;
00138
00139 zc->size = avpicture_get_size(avctx->pix_fmt,
00140 avctx->width, avctx->height);
00141
00142 zstream->zalloc = Z_NULL;
00143 zstream->zfree = Z_NULL;
00144 zstream->opaque = Z_NULL;
00145
00146 zret = inflateInit(zstream);
00147 if (zret != Z_OK) {
00148 av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret);
00149 return AVERROR(ENOMEM);
00150 }
00151
00152 avctx->coded_frame = avcodec_alloc_frame();
00153 if (!avctx->coded_frame) {
00154 av_log(avctx, AV_LOG_ERROR, "Could not allocate frame buffer.\n");
00155 zerocodec_decode_close(avctx);
00156 return AVERROR(ENOMEM);
00157 }
00158
00159 return 0;
00160 }
00161
00162 AVCodec ff_zerocodec_decoder = {
00163 .type = AVMEDIA_TYPE_VIDEO,
00164 .name = "zerocodec",
00165 .id = AV_CODEC_ID_ZEROCODEC,
00166 .priv_data_size = sizeof(ZeroCodecContext),
00167 .init = zerocodec_decode_init,
00168 .decode = zerocodec_decode_frame,
00169 .close = zerocodec_decode_close,
00170 .capabilities = CODEC_CAP_DR1,
00171 .long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"),
00172 };