Libav
|
00001 /* 00002 * Sunplus JPEG decoder (SP5X) 00003 * Copyright (c) 2003 Alex Beregszaszi 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 #if 0 00041 MJpegDecodeContext *s = avctx->priv_data; 00042 #endif 00043 const int qscale = 5; 00044 const uint8_t *buf_ptr; 00045 uint8_t *recoded; 00046 int i = 0, j = 0; 00047 00048 if (!avctx->width || !avctx->height) 00049 return -1; 00050 00051 buf_ptr = buf; 00052 00053 #if 1 00054 recoded = av_mallocz(buf_size + 1024); 00055 if (!recoded) 00056 return -1; 00057 00058 /* SOI */ 00059 recoded[j++] = 0xFF; 00060 recoded[j++] = 0xD8; 00061 00062 memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); 00063 memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); 00064 memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); 00065 j += sizeof(sp5x_data_dqt); 00066 00067 memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); 00068 j += sizeof(sp5x_data_dht); 00069 00070 memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); 00071 AV_WB16(recoded+j+5, avctx->coded_height); 00072 AV_WB16(recoded+j+7, avctx->coded_width); 00073 j += sizeof(sp5x_data_sof); 00074 00075 memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); 00076 j += sizeof(sp5x_data_sos); 00077 00078 if(avctx->codec_id==CODEC_ID_AMV) 00079 for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++) 00080 recoded[j++] = buf[i]; 00081 else 00082 for (i = 14; i < buf_size && j < buf_size+1024-2; i++) 00083 { 00084 recoded[j++] = buf[i]; 00085 if (buf[i] == 0xff) 00086 recoded[j++] = 0; 00087 } 00088 00089 /* EOI */ 00090 recoded[j++] = 0xFF; 00091 recoded[j++] = 0xD9; 00092 00093 avctx->flags &= ~CODEC_FLAG_EMU_EDGE; 00094 av_init_packet(&avpkt_recoded); 00095 avpkt_recoded.data = recoded; 00096 avpkt_recoded.size = j; 00097 i = ff_mjpeg_decode_frame(avctx, data, data_size, &avpkt_recoded); 00098 00099 av_free(recoded); 00100 00101 #else 00102 /* SOF */ 00103 s->bits = 8; 00104 s->width = avctx->coded_width; 00105 s->height = avctx->coded_height; 00106 s->nb_components = 3; 00107 s->component_id[0] = 0; 00108 s->h_count[0] = 2; 00109 s->v_count[0] = 2; 00110 s->quant_index[0] = 0; 00111 s->component_id[1] = 1; 00112 s->h_count[1] = 1; 00113 s->v_count[1] = 1; 00114 s->quant_index[1] = 1; 00115 s->component_id[2] = 2; 00116 s->h_count[2] = 1; 00117 s->v_count[2] = 1; 00118 s->quant_index[2] = 1; 00119 s->h_max = 2; 00120 s->v_max = 2; 00121 00122 s->qscale_table = av_mallocz((s->width+15)/16); 00123 avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420; 00124 s->interlaced = 0; 00125 00126 s->picture.reference = 0; 00127 if (avctx->get_buffer(avctx, &s->picture) < 0) 00128 { 00129 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00130 return -1; 00131 } 00132 00133 s->picture.pict_type = FF_I_TYPE; 00134 s->picture.key_frame = 1; 00135 00136 for (i = 0; i < 3; i++) 00137 s->linesize[i] = s->picture.linesize[i] << s->interlaced; 00138 00139 /* DQT */ 00140 for (i = 0; i < 64; i++) 00141 { 00142 j = s->scantable.permutated[i]; 00143 s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i]; 00144 } 00145 s->qscale[0] = FFMAX( 00146 s->quant_matrixes[0][s->scantable.permutated[1]], 00147 s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1; 00148 00149 for (i = 0; i < 64; i++) 00150 { 00151 j = s->scantable.permutated[i]; 00152 s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i]; 00153 } 00154 s->qscale[1] = FFMAX( 00155 s->quant_matrixes[1][s->scantable.permutated[1]], 00156 s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1; 00157 00158 /* DHT */ 00159 00160 /* SOS */ 00161 s->comp_index[0] = 0; 00162 s->nb_blocks[0] = s->h_count[0] * s->v_count[0]; 00163 s->h_scount[0] = s->h_count[0]; 00164 s->v_scount[0] = s->v_count[0]; 00165 s->dc_index[0] = 0; 00166 s->ac_index[0] = 0; 00167 00168 s->comp_index[1] = 1; 00169 s->nb_blocks[1] = s->h_count[1] * s->v_count[1]; 00170 s->h_scount[1] = s->h_count[1]; 00171 s->v_scount[1] = s->v_count[1]; 00172 s->dc_index[1] = 1; 00173 s->ac_index[1] = 1; 00174 00175 s->comp_index[2] = 2; 00176 s->nb_blocks[2] = s->h_count[2] * s->v_count[2]; 00177 s->h_scount[2] = s->h_count[2]; 00178 s->v_scount[2] = s->v_count[2]; 00179 s->dc_index[2] = 1; 00180 s->ac_index[2] = 1; 00181 00182 for (i = 0; i < 3; i++) 00183 s->last_dc[i] = 1024; 00184 00185 s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8); 00186 s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8); 00187 00188 init_get_bits(&s->gb, buf+14, (buf_size-14)*8); 00189 00190 return mjpeg_decode_scan(s); 00191 #endif 00192 00193 return i; 00194 } 00195 00196 AVCodec sp5x_decoder = { 00197 "sp5x", 00198 AVMEDIA_TYPE_VIDEO, 00199 CODEC_ID_SP5X, 00200 sizeof(MJpegDecodeContext), 00201 ff_mjpeg_decode_init, 00202 NULL, 00203 ff_mjpeg_decode_end, 00204 sp5x_decode_frame, 00205 CODEC_CAP_DR1, 00206 NULL, 00207 .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), 00208 }; 00209 00210 AVCodec amv_decoder = { 00211 "amv", 00212 AVMEDIA_TYPE_VIDEO, 00213 CODEC_ID_AMV, 00214 sizeof(MJpegDecodeContext), 00215 ff_mjpeg_decode_init, 00216 NULL, 00217 ff_mjpeg_decode_end, 00218 sp5x_decode_frame, 00219 CODEC_CAP_DR1, 00220 .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), 00221 };