00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avcodec.h"
00022 #include "bytestream.h"
00023 #include "pnm.h"
00024
00025
00026 static int common_init(AVCodecContext *avctx){
00027 PNMContext *s = avctx->priv_data;
00028
00029 avcodec_get_frame_defaults((AVFrame*)&s->picture);
00030 avctx->coded_frame= (AVFrame*)&s->picture;
00031
00032 return 0;
00033 }
00034
00035 static int pnm_decode_frame(AVCodecContext *avctx,
00036 void *data, int *data_size,
00037 const uint8_t *buf, int buf_size)
00038 {
00039 PNMContext * const s = avctx->priv_data;
00040 AVFrame *picture = data;
00041 AVFrame * const p= (AVFrame*)&s->picture;
00042 int i, n, linesize, h, upgrade = 0;
00043 unsigned char *ptr;
00044
00045 s->bytestream_start=
00046 s->bytestream= buf;
00047 s->bytestream_end= buf + buf_size;
00048
00049 if(ff_pnm_decode_header(avctx, s) < 0)
00050 return -1;
00051
00052 if(p->data[0])
00053 avctx->release_buffer(avctx, p);
00054
00055 p->reference= 0;
00056 if(avctx->get_buffer(avctx, p) < 0){
00057 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00058 return -1;
00059 }
00060 p->pict_type= FF_I_TYPE;
00061 p->key_frame= 1;
00062
00063 switch(avctx->pix_fmt) {
00064 default:
00065 return -1;
00066 case PIX_FMT_RGB24:
00067 n = avctx->width * 3;
00068 goto do_read;
00069 case PIX_FMT_GRAY8:
00070 n = avctx->width;
00071 if (s->maxval < 255)
00072 upgrade = 1;
00073 goto do_read;
00074 case PIX_FMT_GRAY16BE:
00075 case PIX_FMT_GRAY16LE:
00076 n = avctx->width * 2;
00077 if (s->maxval < 65535)
00078 upgrade = 2;
00079 goto do_read;
00080 case PIX_FMT_MONOWHITE:
00081 case PIX_FMT_MONOBLACK:
00082 n = (avctx->width + 7) >> 3;
00083 do_read:
00084 ptr = p->data[0];
00085 linesize = p->linesize[0];
00086 if(s->bytestream + n*avctx->height > s->bytestream_end)
00087 return -1;
00088 for(i = 0; i < avctx->height; i++) {
00089 if (!upgrade)
00090 memcpy(ptr, s->bytestream, n);
00091 else if (upgrade == 1) {
00092 unsigned int j, f = (255*128 + s->maxval/2) / s->maxval;
00093 for (j=0; j<n; j++)
00094 ptr[j] = (s->bytestream[j] * f + 64) >> 7;
00095 } else if (upgrade == 2) {
00096 unsigned int j, v, f = (65535*32768 + s->maxval/2) / s->maxval;
00097 for (j=0; j<n/2; j++) {
00098 v = be2me_16(((uint16_t *)s->bytestream)[j]);
00099 ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
00100 }
00101 }
00102 s->bytestream += n;
00103 ptr += linesize;
00104 }
00105 break;
00106 case PIX_FMT_YUV420P:
00107 {
00108 unsigned char *ptr1, *ptr2;
00109
00110 n = avctx->width;
00111 ptr = p->data[0];
00112 linesize = p->linesize[0];
00113 if(s->bytestream + n*avctx->height*3/2 > s->bytestream_end)
00114 return -1;
00115 for(i = 0; i < avctx->height; i++) {
00116 memcpy(ptr, s->bytestream, n);
00117 s->bytestream += n;
00118 ptr += linesize;
00119 }
00120 ptr1 = p->data[1];
00121 ptr2 = p->data[2];
00122 n >>= 1;
00123 h = avctx->height >> 1;
00124 for(i = 0; i < h; i++) {
00125 memcpy(ptr1, s->bytestream, n);
00126 s->bytestream += n;
00127 memcpy(ptr2, s->bytestream, n);
00128 s->bytestream += n;
00129 ptr1 += p->linesize[1];
00130 ptr2 += p->linesize[2];
00131 }
00132 }
00133 break;
00134 case PIX_FMT_RGB32:
00135 ptr = p->data[0];
00136 linesize = p->linesize[0];
00137 if(s->bytestream + avctx->width*avctx->height*4 > s->bytestream_end)
00138 return -1;
00139 for(i = 0; i < avctx->height; i++) {
00140 int j, r, g, b, a;
00141
00142 for(j = 0;j < avctx->width; j++) {
00143 r = *s->bytestream++;
00144 g = *s->bytestream++;
00145 b = *s->bytestream++;
00146 a = *s->bytestream++;
00147 ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
00148 }
00149 ptr += linesize;
00150 }
00151 break;
00152 }
00153 *picture= *(AVFrame*)&s->picture;
00154 *data_size = sizeof(AVPicture);
00155
00156 return s->bytestream - s->bytestream_start;
00157 }
00158
00159 static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
00160 PNMContext *s = avctx->priv_data;
00161 AVFrame *pict = data;
00162 AVFrame * const p= (AVFrame*)&s->picture;
00163 int i, h, h1, c, n, linesize;
00164 uint8_t *ptr, *ptr1, *ptr2;
00165
00166 if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
00167 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
00168 return -1;
00169 }
00170
00171 *p = *pict;
00172 p->pict_type= FF_I_TYPE;
00173 p->key_frame= 1;
00174
00175 s->bytestream_start=
00176 s->bytestream= outbuf;
00177 s->bytestream_end= outbuf+buf_size;
00178
00179 h = avctx->height;
00180 h1 = h;
00181 switch(avctx->pix_fmt) {
00182 case PIX_FMT_MONOWHITE:
00183 c = '4';
00184 n = (avctx->width + 7) >> 3;
00185 break;
00186 case PIX_FMT_GRAY8:
00187 c = '5';
00188 n = avctx->width;
00189 break;
00190 case PIX_FMT_GRAY16BE:
00191 c = '5';
00192 n = avctx->width * 2;
00193 break;
00194 case PIX_FMT_RGB24:
00195 c = '6';
00196 n = avctx->width * 3;
00197 break;
00198 case PIX_FMT_YUV420P:
00199 c = '5';
00200 n = avctx->width;
00201 h1 = (h * 3) / 2;
00202 break;
00203 default:
00204 return -1;
00205 }
00206 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00207 "P%c\n%d %d\n",
00208 c, avctx->width, h1);
00209 s->bytestream += strlen(s->bytestream);
00210 if (avctx->pix_fmt != PIX_FMT_MONOWHITE) {
00211 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00212 "%d\n", (avctx->pix_fmt != PIX_FMT_GRAY16BE) ? 255 : 65535);
00213 s->bytestream += strlen(s->bytestream);
00214 }
00215
00216 ptr = p->data[0];
00217 linesize = p->linesize[0];
00218 for(i=0;i<h;i++) {
00219 memcpy(s->bytestream, ptr, n);
00220 s->bytestream += n;
00221 ptr += linesize;
00222 }
00223
00224 if (avctx->pix_fmt == PIX_FMT_YUV420P) {
00225 h >>= 1;
00226 n >>= 1;
00227 ptr1 = p->data[1];
00228 ptr2 = p->data[2];
00229 for(i=0;i<h;i++) {
00230 memcpy(s->bytestream, ptr1, n);
00231 s->bytestream += n;
00232 memcpy(s->bytestream, ptr2, n);
00233 s->bytestream += n;
00234 ptr1 += p->linesize[1];
00235 ptr2 += p->linesize[2];
00236 }
00237 }
00238 return s->bytestream - s->bytestream_start;
00239 }
00240
00241 static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int buf_size, void *data){
00242 PNMContext *s = avctx->priv_data;
00243 AVFrame *pict = data;
00244 AVFrame * const p= (AVFrame*)&s->picture;
00245 int i, h, w, n, linesize, depth, maxval;
00246 const char *tuple_type;
00247 uint8_t *ptr;
00248
00249 if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){
00250 av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n");
00251 return -1;
00252 }
00253
00254 *p = *pict;
00255 p->pict_type= FF_I_TYPE;
00256 p->key_frame= 1;
00257
00258 s->bytestream_start=
00259 s->bytestream= outbuf;
00260 s->bytestream_end= outbuf+buf_size;
00261
00262 h = avctx->height;
00263 w = avctx->width;
00264 switch(avctx->pix_fmt) {
00265 case PIX_FMT_MONOWHITE:
00266 n = (w + 7) >> 3;
00267 depth = 1;
00268 maxval = 1;
00269 tuple_type = "BLACKANDWHITE";
00270 break;
00271 case PIX_FMT_GRAY8:
00272 n = w;
00273 depth = 1;
00274 maxval = 255;
00275 tuple_type = "GRAYSCALE";
00276 break;
00277 case PIX_FMT_RGB24:
00278 n = w * 3;
00279 depth = 3;
00280 maxval = 255;
00281 tuple_type = "RGB";
00282 break;
00283 case PIX_FMT_RGB32:
00284 n = w * 4;
00285 depth = 4;
00286 maxval = 255;
00287 tuple_type = "RGB_ALPHA";
00288 break;
00289 default:
00290 return -1;
00291 }
00292 snprintf(s->bytestream, s->bytestream_end - s->bytestream,
00293 "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
00294 w, h, depth, maxval, tuple_type);
00295 s->bytestream += strlen(s->bytestream);
00296
00297 ptr = p->data[0];
00298 linesize = p->linesize[0];
00299
00300 if (avctx->pix_fmt == PIX_FMT_RGB32) {
00301 int j;
00302 unsigned int v;
00303
00304 for(i=0;i<h;i++) {
00305 for(j=0;j<w;j++) {
00306 v = ((uint32_t *)ptr)[j];
00307 bytestream_put_be24(&s->bytestream, v);
00308 *s->bytestream++ = v >> 24;
00309 }
00310 ptr += linesize;
00311 }
00312 } else {
00313 for(i=0;i<h;i++) {
00314 memcpy(s->bytestream, ptr, n);
00315 s->bytestream += n;
00316 ptr += linesize;
00317 }
00318 }
00319 return s->bytestream - s->bytestream_start;
00320 }
00321
00322 #if 0
00323 static int pnm_probe(AVProbeData *pd)
00324 {
00325 const char *p = pd->buf;
00326 if (pd->buf_size >= 8 &&
00327 p[0] == 'P' &&
00328 p[1] >= '4' && p[1] <= '6' &&
00329 pnm_space(p[2]) )
00330 return AVPROBE_SCORE_MAX - 1;
00331 else
00332 return 0;
00333 }
00334
00335 static int pgmyuv_probe(AVProbeData *pd)
00336 {
00337 if (match_ext(pd->filename, "pgmyuv"))
00338 return AVPROBE_SCORE_MAX;
00339 else
00340 return 0;
00341 }
00342
00343 static int pam_probe(AVProbeData *pd)
00344 {
00345 const char *p = pd->buf;
00346 if (pd->buf_size >= 8 &&
00347 p[0] == 'P' &&
00348 p[1] == '7' &&
00349 p[2] == '\n')
00350 return AVPROBE_SCORE_MAX;
00351 else
00352 return 0;
00353 }
00354 #endif
00355
00356
00357 #ifdef CONFIG_PGM_ENCODER
00358 AVCodec pgm_encoder = {
00359 "pgm",
00360 CODEC_TYPE_VIDEO,
00361 CODEC_ID_PGM,
00362 sizeof(PNMContext),
00363 common_init,
00364 pnm_encode_frame,
00365 NULL,
00366 pnm_decode_frame,
00367 .pix_fmts= (enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, -1},
00368 };
00369 #endif // CONFIG_PGM_ENCODER
00370
00371 #ifdef CONFIG_PGMYUV_ENCODER
00372 AVCodec pgmyuv_encoder = {
00373 "pgmyuv",
00374 CODEC_TYPE_VIDEO,
00375 CODEC_ID_PGMYUV,
00376 sizeof(PNMContext),
00377 common_init,
00378 pnm_encode_frame,
00379 NULL,
00380 pnm_decode_frame,
00381 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, -1},
00382 };
00383 #endif // CONFIG_PGMYUV_ENCODER
00384
00385 #ifdef CONFIG_PPM_ENCODER
00386 AVCodec ppm_encoder = {
00387 "ppm",
00388 CODEC_TYPE_VIDEO,
00389 CODEC_ID_PPM,
00390 sizeof(PNMContext),
00391 common_init,
00392 pnm_encode_frame,
00393 NULL,
00394 pnm_decode_frame,
00395 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, -1},
00396 };
00397 #endif // CONFIG_PPM_ENCODER
00398
00399 #ifdef CONFIG_PBM_ENCODER
00400 AVCodec pbm_encoder = {
00401 "pbm",
00402 CODEC_TYPE_VIDEO,
00403 CODEC_ID_PBM,
00404 sizeof(PNMContext),
00405 common_init,
00406 pnm_encode_frame,
00407 NULL,
00408 pnm_decode_frame,
00409 .pix_fmts= (enum PixelFormat[]){PIX_FMT_MONOWHITE, -1},
00410 };
00411 #endif // CONFIG_PBM_ENCODER
00412
00413 #ifdef CONFIG_PAM_ENCODER
00414 AVCodec pam_encoder = {
00415 "pam",
00416 CODEC_TYPE_VIDEO,
00417 CODEC_ID_PAM,
00418 sizeof(PNMContext),
00419 common_init,
00420 pam_encode_frame,
00421 NULL,
00422 pnm_decode_frame,
00423 .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, -1},
00424 };
00425 #endif // CONFIG_PAM_ENCODER