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