yading@10: /* yading@10: * Sunplus JPEG decoder (SP5X) yading@10: * Copyright (c) 2003 Alex Beregszaszi yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: /** yading@10: * @file yading@10: * Sunplus JPEG decoder (SP5X). yading@10: */ yading@10: yading@10: #include "avcodec.h" yading@10: #include "mjpeg.h" yading@10: #include "mjpegdec.h" yading@10: #include "sp5x.h" yading@10: yading@10: yading@10: static int sp5x_decode_frame(AVCodecContext *avctx, yading@10: void *data, int *got_frame, yading@10: AVPacket *avpkt) yading@10: { yading@10: const uint8_t *buf = avpkt->data; yading@10: int buf_size = avpkt->size; yading@10: AVPacket avpkt_recoded; yading@10: const int qscale = 5; yading@10: uint8_t *recoded; yading@10: int i = 0, j = 0; yading@10: yading@10: if (!avctx->width || !avctx->height) yading@10: return -1; yading@10: yading@10: recoded = av_mallocz(buf_size + 1024); yading@10: if (!recoded) yading@10: return -1; yading@10: yading@10: /* SOI */ yading@10: recoded[j++] = 0xFF; yading@10: recoded[j++] = 0xD8; yading@10: yading@10: memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); yading@10: memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); yading@10: memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); yading@10: j += sizeof(sp5x_data_dqt); yading@10: yading@10: memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); yading@10: j += sizeof(sp5x_data_dht); yading@10: yading@10: memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); yading@10: AV_WB16(recoded+j+5, avctx->coded_height); yading@10: AV_WB16(recoded+j+7, avctx->coded_width); yading@10: j += sizeof(sp5x_data_sof); yading@10: yading@10: memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); yading@10: j += sizeof(sp5x_data_sos); yading@10: yading@10: if(avctx->codec_id==AV_CODEC_ID_AMV) yading@10: for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++) yading@10: recoded[j++] = buf[i]; yading@10: else yading@10: for (i = 14; i < buf_size && j < buf_size+1024-3; i++) yading@10: { yading@10: recoded[j++] = buf[i]; yading@10: if (buf[i] == 0xff) yading@10: recoded[j++] = 0; yading@10: } yading@10: yading@10: /* EOI */ yading@10: recoded[j++] = 0xFF; yading@10: recoded[j++] = 0xD9; yading@10: yading@10: av_init_packet(&avpkt_recoded); yading@10: avpkt_recoded.data = recoded; yading@10: avpkt_recoded.size = j; yading@10: i = ff_mjpeg_decode_frame(avctx, data, got_frame, &avpkt_recoded); yading@10: yading@10: av_free(recoded); yading@10: yading@10: return i < 0 ? i : avpkt->size; yading@10: } yading@10: yading@10: #if CONFIG_SP5X_DECODER yading@10: AVCodec ff_sp5x_decoder = { yading@10: .name = "sp5x", yading@10: .type = AVMEDIA_TYPE_VIDEO, yading@10: .id = AV_CODEC_ID_SP5X, yading@10: .priv_data_size = sizeof(MJpegDecodeContext), yading@10: .init = ff_mjpeg_decode_init, yading@10: .close = ff_mjpeg_decode_end, yading@10: .decode = sp5x_decode_frame, yading@10: .capabilities = CODEC_CAP_DR1, yading@10: .max_lowres = 3, yading@10: .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), yading@10: }; yading@10: #endif yading@10: #if CONFIG_AMV_DECODER yading@10: AVCodec ff_amv_decoder = { yading@10: .name = "amv", yading@10: .type = AVMEDIA_TYPE_VIDEO, yading@10: .id = AV_CODEC_ID_AMV, yading@10: .priv_data_size = sizeof(MJpegDecodeContext), yading@10: .init = ff_mjpeg_decode_init, yading@10: .close = ff_mjpeg_decode_end, yading@10: .decode = sp5x_decode_frame, yading@10: .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), yading@10: }; yading@10: #endif