00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include <inttypes.h>
00029
00030 #include "mpeg2.h"
00031 #include "attributes.h"
00032 #include "mpeg2_internal.h"
00033
00034 static int mpeg2_accels = 0;
00035
00036 #define BUFFER_SIZE (1194 * 1024)
00037
00038 const mpeg2_info_t * mpeg2_info (mpeg2dec_t * mpeg2dec)
00039 {
00040 return &(mpeg2dec->info);
00041 }
00042
00043 static inline int skip_chunk (mpeg2dec_t * mpeg2dec, int bytes)
00044 {
00045 uint8_t * current;
00046 uint32_t shift;
00047 uint8_t * limit;
00048 uint8_t byte;
00049
00050 if (!bytes)
00051 return 0;
00052
00053 current = mpeg2dec->buf_start;
00054 shift = mpeg2dec->shift;
00055 limit = current + bytes;
00056
00057 do {
00058 byte = *current++;
00059 if (shift == 0x00000100) {
00060 int skipped;
00061
00062 mpeg2dec->shift = 0xffffff00;
00063 skipped = current - mpeg2dec->buf_start;
00064 mpeg2dec->buf_start = current;
00065 return skipped;
00066 }
00067 shift = (shift | byte) << 8;
00068 } while (current < limit);
00069
00070 mpeg2dec->shift = shift;
00071 mpeg2dec->buf_start = current;
00072 return 0;
00073 }
00074
00075 static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes)
00076 {
00077 uint8_t * current;
00078 uint32_t shift;
00079 uint8_t * chunk_ptr;
00080 uint8_t * limit;
00081 uint8_t byte;
00082
00083 if (!bytes)
00084 return 0;
00085
00086 current = mpeg2dec->buf_start;
00087 shift = mpeg2dec->shift;
00088 chunk_ptr = mpeg2dec->chunk_ptr;
00089 limit = current + bytes;
00090
00091 do {
00092 byte = *current++;
00093 if (shift == 0x00000100) {
00094 int copied;
00095
00096 mpeg2dec->shift = 0xffffff00;
00097 mpeg2dec->chunk_ptr = chunk_ptr + 1;
00098 copied = current - mpeg2dec->buf_start;
00099 mpeg2dec->buf_start = current;
00100 return copied;
00101 }
00102 shift = (shift | byte) << 8;
00103 *chunk_ptr++ = byte;
00104 } while (current < limit);
00105
00106 mpeg2dec->shift = shift;
00107 mpeg2dec->buf_start = current;
00108 return 0;
00109 }
00110
00111 void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end)
00112 {
00113 mpeg2dec->buf_start = start;
00114 mpeg2dec->buf_end = end;
00115 }
00116
00117 int mpeg2_getpos (mpeg2dec_t * mpeg2dec)
00118 {
00119 return mpeg2dec->buf_end - mpeg2dec->buf_start;
00120 }
00121
00122 static inline mpeg2_state_t seek_chunk (mpeg2dec_t * mpeg2dec)
00123 {
00124 int size, skipped;
00125
00126 size = mpeg2dec->buf_end - mpeg2dec->buf_start;
00127 skipped = skip_chunk (mpeg2dec, size);
00128 if (!skipped) {
00129 mpeg2dec->bytes_since_tag += size;
00130 return STATE_BUFFER;
00131 }
00132 mpeg2dec->bytes_since_tag += skipped;
00133 mpeg2dec->code = mpeg2dec->buf_start[-1];
00134 return STATE_INTERNAL_NORETURN;
00135 }
00136
00137 mpeg2_state_t mpeg2_seek_header (mpeg2dec_t * mpeg2dec)
00138 {
00139 while (!(mpeg2dec->code == 0xb3 ||
00140 ((mpeg2dec->code == 0xb7 || mpeg2dec->code == 0xb8 ||
00141 !mpeg2dec->code) && mpeg2dec->sequence.width != (unsigned)-1)))
00142 if (seek_chunk (mpeg2dec) == STATE_BUFFER)
00143 return STATE_BUFFER;
00144 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
00145 mpeg2dec->user_data_len = 0;
00146 return ((mpeg2dec->code == 0xb7) ?
00147 mpeg2_header_end (mpeg2dec) : mpeg2_parse_header (mpeg2dec));
00148 }
00149
00150 #define RECEIVED(code,state) (((state) << 8) + (code))
00151
00152 mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec)
00153 {
00154 int size_buffer, size_chunk, copied;
00155
00156 if (mpeg2dec->action) {
00157 mpeg2_state_t state;
00158
00159 state = mpeg2dec->action (mpeg2dec);
00160 if ((int)state > (int)STATE_INTERNAL_NORETURN)
00161 return state;
00162 }
00163
00164 while (1) {
00165 while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) <
00166 mpeg2dec->nb_decode_slices) {
00167 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
00168 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
00169 mpeg2dec->chunk_ptr);
00170 if (size_buffer <= size_chunk) {
00171 copied = copy_chunk (mpeg2dec, size_buffer);
00172 if (!copied) {
00173 mpeg2dec->bytes_since_tag += size_buffer;
00174 mpeg2dec->chunk_ptr += size_buffer;
00175 return STATE_BUFFER;
00176 }
00177 } else {
00178 copied = copy_chunk (mpeg2dec, size_chunk);
00179 if (!copied) {
00180
00181 mpeg2dec->bytes_since_tag += size_chunk;
00182 mpeg2dec->action = seek_chunk;
00183 return STATE_INVALID;
00184 }
00185 }
00186 mpeg2dec->bytes_since_tag += copied;
00187
00188 mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code,
00189 mpeg2dec->chunk_start);
00190 mpeg2dec->code = mpeg2dec->buf_start[-1];
00191 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
00192 }
00193 if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1)
00194 break;
00195 if (seek_chunk (mpeg2dec) == STATE_BUFFER)
00196 return STATE_BUFFER;
00197 }
00198
00199 mpeg2dec->action = mpeg2_seek_header;
00200 switch (mpeg2dec->code) {
00201 case 0x00:
00202 return mpeg2dec->state;
00203 case 0xb3:
00204 case 0xb7:
00205 case 0xb8:
00206 return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
00207 default:
00208 mpeg2dec->action = seek_chunk;
00209 return STATE_INVALID;
00210 }
00211 }
00212
00213 mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
00214 {
00215 static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = {
00216 mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data,
00217 mpeg2_header_sequence, NULL, NULL, NULL, NULL, mpeg2_header_gop
00218 };
00219 int size_buffer, size_chunk, copied;
00220
00221 mpeg2dec->action = mpeg2_parse_header;
00222 mpeg2dec->info.user_data = NULL; mpeg2dec->info.user_data_len = 0;
00223 while (1) {
00224 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
00225 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
00226 mpeg2dec->chunk_ptr);
00227 if (size_buffer <= size_chunk) {
00228 copied = copy_chunk (mpeg2dec, size_buffer);
00229 if (!copied) {
00230 mpeg2dec->bytes_since_tag += size_buffer;
00231 mpeg2dec->chunk_ptr += size_buffer;
00232 return STATE_BUFFER;
00233 }
00234 } else {
00235 copied = copy_chunk (mpeg2dec, size_chunk);
00236 if (!copied) {
00237
00238 mpeg2dec->bytes_since_tag += size_chunk;
00239 mpeg2dec->code = 0xb4;
00240 mpeg2dec->action = mpeg2_seek_header;
00241 return STATE_INVALID;
00242 }
00243 }
00244 mpeg2dec->bytes_since_tag += copied;
00245
00246 if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) {
00247 mpeg2dec->code = mpeg2dec->buf_start[-1];
00248 mpeg2dec->action = mpeg2_seek_header;
00249 return STATE_INVALID;
00250 }
00251
00252 mpeg2dec->code = mpeg2dec->buf_start[-1];
00253 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) {
00254
00255
00256 case RECEIVED (0x00, STATE_SEQUENCE):
00257 case RECEIVED (0xb8, STATE_SEQUENCE):
00258 mpeg2_header_sequence_finalize (mpeg2dec);
00259 break;
00260
00261
00262 case RECEIVED (0x00, STATE_GOP):
00263 mpeg2_header_gop_finalize (mpeg2dec);
00264 break;
00265 case RECEIVED (0x01, STATE_PICTURE):
00266 case RECEIVED (0x01, STATE_PICTURE_2ND):
00267 mpeg2_header_picture_finalize (mpeg2dec, mpeg2_accels);
00268 mpeg2dec->action = mpeg2_header_slice_start;
00269 break;
00270
00271
00272 case RECEIVED (0xb2, STATE_SEQUENCE):
00273 case RECEIVED (0xb2, STATE_GOP):
00274 case RECEIVED (0xb2, STATE_PICTURE):
00275 case RECEIVED (0xb2, STATE_PICTURE_2ND):
00276 case RECEIVED (0xb5, STATE_SEQUENCE):
00277 case RECEIVED (0xb5, STATE_PICTURE):
00278 case RECEIVED (0xb5, STATE_PICTURE_2ND):
00279 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
00280 continue;
00281
00282 default:
00283 mpeg2dec->action = mpeg2_seek_header;
00284 return STATE_INVALID;
00285 }
00286
00287 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
00288 mpeg2dec->user_data_len = 0;
00289 return mpeg2dec->state;
00290 }
00291 }
00292
00293 int mpeg2_convert (mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg)
00294 {
00295 mpeg2_convert_init_t convert_init;
00296 int error;
00297
00298 error = convert (MPEG2_CONVERT_SET, NULL, &(mpeg2dec->sequence), 0,
00299 mpeg2_accels, arg, &convert_init);
00300 if (!error) {
00301 mpeg2dec->convert = convert;
00302 mpeg2dec->convert_arg = arg;
00303 mpeg2dec->convert_id_size = convert_init.id_size;
00304 mpeg2dec->convert_stride = 0;
00305 }
00306 return error;
00307 }
00308
00309 int mpeg2_stride (mpeg2dec_t * mpeg2dec, int stride)
00310 {
00311 if (!mpeg2dec->convert) {
00312 if (stride < (int) mpeg2dec->sequence.width)
00313 stride = mpeg2dec->sequence.width;
00314 mpeg2dec->decoder.stride_frame = stride;
00315 } else {
00316 mpeg2_convert_init_t convert_init;
00317
00318 stride = mpeg2dec->convert (MPEG2_CONVERT_STRIDE, NULL,
00319 &(mpeg2dec->sequence), stride,
00320 mpeg2_accels, mpeg2dec->convert_arg,
00321 &convert_init);
00322 mpeg2dec->convert_id_size = convert_init.id_size;
00323 mpeg2dec->convert_stride = stride;
00324 }
00325 return stride;
00326 }
00327
00328 void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id)
00329 {
00330 mpeg2_fbuf_t * fbuf;
00331
00332 if (mpeg2dec->custom_fbuf) {
00333 if (mpeg2dec->state == STATE_SEQUENCE) {
00334 mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
00335 mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
00336 }
00337 mpeg2_set_fbuf (mpeg2dec, (mpeg2dec->decoder.coding_type ==
00338 PIC_FLAG_CODING_TYPE_B));
00339 fbuf = mpeg2dec->fbuf[0];
00340 } else {
00341 fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf);
00342 mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index;
00343 }
00344 fbuf->buf[0] = buf[0];
00345 fbuf->buf[1] = buf[1];
00346 fbuf->buf[2] = buf[2];
00347 fbuf->id = id;
00348 }
00349
00350 void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf)
00351 {
00352 mpeg2dec->custom_fbuf = custom_fbuf;
00353 }
00354
00355 void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip)
00356 {
00357 mpeg2dec->first_decode_slice = 1;
00358 mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1);
00359 }
00360
00361 void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end)
00362 {
00363 start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start;
00364 end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end;
00365 mpeg2dec->first_decode_slice = start;
00366 mpeg2dec->nb_decode_slices = end - start;
00367 }
00368
00369 void mpeg2_tag_picture (mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2)
00370 {
00371 mpeg2dec->tag_previous = mpeg2dec->tag_current;
00372 mpeg2dec->tag2_previous = mpeg2dec->tag2_current;
00373 mpeg2dec->tag_current = tag;
00374 mpeg2dec->tag2_current = tag2;
00375 mpeg2dec->num_tags++;
00376 mpeg2dec->bytes_since_tag = 0;
00377 }
00378
00379 uint32_t mpeg2_accel (uint32_t accel)
00380 {
00381 if (!mpeg2_accels) {
00382 mpeg2_accels = mpeg2_detect_accel (accel) | MPEG2_ACCEL_DETECT;
00383 mpeg2_cpu_state_init (mpeg2_accels);
00384 mpeg2_idct_init (mpeg2_accels);
00385 mpeg2_mc_init (mpeg2_accels);
00386 }
00387 return mpeg2_accels & ~MPEG2_ACCEL_DETECT;
00388 }
00389
00390 void mpeg2_reset (mpeg2dec_t * mpeg2dec, int full_reset)
00391 {
00392 mpeg2dec->buf_start = mpeg2dec->buf_end = NULL;
00393 mpeg2dec->num_tags = 0;
00394 mpeg2dec->shift = 0xffffff00;
00395 mpeg2dec->code = 0xb4;
00396 mpeg2dec->action = mpeg2_seek_header;
00397 mpeg2dec->state = STATE_INVALID;
00398 mpeg2dec->first = 1;
00399
00400 mpeg2_reset_info(&(mpeg2dec->info));
00401 mpeg2dec->info.gop = NULL;
00402 mpeg2dec->info.user_data = NULL;
00403 mpeg2dec->info.user_data_len = 0;
00404 if (full_reset) {
00405 mpeg2dec->info.sequence = NULL;
00406 mpeg2_header_state_init (mpeg2dec);
00407 }
00408
00409 }
00410
00411 mpeg2dec_t * mpeg2_init (void)
00412 {
00413 mpeg2dec_t * mpeg2dec;
00414
00415 mpeg2_accel (MPEG2_ACCEL_DETECT);
00416
00417 mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t),
00418 MPEG2_ALLOC_MPEG2DEC);
00419 if (mpeg2dec == NULL)
00420 return NULL;
00421
00422 memset (mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t));
00423 memset (mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t));
00424
00425 mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (BUFFER_SIZE + 4,
00426 MPEG2_ALLOC_CHUNK);
00427
00428 mpeg2dec->sequence.width = (unsigned)-1;
00429 mpeg2_reset (mpeg2dec, 1);
00430
00431 return mpeg2dec;
00432 }
00433
00434 void mpeg2_close (mpeg2dec_t * mpeg2dec)
00435 {
00436 mpeg2_header_state_init (mpeg2dec);
00437 mpeg2_free (mpeg2dec->chunk_buffer);
00438 mpeg2_free (mpeg2dec);
00439 }