1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * XPM image format 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2012 Paul B Mahol 5cabdff1aSopenharmony_ci * Copyright (c) 2017 Paras Chadha 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 25cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 26cabdff1aSopenharmony_ci#include "avcodec.h" 27cabdff1aSopenharmony_ci#include "codec_internal.h" 28cabdff1aSopenharmony_ci#include "internal.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#define MIN_ELEMENT ' ' 31cabdff1aSopenharmony_ci#define MAX_ELEMENT 0xfe 32cabdff1aSopenharmony_ci#define NB_ELEMENTS (MAX_ELEMENT - MIN_ELEMENT + 1) 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_citypedef struct XPMContext { 35cabdff1aSopenharmony_ci uint32_t *pixels; 36cabdff1aSopenharmony_ci int pixels_size; 37cabdff1aSopenharmony_ci uint8_t *buf; 38cabdff1aSopenharmony_ci int buf_size; 39cabdff1aSopenharmony_ci} XPMDecContext; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_citypedef struct ColorEntry { 42cabdff1aSopenharmony_ci const char *name; ///< a string representing the name of the color 43cabdff1aSopenharmony_ci uint32_t rgb_color; ///< RGB values for the color 44cabdff1aSopenharmony_ci} ColorEntry; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic int color_table_compare(const void *lhs, const void *rhs) 47cabdff1aSopenharmony_ci{ 48cabdff1aSopenharmony_ci return av_strcasecmp(lhs, ((const ColorEntry *)rhs)->name); 49cabdff1aSopenharmony_ci} 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_cistatic const ColorEntry color_table[] = { 52cabdff1aSopenharmony_ci { "AliceBlue", 0xFFF0F8FF }, 53cabdff1aSopenharmony_ci { "AntiqueWhite", 0xFFFAEBD7 }, 54cabdff1aSopenharmony_ci { "Aqua", 0xFF00FFFF }, 55cabdff1aSopenharmony_ci { "Aquamarine", 0xFF7FFFD4 }, 56cabdff1aSopenharmony_ci { "Azure", 0xFFF0FFFF }, 57cabdff1aSopenharmony_ci { "Beige", 0xFFF5F5DC }, 58cabdff1aSopenharmony_ci { "Bisque", 0xFFFFE4C4 }, 59cabdff1aSopenharmony_ci { "Black", 0xFF000000 }, 60cabdff1aSopenharmony_ci { "BlanchedAlmond", 0xFFFFEBCD }, 61cabdff1aSopenharmony_ci { "Blue", 0xFF0000FF }, 62cabdff1aSopenharmony_ci { "BlueViolet", 0xFF8A2BE2 }, 63cabdff1aSopenharmony_ci { "Brown", 0xFFA52A2A }, 64cabdff1aSopenharmony_ci { "BurlyWood", 0xFFDEB887 }, 65cabdff1aSopenharmony_ci { "CadetBlue", 0xFF5F9EA0 }, 66cabdff1aSopenharmony_ci { "Chartreuse", 0xFF7FFF00 }, 67cabdff1aSopenharmony_ci { "Chocolate", 0xFFD2691E }, 68cabdff1aSopenharmony_ci { "Coral", 0xFFFF7F50 }, 69cabdff1aSopenharmony_ci { "CornflowerBlue", 0xFF6495ED }, 70cabdff1aSopenharmony_ci { "Cornsilk", 0xFFFFF8DC }, 71cabdff1aSopenharmony_ci { "Crimson", 0xFFDC143C }, 72cabdff1aSopenharmony_ci { "Cyan", 0xFF00FFFF }, 73cabdff1aSopenharmony_ci { "DarkBlue", 0xFF00008B }, 74cabdff1aSopenharmony_ci { "DarkCyan", 0xFF008B8B }, 75cabdff1aSopenharmony_ci { "DarkGoldenRod", 0xFFB8860B }, 76cabdff1aSopenharmony_ci { "DarkGray", 0xFFA9A9A9 }, 77cabdff1aSopenharmony_ci { "DarkGreen", 0xFF006400 }, 78cabdff1aSopenharmony_ci { "DarkKhaki", 0xFFBDB76B }, 79cabdff1aSopenharmony_ci { "DarkMagenta", 0xFF8B008B }, 80cabdff1aSopenharmony_ci { "DarkOliveGreen", 0xFF556B2F }, 81cabdff1aSopenharmony_ci { "Darkorange", 0xFFFF8C00 }, 82cabdff1aSopenharmony_ci { "DarkOrchid", 0xFF9932CC }, 83cabdff1aSopenharmony_ci { "DarkRed", 0xFF8B0000 }, 84cabdff1aSopenharmony_ci { "DarkSalmon", 0xFFE9967A }, 85cabdff1aSopenharmony_ci { "DarkSeaGreen", 0xFF8FBC8F }, 86cabdff1aSopenharmony_ci { "DarkSlateBlue", 0xFF483D8B }, 87cabdff1aSopenharmony_ci { "DarkSlateGray", 0xFF2F4F4F }, 88cabdff1aSopenharmony_ci { "DarkTurquoise", 0xFF00CED1 }, 89cabdff1aSopenharmony_ci { "DarkViolet", 0xFF9400D3 }, 90cabdff1aSopenharmony_ci { "DeepPink", 0xFFFF1493 }, 91cabdff1aSopenharmony_ci { "DeepSkyBlue", 0xFF00BFFF }, 92cabdff1aSopenharmony_ci { "DimGray", 0xFF696969 }, 93cabdff1aSopenharmony_ci { "DodgerBlue", 0xFF1E90FF }, 94cabdff1aSopenharmony_ci { "FireBrick", 0xFFB22222 }, 95cabdff1aSopenharmony_ci { "FloralWhite", 0xFFFFFAF0 }, 96cabdff1aSopenharmony_ci { "ForestGreen", 0xFF228B22 }, 97cabdff1aSopenharmony_ci { "Fuchsia", 0xFFFF00FF }, 98cabdff1aSopenharmony_ci { "Gainsboro", 0xFFDCDCDC }, 99cabdff1aSopenharmony_ci { "GhostWhite", 0xFFF8F8FF }, 100cabdff1aSopenharmony_ci { "Gold", 0xFFFFD700 }, 101cabdff1aSopenharmony_ci { "GoldenRod", 0xFFDAA520 }, 102cabdff1aSopenharmony_ci { "Gray", 0xFFBEBEBE }, 103cabdff1aSopenharmony_ci { "Green", 0xFF00FF00 }, 104cabdff1aSopenharmony_ci { "GreenYellow", 0xFFADFF2F }, 105cabdff1aSopenharmony_ci { "HoneyDew", 0xFFF0FFF0 }, 106cabdff1aSopenharmony_ci { "HotPink", 0xFFFF69B4 }, 107cabdff1aSopenharmony_ci { "IndianRed", 0xFFCD5C5C }, 108cabdff1aSopenharmony_ci { "Indigo", 0xFF4B0082 }, 109cabdff1aSopenharmony_ci { "Ivory", 0xFFFFFFF0 }, 110cabdff1aSopenharmony_ci { "Khaki", 0xFFF0E68C }, 111cabdff1aSopenharmony_ci { "Lavender", 0xFFE6E6FA }, 112cabdff1aSopenharmony_ci { "LavenderBlush", 0xFFFFF0F5 }, 113cabdff1aSopenharmony_ci { "LawnGreen", 0xFF7CFC00 }, 114cabdff1aSopenharmony_ci { "LemonChiffon", 0xFFFFFACD }, 115cabdff1aSopenharmony_ci { "LightBlue", 0xFFADD8E6 }, 116cabdff1aSopenharmony_ci { "LightCoral", 0xFFF08080 }, 117cabdff1aSopenharmony_ci { "LightCyan", 0xFFE0FFFF }, 118cabdff1aSopenharmony_ci { "LightGoldenRodYellow", 0xFFFAFAD2 }, 119cabdff1aSopenharmony_ci { "LightGreen", 0xFF90EE90 }, 120cabdff1aSopenharmony_ci { "LightGrey", 0xFFD3D3D3 }, 121cabdff1aSopenharmony_ci { "LightPink", 0xFFFFB6C1 }, 122cabdff1aSopenharmony_ci { "LightSalmon", 0xFFFFA07A }, 123cabdff1aSopenharmony_ci { "LightSeaGreen", 0xFF20B2AA }, 124cabdff1aSopenharmony_ci { "LightSkyBlue", 0xFF87CEFA }, 125cabdff1aSopenharmony_ci { "LightSlateGray", 0xFF778899 }, 126cabdff1aSopenharmony_ci { "LightSteelBlue", 0xFFB0C4DE }, 127cabdff1aSopenharmony_ci { "LightYellow", 0xFFFFFFE0 }, 128cabdff1aSopenharmony_ci { "Lime", 0xFF00FF00 }, 129cabdff1aSopenharmony_ci { "LimeGreen", 0xFF32CD32 }, 130cabdff1aSopenharmony_ci { "Linen", 0xFFFAF0E6 }, 131cabdff1aSopenharmony_ci { "Magenta", 0xFFFF00FF }, 132cabdff1aSopenharmony_ci { "Maroon", 0xFFB03060 }, 133cabdff1aSopenharmony_ci { "MediumAquaMarine", 0xFF66CDAA }, 134cabdff1aSopenharmony_ci { "MediumBlue", 0xFF0000CD }, 135cabdff1aSopenharmony_ci { "MediumOrchid", 0xFFBA55D3 }, 136cabdff1aSopenharmony_ci { "MediumPurple", 0xFF9370D8 }, 137cabdff1aSopenharmony_ci { "MediumSeaGreen", 0xFF3CB371 }, 138cabdff1aSopenharmony_ci { "MediumSlateBlue", 0xFF7B68EE }, 139cabdff1aSopenharmony_ci { "MediumSpringGreen", 0xFF00FA9A }, 140cabdff1aSopenharmony_ci { "MediumTurquoise", 0xFF48D1CC }, 141cabdff1aSopenharmony_ci { "MediumVioletRed", 0xFFC71585 }, 142cabdff1aSopenharmony_ci { "MidnightBlue", 0xFF191970 }, 143cabdff1aSopenharmony_ci { "MintCream", 0xFFF5FFFA }, 144cabdff1aSopenharmony_ci { "MistyRose", 0xFFFFE4E1 }, 145cabdff1aSopenharmony_ci { "Moccasin", 0xFFFFE4B5 }, 146cabdff1aSopenharmony_ci { "NavajoWhite", 0xFFFFDEAD }, 147cabdff1aSopenharmony_ci { "Navy", 0xFF000080 }, 148cabdff1aSopenharmony_ci { "None", 0x00000000 }, 149cabdff1aSopenharmony_ci { "OldLace", 0xFFFDF5E6 }, 150cabdff1aSopenharmony_ci { "Olive", 0xFF808000 }, 151cabdff1aSopenharmony_ci { "OliveDrab", 0xFF6B8E23 }, 152cabdff1aSopenharmony_ci { "Orange", 0xFFFFA500 }, 153cabdff1aSopenharmony_ci { "OrangeRed", 0xFFFF4500 }, 154cabdff1aSopenharmony_ci { "Orchid", 0xFFDA70D6 }, 155cabdff1aSopenharmony_ci { "PaleGoldenRod", 0xFFEEE8AA }, 156cabdff1aSopenharmony_ci { "PaleGreen", 0xFF98FB98 }, 157cabdff1aSopenharmony_ci { "PaleTurquoise", 0xFFAFEEEE }, 158cabdff1aSopenharmony_ci { "PaleVioletRed", 0xFFD87093 }, 159cabdff1aSopenharmony_ci { "PapayaWhip", 0xFFFFEFD5 }, 160cabdff1aSopenharmony_ci { "PeachPuff", 0xFFFFDAB9 }, 161cabdff1aSopenharmony_ci { "Peru", 0xFFCD853F }, 162cabdff1aSopenharmony_ci { "Pink", 0xFFFFC0CB }, 163cabdff1aSopenharmony_ci { "Plum", 0xFFDDA0DD }, 164cabdff1aSopenharmony_ci { "PowderBlue", 0xFFB0E0E6 }, 165cabdff1aSopenharmony_ci { "Purple", 0xFFA020F0 }, 166cabdff1aSopenharmony_ci { "Red", 0xFFFF0000 }, 167cabdff1aSopenharmony_ci { "RosyBrown", 0xFFBC8F8F }, 168cabdff1aSopenharmony_ci { "RoyalBlue", 0xFF4169E1 }, 169cabdff1aSopenharmony_ci { "SaddleBrown", 0xFF8B4513 }, 170cabdff1aSopenharmony_ci { "Salmon", 0xFFFA8072 }, 171cabdff1aSopenharmony_ci { "SandyBrown", 0xFFF4A460 }, 172cabdff1aSopenharmony_ci { "SeaGreen", 0xFF2E8B57 }, 173cabdff1aSopenharmony_ci { "SeaShell", 0xFFFFF5EE }, 174cabdff1aSopenharmony_ci { "Sienna", 0xFFA0522D }, 175cabdff1aSopenharmony_ci { "Silver", 0xFFC0C0C0 }, 176cabdff1aSopenharmony_ci { "SkyBlue", 0xFF87CEEB }, 177cabdff1aSopenharmony_ci { "SlateBlue", 0xFF6A5ACD }, 178cabdff1aSopenharmony_ci { "SlateGray", 0xFF708090 }, 179cabdff1aSopenharmony_ci { "Snow", 0xFFFFFAFA }, 180cabdff1aSopenharmony_ci { "SpringGreen", 0xFF00FF7F }, 181cabdff1aSopenharmony_ci { "SteelBlue", 0xFF4682B4 }, 182cabdff1aSopenharmony_ci { "Tan", 0xFFD2B48C }, 183cabdff1aSopenharmony_ci { "Teal", 0xFF008080 }, 184cabdff1aSopenharmony_ci { "Thistle", 0xFFD8BFD8 }, 185cabdff1aSopenharmony_ci { "Tomato", 0xFFFF6347 }, 186cabdff1aSopenharmony_ci { "Turquoise", 0xFF40E0D0 }, 187cabdff1aSopenharmony_ci { "Violet", 0xFFEE82EE }, 188cabdff1aSopenharmony_ci { "Wheat", 0xFFF5DEB3 }, 189cabdff1aSopenharmony_ci { "White", 0xFFFFFFFF }, 190cabdff1aSopenharmony_ci { "WhiteSmoke", 0xFFF5F5F5 }, 191cabdff1aSopenharmony_ci { "Yellow", 0xFFFFFF00 }, 192cabdff1aSopenharmony_ci { "YellowGreen", 0xFF9ACD32 } 193cabdff1aSopenharmony_ci}; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_cistatic unsigned hex_char_to_number(uint8_t x) 196cabdff1aSopenharmony_ci{ 197cabdff1aSopenharmony_ci if (x >= 'a' && x <= 'f') 198cabdff1aSopenharmony_ci x -= 'a' - 10; 199cabdff1aSopenharmony_ci else if (x >= 'A' && x <= 'F') 200cabdff1aSopenharmony_ci x -= 'A' - 10; 201cabdff1aSopenharmony_ci else if (x >= '0' && x <= '9') 202cabdff1aSopenharmony_ci x -= '0'; 203cabdff1aSopenharmony_ci else 204cabdff1aSopenharmony_ci x = 0; 205cabdff1aSopenharmony_ci return x; 206cabdff1aSopenharmony_ci} 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci/* 209cabdff1aSopenharmony_ci * Function same as strcspn but ignores characters if they are inside a C style comments 210cabdff1aSopenharmony_ci */ 211cabdff1aSopenharmony_cistatic size_t mod_strcspn(const char *string, const char *reject) 212cabdff1aSopenharmony_ci{ 213cabdff1aSopenharmony_ci int i, j; 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci for (i = 0; string && string[i]; i++) { 216cabdff1aSopenharmony_ci if (string[i] == '/' && string[i+1] == '*') { 217cabdff1aSopenharmony_ci i += 2; 218cabdff1aSopenharmony_ci while ( string && string[i] && (string[i] != '*' || string[i+1] != '/') ) 219cabdff1aSopenharmony_ci i++; 220cabdff1aSopenharmony_ci i++; 221cabdff1aSopenharmony_ci } else if (string[i] == '/' && string[i+1] == '/') { 222cabdff1aSopenharmony_ci i += 2; 223cabdff1aSopenharmony_ci while ( string && string[i] && string[i] != '\n' ) 224cabdff1aSopenharmony_ci i++; 225cabdff1aSopenharmony_ci } else { 226cabdff1aSopenharmony_ci for (j = 0; reject && reject[j]; j++) { 227cabdff1aSopenharmony_ci if (string[i] == reject[j]) 228cabdff1aSopenharmony_ci break; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci if (reject && reject[j]) 231cabdff1aSopenharmony_ci break; 232cabdff1aSopenharmony_ci } 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci return i; 235cabdff1aSopenharmony_ci} 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_cistatic uint32_t color_string_to_rgba(const char *p, int len) 238cabdff1aSopenharmony_ci{ 239cabdff1aSopenharmony_ci uint32_t ret = 0xFF000000; 240cabdff1aSopenharmony_ci const ColorEntry *entry; 241cabdff1aSopenharmony_ci char color_name[100]; 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci len = FFMIN(FFMAX(len, 0), sizeof(color_name) - 1); 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci if (*p == '#') { 246cabdff1aSopenharmony_ci p++; 247cabdff1aSopenharmony_ci len--; 248cabdff1aSopenharmony_ci if (len == 3) { 249cabdff1aSopenharmony_ci ret |= (hex_char_to_number(p[2]) << 4) | 250cabdff1aSopenharmony_ci (hex_char_to_number(p[1]) << 12) | 251cabdff1aSopenharmony_ci (hex_char_to_number(p[0]) << 20); 252cabdff1aSopenharmony_ci } else if (len == 4) { 253cabdff1aSopenharmony_ci ret = (hex_char_to_number(p[3]) << 4) | 254cabdff1aSopenharmony_ci (hex_char_to_number(p[2]) << 12) | 255cabdff1aSopenharmony_ci (hex_char_to_number(p[1]) << 20) | 256cabdff1aSopenharmony_ci (hex_char_to_number(p[0]) << 28); 257cabdff1aSopenharmony_ci } else if (len == 6) { 258cabdff1aSopenharmony_ci ret |= hex_char_to_number(p[5]) | 259cabdff1aSopenharmony_ci (hex_char_to_number(p[4]) << 4) | 260cabdff1aSopenharmony_ci (hex_char_to_number(p[3]) << 8) | 261cabdff1aSopenharmony_ci (hex_char_to_number(p[2]) << 12) | 262cabdff1aSopenharmony_ci (hex_char_to_number(p[1]) << 16) | 263cabdff1aSopenharmony_ci (hex_char_to_number(p[0]) << 20); 264cabdff1aSopenharmony_ci } else if (len == 8) { 265cabdff1aSopenharmony_ci ret = hex_char_to_number(p[7]) | 266cabdff1aSopenharmony_ci (hex_char_to_number(p[6]) << 4) | 267cabdff1aSopenharmony_ci (hex_char_to_number(p[5]) << 8) | 268cabdff1aSopenharmony_ci (hex_char_to_number(p[4]) << 12) | 269cabdff1aSopenharmony_ci (hex_char_to_number(p[3]) << 16) | 270cabdff1aSopenharmony_ci (hex_char_to_number(p[2]) << 20) | 271cabdff1aSopenharmony_ci (hex_char_to_number(p[1]) << 24) | 272cabdff1aSopenharmony_ci (hex_char_to_number(p[0]) << 28); 273cabdff1aSopenharmony_ci } 274cabdff1aSopenharmony_ci } else { 275cabdff1aSopenharmony_ci strncpy(color_name, p, len); 276cabdff1aSopenharmony_ci color_name[len] = '\0'; 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci entry = bsearch(color_name, 279cabdff1aSopenharmony_ci color_table, 280cabdff1aSopenharmony_ci FF_ARRAY_ELEMS(color_table), 281cabdff1aSopenharmony_ci sizeof(ColorEntry), 282cabdff1aSopenharmony_ci color_table_compare); 283cabdff1aSopenharmony_ci 284cabdff1aSopenharmony_ci if (!entry) 285cabdff1aSopenharmony_ci return ret; 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci ret = entry->rgb_color; 288cabdff1aSopenharmony_ci } 289cabdff1aSopenharmony_ci return ret; 290cabdff1aSopenharmony_ci} 291cabdff1aSopenharmony_ci 292cabdff1aSopenharmony_cistatic int ascii2index(const uint8_t *cpixel, int cpp) 293cabdff1aSopenharmony_ci{ 294cabdff1aSopenharmony_ci const uint8_t *p = cpixel; 295cabdff1aSopenharmony_ci int n = 0, m = 1, i; 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci for (i = 0; i < cpp; i++) { 298cabdff1aSopenharmony_ci if (*p < MIN_ELEMENT || *p > MAX_ELEMENT) 299cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 300cabdff1aSopenharmony_ci n += (*p++ - MIN_ELEMENT) * m; 301cabdff1aSopenharmony_ci m *= NB_ELEMENTS; 302cabdff1aSopenharmony_ci } 303cabdff1aSopenharmony_ci return n; 304cabdff1aSopenharmony_ci} 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_cistatic int xpm_decode_frame(AVCodecContext *avctx, AVFrame *p, 307cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 308cabdff1aSopenharmony_ci{ 309cabdff1aSopenharmony_ci XPMDecContext *x = avctx->priv_data; 310cabdff1aSopenharmony_ci const uint8_t *end, *ptr; 311cabdff1aSopenharmony_ci int ncolors, cpp, ret, i, j; 312cabdff1aSopenharmony_ci int64_t size; 313cabdff1aSopenharmony_ci uint32_t *dst; 314cabdff1aSopenharmony_ci int width, height; 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGRA; 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ci av_fast_padded_malloc(&x->buf, &x->buf_size, avpkt->size); 319cabdff1aSopenharmony_ci if (!x->buf) 320cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 321cabdff1aSopenharmony_ci memcpy(x->buf, avpkt->data, avpkt->size); 322cabdff1aSopenharmony_ci x->buf[avpkt->size] = 0; 323cabdff1aSopenharmony_ci 324cabdff1aSopenharmony_ci ptr = x->buf; 325cabdff1aSopenharmony_ci end = x->buf + avpkt->size; 326cabdff1aSopenharmony_ci while (end - ptr > 9 && memcmp(ptr, "/* XPM */", 9)) 327cabdff1aSopenharmony_ci ptr++; 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci if (end - ptr <= 9) { 330cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "missing signature\n"); 331cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 332cabdff1aSopenharmony_ci } 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci ptr += mod_strcspn(ptr, "\""); 335cabdff1aSopenharmony_ci if (sscanf(ptr, "\"%u %u %u %u\",", 336cabdff1aSopenharmony_ci &width, &height, &ncolors, &cpp) != 4) { 337cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "missing image parameters\n"); 338cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 339cabdff1aSopenharmony_ci } 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci if ((ret = ff_set_dimensions(avctx, width, height)) < 0) 342cabdff1aSopenharmony_ci return ret; 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci if (cpp <= 0 || cpp >= 5) { 345cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "unsupported/invalid number of chars per pixel: %d\n", cpp); 346cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 347cabdff1aSopenharmony_ci } 348cabdff1aSopenharmony_ci 349cabdff1aSopenharmony_ci size = 1; 350cabdff1aSopenharmony_ci for (i = 0; i < cpp; i++) 351cabdff1aSopenharmony_ci size *= NB_ELEMENTS; 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ci if (ncolors <= 0 || ncolors > size) { 354cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "invalid number of colors: %d\n", ncolors); 355cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci if (size > SIZE_MAX / 4) 359cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_ci size *= 4; 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ci ptr += mod_strcspn(ptr, ",") + 1; 364cabdff1aSopenharmony_ci if (end - ptr < 1) 365cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 366cabdff1aSopenharmony_ci 367cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, p, 0)) < 0) 368cabdff1aSopenharmony_ci return ret; 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci av_fast_padded_malloc(&x->pixels, &x->pixels_size, size); 371cabdff1aSopenharmony_ci if (!x->pixels) 372cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci for (i = 0; i < ncolors; i++) { 375cabdff1aSopenharmony_ci const uint8_t *index; 376cabdff1aSopenharmony_ci int len; 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci ptr += mod_strcspn(ptr, "\"") + 1; 379cabdff1aSopenharmony_ci if (end - ptr < cpp) 380cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 381cabdff1aSopenharmony_ci index = ptr; 382cabdff1aSopenharmony_ci ptr += cpp; 383cabdff1aSopenharmony_ci 384cabdff1aSopenharmony_ci ptr = strstr(ptr, "c "); 385cabdff1aSopenharmony_ci if (ptr) { 386cabdff1aSopenharmony_ci ptr += 2; 387cabdff1aSopenharmony_ci } else { 388cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 389cabdff1aSopenharmony_ci } 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_ci len = strcspn(ptr, "\" "); 392cabdff1aSopenharmony_ci 393cabdff1aSopenharmony_ci if ((ret = ascii2index(index, cpp)) < 0) 394cabdff1aSopenharmony_ci return ret; 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci x->pixels[ret] = color_string_to_rgba(ptr, len); 397cabdff1aSopenharmony_ci ptr += mod_strcspn(ptr, ",") + 1; 398cabdff1aSopenharmony_ci if (end - ptr < 1) 399cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ci for (i = 0; i < avctx->height; i++) { 403cabdff1aSopenharmony_ci dst = (uint32_t *)(p->data[0] + i * p->linesize[0]); 404cabdff1aSopenharmony_ci if (end - ptr < 1) 405cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 406cabdff1aSopenharmony_ci ptr += mod_strcspn(ptr, "\"") + 1; 407cabdff1aSopenharmony_ci if (end - ptr < 1) 408cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 409cabdff1aSopenharmony_ci 410cabdff1aSopenharmony_ci for (j = 0; j < avctx->width; j++) { 411cabdff1aSopenharmony_ci if (end - ptr < cpp) 412cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 413cabdff1aSopenharmony_ci 414cabdff1aSopenharmony_ci if ((ret = ascii2index(ptr, cpp)) < 0) 415cabdff1aSopenharmony_ci return ret; 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci *dst++ = x->pixels[ret]; 418cabdff1aSopenharmony_ci ptr += cpp; 419cabdff1aSopenharmony_ci } 420cabdff1aSopenharmony_ci ptr += mod_strcspn(ptr, ",") + 1; 421cabdff1aSopenharmony_ci } 422cabdff1aSopenharmony_ci 423cabdff1aSopenharmony_ci p->key_frame = 1; 424cabdff1aSopenharmony_ci p->pict_type = AV_PICTURE_TYPE_I; 425cabdff1aSopenharmony_ci 426cabdff1aSopenharmony_ci *got_frame = 1; 427cabdff1aSopenharmony_ci 428cabdff1aSopenharmony_ci return avpkt->size; 429cabdff1aSopenharmony_ci} 430cabdff1aSopenharmony_ci 431cabdff1aSopenharmony_cistatic av_cold int xpm_decode_close(AVCodecContext *avctx) 432cabdff1aSopenharmony_ci{ 433cabdff1aSopenharmony_ci XPMDecContext *x = avctx->priv_data; 434cabdff1aSopenharmony_ci av_freep(&x->pixels); 435cabdff1aSopenharmony_ci 436cabdff1aSopenharmony_ci av_freep(&x->buf); 437cabdff1aSopenharmony_ci x->buf_size = 0; 438cabdff1aSopenharmony_ci 439cabdff1aSopenharmony_ci return 0; 440cabdff1aSopenharmony_ci} 441cabdff1aSopenharmony_ci 442cabdff1aSopenharmony_ciconst FFCodec ff_xpm_decoder = { 443cabdff1aSopenharmony_ci .p.name = "xpm", 444cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image"), 445cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 446cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_XPM, 447cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 448cabdff1aSopenharmony_ci .priv_data_size = sizeof(XPMDecContext), 449cabdff1aSopenharmony_ci .close = xpm_decode_close, 450cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(xpm_decode_frame), 451cabdff1aSopenharmony_ci}; 452