1 /*
2  * Copyright (C) 2000-2018 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  *
21  * contents:
22  *
23  * buffer types management.
24  * convert FOURCC and audioformattag to BUF_xxx defines
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <inttypes.h>
35 
36 #include <xine/buffer.h>
37 #include <xine/xineutils.h>
38 #include <xine/xine_internal.h>
39 #include "bswap.h"
40 
41 static const uint32_t sorted_audio_tags[] = {
42   0x0001, BUF_AUDIO_LPCM_LE,
43   0x0002, BUF_AUDIO_MSADPCM,
44   0x0006, BUF_AUDIO_ALAW,
45   0x0007, BUF_AUDIO_MULAW,
46   0x000A, BUF_AUDIO_WMAV,
47   0x0011, BUF_AUDIO_MSIMAADPCM,
48   0x0022, BUF_AUDIO_TRUESPEECH,
49   0x0031, BUF_AUDIO_MSGSM,
50   0x0032, BUF_AUDIO_MSGSM,
51   0x0050, BUF_AUDIO_MPEG,
52   0x0055, BUF_AUDIO_MPEG,
53   0x0061, BUF_AUDIO_DK4ADPCM,
54   0x0062, BUF_AUDIO_DK3ADPCM,
55   0x0075, BUF_AUDIO_VOXWARE,
56   0x00ff, BUF_AUDIO_AAC,
57   0x0111, BUF_AUDIO_VIVOG723,
58   0x0112, BUF_AUDIO_VIVOG723,
59   0x0130, BUF_AUDIO_ACELPNET,
60   0x0160, BUF_AUDIO_WMAV1,
61   0x0161, BUF_AUDIO_WMAV2,
62   0x0162, BUF_AUDIO_WMAPRO,
63   0x0163, BUF_AUDIO_WMALL,
64   0x0401, BUF_AUDIO_IMC,
65   0x1101, BUF_AUDIO_LH,
66   0x1102, BUF_AUDIO_LH,
67   0x1103, BUF_AUDIO_LH,
68   0x1104, BUF_AUDIO_LH,
69   0x2000, BUF_AUDIO_A52,
70   0x2001, BUF_AUDIO_DTS,
71   /* these formattags are used by Vorbis ACM encoder and
72    * supported by NanDub, a variant of VirtualDub. */
73   0x674f, BUF_AUDIO_VORBIS,
74   0x6750, BUF_AUDIO_VORBIS,
75   0x6751, BUF_AUDIO_VORBIS,
76   0x676f, BUF_AUDIO_VORBIS,
77   0x6770, BUF_AUDIO_VORBIS,
78   0x6771, BUF_AUDIO_VORBIS
79 };
80 
81 static const uint32_t sorted_audio_4ccs[] = {
82   BE_FOURCC('.', 'm', 'p', '3'), BUF_AUDIO_MPEG,
83   BE_FOURCC('2', '8', '_', '8'), BUF_AUDIO_28_8,
84   BE_FOURCC('4', '2', 'n', 'i'), BUF_AUDIO_LPCM_LE,
85   BE_FOURCC('A', 'A', 'C', ' '), BUF_AUDIO_AAC,
86   BE_FOURCC('E', 'A', 'C', '3'), BUF_AUDIO_EAC3,
87   BE_FOURCC('M', 'A', 'C', '3'), BUF_AUDIO_MAC3,
88   BE_FOURCC('M', 'A', 'C', '6'), BUF_AUDIO_MAC6,
89   BE_FOURCC('M', 'P', '3', ' '), BUF_AUDIO_MPEG,
90   BE_FOURCC('M', 'P', '4', 'A'), BUF_AUDIO_AAC,
91   BE_FOURCC('M', 'P', '4', 'L'), BUF_AUDIO_AAC_LATM,
92   BE_FOURCC('O', 'g', 'g', 'S'), BUF_AUDIO_VORBIS,
93   BE_FOURCC('O', 'g', 'g', 'V'), BUF_AUDIO_VORBIS,
94   BE_FOURCC('O', 'p', 'u', 's'), BUF_AUDIO_OPUS,
95   BE_FOURCC('Q', 'D', 'M', '2'), BUF_AUDIO_QDESIGN2,
96   BE_FOURCC('Q', 'D', 'M', 'C'), BUF_AUDIO_QDESIGN1,
97   BE_FOURCC('Q', 'c', 'l', 'p'), BUF_AUDIO_QCLP,
98   BE_FOURCC('T', 'T', 'A', '1'), BUF_AUDIO_TTA,
99   BE_FOURCC('W', 'V', 'P', 'K'), BUF_AUDIO_WAVPACK,
100   BE_FOURCC('a', 'c', '-', '3'), BUF_AUDIO_A52,
101   BE_FOURCC('a', 'd', 'u',0x55), BUF_AUDIO_MP3ADU,
102   BE_FOURCC('a', 'g', 's', 'm'), BUF_AUDIO_GSM610,
103   BE_FOURCC('a', 'l', 'a', 'c'), BUF_AUDIO_ALAC,
104   BE_FOURCC('a', 'l', 'a', 'w'), BUF_AUDIO_ALAW,
105   BE_FOURCC('a', 't', 'r', 'c'), BUF_AUDIO_ATRK,
106   BE_FOURCC('c', 'o', 'o', 'k'), BUF_AUDIO_COOK,
107   BE_FOURCC('d', 'n', 'e', 't'), BUF_AUDIO_DNET,
108   BE_FOURCC('e', 'c', '-', '3'), BUF_AUDIO_EAC3,
109   BE_FOURCC('i', 'm', 'a', '4'), BUF_AUDIO_QTIMAADPCM,
110   BE_FOURCC('i', 'n', '2', '4'), BUF_AUDIO_LPCM_BE,
111   BE_FOURCC('l', 'p', 'c', 'J'), BUF_AUDIO_14_4,
112   BE_FOURCC('m', 'a', 'c', '3'), BUF_AUDIO_MAC3,
113   BE_FOURCC('m', 'a', 'c', '6'), BUF_AUDIO_MAC6,
114   BE_FOURCC('m', 'p', '4', 'a'), BUF_AUDIO_AAC,
115   BE_FOURCC('r', 'a', 'a', 'c'), BUF_AUDIO_AAC,
116   BE_FOURCC('r', 'a', 'c', 'p'), BUF_AUDIO_AAC,
117   BE_FOURCC('r', 'a', 'w', ' '), BUF_AUDIO_LPCM_LE,
118   BE_FOURCC('s', 'a', 'm', 'r'), BUF_AUDIO_AMR_NB,
119   BE_FOURCC('s', 'a', 'w', 'b'), BUF_AUDIO_AMR_WB,
120   BE_FOURCC('s', 'i', 'p', 'r'), BUF_AUDIO_SIPRO,
121   BE_FOURCC('s', 'o', 'w', 't'), BUF_AUDIO_LPCM_LE,
122   BE_FOURCC('t', 'r', 'h', 'd'), BUF_AUDIO_TRUEHD,
123   BE_FOURCC('t', 'w', 'o', 's'), BUF_AUDIO_LPCM_BE,
124   BE_FOURCC('u', 'l', 'a', 'w'), BUF_AUDIO_MULAW
125 };
126 
_x_formattag_to_buf_audio(uint32_t formattag)127 uint32_t _x_formattag_to_buf_audio (uint32_t formattag) {
128   uint32_t t = formattag;
129   if (t & 0xffff0000) {
130     uint32_t b, e, m;
131 #ifndef WORDS_BIGENDIAN
132     t = (t >> 24) | ((t & 0x00ff0000) >> 8) | ((t & 0x0000ff00) << 8) | (t << 24);
133 #endif
134     b = 0;
135     e = sizeof (sorted_audio_4ccs) / sizeof (sorted_audio_4ccs[0]) / 2;
136     m = e >> 1;
137     do {
138       uint32_t f = sorted_audio_4ccs[2 * m];
139       if (t == f) {
140         return sorted_audio_4ccs[2 * m + 1];
141       } else if (t < f) {
142         e = m;
143       } else {
144         b = m + 1;
145       }
146       m = (b + e) >> 1;
147     } while (b != e);
148     if ((t & 0xffff0000) != BE_FOURCC('m', 's', 0, 0))
149       return 0;
150     t &= 0xffff;
151   }
152   {
153     uint32_t b, e, m;
154     b = 0;
155     e = sizeof (sorted_audio_tags) / sizeof (sorted_audio_tags[0]) / 2;
156     m = e >> 1;
157     do {
158       uint32_t f = sorted_audio_tags[2 * m];
159       if (t == f) {
160         return sorted_audio_tags[2 * m + 1];
161       } else if (t < f) {
162         e = m;
163       } else {
164         b = m + 1;
165       }
166       m = (b + e) >> 1;
167     } while (b != e);
168     return 0;
169   }
170 }
171 
172 static const uint32_t sorted_video_tags[] = {
173   0x0001, BUF_VIDEO_MSRLE,
174   0x0002, BUF_VIDEO_MSRLE  /* MS RLE format identifiers */
175 };
176 
177 static const uint32_t sorted_video_4ccs[] = {
178   BE_FOURCC(0x02, 0, 0, 0x10),   BUF_VIDEO_MPEG,
179   BE_FOURCC('3', 'I', 'V', '1'), BUF_VIDEO_3IVX,
180   BE_FOURCC('3', 'I', 'V', '2'), BUF_VIDEO_3IVX,
181   BE_FOURCC('3', 'I', 'V', 'D'), BUF_VIDEO_MSMPEG4_V3,
182   BE_FOURCC('8', 'B', 'P', 'S'), BUF_VIDEO_8BPS,
183   BE_FOURCC('A', 'A', 'S', 'C'), BUF_VIDEO_AASC,
184   BE_FOURCC('A', 'P', '4', '1'), BUF_VIDEO_MSMPEG4_V3,
185   BE_FOURCC('A', 'S', 'V', '1'), BUF_VIDEO_ASV1,
186   BE_FOURCC('A', 'S', 'V', '2'), BUF_VIDEO_ASV2,
187   BE_FOURCC('A', 'V', 'D', 'J'), BUF_VIDEO_MJPEG,
188   BE_FOURCC('A', 'V', 'R', 'n'), BUF_VIDEO_MJPEG,
189   BE_FOURCC('C', 'O', 'L', '1'), BUF_VIDEO_MSMPEG4_V3,
190   BE_FOURCC('C', 'R', 'A', 'M'), BUF_VIDEO_MSVC,
191   BE_FOURCC('C', 'S', 'C', 'D'), BUF_VIDEO_CSCD,
192   BE_FOURCC('C', 'Y', 'U', 'V'), BUF_VIDEO_CYUV,
193   BE_FOURCC('D', 'I', 'B', ' '), BUF_VIDEO_RGB, /* device-independent bitmap */
194   BE_FOURCC('D', 'I', 'V', '2'), BUF_VIDEO_MSMPEG4_V2,
195   BE_FOURCC('D', 'I', 'V', '3'), BUF_VIDEO_MSMPEG4_V3,
196   BE_FOURCC('D', 'I', 'V', '4'), BUF_VIDEO_MSMPEG4_V3,
197   BE_FOURCC('D', 'I', 'V', '5'), BUF_VIDEO_MSMPEG4_V3,
198   BE_FOURCC('D', 'I', 'V', '6'), BUF_VIDEO_MSMPEG4_V3,
199   BE_FOURCC('D', 'I', 'V', 'X'), BUF_VIDEO_MPEG4,
200   BE_FOURCC('D', 'U', 'C', 'K'), BUF_VIDEO_DUCKTM1,
201   BE_FOURCC('D', 'V', 'S', 'D'), BUF_VIDEO_DV,
202   BE_FOURCC('D', 'X', '5', '0'), BUF_VIDEO_DIVX5,
203   BE_FOURCC('D', 'i', 'v', 'X'), BUF_VIDEO_MPEG4,
204   BE_FOURCC('D', 'i', 'v', 'x'), BUF_VIDEO_MPEG4,
205   BE_FOURCC('F', 'M', 'P', '4'), BUF_VIDEO_MPEG4,
206   BE_FOURCC('F', 'P', 'S', '1'), BUF_VIDEO_FPS1,
207   BE_FOURCC('G', 'R', 'E', 'Y'), BUF_VIDEO_GREY,
208   BE_FOURCC('H', '2', '6', '3'), BUF_VIDEO_H263,
209   BE_FOURCC('H', '2', '6', '4'), BUF_VIDEO_H264,
210   BE_FOURCC('H', 'F', 'Y', 'U'), BUF_VIDEO_HUFFYUV,
211   BE_FOURCC('I', '2', '6', '3'), BUF_VIDEO_I263,
212   BE_FOURCC('I', '4', '2', '0'), BUF_VIDEO_I420,
213   BE_FOURCC('I', 'M', 'G', ' '), BUF_VIDEO_IMAGE,
214   BE_FOURCC('I', 'V', '3', '1'), BUF_VIDEO_IV31,
215   BE_FOURCC('I', 'V', '3', '2'), BUF_VIDEO_IV32,
216   BE_FOURCC('I', 'V', '4', '1'), BUF_VIDEO_IV41,
217   BE_FOURCC('I', 'V', '5', '0'), BUF_VIDEO_IV50,
218   BE_FOURCC('I', 'Y', 'U', 'V'), BUF_VIDEO_I420,
219   BE_FOURCC('J', 'F', 'I', 'F'), BUF_VIDEO_JPEG,
220   BE_FOURCC('K', 'M', 'V', 'C'), BUF_VIDEO_KMVC,
221   BE_FOURCC('L', 'O', 'C', 'O'), BUF_VIDEO_LOCO,
222   BE_FOURCC('M', '4', 'S', '2'), BUF_VIDEO_MPEG4,
223   BE_FOURCC('M', 'J', 'P', 'G'), BUF_VIDEO_MJPEG,
224   BE_FOURCC('M', 'P', '4', '1'), BUF_VIDEO_MSMPEG4_V1,
225 /*BE_FOURCC('M', 'P', '4', '1'), BUF_VIDEO_MSMPEG4_V2,*/
226   BE_FOURCC('M', 'P', '4', '2'), BUF_VIDEO_MSMPEG4_V2,
227   BE_FOURCC('M', 'P', '4', '3'), BUF_VIDEO_MSMPEG4_V3,
228   BE_FOURCC('M', 'P', '4', 'S'), BUF_VIDEO_MPEG4,
229   BE_FOURCC('M', 'P', 'E', 'G'), BUF_VIDEO_MPEG,
230   BE_FOURCC('M', 'P', 'G', '3'), BUF_VIDEO_MSMPEG4_V3,
231   BE_FOURCC('M', 'P', 'G', '4'), BUF_VIDEO_MSMPEG4_V1,
232   BE_FOURCC('M', 'S', 'S', '1'), BUF_VIDEO_MSS1,
233   BE_FOURCC('M', 'S', 'V', 'C'), BUF_VIDEO_MSVC,
234   BE_FOURCC('M', 'S', 'Z', 'H'), BUF_VIDEO_MSZH,
235   BE_FOURCC('M', 'V', 'I', '2'), BUF_VIDEO_MVI2,
236   BE_FOURCC('P', 'G', 'V', 'V'), BUF_VIDEO_PGVV,
237   BE_FOURCC('P', 'I', 'M', '1'), BUF_VIDEO_MPEG,
238   BE_FOURCC('P', 'I', 'X', 'L'), BUF_VIDEO_XL,
239   BE_FOURCC('Q', '1', '.', '0'), BUF_VIDEO_QPEG,
240   BE_FOURCC('Q', '1', '.', '1'), BUF_VIDEO_QPEG,
241   BE_FOURCC('Q', 'P', 'E', 'G'), BUF_VIDEO_QPEG,
242   BE_FOURCC('R', 'T', '2', '1'), BUF_VIDEO_RT21,
243   BE_FOURCC('R', 'V', '1', '0'), BUF_VIDEO_RV10,
244   BE_FOURCC('R', 'V', '2', '0'), BUF_VIDEO_RV20,
245   BE_FOURCC('R', 'V', '3', '0'), BUF_VIDEO_RV30,
246   BE_FOURCC('R', 'V', '4', '0'), BUF_VIDEO_RV40,
247   BE_FOURCC('S', 'E', 'G', 'A'), BUF_VIDEO_SEGA,
248   BE_FOURCC('S', 'N', 'O', 'W'), BUF_VIDEO_SNOW,
249   BE_FOURCC('S', 'V', 'Q', '1'), BUF_VIDEO_SORENSON_V1,
250   BE_FOURCC('S', 'V', 'Q', '3'), BUF_VIDEO_SORENSON_V3,
251   BE_FOURCC('T', 'M', '2', '0'), BUF_VIDEO_DUCKTM2,
252   BE_FOURCC('U', '2', '6', '3'), BUF_VIDEO_H263,
253   BE_FOURCC('U', 'C', 'O', 'D'), BUF_VIDEO_UCOD,
254   BE_FOURCC('U', 'L', 'T', 'I'), BUF_VIDEO_ULTI,
255   BE_FOURCC('V', 'C', 'R', '1'), BUF_VIDEO_ATIVCR1,
256   BE_FOURCC('V', 'C', 'R', '2'), BUF_VIDEO_ATIVCR2,
257   BE_FOURCC('V', 'I', 'V', 'O'), BUF_VIDEO_I263,
258   BE_FOURCC('V', 'M', 'n', 'c'), BUF_VIDEO_VMNC,
259   BE_FOURCC('V', 'P', '3', ' '), BUF_VIDEO_VP31,
260   BE_FOURCC('V', 'P', '3', '0'), BUF_VIDEO_VP31,
261   BE_FOURCC('V', 'P', '3', '1'), BUF_VIDEO_VP31,
262   BE_FOURCC('V', 'P', '4', '0'), BUF_VIDEO_VP4,
263   BE_FOURCC('V', 'P', '5', '0'), BUF_VIDEO_VP5,
264   BE_FOURCC('V', 'P', '6', '0'), BUF_VIDEO_VP6,
265   BE_FOURCC('V', 'P', '6', '1'), BUF_VIDEO_VP6,
266   BE_FOURCC('V', 'P', '6', '2'), BUF_VIDEO_VP6,
267   BE_FOURCC('V', 'P', '6', 'F'), BUF_VIDEO_VP6F,
268   BE_FOURCC('V', 'P', '8', '0'), BUF_VIDEO_VP8,
269   BE_FOURCC('V', 'P', '9', '0'), BUF_VIDEO_VP9,
270   BE_FOURCC('W', 'H', 'A', 'M'), BUF_VIDEO_MSVC,
271   BE_FOURCC('W', 'M', 'V', '1'), BUF_VIDEO_WMV7,
272   BE_FOURCC('W', 'M', 'V', '2'), BUF_VIDEO_WMV8,
273   BE_FOURCC('W', 'M', 'V', '3'), BUF_VIDEO_WMV9,
274   BE_FOURCC('W', 'M', 'V', 'A'), BUF_VIDEO_VC1,
275   BE_FOURCC('W', 'M', 'V', 'P'), BUF_VIDEO_WMV9,
276   BE_FOURCC('W', 'N', 'V', '1'), BUF_VIDEO_WNV1,
277   BE_FOURCC('W', 'V', 'C', '1'), BUF_VIDEO_VC1,
278   BE_FOURCC('X', '2', '6', '4'), BUF_VIDEO_H264,
279   BE_FOURCC('X', 'I', 'X', 'L'), BUF_VIDEO_XL,
280   BE_FOURCC('X', 'V', 'I', 'D'), BUF_VIDEO_XVID,
281   BE_FOURCC('X', 'X', 'A', 'N'), BUF_VIDEO_XXAN,
282   BE_FOURCC('X', 'x', 'a', 'n'), BUF_VIDEO_XXAN,
283   BE_FOURCC('Y', 'U', 'Y', '2'), BUF_VIDEO_YUY2,
284   BE_FOURCC('Y', 'V', '1', '2'), BUF_VIDEO_YV12,
285   BE_FOURCC('Y', 'V', 'U', '9'), BUF_VIDEO_YVU9,
286   BE_FOURCC('Z', 'L', 'I', 'B'), BUF_VIDEO_ZLIB,
287   BE_FOURCC('Z', 'M', 'B', 'V'), BUF_VIDEO_ZMBV,
288   BE_FOURCC('Z', 'y', 'G', 'o'), BUF_VIDEO_ZYGO,
289   BE_FOURCC('a', 'v', '0', '1'), BUF_VIDEO_AV1,
290   BE_FOURCC('a', 'v', 'c', '1'), BUF_VIDEO_H264,
291   BE_FOURCC('a', 'z', 'p', 'r'), BUF_VIDEO_RPZA,
292   BE_FOURCC('c', 'r', 'a', 'm'), BUF_VIDEO_MSVC,
293   BE_FOURCC('c', 'v', 'i', 'd'), BUF_VIDEO_CINEPAK,
294   BE_FOURCC('c', 'y', 'u', 'v'), BUF_VIDEO_CYUV,
295   BE_FOURCC('d', 'i', 'v', '2'), BUF_VIDEO_MSMPEG4_V2,
296   BE_FOURCC('d', 'i', 'v', '3'), BUF_VIDEO_MSMPEG4_V3,
297   BE_FOURCC('d', 'i', 'v', '4'), BUF_VIDEO_MSMPEG4_V3,
298   BE_FOURCC('d', 'i', 'v', '5'), BUF_VIDEO_MSMPEG4_V3,
299   BE_FOURCC('d', 'i', 'v', '6'), BUF_VIDEO_MSMPEG4_V3,
300   BE_FOURCC('d', 'i', 'v', 'x'), BUF_VIDEO_MPEG4,
301   BE_FOURCC('d', 'm', 'b', '1'), BUF_VIDEO_MJPEG,
302   BE_FOURCC('d', 'v', 'c', 'p'), BUF_VIDEO_DV,
303   BE_FOURCC('d', 'v', 's', 'd'), BUF_VIDEO_DV,
304   BE_FOURCC('g', 'i', 'f', ' '), BUF_VIDEO_IMAGE,
305   BE_FOURCC('h', '2', '6', '3'), BUF_VIDEO_H263,
306   BE_FOURCC('h', '2', '6', '4'), BUF_VIDEO_H264,
307   BE_FOURCC('h', 'e', 'v', '1'), BUF_VIDEO_HEVC,
308   BE_FOURCC('h', 'e', 'v', 'c'), BUF_VIDEO_HEVC,
309   BE_FOURCC('h', 'v', 'c', '1'), BUF_VIDEO_HEVC,
310   BE_FOURCC('i', '2', '6', '3'), BUF_VIDEO_I263,
311   BE_FOURCC('i', 'v', '3', '1'), BUF_VIDEO_IV31,
312   BE_FOURCC('i', 'v', '3', '2'), BUF_VIDEO_IV32,
313   BE_FOURCC('i', 'v', '4', '1'), BUF_VIDEO_IV41,
314   BE_FOURCC('i', 'v', '5', '0'), BUF_VIDEO_IV50,
315   BE_FOURCC('j', 'p', 'e', 'g'), BUF_VIDEO_JPEG,
316   BE_FOURCC('m', '4', 's', '2'), BUF_VIDEO_MPEG4,
317   BE_FOURCC('m', 'j', 'p', 'a'), BUF_VIDEO_MJPEG,
318   BE_FOURCC('m', 'j', 'p', 'b'), BUF_VIDEO_MJPEG_B,
319   BE_FOURCC('m', 'p', '4', '1'), BUF_VIDEO_MSMPEG4_V1,
320 /*BE_FOURCC('m', 'p', '4', '1'), BUF_VIDEO_MSMPEG4_V2,*/
321   BE_FOURCC('m', 'p', '4', '2'), BUF_VIDEO_MSMPEG4_V2,
322   BE_FOURCC('m', 'p', '4', '3'), BUF_VIDEO_MSMPEG4_V3,
323   BE_FOURCC('m', 'p', '4', 'v'), BUF_VIDEO_MPEG4,
324   BE_FOURCC('m', 'p', 'e', 'g'), BUF_VIDEO_MPEG,
325   BE_FOURCC('m', 'p', 'g', '1'), BUF_VIDEO_MPEG,
326   BE_FOURCC('m', 'p', 'g', '2'), BUF_VIDEO_MPEG,
327   BE_FOURCC('m', 'p', 'g', '4'), BUF_VIDEO_MSMPEG4_V1,
328   BE_FOURCC('m', 's', 'v', 'c'), BUF_VIDEO_MSVC,
329   BE_FOURCC('m', 'v', 'i', '2'), BUF_VIDEO_MVI2,
330   BE_FOURCC('p', 'n', 'g', ' '), BUF_VIDEO_PNG,
331   BE_FOURCC('q', 'd', 'r', 'w'), BUF_VIDEO_QDRW,
332   BE_FOURCC('r', 'a', 'w', ' '), BUF_VIDEO_RGB,
333   BE_FOURCC('r', 'l', 'e', ' '), BUF_VIDEO_QTRLE,
334   BE_FOURCC('r', 'p', 'z', 'a'), BUF_VIDEO_RPZA,
335   BE_FOURCC('s', '2', '6', '3'), BUF_VIDEO_H263,
336   BE_FOURCC('s', 'e', 'g', 'a'), BUF_VIDEO_SEGA,
337   BE_FOURCC('s', 'm', 'c', ' '), BUF_VIDEO_SMC,
338   BE_FOURCC('s', 'v', 'q', '1'), BUF_VIDEO_SORENSON_V1,
339   BE_FOURCC('s', 'v', 'q', '3'), BUF_VIDEO_SORENSON_V3,
340   BE_FOURCC('s', 'v', 'q', 'i'), BUF_VIDEO_SORENSON_V1,
341   BE_FOURCC('t', 's', 'c', 'c'), BUF_VIDEO_TSCC,
342   BE_FOURCC('u', 'c', 'o', 'd'), BUF_VIDEO_UCOD,
343   BE_FOURCC('v', 'c', '-', '1'), BUF_VIDEO_VC1,
344   BE_FOURCC('v', 'i', 'v', '1'), BUF_VIDEO_I263,
345   BE_FOURCC('v', 'i', 'v', 'o'), BUF_VIDEO_I263,
346   BE_FOURCC('v', 'p', '3', '0'), BUF_VIDEO_VP31,
347   BE_FOURCC('v', 'p', '3', '1'), BUF_VIDEO_VP31,
348   BE_FOURCC('w', 'h', 'a', 'm'), BUF_VIDEO_MSVC,
349   BE_FOURCC('x', '2', '6', '4'), BUF_VIDEO_H264,
350   BE_FOURCC('x', 'v', 'i', 'd'), BUF_VIDEO_XVID,
351   BE_FOURCC('x', 'x', 'a', 'n'), BUF_VIDEO_XXAN,
352   BE_FOURCC('y', 'u', 'v', '2'), BUF_VIDEO_YUY2,
353   BE_FOURCC('y', 'u', 'y', '2'), BUF_VIDEO_YUY2,
354   BE_FOURCC('y', 'v', '1', '2'), BUF_VIDEO_YV12
355 };
356 
_x_fourcc_to_buf_video(uint32_t formattag)357 uint32_t _x_fourcc_to_buf_video (uint32_t formattag) {
358   uint32_t t = formattag;
359   if (t & 0xffff0000) {
360     uint32_t b, e, m;
361 #ifndef WORDS_BIGENDIAN
362     t = (t >> 24) | ((t & 0x00ff0000) >> 8) | ((t & 0x0000ff00) << 8) | (t << 24);
363 #endif
364     b = 0;
365     e = sizeof (sorted_video_4ccs) / sizeof (sorted_video_4ccs[0]) / 2;
366     m = e >> 1;
367     do {
368       uint32_t f = sorted_video_4ccs[2 * m];
369       if (t == f) {
370         return sorted_video_4ccs[2 * m + 1];
371       } else if (t < f) {
372         e = m;
373       } else {
374         b = m + 1;
375       }
376       m = (b + e) >> 1;
377     } while (b != e);
378     return 0;
379   }
380   {
381     uint32_t b, e, m;
382     b = 0;
383     e = sizeof (sorted_video_tags) / sizeof (sorted_video_tags[0]) / 2;
384     m = e >> 1;
385     do {
386       uint32_t f = sorted_video_tags[2 * m];
387       if (t == f) {
388         return sorted_video_tags[2 * m + 1];
389       } else if (t < f) {
390         e = m;
391       } else {
392         b = m + 1;
393       }
394       m = (b + e) >> 1;
395     } while (b != e);
396     return 0;
397   }
398 }
399 
400 static const char * const video_names[] = {
401   /* 00 BUF_VIDEO_MPEG        */ "MPEG 1/2",
402   /* 01 BUF_VIDEO_MPEG4       */ "ISO-MPEG4/OpenDivx",
403   /* 02 BUF_VIDEO_CINEPAK     */ "Cinepak",
404   /* 03 BUF_VIDEO_SORENSON_V1 */ "Sorenson Video 1",
405   /* 04 BUF_VIDEO_MSMPEG4_V2  */ "Microsoft MPEG-4 v2",
406   /* 05 BUF_VIDEO_MSMPEG4_V3  */ "Microsoft MPEG-4 v3",
407   /* 06 BUF_VIDEO_MJPEG       */ "Motion JPEG",
408   /* 07 BUF_VIDEO_IV50        */ "Indeo Video 5.0",
409   /* 08 BUF_VIDEO_IV41        */ "Indeo Video 4.1",
410   /* 09 BUF_VIDEO_IV32        */ "Indeo Video 3.2",
411   /* 0a BUF_VIDEO_IV31        */ "Indeo Video 3.1",
412   /* 0b BUF_VIDEO_ATIVCR1     */ "ATI VCR1",
413   /* 0c BUF_VIDEO_ATIVCR2     */ "ATI VCR2",
414   /* 0d BUF_VIDEO_I263        */ "I263",
415   /* 0e BUF_VIDEO_RV10        */ "Real Video 1.0",
416   /* 0f BUF_VIDEO_??          */ "(unused type 0x0f)",
417   /* 10 BUF_VIDEO_RGB         */ "Raw RGB",
418   /* 11 BUF_VIDEO_YUY2        */ "YUY2",
419   /* 12 BUF_VIDEO_JPEG        */ "JPEG",
420   /* 13 BUF_VIDEO_WMV7        */ "Windows Media Video 7",
421   /* 14 BUF_VIDEO_WMV8        */ "Windows Media Video 8",
422   /* 15 BUF_VIDEO_MSVC        */ "Microsoft Video 1",
423   /* 16 BUF_VIDEO_DV          */ "Sony Digital Video (DV)",
424   /* 17 BUF_VIDEO_REAL        */ "REAL",
425   /* 18 BUF_VIDEO_VP31        */ "On2 VP3.1",
426   /* 19 BUF_VIDEO_H263        */ "H263",
427   /* 1a BUF_VIDEO_3IVX        */ "3ivx MPEG-4",
428   /* 1b BUF_VIDEO_CYUV        */ "Creative YUV",
429   /* 1c BUF_VIDEO_DIVX5       */ "DivX 5",
430   /* 1d BUF_VIDEO_XVID        */ "XviD",
431   /* 1e BUF_VIDEO_SMC         */ "Apple Quicktime Graphics (SMC)",
432   /* 1f BUF_VIDEO_RPZA        */ "Apple Quicktime (RPZA)",
433   /* 20 BUF_VIDEO_QTRLE       */ "Apple Quicktime Animation (RLE)",
434   /* 21 BUF_VIDEO_MSRLE       */ "Microsoft RLE",
435   /* 22 BUF_VIDEO_DUCKTM1     */ "Duck Truemotion v1",
436   /* 23 BUF_VIDEO_FLI         */ "FLI",
437   /* 24 BUF_VIDEO_ROQ         */ "Id Software RoQ",
438   /* 25 BUF_VIDEO_SORENSON_V3 */ "Sorenson Video 3",
439   /* 26 BUF_VIDEO_MSMPEG4_V1  */ "Microsoft MPEG-4 v1",
440   /* 27 BUF_VIDEO_MSS1        */ "Windows Screen Video",
441   /* 28 BUF_VIDEO_IDCIN       */ "Id Software CIN",
442   /* 29 BUF_VIDEO_PGVV        */ "Radius Studio",
443   /* 2a BUF_VIDEO_ZYGO        */ "ZyGo Video",
444   /* 2b BUF_VIDEO_TSCC        */ "TechSmith Screen Capture Codec",
445   /* 2c BUF_VIDEO_YVU9        */ "Raw YVU9 Planar Data",
446   /* 2d BUF_VIDEO_VQA         */ "Westwood Studios VQA",
447   /* 2e BUF_VIDEO_GREY        */ "Raw Greyscale",
448   /* 2f BUF_VIDEO_XXAN        */ "Wing Commander IV Video Codec",
449   /* 30 BUF_VIDEO_WC3         */ "Xan WC3",
450   /* 31 BUF_VIDEO_YV12        */ "Raw Planar YV12",
451   /* 32 BUF_VIDEO_SEGA        */ "Cinepak for Sega",
452   /* 33 BUF_VIDEO_RV20        */ "Real Video 2.0",
453   /* 34 BUF_VIDEO_RV30        */ "Real Video 3.0",
454   /* 35 BUF_VIDEO_MVI2        */ "Motion Pixels",
455   /* 36 BUF_VIDEO_UCOD        */ "ClearVideo",
456   /* 37 BUF_VIDEO_WMV9        */ "Windows Media Video 9",
457   /* 38 BUF_VIDEO_INTERPLAY   */ "Interplay MVE",
458   /* 39 BUF_VIDEO_RV40        */ "Real Video 4.0",
459   /* 3a BUF_VIDEO_PSX_MDEC    */ "PSX MEDC",
460   /* 3b BUF_VIDEO_YUV_FRAMES  */ "Uncompressed YUV",
461   /* 3c BUF_VIDEO_HUFFYUV     */ "HuffYUV",
462   /* 3d BUF_VIDEO_IMAGE       */ "Image",
463   /* 3e BUF_VIDEO_THEORA      */ "Ogg Theora",
464   /* 3f BUF_VIDEO_4XM         */ "4X Video",
465   /* 40 BUF_VIDEO_I420        */ "Raw Planar I420",
466   /* 41 BUF_VIDEO_VP4         */ "On2 VP4",
467   /* 42 BUF_VIDEO_VP5         */ "On2 VP5",
468   /* 43 BUF_VIDEO_VP6         */ "On2 VP6",
469   /* 44 BUF_VIDEO_VMD         */ "Sierra VMD Video",
470   /* 45 BUF_VIDEO_MSZH        */ "MSZH Video",
471   /* 46 BUF_VIDEO_ZLIB        */ "ZLIB Video",
472   /* 47 BUF_VIDEO_8BPS        */ "Planar RGB",
473   /* 48 BUF_VIDEO_ASV1        */ "ASV v1 Video",
474   /* 49 BUF_VIDEO_ASV2        */ "ASV v2 Video",
475   /* 4a BUF_VIDEO_BITPLANE    */ "Amiga picture",
476   /* 4b BUF_VIDEO_BITPLANE_BR1*/ "Amiga picture",
477   /* 4c BUF_VIDEO_FLV1        */ "Flash video 1",
478   /* 4d BUF_VIDEO_H264        */ "Advanced Video Coding (H264)",
479   /* 4e BUF_VIDEO_MJPEG_B     */ "Motion JPEG B",
480   /* 4f BUF_VIDEO_H261        */ "H.261",
481   /* 50 BUF_VIDEO_AASC        */ "Autodesk Animator Studio Codec",
482   /* 51 BUF_VIDEO_LOCO        */ "LOCO",
483   /* 52 BUF_VIDEO_QDRW        */ "QuickDraw",
484   /* 53 BUF_VIDEO_QPEG        */ "Q-Team QPEG Video",
485   /* 54 BUF_VIDEO_ULTI        */ "IBM UltiMotion",
486   /* 55 BUF_VIDEO_WNV1        */ "Winnow Video",
487   /* 56 BUF_VIDEO_XL          */ "Miro/Pinnacle VideoXL",
488   /* 57 BUF_VIDEO_RT21        */ "Indeo/RealTime 2",
489   /* 58 BUF_VIDEO_FPS1        */ "Fraps FPS1",
490   /* 59 BUF_VIDEO_DUCKTM2     */ "Duck TrueMotion 2",
491   /* 5a BUF_VIDEO_CSCD        */ "CamStudio",
492   /* 5b BUF_VIDEO_ALGMM       */ "American Laser Games MM",
493   /* 5c BUF_VIDEO_ZMBV        */ "Zip Motion Blocks Video",
494   /* 5d BUF_VIDEO_AVS         */ "AVS",
495   /* 5e BUF_VIDEO_SMACKER     */ "Smacker",
496   /* 5f BUF_VIDEO_NUV         */ "NullSoft Video",
497   /* 60 BUF_VIDEO_KMVC        */ "Karl Morton's Video Codec",
498   /* 61 BUF_VIDEO_FLASHSV     */ "Flash Screen Video 1",
499   /* 62 BUF_VIDEO_CAVS        */ "Chinese AVS",
500   /* 63 BUF_VIDEO_VP6F        */ "On2 VP6 with alpha channel",
501   /* 64 BUF_VIDEO_THEORA_RAW  */ "Theora",
502   /* 65 BUF_VIDEO_VC1         */ "Windows Media Video VC-1",
503   /* 66 BUF_VIDEO_VMNC        */ "VMware Screen Codec",
504   /* 67 BUF_VIDEO_SNOW        */ "Snow",
505   /* 68 BUF_VIDEO_VP8         */ "On2 VP8",
506   /* 69 BUF_VIDEO_VP9         */ "VP9",
507   /* 6a BUF_VIDEO_HEVC        */ "HEVC",
508   /* 6b BUF_VIDEO_AV1         */ "AV1",
509   /* 6c BUF_VIDEO_PNG         */ "PNG",
510 };
511 
_x_buf_video_name(uint32_t buf_type)512 const char *_x_buf_video_name (uint32_t buf_type) {
513   if ((buf_type & 0xff000000) != BUF_VIDEO_BASE)
514     return "";
515   buf_type = (buf_type >> 16) & 0xff;
516   if (buf_type >= sizeof (video_names) / sizeof (video_names[0]))
517     return "";
518   return video_names[buf_type];
519 }
520 
521 static const char * const audio_names[] = {
522   /* 00 BUF_AUDIO_A52         */ "AC3/A52",
523   /* 01 BUF_AUDIO_MPEG        */ "MPEG layer 1/2/3",
524   /* 02 BUF_AUDIO_LPCM_BE     */ "Linear PCM big endian",
525   /* 03 BUF_AUDIO_LPCM_LE     */ "Linear PCM little endian",
526   /* 04 BUF_AUDIO_WMAV1       */ "Windows Media Audio v1",
527   /* 05 BUF_AUDIO_DTS         */ "Digitales TonSystem (DTS)",
528   /* 06 BUF_AUDIO_MSADPCM     */ "MS ADPCM",
529   /* 07 BUF_AUDIO_MSIMAADPCM  */ "MS IMA ADPCM",
530   /* 08 BUF_AUDIO_MSGSM       */ "MS GSM",
531   /* 09 BUF_AUDIO_VORBIS      */ "OggVorbis Audio",
532   /* 0a BUF_AUDIO_IMC         */ "Intel Music Coder",
533   /* 0b BUF_AUDIO_LH          */ "Lernout & Hauspie",
534   /* 0c BUF_AUDIO_VOXWARE     */ "Voxware Metasound",
535   /* 0d BUF_AUDIO_ACELPNET    */ "ACELP.net",
536   /* 0e BUF_AUDIO_AAC         */ "Advanced Audio Coding (MPEG-4 AAC)",
537   /* 0f BUF_AUDIO_DNET        */ "RealAudio DNET",
538   /* 10 BUF_AUDIO_VIVOG723    */ "Vivo G.723/Siren Audio Codec",
539   /* 11 BUF_AUDIO_DK3ADPCM    */ "Duck DK3 ADPCM (rogue format number)",
540   /* 12 BUF_AUDIO_DK4ADPCM    */ "Duck DK4 ADPCM (rogue format number)",
541   /* 13 BUF_AUDIO_ROQ         */ "RoQ DPCM",
542   /* 14 BUF_AUDIO_QTIMAADPCM  */ "QT IMA ADPCM",
543   /* 15 BUF_AUDIO_MAC3        */ "Apple MACE 3:1 Audio",
544   /* 16 BUF_AUDIO_MAC6        */ "Apple MACE 6:1 Audio",
545   /* 17 BUF_AUDIO_QDESIGN1    */ "QDesign Audio v1",
546   /* 18 BUF_AUDIO_QDESIGN2    */ "QDesign Audio v2",
547   /* 19 BUF_AUDIO_QCLP        */ "Qualcomm PureVoice",
548   /* 1a BUF_AUDIO_SMJPEG_IMA  */ "SMJPEG IMA",
549   /* 1b BUF_AUDIO_VQA_IMA     */ "Westwood Studios IMA",
550   /* 1c BUF_AUDIO_MULAW       */ "mu-law logarithmic PCM",
551   /* 1d BUF_AUDIO_ALAW        */ "A-law logarithmic PCM",
552   /* 1e BUF_AUDIO_GSM610      */ "GSM 6.10",
553   /* 1f BUF_AUDIO_EA_ADPCM    */ "EA ADPCM",
554   /* 20 BUF_AUDIO_WMAV2       */ "Windows Media Audio v2",
555   /* 21 BUF_AUDIO_COOK        */ "RealAudio COOK",
556   /* 22 BUF_AUDIO_ATRK        */ "RealAudio ATRK",
557   /* 23 BUF_AUDIO_14_4        */ "RealAudio 14.4",
558   /* 24 BUF_AUDIO_28_8        */ "RealAudio 28.8",
559   /* 25 BUF_AUDIO_SIPRO       */ "RealAudio SIPRO",
560   /* 26 BUF_AUDIO_WMAPRO      */ "Windows Media Audio Professional",
561   /* 27 BUF_AUDIO_INTERPLAY   */ "Interplay DPCM",
562   /* 28 BUF_AUDIO_XA_ADPCM    */ "XA ADPCM",
563   /* 29 BUF_AUDIO_WESTWOOD    */ "Westwood",
564   /* 2a BUF_AUDIO_DIALOGIC_IMA*/ "DIALOGIC IMA",
565   /* 2b BUF_AUDIO_NSF         */ "Nosefart",
566   /* 2c BUF_AUDIO_FLAC        */ "Free Lossless Audio Codec (FLAC)",
567   /* 2d BUF_AUDIO_DV          */ "DV Audio",
568   /* 2e BUF_AUDIO_WMAV        */ "Windows Media Audio Voice",
569   /* 2f BUF_AUDIO_SPEEX       */ "Speex",
570   /* 30 BUF_AUDIO_RAWPCM      */ "Raw PCM",
571   /* 31 BUF_AUDIO_4X_ADPCM    */ "4x ADPCM",
572   /* 32 BUF_AUDIO_VMD         */ "VMD",
573   /* 33 BUF_AUDIO_XAN_DPCM    */ "XAN DPCM",
574   /* 34 BUF_AUDIO_ALAC        */ "Apple Lossless Audio Codec",
575   /* 35 BUF_AUDIO_MPC         */ "Musepack",
576   /* 36 BUF_AUDIO_SHORTEN     */ "Shorten",
577   /* 37 BUF_AUDIO_WESTWOOD_SND1*/ "Westwood",
578   /* 38 BUF_AUDIO_WMALL       */ "Windows Media Audio Lossless",
579   /* 39 BUF_AUDIO_TRUESPEECH  */ "Truespeech",
580   /* 3a BUF_AUDIO_TTA         */ "True Audio Lossless",
581   /* 3b BUF_AUDIO_SMACKER     */ "Smacker",
582   /* 3c BUF_AUDIO_FLVADPCM    */ "FLV ADPCM",
583   /* 3d BUF_AUDIO_WAVPACK     */ "Wavpack",
584   /* 3e BUF_AUDIO_MP3ADU      */ "MPEG layer-3 adu",
585   /* 3f BUF_AUDIO_AMR_NB      */ "AMR narrow band",
586   /* 40 BUF_AUDIO_AMR_WB      */ "AMR wide band",
587   /* 41 BUF_AUDIO_EAC3        */ "E-AC-3",
588   /* 42 BUF_AUDIO_AAC_LATM    */ "AAC LATM",
589   /* 43 BUF_AUDIO_ADPCM_G726  */ "ADPCM G.726",
590   /* 44 BUF_AUDIO_OPUS        */ "Opus Audio",
591   /* 45 BUF_AUDIO_TRUEHD      */ "TrueHD Audio"
592 };
593 
_x_buf_audio_name(uint32_t buf_type)594 const char *_x_buf_audio_name (uint32_t buf_type) {
595   if ((buf_type & 0xff000000) != BUF_AUDIO_BASE)
596     return "";
597   buf_type = (buf_type >> 16) & 0xff;
598   if (buf_type >= sizeof (audio_names) / sizeof (audio_names[0]))
599     return "";
600   return audio_names[buf_type];
601 }
602 
code_to_text(char ascii[5],uint32_t code)603 static void code_to_text (char ascii[5], uint32_t code)
604 {
605   int i;
606   for (i = 0; i < 4; ++i)
607   {
608     int byte = code & 0xFF;
609     ascii[i] = (byte < ' ') ? ' ' : (byte >= 0x7F) ? '.' : (char) byte;
610     code >>= 8;
611   }
612   ascii[4] = 0;
613 }
614 
_x_report_video_fourcc(xine_t * xine,const char * module,uint32_t code)615 void _x_report_video_fourcc (xine_t *xine, const char *module, uint32_t code)
616 {
617   if (code)
618   {
619     char ascii[5];
620     code_to_text (ascii, code);
621     xprintf (xine, XINE_VERBOSITY_LOG,
622              _("%s: unknown video FourCC code %#x \"%s\"\n"),
623              module, code, ascii);
624   }
625 }
626 
_x_report_audio_format_tag(xine_t * xine,const char * module,uint32_t code)627 void _x_report_audio_format_tag (xine_t *xine, const char *module, uint32_t code)
628 {
629   if (code)
630   {
631     char ascii[5];
632     code_to_text (ascii, code);
633     xprintf (xine, XINE_VERBOSITY_LOG,
634              _("%s: unknown audio format tag code %#x \"%s\"\n"),
635              module, code, ascii);
636   }
637 }
638 
639 
_x_bmiheader_le2me(xine_bmiheader * bih)640 void _x_bmiheader_le2me( xine_bmiheader *bih ) {
641   /* OBS: fourcc must be read using machine endianness
642    *      so don't play with biCompression here!
643    */
644 
645   bih->biSize = le2me_32(bih->biSize);
646   bih->biWidth = le2me_32(bih->biWidth);
647   bih->biHeight = le2me_32(bih->biHeight);
648   bih->biPlanes = le2me_16(bih->biPlanes);
649   bih->biBitCount = le2me_16(bih->biBitCount);
650   bih->biSizeImage = le2me_32(bih->biSizeImage);
651   bih->biXPelsPerMeter = le2me_32(bih->biXPelsPerMeter);
652   bih->biYPelsPerMeter = le2me_32(bih->biYPelsPerMeter);
653   bih->biClrUsed = le2me_32(bih->biClrUsed);
654   bih->biClrImportant = le2me_32(bih->biClrImportant);
655 }
656 
_x_waveformatex_le2me(xine_waveformatex * wavex)657 void _x_waveformatex_le2me( xine_waveformatex *wavex ) {
658 
659   wavex->wFormatTag = le2me_16(wavex->wFormatTag);
660   wavex->nChannels = le2me_16(wavex->nChannels);
661   wavex->nSamplesPerSec = le2me_32(wavex->nSamplesPerSec);
662   wavex->nAvgBytesPerSec = le2me_32(wavex->nAvgBytesPerSec);
663   wavex->nBlockAlign = le2me_16(wavex->nBlockAlign);
664   wavex->wBitsPerSample = le2me_16(wavex->wBitsPerSample);
665   wavex->cbSize = le2me_16(wavex->cbSize);
666 }
667 
_x_tag32_me2str(char * s,uint32_t tag)668 size_t _x_tag32_me2str (char *s, uint32_t tag) {
669   static const uint8_t tab_hex[16] = "0123456789abcdef";
670   union {uint32_t w; uint8_t b[4];} u;
671   uint8_t *q = (uint8_t *)s;
672   int i;
673   if (!q)
674     return 0;
675   u.w = tag;
676   for (i = 0; i < 4; i++) {
677     uint8_t z = u.b[i];
678     if ((z < 32) || (z > 127)) {
679       *q++ = '\\';
680       *q++ = 'x';
681       *q++ = tab_hex[z >> 4];
682       *q++ = tab_hex[z & 15];
683     } else if (z == '\\') {
684       *q++ = '\\';
685       *q++ = '\\';
686     } else {
687       *q++ = z;
688     }
689   }
690   *q = 0;
691   return q - (uint8_t *)s;
692 }
693