/src/ffmpeg/libavcodec/cljrenc.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Cirrus Logic AccuPak (CLJR) encoder  | 
3  |  |  * Copyright (c) 2003 Alex Beregszaszi  | 
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  |  | /**  | 
23  |  |  * @file  | 
24  |  |  * Cirrus Logic AccuPak encoder.  | 
25  |  |  */  | 
26  |  |  | 
27  |  | #include "libavutil/opt.h"  | 
28  |  |  | 
29  |  | #include "avcodec.h"  | 
30  |  | #include "codec_internal.h"  | 
31  |  | #include "encode.h"  | 
32  |  | #include "put_bits.h"  | 
33  |  |  | 
34  |  | typedef struct CLJRContext { | 
35  |  |     AVClass        *avclass;  | 
36  |  |     int             dither_type;  | 
37  |  | } CLJRContext;  | 
38  |  |  | 
39  |  | static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,  | 
40  |  |                         const AVFrame *p, int *got_packet)  | 
41  | 3.13k  | { | 
42  | 3.13k  |     CLJRContext *a = avctx->priv_data;  | 
43  | 3.13k  |     PutBitContext pb;  | 
44  | 3.13k  |     int x, y, ret;  | 
45  | 3.13k  |     uint32_t dither= avctx->frame_num;  | 
46  | 3.13k  |     static const uint32_t ordered_dither[2][2] =  | 
47  | 3.13k  |     { | 
48  | 3.13k  |         { 0x10400000, 0x104F0000 }, | 
49  | 3.13k  |         { 0xCB2A0000, 0xCB250000 }, | 
50  | 3.13k  |     };  | 
51  |  |  | 
52  | 3.13k  |     if (avctx->width%4 && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { | 
53  | 25  |          av_log(avctx, AV_LOG_ERROR,  | 
54  | 25  |                 "Widths which are not a multiple of 4 might fail with some decoders, "  | 
55  | 25  |                 "use vstrict=-1 / -strict -1 to use %d anyway.\n", avctx->width);  | 
56  | 25  |          return AVERROR_EXPERIMENTAL;  | 
57  | 25  |     }  | 
58  |  |  | 
59  | 3.10k  |     ret = ff_get_encode_buffer(avctx, pkt, 4 * avctx->height * ((avctx->width + 3) / 4), 0);  | 
60  | 3.10k  |     if (ret < 0)  | 
61  | 0  |         return ret;  | 
62  |  |  | 
63  | 3.10k  |     init_put_bits(&pb, pkt->data, pkt->size);  | 
64  |  |  | 
65  | 1.23M  |     for (y = 0; y < avctx->height; y++) { | 
66  | 1.23M  |         const uint8_t *luma = &p->data[0][y * p->linesize[0]];  | 
67  | 1.23M  |         const uint8_t *cb   = &p->data[1][y * p->linesize[1]];  | 
68  | 1.23M  |         const uint8_t *cr   = &p->data[2][y * p->linesize[2]];  | 
69  | 1.23M  |         uint8_t luma_tmp[4];  | 
70  | 3.44M  |         for (x = 0; x < avctx->width; x += 4) { | 
71  | 2.21M  |             switch (a->dither_type) { | 
72  | 0  |             case 0: dither = 0x492A0000;                       break;  | 
73  | 2.21M  |             case 1: dither = dither * 1664525 + 1013904223;    break;  | 
74  | 0  |             case 2: dither = ordered_dither[ y&1 ][ (x>>2)&1 ];break;  | 
75  | 2.21M  |             }  | 
76  | 2.21M  |             if (x+3 >= avctx->width) { | 
77  | 933k  |                 memset(luma_tmp, 0, sizeof(luma_tmp));  | 
78  | 933k  |                 memcpy(luma_tmp, luma, avctx->width - x);  | 
79  | 933k  |                 luma = luma_tmp;  | 
80  | 933k  |             }  | 
81  | 2.21M  |             put_bits(&pb, 5, (249*(luma[3] +  (dither>>29)   )) >> 11);  | 
82  | 2.21M  |             put_bits(&pb, 5, (249*(luma[2] + ((dither>>26)&7))) >> 11);  | 
83  | 2.21M  |             put_bits(&pb, 5, (249*(luma[1] + ((dither>>23)&7))) >> 11);  | 
84  | 2.21M  |             put_bits(&pb, 5, (249*(luma[0] + ((dither>>20)&7))) >> 11);  | 
85  | 2.21M  |             luma += 4;  | 
86  | 2.21M  |             put_bits(&pb, 6, (253*(*(cb++) + ((dither>>18)&3))) >> 10);  | 
87  | 2.21M  |             put_bits(&pb, 6, (253*(*(cr++) + ((dither>>16)&3))) >> 10);  | 
88  | 2.21M  |         }  | 
89  | 1.23M  |     }  | 
90  |  |  | 
91  | 3.10k  |     flush_put_bits(&pb);  | 
92  |  |  | 
93  | 3.10k  |     *got_packet = 1;  | 
94  | 3.10k  |     return 0;  | 
95  | 3.10k  | }  | 
96  |  |  | 
97  |  | #define OFFSET(x) offsetof(CLJRContext, x)  | 
98  |  | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM  | 
99  |  | static const AVOption options[] = { | 
100  |  |     { "dither_type",   "Dither type",   OFFSET(dither_type),        AV_OPT_TYPE_INT, { .i64=1 }, 0, 2, VE}, | 
101  |  |     { NULL }, | 
102  |  | };  | 
103  |  |  | 
104  |  | static const AVClass cljr_class = { | 
105  |  |     .class_name = "cljr encoder",  | 
106  |  |     .item_name  = av_default_item_name,  | 
107  |  |     .option     = options,  | 
108  |  |     .version    = LIBAVUTIL_VERSION_INT,  | 
109  |  | };  | 
110  |  |  | 
111  |  | const FFCodec ff_cljr_encoder = { | 
112  |  |     .p.name         = "cljr",  | 
113  |  |     CODEC_LONG_NAME("Cirrus Logic AccuPak"), | 
114  |  |     .p.type         = AVMEDIA_TYPE_VIDEO,  | 
115  |  |     .p.id           = AV_CODEC_ID_CLJR,  | 
116  |  |     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,  | 
117  |  |     .priv_data_size = sizeof(CLJRContext),  | 
118  |  |     FF_CODEC_ENCODE_CB(encode_frame),  | 
119  |  |     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, | 
120  |  |                                                    AV_PIX_FMT_NONE },  | 
121  |  |     .p.priv_class   = &cljr_class,  | 
122  |  | };  |