A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 527 lines 14 kB view raw
1/* 2 * decode.c 3 * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> 4 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> 5 * 6 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. 7 * See http://libmpeg2.sourceforge.net/ for updates. 8 * 9 * mpeg2dec is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * mpeg2dec is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 * $Id$ 24 * libmpeg2 sync history: 25 * 2008-07-01 - CVS revision 1.114 26 */ 27 28#include "plugin.h" 29 30#include "mpeg2dec_config.h" 31 32#include "mpeg2.h" 33#include "attributes.h" 34#include "mpeg2_internal.h" 35 36#define BUFFER_SIZE (1194 * 1024) 37 38#if defined(CPU_COLDFIRE) || (defined(CPU_ARM) && ARM_ARCH >= 6) 39/* twice as large as on other targets because coldfire uses 40 * a secondary, transposed buffer for optimisation */ 41static int16_t static_dct_block[128] IBSS_ATTR ATTR_ALIGN(16); 42#define DCT_BLOCKSIZE (128 * sizeof (int16_t)) 43#else 44static int16_t static_dct_block[64] IBSS_ATTR ATTR_ALIGN(16); 45#define DCT_BLOCKSIZE (64 * sizeof (int16_t)) 46#endif 47 48const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec) 49{ 50 return &mpeg2dec->info; 51} 52 53static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes) 54{ 55 uint8_t * current; 56 uint32_t shift; 57 uint8_t * limit; 58 uint8_t byte; 59 60 if (!bytes) 61 return 0; 62 63 current = mpeg2dec->buf_start; 64 shift = mpeg2dec->shift; 65 limit = current + bytes; 66 67 do 68 { 69 byte = *current++; 70 71 if (shift == 0x00000100) 72 { 73 int skipped; 74 75 mpeg2dec->shift = 0xffffff00; 76 skipped = current - mpeg2dec->buf_start; 77 mpeg2dec->buf_start = current; 78 79 return skipped; 80 } 81 82 shift = (shift | byte) << 8; 83 } 84 while (current < limit); 85 86 mpeg2dec->shift = shift; 87 mpeg2dec->buf_start = current; 88 89 return 0; 90} 91 92static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes) 93{ 94 uint8_t * current; 95 uint32_t shift; 96 uint8_t * chunk_ptr; 97 uint8_t * limit; 98 uint8_t byte; 99 100 if (!bytes) 101 return 0; 102 103 current = mpeg2dec->buf_start; 104 shift = mpeg2dec->shift; 105 chunk_ptr = mpeg2dec->chunk_ptr; 106 limit = current + bytes; 107 108 do 109 { 110 byte = *current++; 111 112 if (shift == 0x00000100) 113 { 114 int copied; 115 116 mpeg2dec->shift = 0xffffff00; 117 mpeg2dec->chunk_ptr = chunk_ptr + 1; 118 copied = current - mpeg2dec->buf_start; 119 mpeg2dec->buf_start = current; 120 return copied; 121 } 122 123 shift = (shift | byte) << 8; 124 *chunk_ptr++ = byte; 125 } 126 while (current < limit); 127 128 mpeg2dec->shift = shift; 129 mpeg2dec->buf_start = current; 130 return 0; 131} 132 133void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end) 134{ 135 mpeg2dec->buf_start = start; 136 mpeg2dec->buf_end = end; 137} 138 139int mpeg2_getpos (mpeg2dec_t * mpeg2dec) 140{ 141 return mpeg2dec->buf_end - mpeg2dec->buf_start; 142} 143 144static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec) 145{ 146 int size, skipped; 147 148 size = mpeg2dec->buf_end - mpeg2dec->buf_start; 149 skipped = skip_chunk (mpeg2dec, size); 150 151 if (!skipped) 152 { 153 mpeg2dec->bytes_since_tag += size; 154 return STATE_BUFFER; 155 } 156 157 mpeg2dec->bytes_since_tag += skipped; 158 mpeg2dec->code = mpeg2dec->buf_start[-1]; 159 160 return STATE_INTERNAL_NORETURN; 161} 162 163mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec) 164{ 165 while (!(mpeg2dec->code == 0xb3 || 166 ((mpeg2dec->code == 0xb7 || mpeg2dec->code == 0xb8 || 167 !mpeg2dec->code) && mpeg2dec->sequence.width != (unsigned)-1))) 168 { 169 if (seek_chunk (mpeg2dec) == STATE_BUFFER) 170 return STATE_BUFFER; 171 } 172 173 mpeg2dec->chunk_start = 174 mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; 175 176 mpeg2dec->user_data_len = 0; 177 178 return ((mpeg2dec->code == 0xb7) ? 179 mpeg2_header_end(mpeg2dec) : mpeg2_parse_header(mpeg2dec)); 180} 181 182#define RECEIVED(code,state) (((state) << 8) + (code)) 183 184mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec) 185{ 186 int size_buffer, size_chunk, copied; 187 188 if (mpeg2dec->action) 189 { 190 mpeg2_state_t state; 191 192 state = mpeg2dec->action (mpeg2dec); 193 194 if (state > STATE_INTERNAL_NORETURN) 195 return state; 196 } 197 198 while (1) 199 { 200 while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < 201 mpeg2dec->nb_decode_slices) 202 { 203 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; 204 size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE - 205 mpeg2dec->chunk_ptr; 206 207 if (size_buffer <= size_chunk) 208 { 209 copied = copy_chunk (mpeg2dec, size_buffer); 210 211 if (!copied) 212 { 213 mpeg2dec->bytes_since_tag += size_buffer; 214 mpeg2dec->chunk_ptr += size_buffer; 215 return STATE_BUFFER; 216 } 217 } 218 else 219 { 220 copied = copy_chunk (mpeg2dec, size_chunk); 221 222 if (!copied) 223 { 224 /* filled the chunk buffer without finding a start code */ 225 mpeg2dec->bytes_since_tag += size_chunk; 226 mpeg2dec->action = seek_chunk; 227 return STATE_INVALID; 228 } 229 } 230 231 mpeg2dec->bytes_since_tag += copied; 232 233 mpeg2_slice (&mpeg2dec->decoder, mpeg2dec->code, 234 mpeg2dec->chunk_start); 235 mpeg2dec->code = mpeg2dec->buf_start[-1]; 236 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; 237 } 238 239 if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) 240 break; 241 242 if (seek_chunk (mpeg2dec) == STATE_BUFFER) 243 return STATE_BUFFER; 244 } 245 246 mpeg2dec->action = mpeg2_seek_header; 247 248 switch (mpeg2dec->code) 249 { 250 case 0x00: 251 return mpeg2dec->state; 252 case 0xb3: 253 case 0xb7: 254 case 0xb8: 255 return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID; 256 default: 257 mpeg2dec->action = seek_chunk; 258 return STATE_INVALID; 259 } 260} 261 262mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec) 263{ 264 static int (* const process_header[9]) (mpeg2dec_t *) = 265 { 266 mpeg2_header_picture, 267 mpeg2_header_extension, 268 mpeg2_header_user_data, 269 mpeg2_header_sequence, 270 NULL, 271 NULL, 272 NULL, 273 NULL, 274 mpeg2_header_gop 275 }; 276 277 int size_buffer, size_chunk, copied; 278 279 mpeg2dec->action = mpeg2_parse_header; 280 mpeg2dec->info.user_data = NULL; 281 mpeg2dec->info.user_data_len = 0; 282 283 while (1) 284 { 285 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; 286 size_chunk = mpeg2dec->chunk_buffer + BUFFER_SIZE - 287 mpeg2dec->chunk_ptr; 288 289 if (size_buffer <= size_chunk) 290 { 291 copied = copy_chunk (mpeg2dec, size_buffer); 292 293 if (!copied) 294 { 295 mpeg2dec->bytes_since_tag += size_buffer; 296 mpeg2dec->chunk_ptr += size_buffer; 297 return STATE_BUFFER; 298 } 299 } 300 else 301 { 302 copied = copy_chunk (mpeg2dec, size_chunk); 303 304 if (!copied) 305 { 306 /* filled the chunk buffer without finding a start code */ 307 mpeg2dec->bytes_since_tag += size_chunk; 308 mpeg2dec->code = 0xb4; 309 mpeg2dec->action = mpeg2_seek_header; 310 return STATE_INVALID; 311 } 312 } 313 314 mpeg2dec->bytes_since_tag += copied; 315 316 if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) 317 { 318 mpeg2dec->code = mpeg2dec->buf_start[-1]; 319 mpeg2dec->action = mpeg2_seek_header; 320 return STATE_INVALID; 321 } 322 323 mpeg2dec->code = mpeg2dec->buf_start[-1]; 324 325 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) 326 { 327 /* state transition after a sequence header */ 328 case RECEIVED (0x00, STATE_SEQUENCE): 329 case RECEIVED (0xb8, STATE_SEQUENCE): 330 mpeg2_header_sequence_finalize (mpeg2dec); 331 break; 332 333 /* other legal state transitions */ 334 case RECEIVED (0x00, STATE_GOP): 335 mpeg2_header_gop_finalize (mpeg2dec); 336 break; 337 case RECEIVED (0x01, STATE_PICTURE): 338 case RECEIVED (0x01, STATE_PICTURE_2ND): 339 mpeg2_header_picture_finalize (mpeg2dec); 340 mpeg2dec->action = mpeg2_header_slice_start; 341 break; 342 343 /* legal headers within a given state */ 344 case RECEIVED (0xb2, STATE_SEQUENCE): 345 case RECEIVED (0xb2, STATE_GOP): 346 case RECEIVED (0xb2, STATE_PICTURE): 347 case RECEIVED (0xb2, STATE_PICTURE_2ND): 348 case RECEIVED (0xb5, STATE_SEQUENCE): 349 case RECEIVED (0xb5, STATE_PICTURE): 350 case RECEIVED (0xb5, STATE_PICTURE_2ND): 351 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; 352 continue; 353 354 default: 355 mpeg2dec->action = mpeg2_seek_header; 356 return STATE_INVALID; 357 } 358 359 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; 360 mpeg2dec->user_data_len = 0; 361 362 return mpeg2dec->state; 363 } 364} 365 366int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg) 367{ 368 mpeg2_convert_init_t convert_init; 369 int error; 370 371 error = convert (MPEG2_CONVERT_SET, NULL, &mpeg2dec->sequence, 0, 372 arg, &convert_init); 373 374 if (!error) 375 { 376 mpeg2dec->convert = convert; 377 mpeg2dec->convert_arg = arg; 378 mpeg2dec->convert_id_size = convert_init.id_size; 379 mpeg2dec->convert_stride = 0; 380 } 381 382 return error; 383} 384 385int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride) 386{ 387 if (!mpeg2dec->convert) 388 { 389 if (stride < (int) mpeg2dec->sequence.width) 390 stride = mpeg2dec->sequence.width; 391 392 mpeg2dec->decoder.stride_frame = stride; 393 } 394 else 395 { 396 mpeg2_convert_init_t convert_init; 397 398 stride = mpeg2dec->convert(MPEG2_CONVERT_STRIDE, NULL, 399 &mpeg2dec->sequence, stride, 400 mpeg2dec->convert_arg, 401 &convert_init); 402 403 mpeg2dec->convert_id_size = convert_init.id_size; 404 mpeg2dec->convert_stride = stride; 405 } 406 407 return stride; 408} 409 410void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[MPEG2_COMPONENTS], void * id) 411{ 412 mpeg2_fbuf_t * fbuf; 413 414 if (mpeg2dec->custom_fbuf) 415 { 416 if (mpeg2dec->state == STATE_SEQUENCE) 417 { 418 mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1]; 419 mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0]; 420 } 421 422 mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type == 423 PIC_FLAG_CODING_TYPE_B)); 424 425 fbuf = mpeg2dec->fbuf[0]; 426 } 427 else 428 { 429 fbuf = &mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf; 430 mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index; 431 } 432 433 fbuf->buf[0] = buf[0]; 434#if MPEG2_COLOR 435 fbuf->buf[1] = buf[1]; 436 fbuf->buf[2] = buf[2]; 437#endif 438 439 fbuf->id = id; 440} 441 442void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf) 443{ 444 mpeg2dec->custom_fbuf = custom_fbuf; 445} 446 447void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip) 448{ 449 mpeg2dec->first_decode_slice = 1; 450 mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1); 451} 452 453void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end) 454{ 455 start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start; 456 end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end; 457 mpeg2dec->first_decode_slice = start; 458 mpeg2dec->nb_decode_slices = end - start; 459} 460 461void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2) 462{ 463 mpeg2dec->tag_previous = mpeg2dec->tag_current; 464 mpeg2dec->tag2_previous = mpeg2dec->tag2_current; 465 mpeg2dec->tag_current = tag; 466 mpeg2dec->tag2_current = tag2; 467 mpeg2dec->num_tags++; 468 mpeg2dec->bytes_since_tag = 0; 469} 470 471void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset) 472{ 473 mpeg2dec->buf_start = mpeg2dec->buf_end = NULL; 474 mpeg2dec->num_tags = 0; 475 mpeg2dec->shift = 0xffffff00; 476 mpeg2dec->code = 0xb4; 477 mpeg2dec->action = mpeg2_seek_header; 478 mpeg2dec->state = STATE_INVALID; 479 mpeg2dec->first = 1; 480 481 mpeg2_reset_info(&mpeg2dec->info); 482 mpeg2dec->info.gop = NULL; 483 mpeg2dec->info.user_data = NULL; 484 mpeg2dec->info.user_data_len = 0; 485 486 if (full_reset) 487 { 488 mpeg2dec->info.sequence = NULL; 489 mpeg2_header_state_init (mpeg2dec); 490 } 491} 492 493mpeg2dec_t * mpeg2_init (void) 494{ 495 mpeg2dec_t * mpeg2dec; 496 497 mpeg2_idct_init (); 498 499 mpeg2dec = (mpeg2dec_t *)mpeg2_bufalloc(sizeof (mpeg2dec_t), 500 MPEG2_ALLOC_MPEG2DEC); 501 if (mpeg2dec == NULL) 502 return NULL; 503 504 mpeg2dec->decoder.DCTblock = static_dct_block; 505 506 rb->memset (mpeg2dec->decoder.DCTblock, 0, DCT_BLOCKSIZE); 507 508 DEBUGF("DCTblock: %p\n", mpeg2dec->decoder.DCTblock); 509 510 mpeg2dec->chunk_buffer = (uint8_t *)mpeg2_bufalloc(BUFFER_SIZE + 4, 511 MPEG2_ALLOC_CHUNK); 512 513 mpeg2dec->sequence.width = (unsigned)-1; 514 mpeg2_reset (mpeg2dec, 1); 515 516 return mpeg2dec; 517} 518 519void mpeg2_close (mpeg2dec_t * mpeg2dec) 520{ 521 mpeg2_header_state_init (mpeg2dec); 522#if 0 523 /* These are dedicated buffers in rockbox */ 524 mpeg2_free (mpeg2dec->chunk_buffer); 525 mpeg2_free (mpeg2dec); 526#endif 527}