Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * 012v decoder
  3.  *
  4.  * Copyright (C) 2012 Carl Eugen Hoyos
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. #include "avcodec.h"
  24. #include "internal.h"
  25. #include "libavutil/intreadwrite.h"
  26.  
  27. static av_cold int zero12v_decode_init(AVCodecContext *avctx)
  28. {
  29.     avctx->pix_fmt             = AV_PIX_FMT_YUV422P16;
  30.     avctx->bits_per_raw_sample = 10;
  31.  
  32.     if (avctx->codec_tag == MKTAG('a', '1', '2', 'v'))
  33.         avpriv_request_sample(avctx, "transparency");
  34.  
  35.     return 0;
  36. }
  37.  
  38. static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
  39.                                 int *got_frame, AVPacket *avpkt)
  40. {
  41.     int line, ret;
  42.     const int width = avctx->width;
  43.     AVFrame *pic = data;
  44.     uint16_t *y, *u, *v;
  45.     const uint8_t *line_end, *src = avpkt->data;
  46.     int stride = avctx->width * 8 / 3;
  47.  
  48.     if (width <= 1 || avctx->height <= 0) {
  49.         av_log(avctx, AV_LOG_ERROR, "Dimensions %dx%d not supported.\n", width, avctx->height);
  50.         return AVERROR_INVALIDDATA;
  51.     }
  52.  
  53.     if (   avctx->codec_tag == MKTAG('0', '1', '2', 'v')
  54.         && avpkt->size % avctx->height == 0
  55.         && avpkt->size / avctx->height * 3 >= width * 8)
  56.         stride = avpkt->size / avctx->height;
  57.  
  58.     if (avpkt->size < avctx->height * stride) {
  59.         av_log(avctx, AV_LOG_ERROR, "Packet too small: %d instead of %d\n",
  60.                avpkt->size, avctx->height * stride);
  61.         return AVERROR_INVALIDDATA;
  62.     }
  63.  
  64.     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
  65.         return ret;
  66.  
  67.     pic->pict_type = AV_PICTURE_TYPE_I;
  68.     pic->key_frame = 1;
  69.  
  70.     line_end = avpkt->data + stride;
  71.     for (line = 0; line < avctx->height; line++) {
  72.         uint16_t y_temp[6] = {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000};
  73.         uint16_t u_temp[3] = {0x8000, 0x8000, 0x8000};
  74.         uint16_t v_temp[3] = {0x8000, 0x8000, 0x8000};
  75.         int x;
  76.         y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
  77.         u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
  78.         v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
  79.  
  80.         for (x = 0; x < width; x += 6) {
  81.             uint32_t t;
  82.  
  83.             if (width - x < 6 || line_end - src < 16) {
  84.                 y = y_temp;
  85.                 u = u_temp;
  86.                 v = v_temp;
  87.             }
  88.  
  89.             if (line_end - src < 4)
  90.                 break;
  91.  
  92.             t = AV_RL32(src);
  93.             src += 4;
  94.             *u++ = t <<  6 & 0xFFC0;
  95.             *y++ = t >>  4 & 0xFFC0;
  96.             *v++ = t >> 14 & 0xFFC0;
  97.  
  98.             if (line_end - src < 4)
  99.                 break;
  100.  
  101.             t = AV_RL32(src);
  102.             src += 4;
  103.             *y++ = t <<  6 & 0xFFC0;
  104.             *u++ = t >>  4 & 0xFFC0;
  105.             *y++ = t >> 14 & 0xFFC0;
  106.  
  107.             if (line_end - src < 4)
  108.                 break;
  109.  
  110.             t = AV_RL32(src);
  111.             src += 4;
  112.             *v++ = t <<  6 & 0xFFC0;
  113.             *y++ = t >>  4 & 0xFFC0;
  114.             *u++ = t >> 14 & 0xFFC0;
  115.  
  116.             if (line_end - src < 4)
  117.                 break;
  118.  
  119.             t = AV_RL32(src);
  120.             src += 4;
  121.             *y++ = t <<  6 & 0xFFC0;
  122.             *v++ = t >>  4 & 0xFFC0;
  123.             *y++ = t >> 14 & 0xFFC0;
  124.  
  125.             if (width - x < 6)
  126.                 break;
  127.         }
  128.  
  129.         if (x < width) {
  130.             y = x   + (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
  131.             u = x/2 + (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
  132.             v = x/2 + (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
  133.             memcpy(y, y_temp, sizeof(*y) * (width - x));
  134.             memcpy(u, u_temp, sizeof(*u) * (width - x + 1) / 2);
  135.             memcpy(v, v_temp, sizeof(*v) * (width - x + 1) / 2);
  136.         }
  137.  
  138.         line_end += stride;
  139.         src = line_end - stride;
  140.     }
  141.  
  142.     *got_frame = 1;
  143.  
  144.     return avpkt->size;
  145. }
  146.  
  147. AVCodec ff_zero12v_decoder = {
  148.     .name           = "012v",
  149.     .long_name      = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
  150.     .type           = AVMEDIA_TYPE_VIDEO,
  151.     .id             = AV_CODEC_ID_012V,
  152.     .init           = zero12v_decode_init,
  153.     .decode         = zero12v_decode_frame,
  154.     .capabilities   = AV_CODEC_CAP_DR1,
  155. };
  156.