1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Silicon Graphics RLE 8-bit video decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Peter Ross 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Silicon Graphics RLE 8-bit video decoder 25cabdff1aSopenharmony_ci * @note Data is packed in rbg323 with rle, contained in mv or mov. 26cabdff1aSopenharmony_ci * The algorithm and pixfmt are subtly different from SGI images. 27cabdff1aSopenharmony_ci */ 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavutil/common.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "avcodec.h" 32cabdff1aSopenharmony_ci#include "codec_internal.h" 33cabdff1aSopenharmony_ci#include "internal.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_cistatic av_cold int sgirle_decode_init(AVCodecContext *avctx) 36cabdff1aSopenharmony_ci{ 37cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGR8; 38cabdff1aSopenharmony_ci return 0; 39cabdff1aSopenharmony_ci} 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci/** 42cabdff1aSopenharmony_ci * Convert SGI RBG323 pixel into AV_PIX_FMT_BGR8 43cabdff1aSopenharmony_ci * SGI RGB data is packed as 8bpp, (msb)3R 2B 3G(lsb) 44cabdff1aSopenharmony_ci */ 45cabdff1aSopenharmony_ci#define RBG323_TO_BGR8(x) ((((x) << 3) & 0xC0) | \ 46cabdff1aSopenharmony_ci (((x) << 3) & 0x38) | \ 47cabdff1aSopenharmony_ci (((x) >> 5) & 7)) 48cabdff1aSopenharmony_cistatic av_always_inline 49cabdff1aSopenharmony_civoid rbg323_to_bgr8(uint8_t *dst, const uint8_t *src, int size) 50cabdff1aSopenharmony_ci{ 51cabdff1aSopenharmony_ci int i; 52cabdff1aSopenharmony_ci for (i = 0; i < size; i++) 53cabdff1aSopenharmony_ci dst[i] = RBG323_TO_BGR8(src[i]); 54cabdff1aSopenharmony_ci} 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci/** 57cabdff1aSopenharmony_ci * @param[out] dst Destination buffer 58cabdff1aSopenharmony_ci * @param[in] src Source buffer 59cabdff1aSopenharmony_ci * @param src_size Source buffer size (bytes) 60cabdff1aSopenharmony_ci * @param width Width of destination buffer (pixels) 61cabdff1aSopenharmony_ci * @param height Height of destination buffer (pixels) 62cabdff1aSopenharmony_ci * @param linesize Line size of destination buffer (bytes) 63cabdff1aSopenharmony_ci * 64cabdff1aSopenharmony_ci * @return <0 on error 65cabdff1aSopenharmony_ci */ 66cabdff1aSopenharmony_cistatic int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, 67cabdff1aSopenharmony_ci const uint8_t *src, int src_size, 68cabdff1aSopenharmony_ci int width, int height, ptrdiff_t linesize) 69cabdff1aSopenharmony_ci{ 70cabdff1aSopenharmony_ci const uint8_t *src_end = src + src_size; 71cabdff1aSopenharmony_ci int x = 0, y = 0; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci#define INC_XY(n) \ 74cabdff1aSopenharmony_ci x += n; \ 75cabdff1aSopenharmony_ci if (x >= width) { \ 76cabdff1aSopenharmony_ci y++; \ 77cabdff1aSopenharmony_ci if (y >= height) \ 78cabdff1aSopenharmony_ci return 0; \ 79cabdff1aSopenharmony_ci x = 0; \ 80cabdff1aSopenharmony_ci } 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci while (src_end - src >= 2) { 83cabdff1aSopenharmony_ci uint8_t v = *src++; 84cabdff1aSopenharmony_ci if (v > 0 && v < 0xC0) { 85cabdff1aSopenharmony_ci do { 86cabdff1aSopenharmony_ci int length = FFMIN(v, width - x); 87cabdff1aSopenharmony_ci if (length <= 0) 88cabdff1aSopenharmony_ci break; 89cabdff1aSopenharmony_ci memset(dst + y * linesize + x, RBG323_TO_BGR8(*src), length); 90cabdff1aSopenharmony_ci INC_XY(length); 91cabdff1aSopenharmony_ci v -= length; 92cabdff1aSopenharmony_ci } while (v > 0); 93cabdff1aSopenharmony_ci src++; 94cabdff1aSopenharmony_ci } else if (v >= 0xC1) { 95cabdff1aSopenharmony_ci v -= 0xC0; 96cabdff1aSopenharmony_ci do { 97cabdff1aSopenharmony_ci int length = FFMIN3(v, width - x, src_end - src); 98cabdff1aSopenharmony_ci if (src_end - src < length || length <= 0) 99cabdff1aSopenharmony_ci break; 100cabdff1aSopenharmony_ci rbg323_to_bgr8(dst + y * linesize + x, src, length); 101cabdff1aSopenharmony_ci INC_XY(length); 102cabdff1aSopenharmony_ci src += length; 103cabdff1aSopenharmony_ci v -= length; 104cabdff1aSopenharmony_ci } while (v > 0); 105cabdff1aSopenharmony_ci } else { 106cabdff1aSopenharmony_ci avpriv_request_sample(avctx, "opcode %d", v); 107cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci } 110cabdff1aSopenharmony_ci return 0; 111cabdff1aSopenharmony_ci} 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_cistatic int sgirle_decode_frame(AVCodecContext *avctx, AVFrame *frame, 114cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci int ret; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 119cabdff1aSopenharmony_ci return ret; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci ret = decode_sgirle8(avctx, frame->data[0], avpkt->data, avpkt->size, 122cabdff1aSopenharmony_ci avctx->width, avctx->height, frame->linesize[0]); 123cabdff1aSopenharmony_ci if (ret < 0) 124cabdff1aSopenharmony_ci return ret; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_I; 127cabdff1aSopenharmony_ci frame->key_frame = 1; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci *got_frame = 1; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci return avpkt->size; 132cabdff1aSopenharmony_ci} 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ciconst FFCodec ff_sgirle_decoder = { 135cabdff1aSopenharmony_ci .p.name = "sgirle", 136cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit video"), 137cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 138cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_SGIRLE, 139cabdff1aSopenharmony_ci .init = sgirle_decode_init, 140cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(sgirle_decode_frame), 141cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 142cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 143cabdff1aSopenharmony_ci}; 144