📄 mpeg2demux.c
字号:
* The modifications are under GNU GPL, but the the original code is * under copyright (C) 1995-1999 by Michael Hipp and has its own license. * mpg123 can be obtained under http://www.mpg123.de */static int head_check(unsigned long head){ if( (head & 0xffe00000) != 0xffe00000) return 0; if(!((head>>17)&3)) return 0; if( ((head>>12)&0xf) == 0xf) return 0; if( ((head>>10)&0x3) == 0x3 ) return 0; if ((head & 0xffff0000) == 0xfffe0000) return 0; return 1;}/* * Exception from GNU General Public License: * This function (decodee_header) is a modification of that function * taken from mpg123. * The modifications are under GNU GPL, but the the original code is * under copyright (C) 1995-1999 by Michael Hipp and has its own license. * mpg123 can be obtained under http://www.mpg123.de *//* * decode a header and write the information * into the frame structure */static int decode_header(struct frame *fr,unsigned long newhead, int *ssize){ if(!head_check(newhead)) return 0; if( newhead & (1<<20) ) { fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1; fr->mpeg25 = 0; } else { fr->lsf = 1; fr->mpeg25 = 1; } fr->lay = 4-((newhead>>17)&3); if( ((newhead>>10)&0x3) == 0x3) { fprintf(stderr,"Audio Stream error\n");; return 0; } if(fr->mpeg25) fr->sampling_frequency = 6 + ((newhead>>10)&0x3); else fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3); fr->error_protection = ((newhead>>16)&0x1)^0x1; fr->bitrate_index = ((newhead>>12)&0xf); fr->padding = ((newhead>>9)&0x1); fr->extension = ((newhead>>8)&0x1); fr->mode = ((newhead>>6)&0x3); fr->mode_ext = ((newhead>>4)&0x3); fr->copyright = ((newhead>>3)&0x1); fr->original = ((newhead>>2)&0x1); fr->emphasis = newhead & 0x3; fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; if(!fr->bitrate_index) { fprintf(stderr,"Free format not supported: (head 0x%lx)\n", newhead); return 0; } switch(fr->lay) { case 1: fr->do_layer = do_layer1; fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; fr->framesize /= freqs[fr->sampling_frequency]; fr->framesize = ((fr->framesize+fr->padding)<<2)-4; break; case 2: fr->do_layer = do_layer2; fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; fr->framesize /= freqs[fr->sampling_frequency]; fr->framesize += fr->padding - 4; break; case 3: fr->do_layer = do_layer3; if(fr->lsf) *ssize = (fr->stereo == 1) ? 9 : 17; else *ssize = (fr->stereo == 1) ? 17 : 32; if(fr->error_protection) *ssize += 2; fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; fr->framesize /= freqs[fr->sampling_frequency]<<(fr->lsf); fr->framesize = fr->framesize + fr->padding - 4; break; default: fprintf(stderr,"Sorry, unknown layer type.\n");; return (0); } return 1;}static int get_audio_head(struct frame *fr,int *ssize){ unsigned long newhead; do { if(!head_read(&newhead)) /* shift through stream and look for header, searching for header */ return 0; } while (!decode_header(fr, newhead, ssize)); if (skipped_mpegaudio_bytes) { fprintf(stderr,"Skipped %ld bytes of audio-stream\n",skipped_mpegaudio_bytes); skipped_mpegaudio_bytes=0; } fr->header_change = 2; if(old_mpegaudio_head) { if((old_mpegaudio_head & 0xc00) == (newhead & 0xc00)) { if( (old_mpegaudio_head & 0xc0) == 0 && (newhead & 0xc0) == 0) fr->header_change = 1; else if( (old_mpegaudio_head & 0xc0) > 0 && (newhead & 0xc0) > 0) fr->header_change = 1; } } old_mpegaudio_head=newhead; return 1;}static int audiobufferfill(){ int bytesleft4buffer; int readbytes; while (rest_of_ts_packet() > 0) { if (!have_mpegaudio_header) /* if no new frame started */ { if (!get_audio_head(&audiobuffer[audiobufferend].fr,&audiobuffer[audiobufferend].ssize)) return 1; else { if ((audiobuffer[audiobufferend].havepts=audio_pts.have_timestamp)) { audiobuffer[audiobufferend].pts=audio_pts.timestamp; audio_pts.have_timestamp=0; } bytes_already_in_audiobuffer=0; have_mpegaudio_header=1; } } /* here we can be sure that we have a header */ bytesleft4buffer=audiobuffer[audiobufferend].fr.framesize-bytes_already_in_audiobuffer; readbytes= bytesleft4buffer < rest_of_ts_packet()?bytesleft4buffer:(rest_of_ts_packet()); bytes_already_in_audiobuffer += copybytes(audiobuffer[audiobufferend].buffer+512+bytes_already_in_audiobuffer,readbytes); if (bytes_already_in_audiobuffer == audiobuffer[audiobufferend].fr.framesize) /* frame complete */ { have_mpegaudio_header=0; /* start new frame in next iteration */ audio_header_bytes_read=0; audio_frames++; if ( (audiobufferend + 2) % AUDIOFRAMESINBUFFER == audiobufferstart) {/* if buffer is full; 2 entries must be free, because mp3 also needs the last frame */ fprintf(stderr,"Audio buffer overrun! Discarding frame\n"); } else { audiobufferend = (audiobufferend + 1) % AUDIOFRAMESINBUFFER; /* advance ringbuffercounter */ if (sem_post(&audiobuffer_sem)) { fprintf(stderr,"Cannot V semaphore\n"); exit(0); } } } } return 1;}int select_program(int program_number){ struct ProgramMapTableEntry *pmt_entry; if (pthread_mutex_lock(&mutex_PMT)) /* lock PMT to ensure that nobody modifies it while we read it */ { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } track_program = program_number; current_program = -1; pmt_entry = getProgramMapTableEntry(program_number); if (pmt_entry) { int hilfv=getVideoPid(pmt_entry); int hilfa=getAudioPid(pmt_entry); if (hilfv==-1 && hilfa==-1) { fprintf(stderr,"stream does not have audio and video\n");; } set_pids_internal(hilfv,hilfa,getPCRPid(pmt_entry)); current_program = program_number; } else { if (debug) { fprintf(stdout,"desired program not yet in PMT -> maybe it appears later...\n"); } set_pids_internal(-1,-1,-1); } if (pthread_mutex_unlock(&mutex_PMT)) { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); } return 0;}int select_any_program(){ struct ProgramMapTableEntry *pmt_temp; if (pthread_mutex_lock(&mutex_PMT)) /* lock PMT to ensure that nobody modifies it while we read it */ { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } track_program = -2; current_program = -1; for (pmt_temp = program_map_table; pmt_temp; pmt_temp=pmt_temp->next) { int hilfv=getVideoPid(pmt_temp); int hilfa=getAudioPid(pmt_temp); if ((hilfv != -1) && (hilfa != -1)) { set_pids_internal(hilfv,hilfa,getPCRPid(pmt_temp)); current_program = pmt_temp->program_number; break; } } if (current_program == -1) { if (debug) { fprintf(stdout,"no TV program available yet -> maybe later one appears...\n"); } set_pids_internal(-1,-1,-1); } if (pthread_mutex_unlock(&mutex_PMT)) { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); } return 0;}int select_first_program(){ struct ProgramMapTableEntry *pmt_entry; int program_number; if (pthread_mutex_lock(&mutex_PMT)) /* lock PMT to ensure that nobody modifies it while we read it */ { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } track_program = -3; current_program = -1; program_number = getFirstProgram(); pmt_entry = getProgramMapTableEntry(program_number); if (pmt_entry) { int hilfv=getVideoPid(pmt_entry); int hilfa=getAudioPid(pmt_entry); if (hilfv==-1 && hilfa==-1) { fprintf(stderr,"stream does not have audio and video\n");; } set_pids_internal(hilfv,hilfa,getPCRPid(pmt_entry)); current_program = program_number; } else { if (debug) { fprintf(stdout,"first program not yet in PMT -> maybe it appears later...\n"); } set_pids_internal(-1,-1,-1); } if (pthread_mutex_unlock(&mutex_PMT)) { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); } return 0;}static void set_pids_internal(int videopid, int audiopid, int pcrpid) { if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; their buffers will not get filled now */ { fprintf(stderr,"cannot lock decoders mutex\n");; exit(1); } (void) video_system_done(); /* reset video and audio decoders */ (void) audio_system_done(); (void) video_system_init(); (void) audio_system_init(); have_mpegaudio_header=0; /* initialization for audiobufferfill */ old_mpegaudio_head = 0,skipped_mpegaudio_bytes=0; /* initialization for get_audio_head */ audio_header_bytes_read=0; /* initialization for head_read */ video_pid=videopid; audio_pid=audiopid; pcr_pid=pcrpid; disable_sync(); /* disable sync; we must re-sync now */ if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now we can resume filling their buffers */ { fprintf(stderr,"cannot unlock decoders mutex\n");; exit(1); }}void set_pids(int videopid, int audiopid, int pcrpid) { current_program=-1; track_program=-1; set_pids_internal(videopid, audiopid, pcrpid);}void get_pids(int *videopid, int *audiopid, int *pcrpid) { if (videopid) *videopid=video_pid; if (audiopid) *audiopid=audio_pid; if (pcrpid) *pcrpid=pcr_pid;}int get_videobuffer_size() { return VIDEOPESPACKETSINBUFFER-1; /* one entry must stay free */}int get_videobuffer_state() { return (videobufferend+VIDEOPESPACKETSINBUFFER-videobufferstart) % VIDEOPESPACKETSINBUFFER -1;}int get_audiobuffer_size() { return AUDIOFRAMESINBUFFER-2; /* two entries stay free in audio buffer */}int get_audiobuffer_state() { return (audiobufferend +AUDIOFRAMESINBUFFER - audiobufferstart) % AUDIOFRAMESINBUFFER;}int getProgramNumbers(int *number_array) { int number=0; struct ProgramMapTableEntry *pmt_entry; if (pthread_mutex_lock(&mutex_PMT)) /* lock PMT */ { fprintf(stderr,"cannot lock PMT mutex\n");; exit(1); } for (pmt_entry = program_map_table; pmt_entry; pmt_entry=pmt_entry->next) { number_array[number++]=pmt_entry->program_number; } if (pthread_mutex_unlock(&mutex_PMT)) /* unlock PMT */ { fprintf(stderr,"cannot unlock PMT mutex\n");; exit(1); } return number;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -