//returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream. //if no pts is found or an error occurs, -1.0 is returned. //Packs are freed. static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, off_t stream_pos) { stream_t *s = demuxer->stream; mpg_demuxer_t *mpg_d = demuxer->priv; float pts = -1.0; //the pts to return; float found_pts1; //the most recently found pts float found_pts2; //the pts found before found_pts1 float found_pts3; //the pts found before found_pts2 int found = 0; if(!mpg_d || stream_pos < 0) return pts; found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; stream_seek(s, stream_pos); //We look for pts. //However, we do not stop at the first found one, as timestamps may reset //Therefore, we seek until we found three consecutive //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE. while(found<3 && !s->eof && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE) && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE) && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN) && ds_fill_buffer(demuxer->video)) { if(mpg_d->last_pts != found_pts1) { if(!found) found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts else { found_pts3 = found_pts2; found_pts2 = found_pts1; found_pts1 = mpg_d->last_pts; } found++; } } if(found == 3) pts = found_pts3; //clean up from searching of first pts; ds_free_packs(demuxer->audio); ds_free_packs(demuxer->video); ds_free_packs(demuxer->sub); return pts; }
static void demux_isdbt_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { demux_stream_t *d_audio=demuxer->audio; demux_stream_t *d_video=demuxer->video; demux_stream_t *d_sub=demuxer->sub; sh_audio_t *sh_audio=d_audio->sh; sh_video_t *sh_video=d_video->sh; //================= seek in isdbt ========================== // ts_dump_streams(demuxer->priv); // reset_fifos(priv, sh_audio != NULL, sh_video != NULL, demuxer->sub->id > 0); demuxer->stream_pts=cur_ts; LOGE("seek from demux!--------------------\n"); if(sh_audio != NULL) ds_free_packs(d_audio); if(sh_video != NULL) ds_free_packs(d_video); if(demuxer->sub->id > 0) ds_free_packs(d_sub); }
//This is an almost verbatim copy of high_res_mp3_seek(), from demux_audio.c static void demux_aac_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { aac_priv_t *priv = (aac_priv_t *) demuxer->priv; demux_stream_t *d_audio=demuxer->audio; sh_audio_t *sh_audio=d_audio->sh; float time; ds_free_packs(d_audio); time = (flags & SEEK_ABSOLUTE) ? rel_seek_secs - priv->last_pts : rel_seek_secs; if(time < 0) { stream_seek(demuxer->stream, demuxer->movi_start); time = priv->last_pts + time; priv->last_pts = 0; } if(time > 0) { int len, nf, srate, num; nf = time * sh_audio->samplerate/1024; while(nf > 0) { if(stream_read(demuxer->stream,priv->buf, 8) < 8) break; len = aac_parse_frame(priv->buf, &srate, &num); if(len <= 0) { stream_skip(demuxer->stream, -7); continue; } stream_skip(demuxer->stream, len - 8); priv->last_pts += (float) (num*1024.0/srate); nf -= num; } } }
static void demux_seek_aac_adif(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { aac_adif_priv_t *priv = (aac_adif_priv_t *) demuxer->priv; demux_stream_t *d_audio=demuxer->audio; sh_audio_t *sh_audio=d_audio->sh; float time; unsigned int frame_len; // frame_len = (1024 / priv->srate) * (priv->bitrate/8); // frame_len = ((1024 * priv->bitrate * 4) / (8 * 44100)); frame_len = ((1024.0 * 16.0) / (float) priv->srate) * ((float) priv->bitrate/8.0); ds_free_packs(d_audio); time = (flags & 1) ? rel_seek_secs : priv->last_pts + rel_seek_secs; if(time < 0) { stream_seek(demuxer->stream, demuxer->movi_start); time = priv->last_pts + time; priv->last_pts = 0; } if(time > 0) { float fltpos; int pos; fltpos = time * (priv->bitrate/8); pos = (int) fltpos; pos /= frame_len; pos *= frame_len; pos += priv->hdrlen; if (pos > demuxer->movi_end) pos = demuxer->movi_end; stream_seek(demuxer->stream, pos); } // sh_audio->delay = priv->last_pts - (ds_tell_pts(demuxer->audio)-sh_audio->a_in_buffer_len)/(float)priv->bitrate; // FIXME - ???? }
static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) { lavf_priv_t *priv = demuxer->priv; switch (cmd) { case DEMUXER_CTRL_CORRECT_PTS: return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_TIME_LENGTH: if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return DEMUXER_CTRL_DONTKNOW; *((double *)arg) = (double)priv->avfc->duration / AV_TIME_BASE; return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_PERCENT_POS: if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return DEMUXER_CTRL_DONTKNOW; *((int *)arg) = (int)((priv->last_pts - priv->avfc->start_time)*100 / priv->avfc->duration); return DEMUXER_CTRL_OK; case DEMUXER_CTRL_SWITCH_AUDIO: case DEMUXER_CTRL_SWITCH_VIDEO: { int id = *((int*)arg); int newid = -2; int i, curridx = -1; int nstreams, *pstreams; demux_stream_t *ds; if(cmd == DEMUXER_CTRL_SWITCH_VIDEO) { ds = demuxer->video; nstreams = priv->video_streams; pstreams = priv->vstreams; } else { ds = demuxer->audio; nstreams = priv->audio_streams; pstreams = priv->astreams; } for(i = 0; i < nstreams; i++) { if(pstreams[i] == ds->id) //current stream id { curridx = i; break; } } if(id == -2) { // no sound i = -1; } else if(id == -1) { // next track i = (curridx + 2) % (nstreams + 1) - 1; if (i >= 0) newid = pstreams[i]; } else // select track by id { if (id >= 0 && id < nstreams) { i = id; newid = pstreams[i]; } } if(i == curridx) return DEMUXER_CTRL_NOTIMPL; else { ds_free_packs(ds); if(ds->id >= 0) priv->avfc->streams[ds->id]->discard = AVDISCARD_ALL; *((int*)arg) = ds->id = newid; if(newid >= 0) priv->avfc->streams[newid]->discard = AVDISCARD_NONE; return DEMUXER_CTRL_OK; } } case DEMUXER_CTRL_IDENTIFY_PROGRAM: { demux_program_t *prog = arg; AVProgram *program; int p, i; int start; prog->vid = prog->aid = prog->sid = -2; //no audio and no video by default if(priv->avfc->nb_programs < 1) return DEMUXER_CTRL_DONTKNOW; if(prog->progid == -1) { p = 0; while(p<priv->avfc->nb_programs && priv->avfc->programs[p]->id != priv->cur_program) p++; p = (p + 1) % priv->avfc->nb_programs; } else { for(i=0; i<priv->avfc->nb_programs; i++) if(priv->avfc->programs[i]->id == prog->progid) break; if(i==priv->avfc->nb_programs) return DEMUXER_CTRL_DONTKNOW; p = i; } start = p; redo: program = priv->avfc->programs[p]; for(i=0; i<program->nb_stream_indexes; i++) { switch(priv->avfc->streams[program->stream_index[i]]->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: if(prog->vid == -2) prog->vid = program->stream_index[i]; break; case AVMEDIA_TYPE_AUDIO: if(prog->aid == -2) prog->aid = program->stream_index[i]; break; case AVMEDIA_TYPE_SUBTITLE: if(prog->sid == -2) prog->sid = program->stream_index[i]; break; } } if (prog->aid >= 0 && prog->aid < MAX_A_STREAMS && demuxer->a_streams[prog->aid]) { sh_audio_t *sh = demuxer->a_streams[prog->aid]; prog->aid = sh->aid; } else prog->aid = -2; if (prog->vid >= 0 && prog->vid < MAX_V_STREAMS && demuxer->v_streams[prog->vid]) { sh_video_t *sh = demuxer->v_streams[prog->vid]; prog->vid = sh->vid; } else prog->vid = -2; if(prog->progid == -1 && prog->vid == -2 && prog->aid == -2) { p = (p + 1) % priv->avfc->nb_programs; if (p == start) return DEMUXER_CTRL_DONTKNOW; goto redo; } priv->cur_program = prog->progid = program->id; return DEMUXER_CTRL_OK; } default: return DEMUXER_CTRL_NOTIMPL; } }
static void ASFThread(Context_t *context) { #ifdef DEBUG printf("%s::%s\n", FILENAME, __FUNCTION__); #endif while (context->playback->isCreationPhase) { #ifdef DEBUG printf("%s::%s Thread waiting for end of init phase...\n", FILENAME, __FUNCTION__); #endif } #ifdef DEBUG printf("%s::%s Running!\n", FILENAME, __FUNCTION__); #endif while (context && context->playback && context->playback->isPlaying) { //printf("%s -->\n", __FUNCTION__); //IF MOVIE IS PAUSED, WAIT if (context->playback->isPaused) { #ifdef DEBUG printf("%s::%s paused\n", FILENAME, __FUNCTION__); #endif usleep(100000); continue; } if (context->playback->isSeeking || whileSeeking) { #ifdef DEBUG printf("%s::%s seeking\n", FILENAME, __FUNCTION__); #endif usleep(100000); continue; } //getASFMutex(FILENAME, __FUNCTION__,__LINE__); if (!demux_asf_fill_buffer(ds->demuxer, ds)) { #ifdef DEBUG printf("%s::%s demux_asf_fill_buffer failed!\n", FILENAME, __FUNCTION__); #endif //releaseASFMutex(FILENAME, __FUNCTION__,__LINE__); break; } else { ASFGenerateParcel(context, ds->demuxer); if (ds->demuxer->sub != NULL && ds->demuxer->sub->first != NULL) { ds_free_packs(ds->demuxer->sub); } /* Dont free the packs, as the fragments would be deleted if (ds->demuxer->audio != NULL && ds->demuxer->audio->first != NULL) { ds_free_packs(ds->demuxer->audio); } if (ds->demuxer->video != NULL && ds->demuxer->video->first != NULL) { ds_free_packs(ds->demuxer->video); } */ //releaseASFMutex(FILENAME, __FUNCTION__,__LINE__); } } hasPlayThreadStarted = 0; // prevent locking situation when calling PLAYBACK_TERM context->playback->Command(context, PLAYBACK_TERM, NULL); #ifdef DEBUG printf("%s::%s terminating\n", FILENAME, __FUNCTION__); #endif }
static void free_demuxer_stream(struct demux_stream *ds) { ds_free_packs(ds); free(ds); }
void demux_flush(demuxer_t *demuxer) { ds_free_packs(demuxer->video); ds_free_packs(demuxer->audio); ds_free_packs(demuxer->sub); }
static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) { lavf_priv_t *priv = demuxer->priv; switch (cmd) { case DEMUXER_CTRL_GET_TIME_LENGTH: if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return DEMUXER_CTRL_DONTKNOW; *((double *)arg) = (double)priv->avfc->duration / AV_TIME_BASE; return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_PERCENT_POS: if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return DEMUXER_CTRL_DONTKNOW; *((int *)arg) = (int)((priv->last_pts - priv->avfc->start_time)*100 / priv->avfc->duration); return DEMUXER_CTRL_OK; case DEMUXER_CTRL_SWITCH_AUDIO: case DEMUXER_CTRL_SWITCH_VIDEO: { int id = *((int*)arg); int newid = -2; int i, curridx = -2; int nstreams, *pstreams; demux_stream_t *ds; if(cmd == DEMUXER_CTRL_SWITCH_VIDEO) { ds = demuxer->video; nstreams = priv->video_streams; pstreams = priv->vstreams; } else { ds = demuxer->audio; nstreams = priv->audio_streams; pstreams = priv->astreams; } if(ds->id == -2) return DEMUXER_CTRL_NOTIMPL; for(i = 0; i < nstreams; i++) { if(pstreams[i] == ds->id) //current stream id { curridx = i; break; } } if(id < 0) { i = (curridx + 1) % nstreams; newid = pstreams[i]; } else { for(i = 0; i < nstreams; i++) { if(pstreams[i] == id) { newid = id; break; } } } if(newid == -2 || i == curridx) return DEMUXER_CTRL_NOTIMPL; else { ds_free_packs(ds); priv->avfc->streams[ds->id]->discard = AVDISCARD_ALL; *((int*)arg) = ds->id = newid; priv->avfc->streams[newid]->discard = AVDISCARD_NONE; return DEMUXER_CTRL_OK; } } default: return DEMUXER_CTRL_NOTIMPL; } }
static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) { lavf_priv_t *priv = demuxer->priv; switch (cmd) { case DEMUXER_CTRL_GET_TIME_LENGTH: if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return DEMUXER_CTRL_DONTKNOW; *((double *)arg) = (double)priv->avfc->duration / AV_TIME_BASE; return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_PERCENT_POS: if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return DEMUXER_CTRL_DONTKNOW; *((int *)arg) = (int)((priv->last_pts - priv->avfc->start_time)*100 / priv->avfc->duration); return DEMUXER_CTRL_OK; case DEMUXER_CTRL_SWITCH_AUDIO: case DEMUXER_CTRL_SWITCH_VIDEO: { int id = *((int*)arg); int newid = -2; int i, curridx = -2; int nstreams, *pstreams; demux_stream_t *ds; if(cmd == DEMUXER_CTRL_SWITCH_VIDEO) { ds = demuxer->video; nstreams = priv->video_streams; pstreams = priv->vstreams; } else { ds = demuxer->audio; nstreams = priv->audio_streams; pstreams = priv->astreams; } if(id == -2) { if(ds->id >= 0) priv->avfc->streams[ds->id]->discard = AVDISCARD_ALL; ds_free_packs(ds); *((int*)arg) = ds->id = -2; return DEMUXER_CTRL_OK; } for(i = 0; i < nstreams; i++) { if(pstreams[i] == ds->id) //current stream id { curridx = i; break; } } if(id < 0) { i = (curridx + 1) % nstreams; newid = pstreams[i]; } else { for(i = 0; i < nstreams; i++) { if(pstreams[i] == id) { newid = id; break; } } } if(i == curridx) return DEMUXER_CTRL_NOTIMPL; else { ds_free_packs(ds); if(ds->id >= 0) priv->avfc->streams[ds->id]->discard = AVDISCARD_ALL; *((int*)arg) = ds->id = newid; if(newid >= 0) priv->avfc->streams[newid]->discard = AVDISCARD_NONE; return DEMUXER_CTRL_OK; } } case DEMUXER_CTRL_IDENTIFY_PROGRAM: { demux_program_t *prog = arg; AVProgram *program; int p, i; if(priv->avfc->nb_programs < 2) return DEMUXER_CTRL_NOTIMPL; if(prog->progid == -1) { p = 0; while(p<priv->avfc->nb_programs && priv->avfc->programs[p]->id != priv->cur_program) p++; p = (p + 1) % priv->avfc->nb_programs; } else { for(i=0; i<priv->avfc->nb_programs; i++) if(priv->avfc->programs[i]->id == prog->progid) break; if(i==priv->avfc->nb_programs) return DEMUXER_CTRL_NOTIMPL; p = i; } prog->vid = prog->aid = prog->sid = -2; //no audio and no video by default redo: program = priv->avfc->programs[p]; for(i=0; i<program->nb_stream_indexes; i++) { switch(priv->avfc->streams[program->stream_index[i]]->codec->codec_type) { case CODEC_TYPE_VIDEO: if(prog->vid == -2) prog->vid = program->stream_index[i]; break; case CODEC_TYPE_AUDIO: if(prog->aid == -2) prog->aid = program->stream_index[i]; break; case CODEC_TYPE_SUBTITLE: if(prog->sid == -2 && priv->avfc->streams[program->stream_index[i]]->codec->codec_id == CODEC_ID_TEXT) prog->sid = program->stream_index[i]; break; } } if(prog->progid == -1 && prog->vid == -2 && prog->aid == -2) { p = (p + 1) % priv->avfc->nb_programs; goto redo; } priv->cur_program = prog->progid = program->id; return DEMUXER_CTRL_OK; } default: return DEMUXER_CTRL_NOTIMPL; } }