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 *got_frame, 35 AVPacket *avpkt) 36{ 37 const uint8_t *buf = avpkt->data; 38 int buf_size = avpkt->size; 39 AVPacket avpkt_recoded; 40 const int qscale = 5; 41 uint8_t *recoded; 42 int i = 0, j = 0; 43 44 if (!avctx->width || !avctx->height) 45 return -1; 46 47 recoded = av_mallocz(buf_size + 1024); 48 if (!recoded) 49 return -1; 50 51 /* SOI */ 52 recoded[j++] = 0xFF; 53 recoded[j++] = 0xD8; 54 55 memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); 56 memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); 57 memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); 58 j += sizeof(sp5x_data_dqt); 59 60 memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); 61 j += sizeof(sp5x_data_dht); 62 63 memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); 64 AV_WB16(recoded+j+5, avctx->coded_height); 65 AV_WB16(recoded+j+7, avctx->coded_width); 66 j += sizeof(sp5x_data_sof); 67 68 memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); 69 j += sizeof(sp5x_data_sos); 70 71 if(avctx->codec_id==AV_CODEC_ID_AMV) 72 for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++) 73 recoded[j++] = buf[i]; 74 else 75 for (i = 14; i < buf_size && j < buf_size+1024-3; i++) 76 { 77 recoded[j++] = buf[i]; 78 if (buf[i] == 0xff) 79 recoded[j++] = 0; 80 } 81 82 /* EOI */ 83 recoded[j++] = 0xFF; 84 recoded[j++] = 0xD9; 85 86 av_init_packet(&avpkt_recoded); 87 avpkt_recoded.data = recoded; 88 avpkt_recoded.size = j; 89 i = ff_mjpeg_decode_frame(avctx, data, got_frame, &avpkt_recoded); 90 91 av_free(recoded); 92 93 return i < 0 ? i : avpkt->size; 94} 95 96#if CONFIG_SP5X_DECODER 97AVCodec ff_sp5x_decoder = { 98 .name = "sp5x", 99 .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), 100 .type = AVMEDIA_TYPE_VIDEO, 101 .id = AV_CODEC_ID_SP5X, 102 .priv_data_size = sizeof(MJpegDecodeContext), 103 .init = ff_mjpeg_decode_init, 104 .close = ff_mjpeg_decode_end, 105 .decode = sp5x_decode_frame, 106 .capabilities = CODEC_CAP_DR1, 107 .max_lowres = 3, 108}; 109#endif 110#if CONFIG_AMV_DECODER 111AVCodec ff_amv_decoder = { 112 .name = "amv", 113 .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), 114 .type = AVMEDIA_TYPE_VIDEO, 115 .id = AV_CODEC_ID_AMV, 116 .priv_data_size = sizeof(MJpegDecodeContext), 117 .init = ff_mjpeg_decode_init, 118 .close = ff_mjpeg_decode_end, 119 .decode = sp5x_decode_frame, 120 .max_lowres = 3, 121}; 122#endif 123