yading@10
|
1 /*
|
yading@10
|
2 * ZeroCodec Decoder
|
yading@10
|
3 *
|
yading@10
|
4 * Copyright (c) 2012, Derek Buitenhuis
|
yading@10
|
5 *
|
yading@10
|
6 * Permission to use, copy, modify, and/or distribute this software for any
|
yading@10
|
7 * purpose with or without fee is hereby granted, provided that the above
|
yading@10
|
8 * copyright notice and this permission notice appear in all copies.
|
yading@10
|
9 *
|
yading@10
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
yading@10
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
yading@10
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
yading@10
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
yading@10
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
yading@10
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
yading@10
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
yading@10
|
17 */
|
yading@10
|
18
|
yading@10
|
19 #include <zlib.h>
|
yading@10
|
20
|
yading@10
|
21 #include "avcodec.h"
|
yading@10
|
22 #include "internal.h"
|
yading@10
|
23 #include "libavutil/common.h"
|
yading@10
|
24
|
yading@10
|
25 typedef struct {
|
yading@10
|
26 AVFrame previous_frame;
|
yading@10
|
27 z_stream zstream;
|
yading@10
|
28 } ZeroCodecContext;
|
yading@10
|
29
|
yading@10
|
30 static int zerocodec_decode_frame(AVCodecContext *avctx, void *data,
|
yading@10
|
31 int *got_frame, AVPacket *avpkt)
|
yading@10
|
32 {
|
yading@10
|
33 ZeroCodecContext *zc = avctx->priv_data;
|
yading@10
|
34 AVFrame *pic = data;
|
yading@10
|
35 AVFrame *prev_pic = &zc->previous_frame;
|
yading@10
|
36 z_stream *zstream = &zc->zstream;
|
yading@10
|
37 uint8_t *prev = prev_pic->data[0];
|
yading@10
|
38 uint8_t *dst;
|
yading@10
|
39 int i, j, zret, ret;
|
yading@10
|
40
|
yading@10
|
41 if (avpkt->flags & AV_PKT_FLAG_KEY) {
|
yading@10
|
42 pic->key_frame = 1;
|
yading@10
|
43 pic->pict_type = AV_PICTURE_TYPE_I;
|
yading@10
|
44 } else {
|
yading@10
|
45 if (!prev) {
|
yading@10
|
46 av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
|
yading@10
|
47 return AVERROR_INVALIDDATA;
|
yading@10
|
48 }
|
yading@10
|
49
|
yading@10
|
50 prev += (avctx->height - 1) * prev_pic->linesize[0];
|
yading@10
|
51
|
yading@10
|
52 pic->key_frame = 0;
|
yading@10
|
53 pic->pict_type = AV_PICTURE_TYPE_P;
|
yading@10
|
54 }
|
yading@10
|
55
|
yading@10
|
56 zret = inflateReset(zstream);
|
yading@10
|
57 if (zret != Z_OK) {
|
yading@10
|
58 av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret);
|
yading@10
|
59 return AVERROR_INVALIDDATA;
|
yading@10
|
60 }
|
yading@10
|
61
|
yading@10
|
62 if ((ret = ff_get_buffer(avctx, pic, AV_GET_BUFFER_FLAG_REF)) < 0)
|
yading@10
|
63 return ret;
|
yading@10
|
64
|
yading@10
|
65 zstream->next_in = avpkt->data;
|
yading@10
|
66 zstream->avail_in = avpkt->size;
|
yading@10
|
67
|
yading@10
|
68 dst = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
|
yading@10
|
69
|
yading@10
|
70 /**
|
yading@10
|
71 * ZeroCodec has very simple interframe compression. If a value
|
yading@10
|
72 * is the same as the previous frame, set it to 0.
|
yading@10
|
73 */
|
yading@10
|
74
|
yading@10
|
75 for (i = 0; i < avctx->height; i++) {
|
yading@10
|
76 zstream->next_out = dst;
|
yading@10
|
77 zstream->avail_out = avctx->width << 1;
|
yading@10
|
78
|
yading@10
|
79 zret = inflate(zstream, Z_SYNC_FLUSH);
|
yading@10
|
80 if (zret != Z_OK && zret != Z_STREAM_END) {
|
yading@10
|
81 av_log(avctx, AV_LOG_ERROR,
|
yading@10
|
82 "Inflate failed with return code: %d.\n", zret);
|
yading@10
|
83 return AVERROR_INVALIDDATA;
|
yading@10
|
84 }
|
yading@10
|
85
|
yading@10
|
86 if (!(avpkt->flags & AV_PKT_FLAG_KEY))
|
yading@10
|
87 for (j = 0; j < avctx->width << 1; j++)
|
yading@10
|
88 dst[j] += prev[j] & -!dst[j];
|
yading@10
|
89
|
yading@10
|
90 prev -= prev_pic->linesize[0];
|
yading@10
|
91 dst -= pic->linesize[0];
|
yading@10
|
92 }
|
yading@10
|
93
|
yading@10
|
94 av_frame_unref(&zc->previous_frame);
|
yading@10
|
95 if ((ret = av_frame_ref(&zc->previous_frame, pic)) < 0)
|
yading@10
|
96 return ret;
|
yading@10
|
97
|
yading@10
|
98 *got_frame = 1;
|
yading@10
|
99
|
yading@10
|
100 return avpkt->size;
|
yading@10
|
101 }
|
yading@10
|
102
|
yading@10
|
103 static av_cold int zerocodec_decode_close(AVCodecContext *avctx)
|
yading@10
|
104 {
|
yading@10
|
105 ZeroCodecContext *zc = avctx->priv_data;
|
yading@10
|
106
|
yading@10
|
107 av_frame_unref(&zc->previous_frame);
|
yading@10
|
108
|
yading@10
|
109 inflateEnd(&zc->zstream);
|
yading@10
|
110
|
yading@10
|
111 return 0;
|
yading@10
|
112 }
|
yading@10
|
113
|
yading@10
|
114 static av_cold int zerocodec_decode_init(AVCodecContext *avctx)
|
yading@10
|
115 {
|
yading@10
|
116 ZeroCodecContext *zc = avctx->priv_data;
|
yading@10
|
117 z_stream *zstream = &zc->zstream;
|
yading@10
|
118 int zret;
|
yading@10
|
119
|
yading@10
|
120 avctx->pix_fmt = AV_PIX_FMT_UYVY422;
|
yading@10
|
121 avctx->bits_per_raw_sample = 8;
|
yading@10
|
122
|
yading@10
|
123 zstream->zalloc = Z_NULL;
|
yading@10
|
124 zstream->zfree = Z_NULL;
|
yading@10
|
125 zstream->opaque = Z_NULL;
|
yading@10
|
126
|
yading@10
|
127 zret = inflateInit(zstream);
|
yading@10
|
128 if (zret != Z_OK) {
|
yading@10
|
129 av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret);
|
yading@10
|
130 return AVERROR(ENOMEM);
|
yading@10
|
131 }
|
yading@10
|
132
|
yading@10
|
133 return 0;
|
yading@10
|
134 }
|
yading@10
|
135
|
yading@10
|
136 AVCodec ff_zerocodec_decoder = {
|
yading@10
|
137 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
138 .name = "zerocodec",
|
yading@10
|
139 .id = AV_CODEC_ID_ZEROCODEC,
|
yading@10
|
140 .priv_data_size = sizeof(ZeroCodecContext),
|
yading@10
|
141 .init = zerocodec_decode_init,
|
yading@10
|
142 .decode = zerocodec_decode_frame,
|
yading@10
|
143 .close = zerocodec_decode_close,
|
yading@10
|
144 .capabilities = CODEC_CAP_DR1,
|
yading@10
|
145 .long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"),
|
yading@10
|
146 };
|