+ memcpy(&frame->data[2][sof*(lw*y + x)], &pkt->data[sof* 3*(lw*y +
x)], sof);
+ memcpy(&frame->data[0][sof*(lw*y + x)], &pkt->data[sof*(3*(lw*y +
x) + 1)], sof);
+ memcpy(&frame->data[1][sof*(lw*y + x)], &pkt->data[sof*(3*(lw*y +
x) + 2)], sof);
+ }
+ }
+ return pkt->size;
+}
+
+static int half_add_alpha(AVCodecContext *avctx, AVFrame *frame, const
AVPacket *pkt)
+{
+ /* ffmpeg doesn't provide RGB half bit depth without alpha channel right
now
+ * we simply add an opaque alpha layer as workaround */
+
+ int x, y, lw;
+ const size_t soh = 2;
+ const uint16_t opaque = 0x3c00;
+
+ lw = frame->width;
+
+ for(y = 0; y < frame->height; y++){
+ for(x = 0; x < frame->width; x++){
+ memcpy(&frame->data[0][soh*4*(lw*y + x)], &pkt->data[soh*3*(lw*y +
x)], soh*3);
+ memcpy(&frame->data[0][soh*(4*(lw*y + x) + 3)], &opaque, soh);
+ }
+ }
+ return pkt->size;
+}
+
+/* DNxUncompressed utilizes a very dense bitpack representation of 10bit and
12bit pixel data.
+
+Lines of Image data, which look like in their ordinary 8bit counterpart,
contain the most
+significant upper bits of the pixel data. These sections alternate with
shorter segments in
+which the complementary least significant bits of information get packed in a
gapless sequence.
+
++----------------------+ +----------------------+ +------------------------+
+----------~
+| 8 m.s.bits of R[1] | | 8 m.s.bits of G[1] | | 8 m.s.bits of B[1] | |
msb R[2] ... one line
++----------------------+ +----------------------+ +------------------------+
+----------~
+
++---------------------------------------------------------------+
+-----------~
+| +------------+ +------------+ +------------+ +--------------+ | | +--------~
+| | 2 lsb R[2] | | 2 lsb B[1] | | 2 lsb G[1] | | 2 lsb R[1] | | | | G[3]lsb
... LSB bits for line
+| +------------+ +------------+ +------------+ +--------------+ | | +--------~
++---------------------------- one byte ------------------------ +
+-----------~
+
+next line of MSB bytes... */
+
+static int unpack_rg10(AVCodecContext *avctx, AVFrame *frame, const AVPacket
*pkt)
+{
+ int x, y, lw, msp, pack, lsp, p_off;
+ uint16_t r,g,b;
+
+ lw = frame->width;
+
+ for(y = 0; y < frame->height; y++){
+ for(x = 0; x < frame->width; x++){
+ msp = pkt->data[y*3*(lw + lw/4) + 3*x];
+ p_off = y*(3*(lw + lw/4)) + 3*lw + 3*x/4;
+ pack = pkt->data[p_off];
+ lsp = (pack >> (3*x%4)*2) & 0x3;
+ r = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "r: %04x, %02x, %02x, %02x, %d\n",
+ // r, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*3*(lw + lw/4) + 3*x + 1];
+ p_off = y*(3*(lw + lw/4)) + 3*lw + (3*x+1)/4;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+1)%4)*2) & 0x3;
+ g = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "g: %04x, %02x, %02x, %02x, %d\n",
+ // g, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*3*(lw + lw/4) + 3*x + 2];
+ p_off = y*(3*(lw + lw/4)) + 3*lw + (3*x+2)/4;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+2)%4)*2) & 0x3;
+ b = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "b: %04x, %02x, %02x, %02x, %d\n\n",
+ // b, msp, lsp, pack, p_off);
+
+ memcpy(&frame->data[2][2*(y*lw + x)], &r, 2);
+ memcpy(&frame->data[0][2*(y*lw + x)], &g, 2);
+ memcpy(&frame->data[1][2*(y*lw + x)], &b, 2);
+ }
+ }
+ return pkt->size;
+}
+
+static int unpack_rg12(AVCodecContext *avctx, AVFrame *frame, const AVPacket
*pkt)
+{
+ int x, y, lw, msp, pack, lsp, p_off;
+ uint16_t r,g,b;
+
+ lw = frame->width;
+
+ for(y = 0; y < frame->height; y++){
+ for(x = 0; x < frame->width; x++){
+ msp = pkt->data[y*3*(lw + lw/2) + 3*x];
+ p_off = y*(3*(lw + lw/2)) + 3*lw + 3*x/2;
+ pack = pkt->data[p_off];
+ lsp = (pack >> (3*x%2)*4) & 0xf;
+ r = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "r: %04x, %02x, %02x, %02x, %d\n",
+ // r, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*3*(lw + lw/2) + 3*x + 1];
+ p_off =y*(3*(lw + lw/2)) + 3*lw + (3*x+1)/2;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+1)%2)*4) & 0xf;
+ g = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "g: %04x, %02x, %02x, %02x, %d\n",
+ // g, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*3*(lw + lw/2) + 3*x + 2];
+ p_off = y*(3*(lw + lw/2)) + 3*lw + (3*x+2)/2;
+ pack = pkt->data[p_off];
+ lsp = (pack >> ((3*x+2)%2)*4) & 0xf;
+ b = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "b: %04x, %02x, %02x, %02x, %d\n\n",
+ // b, msp, lsp, pack, p_off);
+
+ memcpy(&frame->data[2][2*(y*lw + x)], &r, 2);
+ memcpy(&frame->data[0][2*(y*lw + x)], &g, 2);
+ memcpy(&frame->data[1][2*(y*lw + x)], &b, 2);
+ }
+ }
+ return pkt->size;
+}
+
+
+static int unpack_y210(AVCodecContext *avctx, AVFrame *frame, const AVPacket
*pkt)
+{
+ int x, y, lw, msp, pack, lsp, p_off;
+ uint16_t y1, y2, u, v;
+
+ lw = frame->width;
+
+ for(y = 0; y < frame->height; y++){
+ for(x = 0; x < frame->width; x += 2){
+
+ p_off = y*(2*(lw + lw/4)) + 2*lw + x/2;
+ pack = pkt->data[p_off];
+
+ msp = pkt->data[y*2*(lw + lw/4) + 2*x];
+ lsp = pack & 0x3;
+ u = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " u: %04x, %02x, %02x, %02x, %d\n",
+ // u, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*2*(lw + lw/4) + 2*x + 1];
+ lsp = (pack >> 2) & 0x3;
+ y1 = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y1: %04x, %02x, %02x, %02x, %d\n",
+ // y1, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*2*(lw + lw/4) + 2*x + 2];
+ lsp = (pack >> 4) & 0x3;
+ v = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " v: %04x, %02x, %02x, %02x, %d\n",
+ // v, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*2*(lw + lw/4) + 2*x + 3];
+ lsp = (pack >> 6) & 0x3;
+ y2 = (msp << 2) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y2: %04x, %02x, %02x, %02x, %d\n\n",
+ // y2, msp, lsp, pack, p_off);
+
+ memcpy(&frame->data[0][2*(y*lw + x)], &y1, 2);
+ memcpy(&frame->data[0][2*(y*lw + x+1)], &y2, 2);
+ memcpy(&frame->data[1][2*(y*lw/2 + x/2)], &u, 2);
+ memcpy(&frame->data[2][2*(y*lw/2 + x/2)], &v, 2);
+ }
+ }
+ return pkt->size;
+}
+
+
+static int unpack_y212(AVCodecContext *avctx, AVFrame *frame, const AVPacket
*pkt)
+{
+ int x, y, lw, msp, pack, lsp, p_off;
+ uint16_t y1, y2, u, v;
+
+ lw = frame->width;
+
+ for(y = 0; y < frame->height; y++){
+ for(x = 0; x < frame->width; x += 2){
+
+ p_off = y*(2*(lw + lw/2)) + 2*lw + x;
+ pack = pkt->data[p_off];
+
+ msp = pkt->data[y*2*(lw + lw/2) + 2*x];
+ lsp = pack & 0xf;
+ u = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " u: %04x, %02x, %02x, %02x, %d\n",
+ // u, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*2*(lw + lw/2) + 2*x + 1];
+ lsp = (pack >> 4) & 0xf;
+ y1 = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y1: %04x, %02x, %02x, %02x, %d\n",
+ // y1, msp, lsp, pack, p_off);
+
+ p_off = y*(2*(lw + lw/2)) + 2*lw + x+1;
+ pack = pkt->data[p_off];
+
+ msp = pkt->data[y*2*(lw + lw/2) + 2*x + 2];
+ lsp = pack & 0xf;
+ v = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, " v: %04x, %02x, %02x, %02x, %d\n",
+ // v, msp, lsp, pack, p_off);
+
+ msp = pkt->data[y*2*(lw + lw/2) + 2*x + 3];
+ lsp = (pack >> 4) & 0xf;
+ y2 = (msp << 4) + lsp;
+ // av_log(0, AV_LOG_DEBUG, "y2: %04x, %02x, %02x, %02x, %d\n\n",
+ // y2, msp, lsp, pack, p_off);
+
+ memcpy(&frame->data[0][2*(y*lw + x)], &y1, 2);
+ memcpy(&frame->data[0][2*(y*lw + x+1)], &y2, 2);
+ memcpy(&frame->data[1][2*(y*lw/2 + x/2)], &u, 2);
+ memcpy(&frame->data[2][2*(y*lw/2 + x/2)], &v, 2);
+ }
+ }
+ return pkt->size;
+}
+
+static int check_pkt_size(AVCodecContext *avctx, AVPacket *avpkt, int bpp)
+{
+ int needed = ((avctx->width * bpp + 7) / 8) * avctx->height;
+ if (avpkt->size < needed){
+ av_log(avctx, AV_LOG_ERROR,
+ "Insufficient size of AVPacket data (pkg size: %d needed: %d)\n",
avpkt->size, needed);
+ return AVERROR_EXIT;
+ }
+
+ switch (avctx->codec_tag) {
+ case MKTAG('r','g','0','8'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_RGB24, 24,
pass_though);
+ break;
+ case MKTAG('r','g','1','0'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GBRP10LE, 30,
unpack_rg10);
+ break;
+ case MKTAG('r','g','1','2'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GBRP12LE, 36,
unpack_rg12);
+ break;
+ case MKTAG(' ','r','g','h'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_RGBAF16LE, 48,
half_add_alpha);
+ break;
+ case MKTAG(' ','r','g','f'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_GBRPF32LE, 96,
float2planes);
+ break;
+
+ case MKTAG('y','2','0','8'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_UYVY422, 16,
pass_though);
+ break;
+ case MKTAG('y','2','1','0'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV422P10LE, 20,
unpack_y210);
+ break;
+ case MKTAG('y','2','1','2'):
+ ret = fmt_frame(avctx, frame, avpkt, AV_PIX_FMT_YUV422P12LE, 24,
unpack_y212);
+ break;
+
+ default:
+ av_log(avctx, AV_LOG_ERROR,
+ "Unsupported DNxUncompressed pixel format variant: '%s'\n",
+ fourcc_buf);
+ return AVERROR(ENOSYS);