Libav 0.7.1
|
00001 /* 00002 * Sunplus JPEG decoder (SP5X) 00003 * Copyright (c) 2003 Alex Beregszaszi 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include "avcodec.h" 00028 #include "mjpeg.h" 00029 #include "mjpegdec.h" 00030 #include "sp5x.h" 00031 00032 00033 static int sp5x_decode_frame(AVCodecContext *avctx, 00034 void *data, int *data_size, 00035 AVPacket *avpkt) 00036 { 00037 const uint8_t *buf = avpkt->data; 00038 int buf_size = avpkt->size; 00039 AVPacket avpkt_recoded; 00040 const int qscale = 5; 00041 uint8_t *recoded; 00042 int i = 0, j = 0; 00043 00044 if (!avctx->width || !avctx->height) 00045 return -1; 00046 00047 recoded = av_mallocz(buf_size + 1024); 00048 if (!recoded) 00049 return -1; 00050 00051 /* SOI */ 00052 recoded[j++] = 0xFF; 00053 recoded[j++] = 0xD8; 00054 00055 memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); 00056 memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); 00057 memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); 00058 j += sizeof(sp5x_data_dqt); 00059 00060 memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); 00061 j += sizeof(sp5x_data_dht); 00062 00063 memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); 00064 AV_WB16(recoded+j+5, avctx->coded_height); 00065 AV_WB16(recoded+j+7, avctx->coded_width); 00066 j += sizeof(sp5x_data_sof); 00067 00068 memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); 00069 j += sizeof(sp5x_data_sos); 00070 00071 if(avctx->codec_id==CODEC_ID_AMV) 00072 for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++) 00073 recoded[j++] = buf[i]; 00074 else 00075 for (i = 14; i < buf_size && j < buf_size+1024-2; i++) 00076 { 00077 recoded[j++] = buf[i]; 00078 if (buf[i] == 0xff) 00079 recoded[j++] = 0; 00080 } 00081 00082 /* EOI */ 00083 recoded[j++] = 0xFF; 00084 recoded[j++] = 0xD9; 00085 00086 av_init_packet(&avpkt_recoded); 00087 avpkt_recoded.data = recoded; 00088 avpkt_recoded.size = j; 00089 i = ff_mjpeg_decode_frame(avctx, data, data_size, &avpkt_recoded); 00090 00091 av_free(recoded); 00092 00093 return i; 00094 } 00095 00096 AVCodec ff_sp5x_decoder = { 00097 "sp5x", 00098 AVMEDIA_TYPE_VIDEO, 00099 CODEC_ID_SP5X, 00100 sizeof(MJpegDecodeContext), 00101 ff_mjpeg_decode_init, 00102 NULL, 00103 ff_mjpeg_decode_end, 00104 sp5x_decode_frame, 00105 CODEC_CAP_DR1, 00106 NULL, 00107 .max_lowres = 3, 00108 .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), 00109 }; 00110 00111 AVCodec ff_amv_decoder = { 00112 "amv", 00113 AVMEDIA_TYPE_VIDEO, 00114 CODEC_ID_AMV, 00115 sizeof(MJpegDecodeContext), 00116 ff_mjpeg_decode_init, 00117 NULL, 00118 ff_mjpeg_decode_end, 00119 sp5x_decode_frame, 00120 0, 00121 .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), 00122 };