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 av_init_packet(&avpkt_recoded); 00094 avpkt_recoded.data = recoded; 00095 avpkt_recoded.size = j; 00096 i = ff_mjpeg_decode_frame(avctx, data, data_size, &avpkt_recoded); 00097 00098 av_free(recoded); 00099 00100 #else 00101 /* SOF */ 00102 s->bits = 8; 00103 s->width = avctx->coded_width; 00104 s->height = avctx->coded_height; 00105 s->nb_components = 3; 00106 s->component_id[0] = 0; 00107 s->h_count[0] = 2; 00108 s->v_count[0] = 2; 00109 s->quant_index[0] = 0; 00110 s->component_id[1] = 1; 00111 s->h_count[1] = 1; 00112 s->v_count[1] = 1; 00113 s->quant_index[1] = 1; 00114 s->component_id[2] = 2; 00115 s->h_count[2] = 1; 00116 s->v_count[2] = 1; 00117 s->quant_index[2] = 1; 00118 s->h_max = 2; 00119 s->v_max = 2; 00120 00121 s->qscale_table = av_mallocz((s->width+15)/16); 00122 avctx->pix_fmt = s->cs_itu601 ? PIX_FMT_YUV420P : PIX_FMT_YUVJ420; 00123 s->interlaced = 0; 00124 00125 s->picture.reference = 0; 00126 if (avctx->get_buffer(avctx, &s->picture) < 0) 00127 { 00128 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00129 return -1; 00130 } 00131 00132 s->picture.pict_type = FF_I_TYPE; 00133 s->picture.key_frame = 1; 00134 00135 for (i = 0; i < 3; i++) 00136 s->linesize[i] = s->picture.linesize[i] << s->interlaced; 00137 00138 /* DQT */ 00139 for (i = 0; i < 64; i++) 00140 { 00141 j = s->scantable.permutated[i]; 00142 s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i]; 00143 } 00144 s->qscale[0] = FFMAX( 00145 s->quant_matrixes[0][s->scantable.permutated[1]], 00146 s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1; 00147 00148 for (i = 0; i < 64; i++) 00149 { 00150 j = s->scantable.permutated[i]; 00151 s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i]; 00152 } 00153 s->qscale[1] = FFMAX( 00154 s->quant_matrixes[1][s->scantable.permutated[1]], 00155 s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1; 00156 00157 /* DHT */ 00158 00159 /* SOS */ 00160 s->comp_index[0] = 0; 00161 s->nb_blocks[0] = s->h_count[0] * s->v_count[0]; 00162 s->h_scount[0] = s->h_count[0]; 00163 s->v_scount[0] = s->v_count[0]; 00164 s->dc_index[0] = 0; 00165 s->ac_index[0] = 0; 00166 00167 s->comp_index[1] = 1; 00168 s->nb_blocks[1] = s->h_count[1] * s->v_count[1]; 00169 s->h_scount[1] = s->h_count[1]; 00170 s->v_scount[1] = s->v_count[1]; 00171 s->dc_index[1] = 1; 00172 s->ac_index[1] = 1; 00173 00174 s->comp_index[2] = 2; 00175 s->nb_blocks[2] = s->h_count[2] * s->v_count[2]; 00176 s->h_scount[2] = s->h_count[2]; 00177 s->v_scount[2] = s->v_count[2]; 00178 s->dc_index[2] = 1; 00179 s->ac_index[2] = 1; 00180 00181 for (i = 0; i < 3; i++) 00182 s->last_dc[i] = 1024; 00183 00184 s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8); 00185 s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8); 00186 00187 init_get_bits(&s->gb, buf+14, (buf_size-14)*8); 00188 00189 return mjpeg_decode_scan(s); 00190 #endif 00191 00192 return i; 00193 } 00194 00195 AVCodec sp5x_decoder = { 00196 "sp5x", 00197 AVMEDIA_TYPE_VIDEO, 00198 CODEC_ID_SP5X, 00199 sizeof(MJpegDecodeContext), 00200 ff_mjpeg_decode_init, 00201 NULL, 00202 ff_mjpeg_decode_end, 00203 sp5x_decode_frame, 00204 CODEC_CAP_DR1, 00205 NULL, 00206 .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), 00207 }; 00208 00209 AVCodec amv_decoder = { 00210 "amv", 00211 AVMEDIA_TYPE_VIDEO, 00212 CODEC_ID_AMV, 00213 sizeof(MJpegDecodeContext), 00214 ff_mjpeg_decode_init, 00215 NULL, 00216 ff_mjpeg_decode_end, 00217 sp5x_decode_frame, 00218 0, 00219 .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), 00220 };