| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2016 Michael Niedermayer | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include "libavutil/intreadwrite.h" | ||
| 22 | |||
| 23 | #include "avcodec.h" | ||
| 24 | #include "codec_internal.h" | ||
| 25 | #include "decode.h" | ||
| 26 | |||
| 27 | |||
| 28 | ✗ | static av_cold int m101_decode_init(AVCodecContext *avctx) | |
| 29 | { | ||
| 30 | ✗ | if (avctx->extradata_size < 6*4) { | |
| 31 | ✗ | avpriv_request_sample(avctx, "Missing or too small extradata (size %d)", avctx->extradata_size); | |
| 32 | ✗ | return AVERROR_INVALIDDATA; | |
| 33 | } | ||
| 34 | |||
| 35 | ✗ | if (avctx->extradata[2*4] == 10) | |
| 36 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUV422P10; | |
| 37 | ✗ | else if (avctx->extradata[2*4] == 8) { | |
| 38 | ✗ | avctx->pix_fmt = AV_PIX_FMT_YUYV422; | |
| 39 | } else { | ||
| 40 | ✗ | avpriv_request_sample(avctx, "BPS %d", avctx->extradata[2*4]); | |
| 41 | ✗ | return AVERROR_INVALIDDATA; | |
| 42 | } | ||
| 43 | |||
| 44 | ✗ | return 0; | |
| 45 | } | ||
| 46 | |||
| 47 | ✗ | static int m101_decode_frame(AVCodecContext *avctx, AVFrame *frame, | |
| 48 | int *got_frame, AVPacket *avpkt) | ||
| 49 | { | ||
| 50 | ✗ | const uint8_t *buf = avpkt->data; | |
| 51 | int stride, ret; | ||
| 52 | int x, y; | ||
| 53 | ✗ | int min_stride = 2 * avctx->width; | |
| 54 | ✗ | int bits = avctx->extradata[2*4]; | |
| 55 | |||
| 56 | ✗ | stride = AV_RL32(avctx->extradata + 5*4); | |
| 57 | |||
| 58 | ✗ | if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) | |
| 59 | ✗ | min_stride = (avctx->width + 15) / 16 * 40; | |
| 60 | |||
| 61 | ✗ | if (stride < min_stride || avpkt->size < stride * (uint64_t)avctx->height) { | |
| 62 | ✗ | av_log(avctx, AV_LOG_ERROR, "stride (%d) is invalid for packet sized %d\n", | |
| 63 | stride, avpkt->size); | ||
| 64 | ✗ | return AVERROR_INVALIDDATA; | |
| 65 | } | ||
| 66 | |||
| 67 | ✗ | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
| 68 | ✗ | return ret; | |
| 69 | ✗ | if ((avctx->extradata[3*4] & 3) != 3) { | |
| 70 | ✗ | frame->flags |= AV_FRAME_FLAG_INTERLACED; | |
| 71 | ✗ | if (avctx->extradata[3*4] & 1) | |
| 72 | ✗ | frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; | |
| 73 | } | ||
| 74 | |||
| 75 | ✗ | for (y = 0; y < avctx->height; y++) { | |
| 76 | ✗ | int src_y = y; | |
| 77 | ✗ | if (frame->flags & AV_FRAME_FLAG_INTERLACED) | |
| 78 | ✗ | src_y = ((y&1) ^ !!(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST)) ? y/2 : (y/2 + avctx->height/2); | |
| 79 | ✗ | if (bits == 8) { | |
| 80 | ✗ | uint8_t *line = frame->data[0] + y*frame->linesize[0]; | |
| 81 | ✗ | memcpy(line, buf + src_y*stride, 2*avctx->width); | |
| 82 | } else { | ||
| 83 | int block; | ||
| 84 | ✗ | uint16_t *luma = (uint16_t*)&frame->data[0][y*frame->linesize[0]]; | |
| 85 | ✗ | uint16_t *cb = (uint16_t*)&frame->data[1][y*frame->linesize[1]]; | |
| 86 | ✗ | uint16_t *cr = (uint16_t*)&frame->data[2][y*frame->linesize[2]]; | |
| 87 | ✗ | for (block = 0; 16*block < avctx->width; block ++) { | |
| 88 | ✗ | const uint8_t *buf_src = buf + src_y*stride + 40*block; | |
| 89 | ✗ | for (x = 0; x < 16 && x + 16*block < avctx->width; x++) { | |
| 90 | ✗ | int xd = x + 16*block; | |
| 91 | ✗ | if (x&1) { | |
| 92 | ✗ | luma [xd] = (4*buf_src[2*x + 0]) + ((buf_src[32 + (x>>1)]>>4)&3); | |
| 93 | } else { | ||
| 94 | ✗ | luma [xd] = (4*buf_src[2*x + 0]) + (buf_src[32 + (x>>1)] &3); | |
| 95 | ✗ | cb[xd>>1] = (4*buf_src[2*x + 1]) + ((buf_src[32 + (x>>1)]>>2)&3); | |
| 96 | ✗ | cr[xd>>1] = (4*buf_src[2*x + 3]) + (buf_src[32 + (x>>1)]>>6); | |
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | ✗ | *got_frame = 1; | |
| 104 | ✗ | return avpkt->size; | |
| 105 | } | ||
| 106 | |||
| 107 | const FFCodec ff_m101_decoder = { | ||
| 108 | .p.name = "m101", | ||
| 109 | CODEC_LONG_NAME("Matrox Uncompressed SD"), | ||
| 110 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
| 111 | .p.id = AV_CODEC_ID_M101, | ||
| 112 | .init = m101_decode_init, | ||
| 113 | FF_CODEC_DECODE_CB(m101_decode_frame), | ||
| 114 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
| 115 | }; | ||
| 116 |