FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/media100.c
Date: 2022-12-09 07:38:14
Exec Total Coverage
Lines: 0 123 0.0%
Functions: 0 3 0.0%
Branches: 0 32 0.0%

Line Branch Exec Source
1 /*
2 * Media 100 decoder
3 * Copyright (c) 2022 Paul B Mahol
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 * Media 100 decoder.
25 */
26
27 #include <inttypes.h>
28
29 #include "libavutil/intreadwrite.h"
30 #include "avcodec.h"
31 #include "bytestream.h"
32 #include "codec_internal.h"
33
34 typedef struct Media100Context {
35 AVCodecContext *avctx; // wrapper context for mjpegb
36 AVPacket *pkt;
37 } Media100Context;
38
39 static av_cold int media100_decode_init(AVCodecContext *avctx)
40 {
41 Media100Context *ctx = avctx->priv_data;
42 const AVCodec *codec;
43 int ret;
44
45 codec = avcodec_find_decoder(AV_CODEC_ID_MJPEGB);
46 if (!codec)
47 return AVERROR_BUG;
48 ctx->avctx = avcodec_alloc_context3(codec);
49 if (!ctx->avctx)
50 return AVERROR(ENOMEM);
51 ctx->avctx->thread_count = 1;
52 ctx->avctx->flags = avctx->flags;
53 ctx->avctx->flags2 = avctx->flags2;
54 ctx->avctx->width = ctx->avctx->coded_width = avctx->width;
55 ctx->avctx->height = ctx->avctx->coded_height = avctx->height;
56
57 ret = avcodec_open2(ctx->avctx, codec, NULL);
58 if (ret < 0)
59 return ret;
60
61 ctx->pkt = av_packet_alloc();
62 if (!ctx->pkt)
63 return AVERROR(ENOMEM);
64
65 return 0;
66 }
67
68 static int media100_decode_frame(AVCodecContext *avctx,
69 AVFrame *frame, int *got_frame,
70 AVPacket *avpkt)
71 {
72 Media100Context *ctx = avctx->priv_data;
73 unsigned second_field_offset = 0;
74 unsigned next_field = 0;
75 unsigned dht_offset[2];
76 unsigned dqt_offset[2];
77 unsigned sod_offset[2];
78 unsigned sof_offset[2];
79 unsigned sos_offset[2];
80 unsigned field = 0;
81 GetByteContext gb;
82 PutByteContext pb;
83 AVPacket *pkt;
84 int ret;
85
86 if (avpkt->size + 1024 > ctx->pkt->size) {
87 ret = av_grow_packet(ctx->pkt, avpkt->size + 1024 - ctx->pkt->size);
88 if (ret < 0)
89 return ret;
90 }
91
92 ret = av_packet_make_writable(ctx->pkt);
93 if (ret < 0)
94 return ret;
95
96 bytestream2_init(&gb, avpkt->data, avpkt->size);
97 bytestream2_init_writer(&pb, ctx->pkt->data, ctx->pkt->size);
98
99 second_field:
100 bytestream2_put_be32(&pb, 0);
101 bytestream2_put_be32(&pb, AV_RB32("mjpg"));
102 bytestream2_put_be32(&pb, 0);
103 bytestream2_put_be32(&pb, 0);
104 for (int i = 0; i < 6; i++)
105 bytestream2_put_be32(&pb, 0);
106
107 sof_offset[field] = bytestream2_tell_p(&pb);
108 bytestream2_put_be16(&pb, 17);
109 bytestream2_put_byte(&pb, 8);
110 bytestream2_put_be16(&pb, avctx->height / 2);
111 bytestream2_put_be16(&pb, avctx->width);
112 bytestream2_put_byte(&pb, 3);
113 bytestream2_put_byte(&pb, 1);
114 bytestream2_put_byte(&pb, 0x21);
115 bytestream2_put_byte(&pb, 0);
116 bytestream2_put_byte(&pb, 2);
117 bytestream2_put_byte(&pb, 0x11);
118 bytestream2_put_byte(&pb, 1);
119 bytestream2_put_byte(&pb, 3);
120 bytestream2_put_byte(&pb, 0x11);
121 bytestream2_put_byte(&pb, 1);
122
123 sos_offset[field] = bytestream2_tell_p(&pb);
124 bytestream2_put_be16(&pb, 12);
125 bytestream2_put_byte(&pb, 3);
126 bytestream2_put_byte(&pb, 1);
127 bytestream2_put_byte(&pb, 0);
128 bytestream2_put_byte(&pb, 2);
129 bytestream2_put_byte(&pb, 0x11);
130 bytestream2_put_byte(&pb, 3);
131 bytestream2_put_byte(&pb, 0x11);
132 bytestream2_put_byte(&pb, 0);
133 bytestream2_put_byte(&pb, 0);
134 bytestream2_put_byte(&pb, 0);
135
136 dqt_offset[field] = bytestream2_tell_p(&pb);
137 bytestream2_put_be16(&pb, 132);
138 bytestream2_put_byte(&pb, 0);
139 bytestream2_skip(&gb, 4);
140 for (int i = 0; i < 64; i++)
141 bytestream2_put_byte(&pb, bytestream2_get_be32(&gb));
142 bytestream2_put_byte(&pb, 1);
143 for (int i = 0; i < 64; i++)
144 bytestream2_put_byte(&pb, bytestream2_get_be32(&gb));
145
146 dht_offset[field] = 0;
147 sod_offset[field] = bytestream2_tell_p(&pb);
148
149 for (int i = bytestream2_tell(&gb) + 8; next_field == 0 && i < avpkt->size - 4; i++) {
150 if (AV_RB32(avpkt->data + i) == 0x00000001) {
151 next_field = i;
152 break;
153 }
154 }
155
156 bytestream2_skip(&gb, 8);
157 bytestream2_copy_buffer(&pb, &gb, next_field - bytestream2_tell(&gb));
158 bytestream2_put_be64(&pb, 0);
159
160 if (field == 0) {
161 field = 1;
162 second_field_offset = bytestream2_tell_p(&pb);
163 next_field = avpkt->size;
164 goto second_field;
165 }
166
167 pkt = ctx->pkt;
168
169 AV_WB32(pkt->data + 8, second_field_offset);
170 AV_WB32(pkt->data + 12, second_field_offset);
171 AV_WB32(pkt->data + 16, second_field_offset);
172 AV_WB32(pkt->data + 20, dqt_offset[0]);
173 AV_WB32(pkt->data + 24, dht_offset[0]);
174 AV_WB32(pkt->data + 28, sof_offset[0]);
175 AV_WB32(pkt->data + 32, sos_offset[0]);
176 AV_WB32(pkt->data + 36, sod_offset[0]);
177
178 AV_WB32(pkt->data + second_field_offset + 8, bytestream2_tell_p(&pb) - second_field_offset);
179 AV_WB32(pkt->data + second_field_offset + 12, bytestream2_tell_p(&pb) - second_field_offset);
180 AV_WB32(pkt->data + second_field_offset + 16, 0);
181 AV_WB32(pkt->data + second_field_offset + 20, dqt_offset[1] - second_field_offset);
182 AV_WB32(pkt->data + second_field_offset + 24, dht_offset[1]);
183 AV_WB32(pkt->data + second_field_offset + 28, sof_offset[1] - second_field_offset);
184 AV_WB32(pkt->data + second_field_offset + 32, sos_offset[1] - second_field_offset);
185 AV_WB32(pkt->data + second_field_offset + 36, sod_offset[1] - second_field_offset);
186
187 pkt->size = bytestream2_tell_p(&pb);
188
189 ret = avcodec_send_packet(ctx->avctx, pkt);
190 if (ret < 0) {
191 av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
192 return ret;
193 }
194
195 ret = avcodec_receive_frame(ctx->avctx, frame);
196 if (ret < 0)
197 return ret;
198
199 *got_frame = 1;
200
201 return avpkt->size;
202 }
203
204 static av_cold int media100_decode_end(AVCodecContext *avctx)
205 {
206 Media100Context *ctx = avctx->priv_data;
207
208 avcodec_free_context(&ctx->avctx);
209 av_packet_free(&ctx->pkt);
210
211 return 0;
212 }
213
214 const FFCodec ff_media100_decoder = {
215 .p.name = "media100",
216 CODEC_LONG_NAME("Media 100"),
217 .p.type = AVMEDIA_TYPE_VIDEO,
218 .p.id = AV_CODEC_ID_MEDIA100,
219 .priv_data_size = sizeof(Media100Context),
220 .init = media100_decode_init,
221 .close = media100_decode_end,
222 FF_CODEC_DECODE_CB(media100_decode_frame),
223 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
224 };
225