1/* 2 * Sunplus JPEG decoder (SP5X) 3 * Copyright (c) 2003 Alex Beregszaszi 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Sunplus JPEG decoder (SP5X). 25 */ 26 27#include "avcodec.h" 28#include "mjpeg.h" 29#include "mjpegdec.h" 30#include "sp5x.h" 31 32 33static int sp5x_decode_frame(AVCodecContext *avctx, 34 void *data, int *data_size, 35 AVPacket *avpkt) 36{ 37 const uint8_t *buf = avpkt->data; 38 int buf_size = avpkt->size; 39 AVPacket avpkt_recoded; 40#if 0 41 MJpegDecodeContext *s = avctx->priv_data; 42#endif 43 const int qscale = 5; 44 const uint8_t *buf_ptr; 45 uint8_t *recoded; 46 int i = 0, j = 0; 47 48 if (!avctx->width || !avctx->height) 49 return -1; 50 51 buf_ptr = buf; 52 53#if 1 54 recoded = av_mallocz(buf_size + 1024); 55 if (!recoded) 56 return -1; 57 58 /* SOI */ 59 recoded[j++] = 0xFF; 60 recoded[j++] = 0xD8; 61 62 memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); 63 memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); 64 memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); 65 j += sizeof(sp5x_data_dqt); 66 67 memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); 68 j += sizeof(sp5x_data_dht); 69 70 memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); 71 AV_WB16(recoded+j+5, avctx->coded_height); 72 AV_WB16(recoded+j+7, avctx->coded_width); 73 j += sizeof(sp5x_data_sof); 74 75 memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); 76 j += sizeof(sp5x_data_sos); 77 78 if(avctx->codec_id==CODEC_ID_AMV) 79 for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++) 80 recoded[j++] = buf[i]; 81 else 82 for (i = 14; i < buf_size && j < buf_size+1024-2; i++) 83 { 84 recoded[j++] = buf[i]; 85 if (buf[i] == 0xff) 86 recoded[j++] = 0; 87 } 88 89 /* EOI */ 90 recoded[j++] = 0xFF; 91 recoded[j++] = 0xD9; 92 93 avctx->flags &= ~CODEC_FLAG_EMU_EDGE; 94 av_init_packet(&avpkt_recoded); 95 avpkt_recoded.data = recoded; 96 avpkt_recoded.size = j; 97 i = ff_mjpeg_decode_frame(avctx, data, data_size, &avpkt_recoded); 98 99 av_free(recoded); 100 101#else 102 /* SOF */ 103 s->bits = 8; 104 s->width = avctx->coded_width; 105 s->height = avctx->coded_height; 106 s->nb_components = 3; 107 s->component_id[0] = 0; 108 s->h_count[0] = 2; 109 s->v_count[0] = 2; 110 s->quant_index[0] = 0; 111 s->component_id[1] = 1; 112 s->h_count[1] = 1; 113 s->v_count[1] = 1; 114 s->quant_index[1] = 1; 115 s->component_id[2] = 2; 116 s->h_count[2] = 1; 117 s->v_count[2] = 1; 118 s->quant_index[2] = 1; 119 s->h_max = 2; 120 s->v_max = 2; 121 122 s->qscale_table = av_mallocz((s->width+15)/16); 123 avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420; 124 s->interlaced = 0; 125 126 s->picture.reference = 0; 127 if (avctx->get_buffer(avctx, &s->picture) < 0) 128 { 129 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 130 return -1; 131 } 132 133 s->picture.pict_type = FF_I_TYPE; 134 s->picture.key_frame = 1; 135 136 for (i = 0; i < 3; i++) 137 s->linesize[i] = s->picture.linesize[i] << s->interlaced; 138 139 /* DQT */ 140 for (i = 0; i < 64; i++) 141 { 142 j = s->scantable.permutated[i]; 143 s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i]; 144 } 145 s->qscale[0] = FFMAX( 146 s->quant_matrixes[0][s->scantable.permutated[1]], 147 s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1; 148 149 for (i = 0; i < 64; i++) 150 { 151 j = s->scantable.permutated[i]; 152 s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i]; 153 } 154 s->qscale[1] = FFMAX( 155 s->quant_matrixes[1][s->scantable.permutated[1]], 156 s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1; 157 158 /* DHT */ 159 160 /* SOS */ 161 s->comp_index[0] = 0; 162 s->nb_blocks[0] = s->h_count[0] * s->v_count[0]; 163 s->h_scount[0] = s->h_count[0]; 164 s->v_scount[0] = s->v_count[0]; 165 s->dc_index[0] = 0; 166 s->ac_index[0] = 0; 167 168 s->comp_index[1] = 1; 169 s->nb_blocks[1] = s->h_count[1] * s->v_count[1]; 170 s->h_scount[1] = s->h_count[1]; 171 s->v_scount[1] = s->v_count[1]; 172 s->dc_index[1] = 1; 173 s->ac_index[1] = 1; 174 175 s->comp_index[2] = 2; 176 s->nb_blocks[2] = s->h_count[2] * s->v_count[2]; 177 s->h_scount[2] = s->h_count[2]; 178 s->v_scount[2] = s->v_count[2]; 179 s->dc_index[2] = 1; 180 s->ac_index[2] = 1; 181 182 for (i = 0; i < 3; i++) 183 s->last_dc[i] = 1024; 184 185 s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8); 186 s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8); 187 188 init_get_bits(&s->gb, buf+14, (buf_size-14)*8); 189 190 return mjpeg_decode_scan(s); 191#endif 192 193 return i; 194} 195 196AVCodec sp5x_decoder = { 197 "sp5x", 198 AVMEDIA_TYPE_VIDEO, 199 CODEC_ID_SP5X, 200 sizeof(MJpegDecodeContext), 201 ff_mjpeg_decode_init, 202 NULL, 203 ff_mjpeg_decode_end, 204 sp5x_decode_frame, 205 CODEC_CAP_DR1, 206 NULL, 207 .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), 208}; 209 210AVCodec amv_decoder = { 211 "amv", 212 AVMEDIA_TYPE_VIDEO, 213 CODEC_ID_AMV, 214 sizeof(MJpegDecodeContext), 215 ff_mjpeg_decode_init, 216 NULL, 217 ff_mjpeg_decode_end, 218 sp5x_decode_frame, 219 CODEC_CAP_DR1, 220 .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), 221}; 222