1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2026-05-04 21:08:03 +02:00
Files
FFmpeg/libavcodec/zerocodec.c
T

149 lines
4.3 KiB
C
Raw Normal View History

2012-03-18 15:04:38 -04:00
/*
* ZeroCodec Decoder
*
* Copyright (c) 2012, Derek Buitenhuis
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <zlib.h>
#include "avcodec.h"
#include "internal.h"
2012-08-06 16:49:32 +03:00
#include "libavutil/common.h"
2012-03-18 15:04:38 -04:00
typedef struct {
AVFrame previous_frame;
z_stream zstream;
} ZeroCodecContext;
static int zerocodec_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame, AVPacket *avpkt)
2012-03-18 15:04:38 -04:00
{
ZeroCodecContext *zc = avctx->priv_data;
2012-11-21 21:34:46 +01:00
AVFrame *pic = data;
2012-03-18 15:04:38 -04:00
AVFrame *prev_pic = &zc->previous_frame;
z_stream *zstream = &zc->zstream;
2012-08-03 21:41:24 -04:00
uint8_t *prev = prev_pic->data[0];
uint8_t *dst;
2012-11-21 21:34:46 +01:00
int i, j, zret, ret;
2012-03-18 15:04:38 -04:00
2012-07-21 13:22:04 +02:00
if (avpkt->flags & AV_PKT_FLAG_KEY) {
pic->key_frame = 1;
pic->pict_type = AV_PICTURE_TYPE_I;
} else {
if (!prev) {
2012-08-03 21:41:24 -04:00
av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
2012-07-21 13:22:04 +02:00
return AVERROR_INVALIDDATA;
}
2012-12-09 10:24:16 +01:00
prev += (avctx->height - 1) * prev_pic->linesize[0];
2012-07-21 13:22:04 +02:00
pic->key_frame = 0;
pic->pict_type = AV_PICTURE_TYPE_P;
}
2012-03-18 15:04:38 -04:00
zret = inflateReset(zstream);
if (zret != Z_OK) {
2012-08-03 21:41:24 -04:00
av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret);
return AVERROR_INVALIDDATA;
2012-03-18 15:04:38 -04:00
}
2012-11-21 21:34:46 +01:00
if (ff_get_buffer(avctx, pic, AV_GET_BUFFER_FLAG_REF) < 0) {
2012-08-03 22:13:43 -04:00
av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
return AVERROR(ENOMEM);
}
2012-03-18 15:04:38 -04:00
zstream->next_in = avpkt->data;
zstream->avail_in = avpkt->size;
2012-12-09 10:24:16 +01:00
dst = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
2012-03-18 15:04:38 -04:00
/**
* ZeroCodec has very simple interframe compression. If a value
* is the same as the previous frame, set it to 0.
*/
2012-03-22 15:50:58 -04:00
for (i = 0; i < avctx->height; i++) {
zstream->next_out = dst;
zstream->avail_out = avctx->width << 1;
2012-03-18 15:04:38 -04:00
2012-03-22 15:50:58 -04:00
zret = inflate(zstream, Z_SYNC_FLUSH);
if (zret != Z_OK && zret != Z_STREAM_END) {
av_log(avctx, AV_LOG_ERROR,
2012-08-03 21:41:24 -04:00
"Inflate failed with return code: %d.\n", zret);
return AVERROR_INVALIDDATA;
2012-03-22 15:50:58 -04:00
}
2012-03-18 15:04:38 -04:00
2012-03-22 15:50:58 -04:00
if (!(avpkt->flags & AV_PKT_FLAG_KEY))
2012-03-18 15:04:38 -04:00
for (j = 0; j < avctx->width << 1; j++)
dst[j] += prev[j] & -!dst[j];
2012-12-09 10:24:16 +01:00
prev -= prev_pic->linesize[0];
dst -= pic->linesize[0];
2012-03-18 15:04:38 -04:00
}
2012-11-21 21:34:46 +01:00
av_frame_unref(&zc->previous_frame);
if ((ret = av_frame_ref(&zc->previous_frame, pic)) < 0)
return ret;
2012-03-18 15:04:38 -04:00
*got_frame = 1;
2012-07-21 13:22:04 +02:00
2012-03-18 15:04:38 -04:00
return avpkt->size;
}
static av_cold int zerocodec_decode_close(AVCodecContext *avctx)
{
ZeroCodecContext *zc = avctx->priv_data;
2012-11-21 21:34:46 +01:00
av_frame_unref(&zc->previous_frame);
2012-03-18 15:04:38 -04:00
2012-11-21 21:34:46 +01:00
inflateEnd(&zc->zstream);
2012-03-18 15:04:38 -04:00
return 0;
}
static av_cold int zerocodec_decode_init(AVCodecContext *avctx)
{
ZeroCodecContext *zc = avctx->priv_data;
z_stream *zstream = &zc->zstream;
int zret;
avctx->pix_fmt = AV_PIX_FMT_UYVY422;
2012-03-18 15:04:38 -04:00
avctx->bits_per_raw_sample = 8;
zstream->zalloc = Z_NULL;
zstream->zfree = Z_NULL;
zstream->opaque = Z_NULL;
zret = inflateInit(zstream);
if (zret != Z_OK) {
2012-08-03 21:41:24 -04:00
av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret);
2012-03-18 15:04:38 -04:00
return AVERROR(ENOMEM);
}
return 0;
}
AVCodec ff_zerocodec_decoder = {
.type = AVMEDIA_TYPE_VIDEO,
.name = "zerocodec",
2012-08-05 11:11:04 +02:00
.id = AV_CODEC_ID_ZEROCODEC,
2012-03-18 15:04:38 -04:00
.priv_data_size = sizeof(ZeroCodecContext),
.init = zerocodec_decode_init,
.decode = zerocodec_decode_frame,
.close = zerocodec_decode_close,
.capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"),
};