• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Unpack bit-packed streams to formats supported by FFmpeg
3  * Copyright (c) 2017 Savoir-faire Linux, Inc
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 /* Development sponsored by CBC/Radio-Canada */
23 
24 /**
25  * @file
26  * Bitpacked
27  */
28 
29 #include "avcodec.h"
30 #include "codec_internal.h"
31 #include "get_bits.h"
32 #include "libavutil/imgutils.h"
33 #include "thread.h"
34 
35 struct BitpackedContext {
36     int (*decode)(AVCodecContext *avctx, AVFrame *frame,
37                   const AVPacket *pkt);
38 };
39 
40 /* For this format, it's a simple passthrough */
bitpacked_decode_uyvy422(AVCodecContext * avctx,AVFrame * frame,const AVPacket * avpkt)41 static int bitpacked_decode_uyvy422(AVCodecContext *avctx, AVFrame *frame,
42                                     const AVPacket *avpkt)
43 {
44     int ret;
45 
46     /* there is no need to copy as the data already match
47      * a known pixel format */
48     frame->buf[0] = av_buffer_ref(avpkt->buf);
49     if (!frame->buf[0]) {
50         return AVERROR(ENOMEM);
51     }
52 
53     ret = av_image_fill_arrays(frame->data, frame->linesize, avpkt->data,
54                                avctx->pix_fmt, avctx->width, avctx->height, 1);
55     if (ret < 0) {
56         av_buffer_unref(&frame->buf[0]);
57         return ret;
58     }
59 
60     return 0;
61 }
62 
bitpacked_decode_yuv422p10(AVCodecContext * avctx,AVFrame * frame,const AVPacket * avpkt)63 static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame,
64                                       const AVPacket *avpkt)
65 {
66     uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 20;
67     uint64_t packet_size = (uint64_t)avpkt->size * 8;
68     GetBitContext bc;
69     uint16_t *y, *u, *v;
70     int ret, i, j;
71 
72     ret = ff_thread_get_buffer(avctx, frame, 0);
73     if (ret < 0)
74         return ret;
75 
76     if (frame_size > packet_size)
77         return AVERROR_INVALIDDATA;
78 
79     if (avctx->width % 2)
80         return AVERROR_PATCHWELCOME;
81 
82     ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 20);
83     if (ret)
84         return ret;
85 
86     for (i = 0; i < avctx->height; i++) {
87         y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
88         u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]);
89         v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]);
90 
91         for (j = 0; j < avctx->width; j += 2) {
92             *u++ = get_bits(&bc, 10);
93             *y++ = get_bits(&bc, 10);
94             *v++ = get_bits(&bc, 10);
95             *y++ = get_bits(&bc, 10);
96         }
97     }
98 
99     return 0;
100 }
101 
bitpacked_init_decoder(AVCodecContext * avctx)102 static av_cold int bitpacked_init_decoder(AVCodecContext *avctx)
103 {
104     struct BitpackedContext *bc = avctx->priv_data;
105 
106     if (!avctx->codec_tag || !avctx->width || !avctx->height)
107         return AVERROR_INVALIDDATA;
108 
109     if (avctx->codec_tag == MKTAG('U', 'Y', 'V', 'Y')) {
110         if (avctx->bits_per_coded_sample == 16 &&
111             avctx->pix_fmt == AV_PIX_FMT_UYVY422)
112             bc->decode = bitpacked_decode_uyvy422;
113         else if (avctx->bits_per_coded_sample == 20 &&
114                  avctx->pix_fmt == AV_PIX_FMT_YUV422P10)
115             bc->decode = bitpacked_decode_yuv422p10;
116         else
117             return AVERROR_INVALIDDATA;
118     } else {
119         return AVERROR_INVALIDDATA;
120     }
121 
122     return 0;
123 }
124 
bitpacked_decode(AVCodecContext * avctx,AVFrame * frame,int * got_frame,AVPacket * avpkt)125 static int bitpacked_decode(AVCodecContext *avctx, AVFrame *frame,
126                             int *got_frame, AVPacket *avpkt)
127 {
128     struct BitpackedContext *bc = avctx->priv_data;
129     int buf_size = avpkt->size;
130     int res;
131 
132     res = bc->decode(avctx, frame, avpkt);
133     if (res)
134         return res;
135 
136     frame->pict_type = AV_PICTURE_TYPE_I;
137     frame->key_frame = 1;
138 
139     *got_frame = 1;
140     return buf_size;
141 
142 }
143 
144 const FFCodec ff_bitpacked_decoder = {
145     .p.name          = "bitpacked",
146     .p.long_name     = NULL_IF_CONFIG_SMALL("Bitpacked"),
147     .p.type          = AVMEDIA_TYPE_VIDEO,
148     .p.id            = AV_CODEC_ID_BITPACKED,
149     .p.capabilities  = AV_CODEC_CAP_FRAME_THREADS,
150     .priv_data_size        = sizeof(struct BitpackedContext),
151     .init = bitpacked_init_decoder,
152     FF_CODEC_DECODE_CB(bitpacked_decode),
153     .codec_tags     = (const uint32_t []){
154         MKTAG('U', 'Y', 'V', 'Y'),
155         FF_CODEC_TAGS_END,
156     },
157     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
158 };
159