mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 12:36:41 +08:00 
			
		
		
		
	ZeroCodec Decoder
An obscure Japanese lossless video codec, originally intended for use with a remote desktop application. Signed-off-by: Derek Buitenhuis <derek.buitenhuis@gmail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
		 Derek Buitenhuis
					Derek Buitenhuis
				
			
				
					committed by
					
						 Michael Niedermayer
						Michael Niedermayer
					
				
			
			
				
	
			
			
			 Michael Niedermayer
						Michael Niedermayer
					
				
			
						parent
						
							bae053fca4
						
					
				
				
					commit
					6cabb679d6
				
			| @@ -16,6 +16,7 @@ version next: | |||||||
| - swapuv filter | - swapuv filter | ||||||
| - bbox filter | - bbox filter | ||||||
| - XBM encoder | - XBM encoder | ||||||
|  | - ZeroCodec decoder | ||||||
|  |  | ||||||
|  |  | ||||||
| version 0.10: | version 0.10: | ||||||
|   | |||||||
| @@ -244,6 +244,7 @@ Codecs: | |||||||
|   xan.c                                 Mike Melanson |   xan.c                                 Mike Melanson | ||||||
|   xl.c                                  Kostya Shishkov |   xl.c                                  Kostya Shishkov | ||||||
|   xvmc.c                                Ivan Kalvachev |   xvmc.c                                Ivan Kalvachev | ||||||
|  |   zerocodec.c                           Derek Buitenhuis | ||||||
|   zmbv*                                 Kostya Shishkov |   zmbv*                                 Kostya Shishkov | ||||||
|  |  | ||||||
| Hardware acceleration: | Hardware acceleration: | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -1527,6 +1527,7 @@ wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" | |||||||
| wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" | wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" | ||||||
| wmv3_vdpau_decoder_select="vc1_vdpau_decoder" | wmv3_vdpau_decoder_select="vc1_vdpau_decoder" | ||||||
| wmv3image_decoder_select="wmv3_decoder" | wmv3image_decoder_select="wmv3_decoder" | ||||||
|  | zerocodec_decoder_select="zlib" | ||||||
| zlib_decoder_select="zlib" | zlib_decoder_select="zlib" | ||||||
| zlib_encoder_select="zlib" | zlib_encoder_select="zlib" | ||||||
| zmbv_decoder_select="zlib" | zmbv_decoder_select="zlib" | ||||||
|   | |||||||
| @@ -351,6 +351,7 @@ library: | |||||||
| @item eXtended BINary text (XBIN) @tab @tab X | @item eXtended BINary text (XBIN) @tab @tab X | ||||||
| @item YUV4MPEG pipe             @tab X @tab X | @item YUV4MPEG pipe             @tab X @tab X | ||||||
| @item Psygnosis YOP             @tab   @tab X | @item Psygnosis YOP             @tab   @tab X | ||||||
|  | @item ZeroCodec Lossless Video  @tab   @tab X | ||||||
| @end multitable | @end multitable | ||||||
|  |  | ||||||
| @code{X} means that encoding (resp. decoding) is supported. | @code{X} means that encoding (resp. decoding) is supported. | ||||||
|   | |||||||
| @@ -493,6 +493,7 @@ OBJS-$(CONFIG_Y41P_ENCODER)            += y41penc.o | |||||||
| OBJS-$(CONFIG_YOP_DECODER)             += yop.o | OBJS-$(CONFIG_YOP_DECODER)             += yop.o | ||||||
| OBJS-$(CONFIG_YUV4_DECODER)            += yuv4dec.o | OBJS-$(CONFIG_YUV4_DECODER)            += yuv4dec.o | ||||||
| OBJS-$(CONFIG_YUV4_ENCODER)            += yuv4enc.o | OBJS-$(CONFIG_YUV4_ENCODER)            += yuv4enc.o | ||||||
|  | OBJS-$(CONFIG_ZEROCODEC_DECODER)       += zerocodec.o | ||||||
| OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o | OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o | ||||||
| OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o | OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o | ||||||
| OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o | OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o | ||||||
|   | |||||||
| @@ -255,6 +255,7 @@ void avcodec_register_all(void) | |||||||
|     REGISTER_ENCDEC  (Y41P, y41p); |     REGISTER_ENCDEC  (Y41P, y41p); | ||||||
|     REGISTER_DECODER (YOP, yop); |     REGISTER_DECODER (YOP, yop); | ||||||
|     REGISTER_ENCDEC  (YUV4, yuv4); |     REGISTER_ENCDEC  (YUV4, yuv4); | ||||||
|  |     REGISTER_DECODER (ZEROCODEC, zerocodec); | ||||||
|     REGISTER_ENCDEC  (ZLIB, zlib); |     REGISTER_ENCDEC  (ZLIB, zlib); | ||||||
|     REGISTER_ENCDEC  (ZMBV, zmbv); |     REGISTER_ENCDEC  (ZMBV, zmbv); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -248,6 +248,7 @@ enum CodecID { | |||||||
|     CODEC_ID_XWD, |     CODEC_ID_XWD, | ||||||
|     CODEC_ID_CDXL, |     CODEC_ID_CDXL, | ||||||
|     CODEC_ID_XBM, |     CODEC_ID_XBM, | ||||||
|  |     CODEC_ID_ZEROCODEC, | ||||||
|     CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'), |     CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'), | ||||||
|     CODEC_ID_ESCAPE130  = MKBETAG('E','1','3','0'), |     CODEC_ID_ESCAPE130  = MKBETAG('E','1','3','0'), | ||||||
|     CODEC_ID_AVRP       = MKBETAG('A','V','R','P'), |     CODEC_ID_AVRP       = MKBETAG('A','V','R','P'), | ||||||
|   | |||||||
							
								
								
									
										182
									
								
								libavcodec/zerocodec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								libavcodec/zerocodec.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,182 @@ | |||||||
|  | /* | ||||||
|  |  * ZeroCodec Decoder | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2012, Derek Buitenhuis | ||||||
|  |  * | ||||||
|  |  * This file is part of FFMpeg. | ||||||
|  |  * | ||||||
|  |  * 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" | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     AVFrame  previous_frame; | ||||||
|  |     z_stream zstream; | ||||||
|  |     int size; | ||||||
|  | } ZeroCodecContext; | ||||||
|  |  | ||||||
|  | static int zerocodec_decode_frame(AVCodecContext *avctx, void *data, | ||||||
|  |                                   int *data_size, AVPacket *avpkt) | ||||||
|  | { | ||||||
|  |     ZeroCodecContext *zc = avctx->priv_data; | ||||||
|  |     AVFrame *pic         = avctx->coded_frame; | ||||||
|  |     AVFrame *prev_pic    = &zc->previous_frame; | ||||||
|  |     z_stream *zstream    = &zc->zstream; | ||||||
|  |     uint8_t *prev, *dst; | ||||||
|  |     int i, j, zret; | ||||||
|  |  | ||||||
|  |     pic->reference = 3; | ||||||
|  |  | ||||||
|  |     if (avctx->get_buffer(avctx, pic) < 0) { | ||||||
|  |         av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     zret = inflateReset(zstream); | ||||||
|  |  | ||||||
|  |     if (zret != Z_OK) { | ||||||
|  |         av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d\n", zret); | ||||||
|  |         return AVERROR(EINVAL); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     zstream->next_in   = avpkt->data; | ||||||
|  |     zstream->avail_in  = avpkt->size; | ||||||
|  |  | ||||||
|  |     prev = prev_pic->data[0]; | ||||||
|  |     dst  = pic->data[0]; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * ZeroCodec has very simple interframe compression. If a value | ||||||
|  |      * is the same as the previous frame, set it to 0. | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     if (avpkt->flags & AV_PKT_FLAG_KEY) { | ||||||
|  |  | ||||||
|  |         pic->key_frame = 1; | ||||||
|  |         pic->pict_type = AV_PICTURE_TYPE_I; | ||||||
|  |  | ||||||
|  |         for (i = 0; i < avctx->height; i++) { | ||||||
|  |  | ||||||
|  |             zstream->next_out  = dst; | ||||||
|  |             zstream->avail_out = avctx->width << 1; | ||||||
|  |  | ||||||
|  |             zret = inflate(zstream, Z_SYNC_FLUSH); | ||||||
|  |  | ||||||
|  |             if (zret != Z_OK && zret != Z_STREAM_END) { | ||||||
|  |                 av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d\n", zret); | ||||||
|  |                 return AVERROR(EINVAL); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             dst += pic->linesize[0]; | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |  | ||||||
|  |         pic->key_frame = 0; | ||||||
|  |         pic->pict_type = AV_PICTURE_TYPE_P; | ||||||
|  |  | ||||||
|  |         for (i = 0; i < avctx->height; i++) { | ||||||
|  |  | ||||||
|  |             zstream->next_out  = dst; | ||||||
|  |             zstream->avail_out = avctx->width << 1; | ||||||
|  |  | ||||||
|  |             zret = inflate(zstream, Z_SYNC_FLUSH); | ||||||
|  |  | ||||||
|  |             if (zret != Z_OK && zret != Z_STREAM_END) { | ||||||
|  |                 av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d\n", zret); | ||||||
|  |                 return AVERROR(EINVAL); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             for (j = 0; j < avctx->width << 1; j++) | ||||||
|  |                 dst[j] += prev[j] & -!dst[j]; | ||||||
|  |  | ||||||
|  |             prev += prev_pic->linesize[0]; | ||||||
|  |             dst  += pic->linesize[0]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* Release the previous buffer if need be */ | ||||||
|  |     if (prev_pic->data[0]) | ||||||
|  |         avctx->release_buffer(avctx, prev_pic); | ||||||
|  |  | ||||||
|  |     /* Store the previouse frame for use later */ | ||||||
|  |     *prev_pic = *pic; | ||||||
|  |  | ||||||
|  |     *data_size = sizeof(AVFrame); | ||||||
|  |     *(AVFrame *)data = *pic; | ||||||
|  |  | ||||||
|  |     return avpkt->size; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static av_cold int zerocodec_decode_close(AVCodecContext *avctx) | ||||||
|  | { | ||||||
|  |     ZeroCodecContext *zc = avctx->priv_data; | ||||||
|  |     AVFrame *prev_pic    = &zc->previous_frame; | ||||||
|  |  | ||||||
|  |     inflateEnd(&zc->zstream); | ||||||
|  |  | ||||||
|  |     /* Release last frame */ | ||||||
|  |     if (prev_pic->data[0]) | ||||||
|  |         avctx->release_buffer(avctx, prev_pic); | ||||||
|  |  | ||||||
|  |     av_freep(&avctx->coded_frame); | ||||||
|  |  | ||||||
|  |     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             = PIX_FMT_UYVY422; | ||||||
|  |     avctx->bits_per_raw_sample = 8; | ||||||
|  |  | ||||||
|  |     zc->size = avpicture_get_size(avctx->pix_fmt, | ||||||
|  |                                   avctx->width, avctx->height); | ||||||
|  |  | ||||||
|  |     zstream->zalloc = Z_NULL; | ||||||
|  |     zstream->zfree  = Z_NULL; | ||||||
|  |     zstream->opaque = Z_NULL; | ||||||
|  |  | ||||||
|  |     zret = inflateInit(zstream); | ||||||
|  |  | ||||||
|  |     if (zret != Z_OK) { | ||||||
|  |         av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d\n", zret); | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     avctx->coded_frame = avcodec_alloc_frame(); | ||||||
|  |  | ||||||
|  |     if (!avctx->coded_frame) { | ||||||
|  |         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame buffer.\n"); | ||||||
|  |         zerocodec_decode_close(avctx); | ||||||
|  |         return AVERROR(ENOMEM); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AVCodec ff_zerocodec_decoder = { | ||||||
|  |     .type           = AVMEDIA_TYPE_VIDEO, | ||||||
|  |     .name           = "zerocodec", | ||||||
|  |     .id             = CODEC_ID_ZEROCODEC, | ||||||
|  |     .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"), | ||||||
|  | }; | ||||||
| @@ -298,6 +298,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { | |||||||
|     { CODEC_ID_VBLE,         MKTAG('V', 'B', 'L', 'E') }, |     { CODEC_ID_VBLE,         MKTAG('V', 'B', 'L', 'E') }, | ||||||
|     { CODEC_ID_ESCAPE130,    MKTAG('E', '1', '3', '0') }, |     { CODEC_ID_ESCAPE130,    MKTAG('E', '1', '3', '0') }, | ||||||
|     { CODEC_ID_DXTORY,       MKTAG('x', 't', 'o', 'r') }, |     { CODEC_ID_DXTORY,       MKTAG('x', 't', 'o', 'r') }, | ||||||
|  |     { CODEC_ID_ZEROCODEC,    MKTAG('Z', 'E', 'C', 'O') }, | ||||||
|     { CODEC_ID_Y41P,         MKTAG('Y', '4', '1', 'P') }, |     { CODEC_ID_Y41P,         MKTAG('Y', '4', '1', 'P') }, | ||||||
|     { CODEC_ID_NONE,         0 } |     { CODEC_ID_NONE,         0 } | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user