FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/media100_to_mjpegb.c
Date: 2024-07-14 13:34:57
Exec Total Coverage
Lines: 0 97 0.0%
Functions: 0 2 0.0%
Branches: 0 22 0.0%

Line Branch Exec Source
1 /*
2 * Media 100 to MJPEGB bitstream filter
3 * Copyright (c) 2023 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 to MJPEGB bitstream filter.
25 */
26
27 #include "libavutil/intreadwrite.h"
28 #include "bsf.h"
29 #include "bsf_internal.h"
30 #include "bytestream.h"
31
32 static av_cold int init(AVBSFContext *ctx)
33 {
34 ctx->par_out->codec_id = AV_CODEC_ID_MJPEGB;
35 return 0;
36 }
37
38 static int filter(AVBSFContext *ctx, AVPacket *out)
39 {
40 unsigned second_field_offset = 0;
41 unsigned next_field = 0;
42 unsigned dht_offset[2];
43 unsigned dqt_offset[2];
44 unsigned sod_offset[2];
45 unsigned sof_offset[2];
46 unsigned sos_offset[2];
47 unsigned field = 0;
48 GetByteContext gb;
49 PutByteContext pb;
50 AVPacket *in;
51 int ret;
52
53 ret = ff_bsf_get_packet(ctx, &in);
54 if (ret < 0)
55 return ret;
56
57 ret = av_new_packet(out, in->size + 1024);
58 if (ret < 0)
59 goto fail;
60
61 bytestream2_init(&gb, in->data, in->size);
62 bytestream2_init_writer(&pb, out->data, out->size);
63
64 second_field:
65 bytestream2_put_be32(&pb, 0);
66 bytestream2_put_be32(&pb, AV_RB32("mjpg"));
67 bytestream2_put_be32(&pb, 0);
68 bytestream2_put_be32(&pb, 0);
69 for (int i = 0; i < 6; i++)
70 bytestream2_put_be32(&pb, 0);
71
72 sof_offset[field] = bytestream2_tell_p(&pb);
73 bytestream2_put_be16(&pb, 17);
74 bytestream2_put_byte(&pb, 8);
75 bytestream2_put_be16(&pb, ctx->par_in->height / 2);
76 bytestream2_put_be16(&pb, ctx->par_in->width);
77 bytestream2_put_byte(&pb, 3);
78 bytestream2_put_byte(&pb, 1);
79 bytestream2_put_byte(&pb, 0x21);
80 bytestream2_put_byte(&pb, 0);
81 bytestream2_put_byte(&pb, 2);
82 bytestream2_put_byte(&pb, 0x11);
83 bytestream2_put_byte(&pb, 1);
84 bytestream2_put_byte(&pb, 3);
85 bytestream2_put_byte(&pb, 0x11);
86 bytestream2_put_byte(&pb, 1);
87
88 sos_offset[field] = bytestream2_tell_p(&pb);
89 bytestream2_put_be16(&pb, 12);
90 bytestream2_put_byte(&pb, 3);
91 bytestream2_put_byte(&pb, 1);
92 bytestream2_put_byte(&pb, 0);
93 bytestream2_put_byte(&pb, 2);
94 bytestream2_put_byte(&pb, 0x11);
95 bytestream2_put_byte(&pb, 3);
96 bytestream2_put_byte(&pb, 0x11);
97 bytestream2_put_byte(&pb, 0);
98 bytestream2_put_byte(&pb, 0);
99 bytestream2_put_byte(&pb, 0);
100
101 dqt_offset[field] = bytestream2_tell_p(&pb);
102 bytestream2_put_be16(&pb, 132);
103 bytestream2_put_byte(&pb, 0);
104 bytestream2_skip(&gb, 4);
105 for (int i = 0; i < 64; i++)
106 bytestream2_put_byte(&pb, bytestream2_get_be32(&gb));
107 bytestream2_put_byte(&pb, 1);
108 for (int i = 0; i < 64; i++)
109 bytestream2_put_byte(&pb, bytestream2_get_be32(&gb));
110
111 dht_offset[field] = 0;
112 sod_offset[field] = bytestream2_tell_p(&pb);
113
114 for (int i = bytestream2_tell(&gb) + 8; next_field == 0 && i < in->size - 4; i++) {
115 if (AV_RB32(in->data + i) == 0x00000001) {
116 next_field = i;
117 break;
118 }
119 }
120
121 bytestream2_skip(&gb, 8);
122 bytestream2_copy_buffer(&pb, &gb, next_field - bytestream2_tell(&gb));
123 bytestream2_put_be64(&pb, 0);
124
125 if (field == 0) {
126 field = 1;
127 second_field_offset = bytestream2_tell_p(&pb);
128 next_field = in->size;
129 goto second_field;
130 }
131
132 AV_WB32(out->data + 8, second_field_offset);
133 AV_WB32(out->data + 12, second_field_offset);
134 AV_WB32(out->data + 16, second_field_offset);
135 AV_WB32(out->data + 20, dqt_offset[0]);
136 AV_WB32(out->data + 24, dht_offset[0]);
137 AV_WB32(out->data + 28, sof_offset[0]);
138 AV_WB32(out->data + 32, sos_offset[0]);
139 AV_WB32(out->data + 36, sod_offset[0]);
140
141 AV_WB32(out->data + second_field_offset + 8, bytestream2_tell_p(&pb) - second_field_offset);
142 AV_WB32(out->data + second_field_offset + 12, bytestream2_tell_p(&pb) - second_field_offset);
143 AV_WB32(out->data + second_field_offset + 16, 0);
144 AV_WB32(out->data + second_field_offset + 20, dqt_offset[1] - second_field_offset);
145 AV_WB32(out->data + second_field_offset + 24, dht_offset[1]);
146 AV_WB32(out->data + second_field_offset + 28, sof_offset[1] - second_field_offset);
147 AV_WB32(out->data + second_field_offset + 32, sos_offset[1] - second_field_offset);
148 AV_WB32(out->data + second_field_offset + 36, sod_offset[1] - second_field_offset);
149
150 out->size = bytestream2_tell_p(&pb);
151
152 ret = av_packet_copy_props(out, in);
153 if (ret < 0)
154 goto fail;
155
156 fail:
157 if (ret < 0)
158 av_packet_unref(out);
159 av_packet_free(&in);
160 return ret;
161 }
162
163 const FFBitStreamFilter ff_media100_to_mjpegb_bsf = {
164 .p.name = "media100_to_mjpegb",
165 .p.codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_MEDIA100, AV_CODEC_ID_NONE },
166 .init = init,
167 .filter = filter,
168 };
169