안드로이드 개발 질문/답변
(글 수 45,052)
double pos = 7.1;
int64_t tm = (int64_t)(pos * AV_TIME_BASE);
tm = av_rescale_q(tm, AV_TIME_BASE_Q, gFormatCtx->streams[gVideoStreamIdx]->time_base);
if(avformat_seek_file(gFormatCtx, gVideoStreamIdx, 0, tm, tm, 0)<0){
INFO("av_seek_frame error");
}else{
INFO("av_seek_frame success");
avcodec_flush_buffers(gVideoCodecCtx);
}
전에 조언받은대로 av_seek_frame대신 avformat_seek_file을 사용했습니다. 그런데 궁금한게 저는 썸네일을 1초짜리 동영상이라면
0.1초 단위로 보여주려고 하는데요. 저기있는 pos값을 0.1단위로 고쳐서 이동시켜보아도 계속 같은 자리의 동영상만 나옵니다;
gFrame->best_effort_timestamp 이렇게 현재 프레임 위치를 조회해봐도 변하질 않네요??? avformat_seek_file에서 min값을
0으로 줬는데도 작은값으로 이동하는건 왜일까요ㅡㅡ?? 동영상으로 치면 계속 0.1초값에 머물러 있네요.




포멧마다 다르겠지만 대부분 영상은 seek을 위해 시간 + 실제 파일위치 정보를 가진 인덱스 테이블이 존재하며,
ffmpeg는 이 인덱스 테이블을 기준으로 이동이 됩니다. 인덱스 테이블이 0.1초 단위로 존재한다면,
0.1초 단위로 seek 이 되겠지만 그럴 경우 인덱스 테이블이 엄청 커집니다.
따라서 인덱스 테이블에 들어 있는 시간단위가 0.1초 단위로 seek이 잘 되지 않고 가장 가까운 0초로 seek이 된듯 합니다.
그리고 0.1초 단위로 썸네일을 만들면 10fps 영상을 SW플레이어로 재생 하는 것이라 봐도 되기 때문에 저장 하는데 걸리는 시간까자 하면 상당히 많은 시간이 걸릴듯 합니다.. 용량도 압축된 데이터가 풀어졌기 때문에 원본 데이터 사이즈 보다 더 클 수 있습니다.
가급적이면 10초이상 단위로 저장을 하시는 것을 권장합니다.
그리고 안드로이드 기본 플레이어서 돌아가는 일반적인 콘텐츠라면. 안드로이드에서 제공하는 java api 이용하여 HW코덱으로 썸네일을 만드시길 수도 있으니 가급적 안드로이드 기본 api를 사용하시는 것을 권장합니다.
사족인데 seek이 되더라도 헤딩 데이터가 P프레임이나 B프레임일 경우 ffmpeg를 통해 Thumbnail을 뽑으면 깨진 화면이 나오게 됩니다.
I프레임 부터 디코딩을 해주셔야 한 깨집니다.(ffmpeg를 사용하실 거라면 seek시 I프레임 단위로 seek을 시켜주는 플러그를 넣으시는 것을 권장합니다..)