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