mpeg2_state_t mpeg2_parse (mpeg2dec_t * mpeg2dec) { int size_buffer, size_chunk, copied; if (mpeg2dec->action) { mpeg2_state_t state; state = mpeg2dec->action (mpeg2dec); if ((int)state > (int)STATE_INTERNAL_NORETURN) return state; } while (1) { while ((unsigned) (mpeg2dec->code - mpeg2dec->first_decode_slice) < mpeg2dec->nb_decode_slices) { size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - mpeg2dec->chunk_ptr); if (size_buffer <= size_chunk) { copied = copy_chunk (mpeg2dec, size_buffer); if (!copied) { mpeg2dec->bytes_since_tag += size_buffer; mpeg2dec->chunk_ptr += size_buffer; return STATE_BUFFER; } } else { copied = copy_chunk (mpeg2dec, size_chunk); if (!copied) { /* filled the chunk buffer without finding a start code */ mpeg2dec->bytes_since_tag += size_chunk; mpeg2dec->action = seek_chunk; return STATE_INVALID; } } mpeg2dec->bytes_since_tag += copied; mpeg2_slice (&(mpeg2dec->decoder), mpeg2dec->code, mpeg2dec->chunk_start); mpeg2dec->code = mpeg2dec->buf_start[-1]; mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; } if ((unsigned) (mpeg2dec->code - 1) >= 0xb0 - 1) break; if (seek_chunk (mpeg2dec) == STATE_BUFFER) return STATE_BUFFER; } mpeg2dec->action = mpeg2_seek_header; switch (mpeg2dec->code) { case 0x00: return mpeg2dec->state; case 0xb3: case 0xb7: case 0xb8: return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID; default: mpeg2dec->action = seek_chunk; return STATE_INVALID; } }
static size_t copy_bundle2_chunk(FILE *in, FILE *out) { return copy_chunk(0, in, out); }
static size_t copy_changegroup_chunk(FILE *in, FILE *out) { return copy_chunk(4, in, out); }
mpeg2_state_t mpeg2_parse_header (mpeg2dec_t * mpeg2dec) { static int (* process_header[]) (mpeg2dec_t * mpeg2dec) = { mpeg2_header_picture, mpeg2_header_extension, mpeg2_header_user_data, mpeg2_header_sequence, NULL, NULL, NULL, NULL, mpeg2_header_gop }; int size_buffer, size_chunk, copied; mpeg2dec->action = mpeg2_parse_header; mpeg2dec->info.user_data = NULL; mpeg2dec->info.user_data_len = 0; while (1) { size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start; size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE - mpeg2dec->chunk_ptr); if (size_buffer <= size_chunk) { copied = copy_chunk (mpeg2dec, size_buffer); if (!copied) { mpeg2dec->bytes_since_tag += size_buffer; mpeg2dec->chunk_ptr += size_buffer; return STATE_BUFFER; } } else { copied = copy_chunk (mpeg2dec, size_chunk); if (!copied) { /* filled the chunk buffer without finding a start code */ mpeg2dec->bytes_since_tag += size_chunk; mpeg2dec->code = 0xb4; mpeg2dec->action = mpeg2_seek_header; return STATE_INVALID; } } mpeg2dec->bytes_since_tag += copied; if (process_header[mpeg2dec->code & 0x0b] (mpeg2dec)) { mpeg2dec->code = mpeg2dec->buf_start[-1]; mpeg2dec->action = mpeg2_seek_header; return STATE_INVALID; } mpeg2dec->code = mpeg2dec->buf_start[-1]; switch (RECEIVED (mpeg2dec->code, mpeg2dec->state)) { /* state transition after a sequence header */ case RECEIVED (0x00, STATE_SEQUENCE): case RECEIVED (0xb8, STATE_SEQUENCE): mpeg2_header_sequence_finalize (mpeg2dec); break; /* other legal state transitions */ case RECEIVED (0x00, STATE_GOP): mpeg2_header_gop_finalize (mpeg2dec); break; case RECEIVED (0x01, STATE_PICTURE): case RECEIVED (0x01, STATE_PICTURE_2ND): mpeg2_header_picture_finalize (mpeg2dec, mpeg2_accels); mpeg2dec->action = mpeg2_header_slice_start; break; /* legal headers within a given state */ case RECEIVED (0xb2, STATE_SEQUENCE): case RECEIVED (0xb2, STATE_GOP): case RECEIVED (0xb2, STATE_PICTURE): case RECEIVED (0xb2, STATE_PICTURE_2ND): case RECEIVED (0xb5, STATE_SEQUENCE): case RECEIVED (0xb5, STATE_PICTURE): case RECEIVED (0xb5, STATE_PICTURE_2ND): mpeg2dec->chunk_ptr = mpeg2dec->chunk_start; continue; default: mpeg2dec->action = mpeg2_seek_header; return STATE_INVALID; } mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer; mpeg2dec->user_data_len = 0; return mpeg2dec->state; } }
static int probe_audio_tick_size(tystream_holder_t * tystream) { /* Iteration */ int i; /* Chunks */ chunk_t * chunks; chunk_t * right_audio_chunk; /* Counting variables */ int nr_size; int nr_time; int nr_audio_pes; /* Total timediff and size */ ticks_t total_time; ticks_t time_diff; ticks_t audio_median_tick_diff; int total_size; int med_size; /* Markers */ int gotit; /* Init */ chunks = tystream->chunks; right_audio_chunk=NULL; nr_size = 0; nr_time = 0; nr_audio_pes = 0; total_time = 0; gotit = 0; total_size = 0; //printf("Audio Tick size\n"); while(chunks) { gotit = 0; for(i=0; i < chunks->nr_records; i++){ if(chunks->record_header[i].type == tystream->right_audio) { /* okay so lets save it - in junk_chunks */ //printf("Audio Tick size copy %i\n", i); right_audio_chunk = copy_chunk(chunks); //printf("Audio Tick size copy finished %i\n", i); if(right_audio_chunk) { tystream->junk_chunks = add_chunk(tystream, right_audio_chunk, tystream->junk_chunks); } gotit = 1; } else if (chunks->record_header[i].type == tystream->wrong_audio) { gotit = 1; } if(gotit) { break; } } chunks = chunks->next; } if( tystream->junk_chunks == NULL) { /* Abort */ LOG_ERROR("ABORTING \n"); return(0); } right_audio_chunk = tystream->junk_chunks; //printf("Audio Tick size - 1\n"); /* Okay so get the total size - two stage to remove unwanted values FIXME*/ while(right_audio_chunk) { for(i=0; i < right_audio_chunk->nr_records; i++) { switch(right_audio_chunk->record_header[i].type){ case 0x2c0: case 0x4c0: case 0x3c0: case 0x9c0: if(right_audio_chunk->record_header[i].size > 300 && right_audio_chunk->record_header[i].size < 2000) { nr_size++; total_size = total_size + right_audio_chunk->record_header[i].size; LOG_DEVDIAG1("Size is %i\n",right_audio_chunk->record_header[i].size ); LOG_DEVDIAG1("Total Size is %i\n", total_size); } break; } } right_audio_chunk = right_audio_chunk->next; } if(!nr_size) { LOG_ERROR("Major error div by zero\n"); return(0); } med_size = total_size / nr_size; //printf("Audio Tick size - 2\n"); nr_size = 0; total_size = 0; right_audio_chunk = tystream->junk_chunks; while(right_audio_chunk) { for(i=0; i < right_audio_chunk->nr_records; i++) { switch(right_audio_chunk->record_header[i].type){ case 0x2c0: case 0x4c0: case 0x3c0: case 0x9c0: if((int)right_audio_chunk->record_header[i].size > (med_size - 200) && (int)right_audio_chunk->record_header[i].size < (med_size + 200)) { nr_size++; total_size = total_size + right_audio_chunk->record_header[i].size; LOG_DEVDIAG1("Size is %i\n",right_audio_chunk->record_header[i].size ); LOG_DEVDIAG1("Total Size is %i\n", total_size); } break; } } right_audio_chunk = right_audio_chunk->next; } if(!nr_size) { LOG_ERROR("Major error div by zero\n"); } //printf("Audio Tick size - 3 \n"); med_size = total_size / nr_size; tystream->med_size = med_size; /* This is the typical sizes of TIVO mpeg/ac3 audio * Hence we want to control if we have a typical one * if we don't we give a waring and tell the user to * save the tystream. FIXME WE SHOULD EXIT */ if(med_size > 1532 && med_size < 1572) { tystream->std_audio_size = 1552; tystream->audio_frame_size = 1536; tystream->audio_type = DTIVO_AC3; } else if ( med_size > 840 && med_size < 910) { tystream->std_audio_size = 880; tystream->audio_frame_size = 864; tystream->audio_type = SA_MPEG; } else if ( med_size > 760 && med_size < 800) { tystream->std_audio_size = 780; tystream->audio_frame_size = 768; tystream->audio_type = DTIVO_MPEG_1; } else if ( med_size > 568 && med_size < 608) { tystream->std_audio_size = 588; tystream->audio_frame_size = 576; tystream->audio_type = DTIVO_MPEG_2; } else if ( med_size > 460 && med_size < 500) { tystream->std_audio_size = 492; tystream->audio_frame_size = 480; tystream->audio_type = DTIVO_MPEG_3; } else if ( med_size > 328 && med_size < 368) { /* This one is a bit of guess work FIXME */ tystream->std_audio_size = 348; tystream->audio_frame_size = 336; tystream->audio_type = DTIVO_MPEG_4; LOG_ERROR("probe_audio_tick_size: PLEASE SEND A REPORT - SAVE THE TYSTREAM\n"); } else { tystream->std_audio_size = 0; tystream->audio_frame_size = 0; tystream->audio_type = AUDIO_TYPE_UNKNOW; LOG_WARNING("probe_audio_tick_size: Warning: can't determine std audio size PLEASE SEND A REPORT - SAVE THE TYSTREAM\n"); } /* Now we collect the median tickdiff of the audio stream */ right_audio_chunk = tystream->junk_chunks; while(right_audio_chunk) { nr_audio_pes = get_nr_audio_pes(tystream, right_audio_chunk); for(i=0; i < nr_audio_pes - 2; i++) { time_diff = get_time_X(i + 1, right_audio_chunk, AUDIO, tystream) - get_time_X(i, right_audio_chunk, AUDIO, tystream); if(time_diff > 1000 && time_diff < 4000) { total_time = total_time + time_diff; nr_time++; } } right_audio_chunk = right_audio_chunk->next; } //printf("Out of Audio Tick\n"); audio_median_tick_diff = total_time / nr_time; if(audio_median_tick_diff < 3245 && audio_median_tick_diff > 3235) { tystream->audio_median_tick_diff = 3240; } else if (audio_median_tick_diff < 2165 && audio_median_tick_diff > 2155) { tystream->audio_median_tick_diff = 2160; } else if (audio_median_tick_diff < 2885 && audio_median_tick_diff > 2875) { tystream->audio_median_tick_diff = 2880; } else { LOG_WARNING1("probe_audio_tick_size: Warning: can't determine audio_median_tick_diff "I64FORMAT"PLEASE SEND A REPORT - SAVE THE TYSTREAM\n", audio_median_tick_diff); return(0); } return(1); }