-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path0003-avcodec-jpeg2000dec-support-of-2-fields-in-1-AVPacke.patch
More file actions
186 lines (167 loc) · 8.13 KB
/
0003-avcodec-jpeg2000dec-support-of-2-fields-in-1-AVPacke.patch
File metadata and controls
186 lines (167 loc) · 8.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
From 3b39c536be1dde63081da43e953b407f68210131 Mon Sep 17 00:00:00 2001
From: Jerome Martinez <jerome@mediaarea.net>
Date: Tue, 20 Feb 2024 16:04:11 +0100
Subject: [PATCH 03/19] avcodec/jpeg2000dec: support of 2 fields in 1 AVPacket
---
libavcodec/jpeg2000dec.c | 78 +++++++++++++++++++++++++++++++++++-----
libavcodec/jpeg2000dec.h | 5 +++
2 files changed, 74 insertions(+), 9 deletions(-)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 276c0a6e43..a906a47763 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -204,6 +204,8 @@ static int get_siz(Jpeg2000DecoderContext *s)
int ret;
int o_dimx, o_dimy; //original image dimensions.
int dimx, dimy;
+ int previous_width = s->width;
+ int previous_height = s->height;
if (bytestream2_get_bytes_left(&s->g) < 36) {
av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for SIZ\n");
@@ -221,7 +223,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz
ncomponents = bytestream2_get_be16u(&s->g); // CSiz
- if (av_image_check_size2(s->width, s->height, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx)) {
+ if (av_image_check_size2(s->width, s->height << (s->has_2_fields && s->height >= 0), s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx)) {
avpriv_request_sample(s->avctx, "Large Dimensions");
return AVERROR_PATCHWELCOME;
}
@@ -332,6 +334,20 @@ static int get_siz(Jpeg2000DecoderContext *s)
return AVERROR(ENOMEM);
}
+ /* management of frames having 2 separate codestreams */
+ if (s->has_2_fields) {
+ s->height <<= 1;
+ s->image_offset_y <<= 1;
+ s->tile_offset_y <<= 1;
+ if (s->is_second_field && (s->width != previous_width || s->height != previous_height)) {
+ avpriv_request_sample(s->avctx, "Support of 2 JPEG 2000 codestreams with different base characteristics");
+ return AVERROR_PATCHWELCOME;
+ }
+ if (s->image_offset_y || s->tile_offset_y || (s->tile_height << 1) != s->height) {
+ av_log(s->avctx, AV_LOG_WARNING, "Decoding of 2 fields having titles in 1 AVPacket was not tested\n");
+ }
+ }
+
/* compute image size with reduction factor */
o_dimx = ff_jpeg2000_ceildivpow2(s->width - s->image_offset_x,
s->reduction_factor);
@@ -2354,7 +2370,7 @@ static inline int tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile
\
y = tile->comp[compno].coord[1][0] - \
ff_jpeg2000_ceildiv(s->image_offset_y, s->cdy[compno]); \
- line = (PIXEL *)picture->data[plane] + y * (picture->linesize[plane] / sizeof(PIXEL));\
+ line = (PIXEL *)picture->data[plane] + (y + (s->is_second_field ^ s->is_bottom_coded_first)) * (picture->linesize[plane] / sizeof(PIXEL));\
for (; y < h; y++) { \
PIXEL *dst; \
\
@@ -2381,7 +2397,7 @@ static inline int tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile
dst += pixelsize; \
} \
} \
- line += picture->linesize[plane] / sizeof(PIXEL); \
+ line += (picture->linesize[plane] << s->has_2_fields) / sizeof(PIXEL); \
} \
} \
\
@@ -2854,6 +2870,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture,
{
Jpeg2000DecoderContext *s = avctx->priv_data;
int ret;
+ int codestream_size;
s->avctx = avctx;
bytestream2_init(&s->g, avpkt->data, avpkt->size);
@@ -2888,20 +2905,50 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture,
ret = AVERROR_INVALIDDATA;
goto end;
}
+
+ /* management of frames having 2 separate codestreams */
+ if (s->has_2_fields && !s->is_second_field) {
+ switch (avctx->field_order) {
+ case AV_FIELD_BB:
+ case AV_FIELD_BT:
+ s->is_bottom_coded_first = 1;
+ break;
+ default:
+ s->is_bottom_coded_first = 0;
+ }
+ }
+
if (ret = jpeg2000_read_main_headers(s))
goto end;
+ codestream_size = avpkt->size - bytestream2_get_bytes_left(&s->g);
+
+ /* management of frames having 2 separate codestreams */
+ if (bytestream2_get_bytes_left(&s->g) > 1 && bytestream2_peek_be16(&s->g) == JPEG2000_SOC) {
+ if (!s->has_2_fields) {
+ /* 2 codestreams newly detected, adatping output frame structure for handling 2 codestreams and parsing again the headers (fast and done once for a stable stream) */
+ s->has_2_fields = 1;
+ jpeg2000_dec_cleanup(s);
+ return jpeg2000_decode_frame(avctx, picture, got_frame, avpkt);
+ }
+ } else if (s->has_2_fields && !s->is_second_field) {
+ /* 1 codestream newly detected, adatping output frame structure for handling 1 codestream and parsing again the headers (fast and never done for a stable stream) */
+ s->has_2_fields = 0;
+ s->is_bottom_coded_first = 0;
+ jpeg2000_dec_cleanup(s);
+ return jpeg2000_decode_frame(avctx, picture, got_frame, avpkt);
+ }
if (s->sar.num && s->sar.den)
avctx->sample_aspect_ratio = s->sar;
s->sar.num = s->sar.den = 0;
if (avctx->skip_frame >= AVDISCARD_ALL) {
- jpeg2000_dec_cleanup(s);
- return avpkt->size;
+ ret = codestream_size;
+ goto end;
}
/* get picture buffer */
- if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0)
+ if ((!s->has_2_fields || !s->is_second_field) && (ret = ff_thread_get_buffer(avctx, picture, 0)) < 0)
goto end;
if (ret = jpeg2000_read_bitstream_packets(s))
@@ -2913,17 +2960,30 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture,
avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL, s->numXtiles * s->numYtiles);
- jpeg2000_dec_cleanup(s);
-
*got_frame = 1;
if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
memcpy(picture->data[1], s->palette, 256 * sizeof(uint32_t));
- return bytestream2_tell(&s->g);
+ ret = codestream_size;
end:
jpeg2000_dec_cleanup(s);
+
+ /* management of frames having 2 separate codestreams */
+ if (s->has_2_fields && !s->is_second_field && ret < avpkt->size && ret >= 0) {
+ /* only the 1st codestream was parsed, parsing now the 2nd codestream */
+ s->is_second_field = 1;
+ avpkt->data += ret;
+ avpkt->size -= ret;
+ ret = jpeg2000_decode_frame(avctx, picture, got_frame, avpkt);
+ avpkt->data -= ret;
+ avpkt->size += ret;
+ s->is_second_field = 0;
+ if (ret >= 0)
+ ret += codestream_size;
+ }
+
return ret;
}
diff --git a/libavcodec/jpeg2000dec.h b/libavcodec/jpeg2000dec.h
index fce3823164..1fe0491788 100644
--- a/libavcodec/jpeg2000dec.h
+++ b/libavcodec/jpeg2000dec.h
@@ -120,6 +120,11 @@ typedef struct Jpeg2000DecoderContext {
/*options parameters*/
int reduction_factor;
+
+ /* field info */
+ int8_t has_2_fields;
+ int8_t is_bottom_coded_first;
+ int8_t is_second_field;
} Jpeg2000DecoderContext;
#endif //AVCODEC_JPEG2000DEC_H
--
2.52.0