mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 20:42:49 +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 | ||||
| - bbox filter | ||||
| - XBM encoder | ||||
| - ZeroCodec decoder | ||||
|  | ||||
|  | ||||
| version 0.10: | ||||
|   | ||||
| @@ -244,6 +244,7 @@ Codecs: | ||||
|   xan.c                                 Mike Melanson | ||||
|   xl.c                                  Kostya Shishkov | ||||
|   xvmc.c                                Ivan Kalvachev | ||||
|   zerocodec.c                           Derek Buitenhuis | ||||
|   zmbv*                                 Kostya Shishkov | ||||
|  | ||||
| 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_vdpau_decoder_select="vc1_vdpau_decoder" | ||||
| wmv3image_decoder_select="wmv3_decoder" | ||||
| zerocodec_decoder_select="zlib" | ||||
| zlib_decoder_select="zlib" | ||||
| zlib_encoder_select="zlib" | ||||
| zmbv_decoder_select="zlib" | ||||
|   | ||||
| @@ -351,6 +351,7 @@ library: | ||||
| @item eXtended BINary text (XBIN) @tab @tab X | ||||
| @item YUV4MPEG pipe             @tab X @tab X | ||||
| @item Psygnosis YOP             @tab   @tab X | ||||
| @item ZeroCodec Lossless Video  @tab   @tab X | ||||
| @end multitable | ||||
|  | ||||
| @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_YUV4_DECODER)            += yuv4dec.o | ||||
| OBJS-$(CONFIG_YUV4_ENCODER)            += yuv4enc.o | ||||
| OBJS-$(CONFIG_ZEROCODEC_DECODER)       += zerocodec.o | ||||
| OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o | ||||
| OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o | ||||
| OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o | ||||
|   | ||||
| @@ -255,6 +255,7 @@ void avcodec_register_all(void) | ||||
|     REGISTER_ENCDEC  (Y41P, y41p); | ||||
|     REGISTER_DECODER (YOP, yop); | ||||
|     REGISTER_ENCDEC  (YUV4, yuv4); | ||||
|     REGISTER_DECODER (ZEROCODEC, zerocodec); | ||||
|     REGISTER_ENCDEC  (ZLIB, zlib); | ||||
|     REGISTER_ENCDEC  (ZMBV, zmbv); | ||||
|  | ||||
|   | ||||
| @@ -248,6 +248,7 @@ enum CodecID { | ||||
|     CODEC_ID_XWD, | ||||
|     CODEC_ID_CDXL, | ||||
|     CODEC_ID_XBM, | ||||
|     CODEC_ID_ZEROCODEC, | ||||
|     CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'), | ||||
|     CODEC_ID_ESCAPE130  = MKBETAG('E','1','3','0'), | ||||
|     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_ESCAPE130,    MKTAG('E', '1', '3', '0') }, | ||||
|     { 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_NONE,         0 } | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user