4
* Copyright (c) 2012, Derek Buitenhuis
6
* Permission to use, copy, modify, and/or distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
#include "libavutil/common.h"
26
AVFrame previous_frame;
30
static int zerocodec_decode_frame(AVCodecContext *avctx, void *data,
31
int *got_frame, AVPacket *avpkt)
33
ZeroCodecContext *zc = avctx->priv_data;
34
AVFrame *pic = avctx->coded_frame;
35
AVFrame *prev_pic = &zc->previous_frame;
36
z_stream *zstream = &zc->zstream;
37
uint8_t *prev = prev_pic->data[0];
43
if (avpkt->flags & AV_PKT_FLAG_KEY) {
45
pic->pict_type = AV_PICTURE_TYPE_I;
48
av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
49
return AVERROR_INVALIDDATA;
52
prev += (avctx->height - 1) * prev_pic->linesize[0];
55
pic->pict_type = AV_PICTURE_TYPE_P;
58
zret = inflateReset(zstream);
60
av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret);
61
return AVERROR_INVALIDDATA;
64
if (ff_get_buffer(avctx, pic) < 0) {
65
av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
66
return AVERROR(ENOMEM);
69
zstream->next_in = avpkt->data;
70
zstream->avail_in = avpkt->size;
72
dst = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
75
* ZeroCodec has very simple interframe compression. If a value
76
* is the same as the previous frame, set it to 0.
79
for (i = 0; i < avctx->height; i++) {
80
zstream->next_out = dst;
81
zstream->avail_out = avctx->width << 1;
83
zret = inflate(zstream, Z_SYNC_FLUSH);
84
if (zret != Z_OK && zret != Z_STREAM_END) {
85
avctx->release_buffer(avctx, pic);
86
av_log(avctx, AV_LOG_ERROR,
87
"Inflate failed with return code: %d.\n", zret);
88
return AVERROR_INVALIDDATA;
91
if (!(avpkt->flags & AV_PKT_FLAG_KEY))
92
for (j = 0; j < avctx->width << 1; j++)
93
dst[j] += prev[j] & -!dst[j];
95
prev -= prev_pic->linesize[0];
96
dst -= pic->linesize[0];
99
/* Release the previous buffer if need be */
100
if (prev_pic->data[0])
101
avctx->release_buffer(avctx, prev_pic);
104
*(AVFrame *)data = *pic;
106
/* Store the previous frame for use later.
107
* FFSWAP ensures that e.g. pic->data is NULLed. */
108
FFSWAP(AVFrame, *pic, *prev_pic);
113
static av_cold int zerocodec_decode_close(AVCodecContext *avctx)
115
ZeroCodecContext *zc = avctx->priv_data;
116
AVFrame *prev_pic = &zc->previous_frame;
118
inflateEnd(&zc->zstream);
120
/* Release last frame */
121
if (prev_pic->data[0])
122
avctx->release_buffer(avctx, prev_pic);
124
av_freep(&avctx->coded_frame);
129
static av_cold int zerocodec_decode_init(AVCodecContext *avctx)
131
ZeroCodecContext *zc = avctx->priv_data;
132
z_stream *zstream = &zc->zstream;
135
avctx->pix_fmt = AV_PIX_FMT_UYVY422;
136
avctx->bits_per_raw_sample = 8;
138
zstream->zalloc = Z_NULL;
139
zstream->zfree = Z_NULL;
140
zstream->opaque = Z_NULL;
142
zret = inflateInit(zstream);
144
av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret);
145
return AVERROR(ENOMEM);
148
avctx->coded_frame = avcodec_alloc_frame();
149
if (!avctx->coded_frame) {
150
av_log(avctx, AV_LOG_ERROR, "Could not allocate frame buffer.\n");
151
zerocodec_decode_close(avctx);
152
return AVERROR(ENOMEM);
158
AVCodec ff_zerocodec_decoder = {
159
.type = AVMEDIA_TYPE_VIDEO,
161
.id = AV_CODEC_ID_ZEROCODEC,
162
.priv_data_size = sizeof(ZeroCodecContext),
163
.init = zerocodec_decode_init,
164
.decode = zerocodec_decode_frame,
165
.close = zerocodec_decode_close,
166
.capabilities = CODEC_CAP_DR1,
167
.long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"),