Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6148 serge 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 = 0, 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) {
49
        av_log(avctx, AV_LOG_ERROR, "Width 1 not supported.\n");
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
    y = (uint16_t *)pic->data[0];
71
    u = (uint16_t *)pic->data[1];
72
    v = (uint16_t *)pic->data[2];
73
    line_end = avpkt->data + stride;
74
 
75
    while (line++ < avctx->height) {
76
        while (1) {
77
            uint32_t t = AV_RL32(src);
78
            src += 4;
79
            *u++ = t <<  6 & 0xFFC0;
80
            *y++ = t >>  4 & 0xFFC0;
81
            *v++ = t >> 14 & 0xFFC0;
82
 
83
            if (src >= line_end - 1) {
84
                *y = 0x80;
85
                src++;
86
                line_end += stride;
87
                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
88
                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
89
                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
90
                break;
91
            }
92
 
93
            t = AV_RL32(src);
94
            src += 4;
95
            *y++ = t <<  6 & 0xFFC0;
96
            *u++ = t >>  4 & 0xFFC0;
97
            *y++ = t >> 14 & 0xFFC0;
98
            if (src >= line_end - 2) {
99
                if (!(width & 1)) {
100
                    *y = 0x80;
101
                    src += 2;
102
                }
103
                line_end += stride;
104
                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
105
                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
106
                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
107
                break;
108
            }
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 (src >= line_end - 1) {
117
                *y = 0x80;
118
                src++;
119
                line_end += stride;
120
                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
121
                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
122
                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
123
                break;
124
            }
125
 
126
            t = AV_RL32(src);
127
            src += 4;
128
            *y++ = t <<  6 & 0xFFC0;
129
            *v++ = t >>  4 & 0xFFC0;
130
            *y++ = t >> 14 & 0xFFC0;
131
 
132
            if (src >= line_end - 2) {
133
                if (width & 1) {
134
                    *y = 0x80;
135
                    src += 2;
136
                }
137
                line_end += stride;
138
                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
139
                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
140
                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
141
                break;
142
            }
143
        }
144
    }
145
 
146
    *got_frame = 1;
147
 
148
    return avpkt->size;
149
}
150
 
151
AVCodec ff_zero12v_decoder = {
152
    .name           = "012v",
153
    .long_name      = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
154
    .type           = AVMEDIA_TYPE_VIDEO,
155
    .id             = AV_CODEC_ID_012V,
156
    .init           = zero12v_decode_init,
157
    .decode         = zero12v_decode_frame,
158
    .capabilities   = CODEC_CAP_DR1,
159
};