Doxygen Source Code Documentation
Main Page Alphabetical List Data Structures File List Data Fields Globals Search
decode.c
Go to the documentation of this file.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 "mpeg2_internal.h"
00032 #include "convert.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 * chunk_ptr;
00048 uint8_t * limit;
00049 uint8_t byte;
00050
00051 if (!bytes)
00052 return 0;
00053
00054 current = mpeg2dec->buf_start;
00055 shift = mpeg2dec->shift;
00056 chunk_ptr = mpeg2dec->chunk_ptr;
00057 limit = current + bytes;
00058
00059 do {
00060 byte = *current++;
00061 if (shift == 0x00000100) {
00062 int skipped;
00063
00064 mpeg2dec->shift = 0xffffff00;
00065 skipped = current - mpeg2dec->buf_start;
00066 mpeg2dec->buf_start = current;
00067 return skipped;
00068 }
00069 shift = (shift | byte) << 8;
00070 } while (current < limit);
00071
00072 mpeg2dec->shift = shift;
00073 mpeg2dec->buf_start = current;
00074 return 0;
00075 }
00076
00077 static inline int copy_chunk (mpeg2dec_t * mpeg2dec, int bytes)
00078 {
00079 uint8_t * current;
00080 uint32_t shift;
00081 uint8_t * chunk_ptr;
00082 uint8_t * limit;
00083 uint8_t byte;
00084
00085 if (!bytes)
00086 return 0;
00087
00088 current = mpeg2dec->buf_start;
00089 shift = mpeg2dec->shift;
00090 chunk_ptr = mpeg2dec->chunk_ptr;
00091 limit = current + bytes;
00092
00093 do {
00094 byte = *current++;
00095 if (shift == 0x00000100) {
00096 int copied;
00097
00098 mpeg2dec->shift = 0xffffff00;
00099 mpeg2dec->chunk_ptr = chunk_ptr + 1;
00100 copied = current - mpeg2dec->buf_start;
00101 mpeg2dec->buf_start = current;
00102 return copied;
00103 }
00104 shift = (shift | byte) << 8;
00105 *chunk_ptr++ = byte;
00106 } while (current < limit);
00107
00108 mpeg2dec->shift = shift;
00109 mpeg2dec->buf_start = current;
00110 return 0;
00111 }
00112
00113 void mpeg2_buffer (mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end)
00114 {
00115 mpeg2dec->buf_start = start;
00116 mpeg2dec->buf_end = end;
00117 }
00118
00119 static inline int seek_chunk (mpeg2dec_t * mpeg2dec)
00120 {
00121 int size, skipped;
00122
00123 size = mpeg2dec->buf_end - mpeg2dec->buf_start;
00124 skipped = skip_chunk (mpeg2dec, size);
00125 if (!skipped) {
00126 mpeg2dec->bytes_since_pts += size;
00127 return -1;
00128 }
00129 mpeg2dec->bytes_since_pts += skipped;
00130 mpeg2dec->code = mpeg2dec->buf_start[-1];
00131 return 0;
00132 }
00133
00134 int mpeg2_seek_header (mpeg2dec_t * mpeg2dec)
00135 {
00136 while (mpeg2dec->code != 0xb3 &&
00137 ((mpeg2dec->code != 0xb7 && mpeg2dec->code != 0xb8 &&
00138 mpeg2dec->code) || mpeg2dec->sequence.width == -1))
00139 if (seek_chunk (mpeg2dec))
00140 return -1;
00141 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
00142 return mpeg2_parse_header (mpeg2dec);
00143 }
00144
00145 int mpeg2_seek_sequence (mpeg2dec_t * mpeg2dec)
00146 {
00147 mpeg2dec->sequence.width = -1;
00148 return mpeg2_seek_header (mpeg2dec);
00149 }
00150
00151 #define RECEIVED(code,state) (((state) << 8) + (code))
00152
00153 int mpeg2_parse (mpeg2dec_t * mpeg2dec)
00154 {
00155 int size_buffer, size_chunk, copied;
00156
00157 if (mpeg2dec->action) {
00158 int state;
00159
00160 state = mpeg2dec->action (mpeg2dec);
00161 if (state)
00162 return state;
00163 }
00164
00165 while (1) {
00166 while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) <
00167 mpeg2dec->nb_decode_slices) {
00168 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
00169 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
00170 mpeg2dec->chunk_ptr);
00171 if (size_buffer <= size_chunk) {
00172 copied = copy_chunk (mpeg2dec, size_buffer);
00173 if (!copied) {
00174 mpeg2dec->bytes_since_pts += size_buffer;
00175 mpeg2dec->chunk_ptr += size_buffer;
00176 return -1;
00177 }
00178 } else {
00179 copied = copy_chunk (mpeg2dec, size_chunk);
00180 if (!copied) {
00181
00182 mpeg2dec->bytes_since_pts += size_chunk;
00183 mpeg2dec->action = seek_chunk;
00184 return STATE_INVALID;
00185 }
00186 }
00187 mpeg2dec->bytes_since_pts += copied;
00188
00189 mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code,
00190 mpeg2dec->chunk_start);
00191 mpeg2dec->code = mpeg2dec->buf_start[-1];
00192 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
00193 }
00194 if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1)
00195 break;
00196 if (seek_chunk (mpeg2dec))
00197 return -1;
00198 }
00199
00200 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) {
00201 case RECEIVED (0x00, STATE_SLICE_1ST):
00202 case RECEIVED (0x00, STATE_SLICE):
00203 mpeg2dec->action = mpeg2_header_picture_start;
00204 break;
00205 case RECEIVED (0xb7, STATE_SLICE):
00206 mpeg2dec->action = mpeg2_header_end;
00207 break;
00208 case RECEIVED (0xb3, STATE_SLICE):
00209 case RECEIVED (0xb8, STATE_SLICE):
00210 mpeg2dec->action = mpeg2_parse_header;
00211 break;
00212 default:
00213 mpeg2dec->action = mpeg2_seek_header;
00214 return STATE_INVALID;
00215 }
00216 return mpeg2dec->state;
00217 }
00218
00219 int mpeg2_parse_header (mpeg2dec_t * mpeg2dec)
00220 {
00221 static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = {
00222 mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data,
00223 mpeg2_header_sequence, NULL, NULL, NULL, NULL, mpeg2_header_gop
00224 };
00225 int size_buffer, size_chunk, copied;
00226
00227 mpeg2dec->action = mpeg2_parse_header;
00228 while (1) {
00229 size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
00230 size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
00231 mpeg2dec->chunk_ptr);
00232 if (size_buffer <= size_chunk) {
00233 copied = copy_chunk (mpeg2dec, size_buffer);
00234 if (!copied) {
00235 mpeg2dec->bytes_since_pts += size_buffer;
00236 mpeg2dec->chunk_ptr += size_buffer;
00237 return -1;
00238 }
00239 } else {
00240 copied = copy_chunk (mpeg2dec, size_chunk);
00241 if (!copied) {
00242
00243 mpeg2dec->bytes_since_pts += size_chunk;
00244 mpeg2dec->code = 0xb4;
00245 mpeg2dec->action = mpeg2_seek_header;
00246 return STATE_INVALID;
00247 }
00248 }
00249 mpeg2dec->bytes_since_pts += copied;
00250
00251 if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) {
00252 mpeg2dec->code = mpeg2dec->buf_start[-1];
00253 mpeg2dec->action = mpeg2_seek_header;
00254 return STATE_INVALID;
00255 }
00256
00257 mpeg2dec->code = mpeg2dec->buf_start[-1];
00258 switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) {
00259
00260
00261 case RECEIVED (0x00, STATE_SEQUENCE):
00262 mpeg2dec->action = mpeg2_header_picture_start;
00263 case RECEIVED (0xb8, STATE_SEQUENCE):
00264 mpeg2_header_sequence_finalize (mpeg2dec);
00265 break;
00266
00267
00268 case RECEIVED (0x00, STATE_GOP):
00269 mpeg2dec->action = mpeg2_header_picture_start;
00270 break;
00271 case RECEIVED (0x01, STATE_PICTURE):
00272 case RECEIVED (0x01, STATE_PICTURE_2ND):
00273 mpeg2dec->action = mpeg2_header_slice_start;
00274 break;
00275
00276
00277 case RECEIVED (0xb2, STATE_SEQUENCE):
00278 case RECEIVED (0xb2, STATE_GOP):
00279 case RECEIVED (0xb2, STATE_PICTURE):
00280 case RECEIVED (0xb2, STATE_PICTURE_2ND):
00281 case RECEIVED (0xb5, STATE_SEQUENCE):
00282 case RECEIVED (0xb5, STATE_PICTURE):
00283 case RECEIVED (0xb5, STATE_PICTURE_2ND):
00284 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
00285 continue;
00286
00287 default:
00288 mpeg2dec->action = mpeg2_seek_header;
00289 return STATE_INVALID;
00290 }
00291
00292 mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
00293 return mpeg2dec->state;
00294 }
00295 }
00296
00297 void mpeg2_convert (mpeg2dec_t * mpeg2dec,
00298 void (* convert) (int, int, uint32_t, void *,
00299 struct convert_init_s *), void * arg)
00300 {
00301 convert_init_t convert_init;
00302 int size;
00303
00304 convert_init.id = NULL;
00305 convert (mpeg2dec->decoder.width, mpeg2dec->decoder.height,
00306 mpeg2_accels, arg, &convert_init);
00307 if (convert_init.id_size) {
00308 convert_init.id = mpeg2dec->convert_id =
00309 mpeg2_malloc (convert_init.id_size, ALLOC_CONVERT_ID);
00310 convert (mpeg2dec->decoder.width, mpeg2dec->decoder.height,
00311 mpeg2_accels, arg, &convert_init);
00312 }
00313 mpeg2dec->convert_size[0] = size = convert_init.buf_size[0];
00314 mpeg2dec->convert_size[1] = size += convert_init.buf_size[1];
00315 mpeg2dec->convert_size[2] = size += convert_init.buf_size[2];
00316 mpeg2dec->convert_start = convert_init.start;
00317 mpeg2dec->convert_copy = convert_init.copy;
00318
00319 size = mpeg2dec->decoder.width * mpeg2dec->decoder.height >> 2;
00320 mpeg2dec->yuv_buf[0][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV);
00321 mpeg2dec->yuv_buf[0][1] = mpeg2dec->yuv_buf[0][0] + 4 * size;
00322 mpeg2dec->yuv_buf[0][2] = mpeg2dec->yuv_buf[0][0] + 5 * size;
00323 mpeg2dec->yuv_buf[1][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV);
00324 mpeg2dec->yuv_buf[1][1] = mpeg2dec->yuv_buf[1][0] + 4 * size;
00325 mpeg2dec->yuv_buf[1][2] = mpeg2dec->yuv_buf[1][0] + 5 * size;
00326 size = mpeg2dec->decoder.width * 8;
00327 mpeg2dec->yuv_buf[2][0] = (uint8_t *) mpeg2_malloc (6 * size, ALLOC_YUV);
00328 mpeg2dec->yuv_buf[2][1] = mpeg2dec->yuv_buf[2][0] + 4 * size;
00329 mpeg2dec->yuv_buf[2][2] = mpeg2dec->yuv_buf[2][0] + 5 * size;
00330 }
00331
00332 void mpeg2_set_buf (mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id)
00333 {
00334 fbuf_t * fbuf;
00335
00336 if (mpeg2dec->custom_fbuf) {
00337 mpeg2_set_fbuf (mpeg2dec, mpeg2dec->decoder.coding_type);
00338 fbuf = mpeg2dec->fbuf[0];
00339 if (mpeg2dec->state == STATE_SEQUENCE) {
00340 mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
00341 mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
00342 }
00343 } else {
00344 fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf);
00345 mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index;
00346 }
00347 fbuf->buf[0] = buf[0];
00348 fbuf->buf[1] = buf[1];
00349 fbuf->buf[2] = buf[2];
00350 fbuf->id = id;
00351 }
00352
00353 void mpeg2_custom_fbuf (mpeg2dec_t * mpeg2dec, int custom_fbuf)
00354 {
00355 mpeg2dec->custom_fbuf = custom_fbuf;
00356 }
00357
00358 void mpeg2_skip (mpeg2dec_t * mpeg2dec, int skip)
00359 {
00360 mpeg2dec->first_decode_slice = 1;
00361 mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1);
00362 }
00363
00364 void mpeg2_slice_region (mpeg2dec_t * mpeg2dec, int start, int end)
00365 {
00366 start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start;
00367 end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end;
00368 mpeg2dec->first_decode_slice = start;
00369 mpeg2dec->nb_decode_slices = end - start;
00370 }
00371
00372 void mpeg2_pts (mpeg2dec_t * mpeg2dec, uint32_t pts)
00373 {
00374 mpeg2dec->pts_previous = mpeg2dec->pts_current;
00375 mpeg2dec->pts_current = pts;
00376 mpeg2dec->num_pts++;
00377 mpeg2dec->bytes_since_pts = 0;
00378 }
00379
00380 uint32_t mpeg2_accel (uint32_t accel)
00381 {
00382 if (!mpeg2_accels) {
00383 if (accel & MPEG2_ACCEL_DETECT)
00384 accel |= mpeg2_detect_accel ();
00385 mpeg2_accels = accel |= MPEG2_ACCEL_DETECT;
00386 mpeg2_cpu_state_init (accel);
00387 mpeg2_idct_init (accel);
00388 mpeg2_mc_init (accel);
00389 }
00390 return mpeg2_accels & ~MPEG2_ACCEL_DETECT;
00391 }
00392
00393 mpeg2dec_t * mpeg2_init (void)
00394 {
00395 mpeg2dec_t * mpeg2dec;
00396
00397 mpeg2_accel (MPEG2_ACCEL_DETECT);
00398
00399 mpeg2dec = (mpeg2dec_t *) mpeg2_malloc (sizeof (mpeg2dec_t),
00400 ALLOC_MPEG2DEC);
00401 if (mpeg2dec == NULL)
00402 return NULL;
00403
00404 memset (mpeg2dec, 0, sizeof (mpeg2dec_t));
00405
00406 mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc (BUFFER_SIZE + 4,
00407 ALLOC_CHUNK);
00408
00409 mpeg2dec->shift = 0xffffff00;
00410 mpeg2dec->action = mpeg2_seek_sequence;
00411 mpeg2dec->code = 0xb4;
00412 mpeg2dec->first_decode_slice = 1;
00413 mpeg2dec->nb_decode_slices = 0xb0 - 1;
00414 mpeg2dec->convert_id = NULL;
00415
00416
00417 mpeg2_header_state_init (mpeg2dec);
00418
00419 return mpeg2dec;
00420 }
00421
00422 void mpeg2_close (mpeg2dec_t * mpeg2dec)
00423 {
00424 int i;
00425
00426
00427
00428
00429 mpeg2_free (mpeg2dec->chunk_buffer);
00430 if (!mpeg2dec->custom_fbuf)
00431 for (i = mpeg2dec->alloc_index_user; i < mpeg2dec->alloc_index; i++)
00432 mpeg2_free (mpeg2dec->fbuf_alloc[i].fbuf.buf[0]);
00433 if (mpeg2dec->convert_start)
00434 for (i = 0; i < 3; i++)
00435 mpeg2_free (mpeg2dec->yuv_buf[i][0]);
00436 if (mpeg2dec->convert_id)
00437 mpeg2_free (mpeg2dec->convert_id);
00438 mpeg2_free (mpeg2dec);
00439 }