Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Alias PIX image encoder
  3.  * Copyright (C) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/intreadwrite.h"
  23.  
  24. #include "avcodec.h"
  25. #include "bytestream.h"
  26. #include "internal.h"
  27.  
  28. #define ALIAS_HEADER_SIZE 10
  29.  
  30. static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
  31.                         const AVFrame *frame, int *got_packet)
  32. {
  33.     int width, height, bits_pixel, i, j, length, ret;
  34.     uint8_t *in_buf, *buf;
  35.  
  36. #if FF_API_CODED_FRAME
  37. FF_DISABLE_DEPRECATION_WARNINGS
  38.     avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
  39.     avctx->coded_frame->key_frame = 1;
  40. FF_ENABLE_DEPRECATION_WARNINGS
  41. #endif
  42.  
  43.     width  = avctx->width;
  44.     height = avctx->height;
  45.  
  46.     if (width > 65535 || height > 65535 ||
  47.         width * height >= INT_MAX / 4 - ALIAS_HEADER_SIZE) {
  48.         av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", width, height);
  49.         return AVERROR_INVALIDDATA;
  50.     }
  51.  
  52.     switch (avctx->pix_fmt) {
  53.     case AV_PIX_FMT_GRAY8:
  54.         bits_pixel = 8;
  55.         break;
  56.     case AV_PIX_FMT_BGR24:
  57.         bits_pixel = 24;
  58.         break;
  59.     default:
  60.         return AVERROR(EINVAL);
  61.     }
  62.  
  63.     length = ALIAS_HEADER_SIZE + 4 * width * height; // max possible
  64.     if ((ret = ff_alloc_packet2(avctx, pkt, length, ALIAS_HEADER_SIZE + height*2)) < 0) {
  65.         av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", length);
  66.         return ret;
  67.     }
  68.  
  69.     buf = pkt->data;
  70.  
  71.     /* Encode header. */
  72.     bytestream_put_be16(&buf, width);
  73.     bytestream_put_be16(&buf, height);
  74.     bytestream_put_be32(&buf, 0); /* X, Y offset */
  75.     bytestream_put_be16(&buf, bits_pixel);
  76.  
  77.     for (j = 0; j < height; j++) {
  78.         in_buf = frame->data[0] + frame->linesize[0] * j;
  79.         for (i = 0; i < width; ) {
  80.             int count = 0;
  81.             int pixel;
  82.  
  83.             if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
  84.                 pixel = *in_buf;
  85.                 while (count < 255 && count + i < width && pixel == *in_buf) {
  86.                     count++;
  87.                     in_buf++;
  88.                 }
  89.                 bytestream_put_byte(&buf, count);
  90.                 bytestream_put_byte(&buf, pixel);
  91.             } else { /* AV_PIX_FMT_BGR24 */
  92.                 pixel = AV_RB24(in_buf);
  93.                 while (count < 255 && count + i < width &&
  94.                        pixel == AV_RB24(in_buf)) {
  95.                     count++;
  96.                     in_buf += 3;
  97.                 }
  98.                 bytestream_put_byte(&buf, count);
  99.                 bytestream_put_be24(&buf, pixel);
  100.             }
  101.             i += count;
  102.         }
  103.     }
  104.  
  105.     /* Total length */
  106.     av_shrink_packet(pkt, buf - pkt->data);
  107.     pkt->flags |= AV_PKT_FLAG_KEY;
  108.     *got_packet = 1;
  109.  
  110.     return 0;
  111. }
  112.  
  113. AVCodec ff_alias_pix_encoder = {
  114.     .name      = "alias_pix",
  115.     .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"),
  116.     .type      = AVMEDIA_TYPE_VIDEO,
  117.     .id        = AV_CODEC_ID_ALIAS_PIX,
  118.     .encode2   = encode_frame,
  119.     .pix_fmts  = (const enum AVPixelFormat[]) {
  120.         AV_PIX_FMT_BGR24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
  121.     },
  122. };
  123.