0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00

AVI demuxer cleanups, fileformat-dependent stuff moved to priv_t

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@1486 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2001-08-11 20:37:33 +00:00
parent 5a09680795
commit 610912b8b5
12 changed files with 304 additions and 253 deletions

24
asf.h
View File

@ -156,12 +156,36 @@ typedef enum {
(h)->comment_size = le2me_16((h)->comment_size); \
(h)->rating_size = le2me_16((h)->rating_size); \
}
#define le2me_BITMAPINFOHEADER(h) { \
(h)->biSize = le2me_32((h)->biSize); \
(h)->biWidth = le2me_32((h)->biWidth); \
(h)->biHeight = le2me_32((h)->biHeight); \
(h)->biPlanes = le2me_16((h)->biPlanes); \
(h)->biBitCount = le2me_16((h)->biBitCount); \
(h)->biCompression = le2me_32((h)->biCompression); \
(h)->biSizeImage = le2me_32((h)->biSizeImage); \
(h)->biXPelsPerMeter = le2me_32((h)->biXPelsPerMeter); \
(h)->biYPelsPerMeter = le2me_32((h)->biYPelsPerMeter); \
(h)->biClrUsed = le2me_32((h)->biClrUsed); \
(h)->biClrImportant = le2me_32((h)->biClrImportant); \
}
#define le2me_WAVEFORMATEX(h) { \
(h)->wFormatTag = le2me_16((h)->wFormatTag); \
(h)->nChannels = le2me_16((h)->nChannels); \
(h)->nSamplesPerSec = le2me_32((h)->nSamplesPerSec); \
(h)->nAvgBytesPerSec = le2me_32((h)->nAvgBytesPerSec); \
(h)->nBlockAlign = le2me_16((h)->nBlockAlign); \
(h)->wBitsPerSample = le2me_16((h)->wBitsPerSample); \
(h)->cbSize = le2me_16((h)->cbSize); \
}
#else
#define le2me_ASF_obj_header_t(h) /**/
#define le2me_ASF_header_t(h) /**/
#define le2me_ASF_stream_header_t(h) /**/
#define le2me_ASF_file_header_t(h) /**/
#define le2me_ASF_content_description_t(h) /**/
#define le2me_BITMAPINFOHEADER(h) /**/
#define le2me_WAVEFORMATEX(h) /**/
#endif

View File

@ -16,7 +16,7 @@ extern int verbose; // defined in mplayer.c
#include "codec-cfg.h"
#include "stheader.h"
#include "aviheader.h"
//#include "aviheader.h"
#include "asf.h"
#ifdef ARCH_X86

View File

@ -1,9 +1,10 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "config.h"
extern int verbose; // defined in mplayer.c
#include "stream.h"
@ -35,9 +36,10 @@ sh_video_t *sh_video=NULL;
int stream_id=-1;
int idxfix_videostream=0;
int idxfix_divx=0;
avi_priv_t* priv=demuxer->priv;
//---- AVI header:
demuxer->idx_size=0;
priv->idx_size=0;
while(1){
int id=stream_read_dword_le(demuxer->stream);
int chunksize,size2;
@ -137,15 +139,15 @@ while(1){
}
case ckidAVINEWINDEX: if(index_mode){
int i;
demuxer->idx_size=size2>>4;
priv->idx_size=size2>>4;
if(verbose>=1) printf("Reading INDEX block, %d chunks for %ld frames\n",
demuxer->idx_size,avih.dwTotalFrames);
demuxer->idx=malloc(demuxer->idx_size<<4);
stream_read(demuxer->stream,(char*)demuxer->idx,demuxer->idx_size<<4);
for (i = 0; i < demuxer->idx_size; i++) // swap index to machine endian
le2me_AVIINDEXENTRY((AVIINDEXENTRY*)demuxer->idx + i);
chunksize-=demuxer->idx_size<<4;
if(verbose>=2) print_index(demuxer->idx,demuxer->idx_size);
priv->idx_size,avih.dwTotalFrames);
priv->idx=malloc(priv->idx_size<<4);
stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4);
for (i = 0; i < priv->idx_size; i++) // swap index to machine endian
le2me_AVIINDEXENTRY((AVIINDEXENTRY*)priv->idx + i);
chunksize-=priv->idx_size<<4;
if(verbose>=2) print_index(priv->idx,priv->idx_size);
break;
}
}
@ -154,14 +156,14 @@ while(1){
}
if(index_mode>=2 || (demuxer->idx_size==0 && index_mode==1)){
if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){
// build index for file:
stream_reset(demuxer->stream);
stream_seek(demuxer->stream,demuxer->movi_start);
demuxer->idx_pos=0;
demuxer->idx_size=0;
demuxer->idx=NULL;
priv->idx_pos=0;
priv->idx_size=0;
priv->idx=NULL;
while(1){
int id,len,skip;
@ -178,13 +180,13 @@ if(index_mode>=2 || (demuxer->idx_size==0 && index_mode==1)){
if(stream_eof(demuxer->stream)) break;
if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?)
if(demuxer->idx_pos<=demuxer->idx_size){
// demuxer->idx_size+=32;
demuxer->idx_size+=1024; // +16kB
demuxer->idx=realloc(demuxer->idx,demuxer->idx_size*sizeof(AVIINDEXENTRY));
if(!demuxer->idx){demuxer->idx_pos=0; break;} // error!
if(priv->idx_pos<=priv->idx_size){
// priv->idx_size+=32;
priv->idx_size+=1024; // +16kB
priv->idx=realloc(priv->idx,priv->idx_size*sizeof(AVIINDEXENTRY));
if(!priv->idx){priv->idx_pos=0; break;} // error!
}
idx=&((AVIINDEXENTRY *)demuxer->idx)[demuxer->idx_pos++];
idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
idx->ckid=id;
idx->dwFlags=AVIIF_KEYFRAME; // FIXME
idx->dwChunkOffset=demuxer->filepos;
@ -212,11 +214,12 @@ skip_chunk:
skip=(len+1)&(~1); // total bytes in this chunk
stream_seek(demuxer->stream,8+demuxer->filepos+skip);
}
demuxer->idx_size=demuxer->idx_pos;
printf("AVI: Generated index table for %d chunks!\n",demuxer->idx_size);
priv->idx_size=priv->idx_pos;
printf("AVI: Generated index table for %d chunks!\n",priv->idx_size);
}
}
#undef MIN

View File

@ -1,7 +1,7 @@
#ifndef _aviheader_h
#define _aviheader_h
#include "config.h" /* get correct definition WORDS_BIGENDIAN */
//#include "config.h" /* get correct definition WORDS_BIGENDIAN */
#include "bswap.h"
/*
@ -83,3 +83,24 @@
#endif
typedef struct {
// index stuff:
void* idx;
int idx_size;
int idx_pos;
int idx_pos_a;
int idx_pos_v;
int idx_offset; // ennyit kell hozzaadni az index offset ertekekhez
// interleaved PTS stuff:
int skip_video_frames;
float avi_audio_pts;
float avi_video_pts;
float pts_correction;
unsigned int pts_corr_bytes;
unsigned char pts_corrected;
unsigned char pts_has_video;
} avi_priv_t;
#define AVI_PRIV ((avi_priv_t*)(demuxer->priv))

View File

@ -79,14 +79,23 @@ void print_video_header(BITMAPINFOHEADER *h){
void print_index(AVIINDEXENTRY *idx,int idx_size){
int i;
unsigned int pos[256];
unsigned int num[256];
for(i=0;i<256;i++) num[i]=pos[i]=0;
for(i=0;i<idx_size;i++){
printf("%5d: %.4s %4X %08X %ld\n",i,
int id=avi_stream_id(idx[i].ckid);
if(id<0 || id>255) id=255;
printf("%5d: %.4s %4X %08X len:%6ld pos:%7d->%7.3f %7d->%7.3f\n",i,
(char *)&idx[i].ckid,
(unsigned int)idx[i].dwFlags,
(unsigned int)idx[i].dwChunkOffset,
// idx[i].dwChunkOffset+demuxer->movi_start,
idx[i].dwChunkLength
idx[i].dwChunkLength,
pos[id],(float)pos[id]/18747.0f,
num[id],(float)num[id]/23.976f
);
pos[id]+=idx[i].dwChunkLength;
++num[id];
}
}

View File

@ -282,6 +282,7 @@ int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){
switch(sh_audio->codec->driver){
case AFM_MPEG: // MPEG layer 2 or 3
len=MP3_DecodeFrame(buf,-1);
// len=MP3_DecodeFrame(buf,3);
break;
case AFM_PCM: // AVI PCM
len=demux_read_data(sh_audio->ds,buf,minlen);

View File

@ -37,13 +37,6 @@ extern int asf_packetsize;
// based on asf file-format doc by Eugene [http://divx.euro.ru]
//static float avi_pts_frametime=1.0f/25.0f;
//static float avi_audio_pts=0;
//static float avi_video_pts=0;
//static int skip_video_frames=0;
static void asf_descrambling(unsigned char *src,int len){
unsigned char *dst=malloc(len);
unsigned char *s2=src;

View File

@ -1,4 +1,4 @@
// AVI file parser for DEMUXER v2.6 by A'rpi/ESP-team
// AVI file parser for DEMUXER v2.9 by A'rpi/ESP-team
#include <stdio.h>
#include <stdlib.h>
@ -16,11 +16,7 @@ extern int verbose; // defined in mplayer.c
#include "codec-cfg.h"
#include "stheader.h"
//static float avi_pts_frametime=1.0f/25.0f;
float avi_audio_pts=0;
float avi_video_pts=0;
//float avi_video_ftime=0.04;
int skip_video_frames=0;
#include "aviheader.h"
// Select ds from ID
demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){
@ -58,12 +54,9 @@ demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){
return NULL;
}
static float pts_correction=0.0;
static int pts_corrected=0;
static int pts_has_video=0;
static unsigned int pts_corr_bytes=0;
static int demux_avi_read_packet(demuxer_t *demux,unsigned int id,unsigned int len,int idxpos,int flags){
avi_priv_t *priv=demux->priv;
int skip;
float pts=0;
demux_stream_t *ds=demux_avi_select_stream(demux,id);
@ -72,50 +65,50 @@ static int demux_avi_read_packet(demuxer_t *demux,unsigned int id,unsigned int l
if(ds==demux->audio){
if(pts_corrected==0){
// printf("\rYYY-A A: %5.3f V: %5.3f \n",avi_audio_pts,avi_video_pts);
if(pts_has_video){
if(priv->pts_corrected==0){
// printf("\rYYY-A A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts);
if(priv->pts_has_video){
// we have video pts now
float delay=(float)pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec;
printf("XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",avi_audio_pts,pts_corr_bytes,delay);
//pts_correction=-avi_audio_pts+delay;
pts_correction=delay-avi_audio_pts;
avi_audio_pts+=pts_correction;
pts_corrected=1;
float delay=(float)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec;
printf("XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",priv->avi_audio_pts,priv->pts_corr_bytes,delay);
//priv->pts_correction=-priv->avi_audio_pts+delay;
priv->pts_correction=delay-priv->avi_audio_pts;
priv->avi_audio_pts+=priv->pts_correction;
priv->pts_corrected=1;
} else
pts_corr_bytes+=len;
priv->pts_corr_bytes+=len;
}
pts=avi_audio_pts; //+pts_correction;
avi_audio_pts=0;
pts=priv->avi_audio_pts; //+priv->pts_correction;
priv->avi_audio_pts=0;
} else
if(ds==demux->video){
// video
if(skip_video_frames>0){
if(priv->skip_video_frames>0){
// drop frame (seeking)
--skip_video_frames;
--priv->skip_video_frames;
ds=NULL;
} else {
pts=avi_video_pts;
pts=priv->avi_video_pts;
}
// ezt a 2 sort lehet hogy fell kell majd cserelni:
//avi_video_pts+=avi_pts_frametime;
//avi_video_pts+=(float)avi_header.video.dwScale/(float)avi_header.video.dwRate;
//avi_video_pts+=((sh_video_t*)ds->sh)->frametime;
//priv->avi_video_pts+=avi_pts_frametime;
//priv->avi_video_pts+=(float)avi_header.video.dwScale/(float)avi_header.video.dwRate;
//priv->avi_video_pts+=((sh_video_t*)ds->sh)->frametime;
// FIXME!!!
#if 1
// printf("ds=0x%X\n",ds);
// printf("packno=%d\n",ds->pack_no);
// printf("### pack_no=%d\n",demux->video->pack_no+demux->video->packs);
avi_video_pts = (demux->video->pack_no+demux->video->packs) *
priv->avi_video_pts = (demux->video->pack_no+demux->video->packs) *
(float)((sh_video_t*)demux->video->sh)->video.dwScale /
(float)((sh_video_t*)demux->video->sh)->video.dwRate;
#else
avi_video_pts+=(float)((sh_video_t*)(demux->video->sh))->video.dwScale/(float)((sh_video_t*)(demux->video->sh))->video.dwRate;
// avi_video_pts+=avi_video_ftime;
priv->avi_video_pts+=(float)((sh_video_t*)(demux->video->sh))->video.dwScale/(float)((sh_video_t*)(demux->video->sh))->video.dwRate;
// priv->avi_video_pts+=avi_video_ftime;
#endif
// printf("\rYYY-V A: %5.3f V: %5.3f \n",avi_audio_pts,avi_video_pts);
avi_audio_pts=avi_video_pts+pts_correction;
pts_has_video=1;
// printf("\rYYY-V A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts);
priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction;
priv->pts_has_video=1;
}
@ -134,13 +127,11 @@ static int demux_avi_read_packet(demuxer_t *demux,unsigned int id,unsigned int l
return ds?1:0;
}
//static int num_elementary_packets100=0;
//static int num_elementary_packets101=0;
// return value:
// 0 = EOF or no stream found
// 1 = successfully read a packet
int demux_avi_fill_buffer(demuxer_t *demux){
avi_priv_t *priv=demux->priv;
unsigned int id=0;
unsigned int len;
int max_packs=128;
@ -157,14 +148,14 @@ do{
}
if(stream_eof(demux->stream)) return 0;
#endif
if(demux->idx_size>0 && demux->idx_pos<demux->idx_size){
if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){
unsigned int pos;
//if(demux->idx_pos<0) printf("Fatal! idx_pos=%d\n",demux->idx_pos);
//if(priv->idx_pos<0) printf("Fatal! idx_pos=%d\n",priv->idx_pos);
idx=&((AVIINDEXENTRY *)demux->idx)[demux->idx_pos++];
idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
//printf("[%d]",demux->idx_pos);fflush(stdout);
//printf("[%d]",priv->idx_pos);fflush(stdout);
//stream_seek(demux->stream,idx.dwChunkOffset);
//printf("IDX pos=%X idx.pos=%X idx.size=%X idx.flags=%X\n",demux->filepos,
@ -178,7 +169,7 @@ do{
continue; // skip this chunk
}
pos=idx->dwChunkOffset+demux->idx_offset;
pos=idx->dwChunkOffset+priv->idx_offset;
if(pos<demux->movi_start || pos>=demux->movi_end){
printf("ChunkOffset out of range! idx=0x%X \n",pos);
continue;
@ -222,8 +213,8 @@ do{
continue;
}
}
ret=demux_avi_read_packet(demux,id,len,demux->idx_pos-1,flags);
if(!ret && skip_video_frames<=0)
ret=demux_avi_read_packet(demux,id,len,priv->idx_pos-1,flags);
if(!ret && priv->skip_video_frames<=0)
if(--max_packs==0){
demux->stream->eof=1;
printf("demux: file doesn't contain the selected audio or video stream\n");
@ -238,6 +229,7 @@ do{
// 0 = EOF or no stream found
// 1 = successfully read a packet
int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){
avi_priv_t *priv=demux->priv;
unsigned int id=0;
unsigned int len;
int max_packs=128;
@ -249,14 +241,14 @@ do{
int idx_pos=0;
demux->filepos=stream_tell(demux->stream);
if(ds==demux->video) idx_pos=demux->idx_pos_v++; else
if(ds==demux->audio) idx_pos=demux->idx_pos_a++; else
idx_pos=demux->idx_pos++;
if(ds==demux->video) idx_pos=priv->idx_pos_v++; else
if(ds==demux->audio) idx_pos=priv->idx_pos_a++; else
idx_pos=priv->idx_pos++;
if(demux->idx_size>0 && idx_pos<demux->idx_size){
if(priv->idx_size>0 && idx_pos<priv->idx_size){
unsigned int pos;
idx=&((AVIINDEXENTRY *)demux->idx)[idx_pos];
// idx=&demux->idx[idx_pos];
idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos];
// idx=&priv->idx[idx_pos];
if(idx->dwFlags&AVIIF_LIST){
// LIST
@ -267,7 +259,7 @@ do{
continue; // skip this chunk
}
pos=idx->dwChunkOffset+demux->idx_offset;
pos=idx->dwChunkOffset+priv->idx_offset;
if(pos<demux->movi_start || pos>=demux->movi_end){
printf("ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos);
continue;
@ -299,7 +291,7 @@ do{
if(idx->dwFlags&AVIIF_KEYFRAME) flags=1;
} else return 0;
ret=demux_avi_read_packet(demux,id,len,idx_pos,flags);
if(!ret && skip_video_frames<=0)
if(!ret && priv->skip_video_frames<=0)
if(--max_packs==0){
demux->stream->eof=1;
printf("demux: file doesn't contain the selected audio or video stream\n");
@ -314,13 +306,14 @@ do{
// 0 = EOF or no stream found
// 1 = successfully read a packet
int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){
avi_priv_t *priv=demux->priv;
unsigned int id=0;
unsigned int len;
int ret=0;
int *fpos=NULL;
if(ds==demux->video) fpos=&demux->idx_pos_v; else
if(ds==demux->audio) fpos=&demux->idx_pos_a; else
if(ds==demux->video) fpos=&priv->idx_pos_v; else
if(ds==demux->audio) fpos=&priv->idx_pos_a; else
return 0;
stream_seek(demux->stream,fpos[0]);
@ -343,7 +336,7 @@ do{
if(ds==demux_avi_select_stream(demux,id)){
// read it!
ret=demux_avi_read_packet(demux,id,len,demux->idx_pos-1,0);
ret=demux_avi_read_packet(demux,id,len,priv->idx_pos-1,0);
} else {
// skip it!
int skip=(len+1)&(~1); // total bytes in this chunk
@ -355,9 +348,130 @@ do{
return 1;
}
extern float initial_pts_delay;
extern int audio_id;
extern int video_id;
extern int index_mode; // -1=untouched 0=don't use index 1=use (geneate) index
extern int force_ni;
extern int pts_from_bps;
demuxer_t* demux_open_avi(demuxer_t* demuxer){
demux_stream_t *d_audio=demuxer->audio;
demux_stream_t *d_video=demuxer->video;
sh_audio_t *sh_audio=NULL;
sh_video_t *sh_video=NULL;
avi_priv_t* priv=malloc(sizeof(avi_priv_t));
// priv struct:
priv->avi_audio_pts=priv->avi_video_pts=0.0f;
priv->pts_correction=0.0f;
priv->skip_video_frames=0;
priv->pts_corr_bytes=0;
priv->pts_has_video=priv->pts_corrected=0;
demuxer->priv=(void*)priv;
//---- AVI header:
read_avi_header(demuxer,(demuxer->stream->type!=STREAMTYPE_STREAM)?index_mode:-2);
stream_reset(demuxer->stream);
stream_seek(demuxer->stream,demuxer->movi_start);
priv->idx_pos=0;
priv->idx_pos_a=0;
priv->idx_pos_v=0;
if(priv->idx_size>0){
// decide index format:
if(((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset<demuxer->movi_start)
priv->idx_offset=demuxer->movi_start-4;
else
priv->idx_offset=0;
if(verbose) printf("AVI index offset: %d\n",priv->idx_offset);
}
// demuxer->endpos=avi_header.movi_end;
if(priv->idx_size>0){
// check that file is non-interleaved:
int i;
int a_pos=-1;
int v_pos=-1;
for(i=0;i<priv->idx_size;i++){
AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)priv->idx)[i];
demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
int pos=idx->dwChunkOffset+priv->idx_offset;
if(a_pos==-1 && ds==demuxer->audio){
a_pos=pos;
if(v_pos!=-1) break;
}
if(v_pos==-1 && ds==demuxer->video){
v_pos=pos;
if(a_pos!=-1) break;
}
}
if(v_pos==-1){
fprintf(stderr,"AVI_NI: missing video stream!? contact the author, it may be a bug :(\n");
return NULL;
// GUI_MSG( mplErrorAVINI )
// exit(1);
}
if(a_pos==-1){
printf("AVI_NI: No audio stream found -> nosound\n");
sh_audio=NULL;
} else {
if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
printf("%s NON-INTERLEAVED AVI file-format!\n",force_ni?"Forced":"Detected");
demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
pts_from_bps=1; // force BPS sync!
}
}
} else {
// no index
if(force_ni){
printf("Using NON-INTERLEAVED Broken AVI file-format!\n");
demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
priv->idx_pos_a=
priv->idx_pos_v=demuxer->movi_start;
pts_from_bps=1; // force BPS sync!
}
}
if(!ds_fill_buffer(d_video)){
fprintf(stderr,"AVI: missing video stream!? contact the author, it may be a bug :(\n");
return NULL;
// GUI_MSG( mplAVIErrorMissingVideoStream )
// exit(1);
}
sh_video=d_video->sh;sh_video->ds=d_video;
if(audio_id!=-2){
if(verbose) printf("AVI: Searching for audio stream (id:%d)\n",d_audio->id);
if(!ds_fill_buffer(d_audio)){
printf("AVI: No Audio stream found... ->nosound\n");
sh_audio=NULL;
} else {
sh_audio=d_audio->sh;sh_audio->ds=d_audio;
sh_audio->format=sh_audio->wf->wFormatTag;
}
}
// calc. FPS:
sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
// calculating video bitrate:
sh_video->i_bps=demuxer->movi_end-demuxer->movi_start-priv->idx_size*8;
if(sh_audio) sh_video->i_bps-=sh_audio->audio.dwLength;
if(verbose) printf("AVI video length=%d\n",sh_video->i_bps);
sh_video->i_bps=((float)sh_video->i_bps/(float)sh_video->video.dwLength)*sh_video->fps;
printf("VIDEO: [%.4s] %ldx%ld %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
(char *)&sh_video->bih->biCompression,
sh_video->bih->biWidth,
sh_video->bih->biHeight,
sh_video->bih->biBitCount,
sh_video->fps,
sh_video->i_bps*0.008f,
sh_video->i_bps/1024.0f );
return demuxer;
}
//extern float initial_pts_delay;
void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
avi_priv_t *priv=demuxer->priv;
demux_stream_t *d_audio=demuxer->audio;
demux_stream_t *d_video=demuxer->video;
sh_audio_t *sh_audio=d_audio->sh;
@ -370,40 +484,40 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
int video_chunk_pos=d_video->pos;
int i;
skip_video_frames=0;
avi_audio_pts=0;
priv->skip_video_frames=0;
priv->avi_audio_pts=0;
// ------------ STEP 1: find nearest video keyframe chunk ------------
// find nearest video keyframe chunk pos:
if(rel_seek_frames>0){
// seek forward
while(video_chunk_pos<demuxer->idx_size){
int id=((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].ckid;
while(video_chunk_pos<priv->idx_size){
int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
if(avi_stream_id(id)==d_video->id){ // video frame
if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
}
++video_chunk_pos;
}
} else {
// seek backward
while(video_chunk_pos>=0){
int id=((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].ckid;
int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
if(avi_stream_id(id)==d_video->id){ // video frame
if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
}
--video_chunk_pos;
}
}
demuxer->idx_pos_a=demuxer->idx_pos_v=demuxer->idx_pos=video_chunk_pos;
priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=video_chunk_pos;
// re-calc video pts:
d_video->pack_no=0;
for(i=0;i<video_chunk_pos;i++){
int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid;
int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;
}
sh_video->num_frames=d_video->pack_no;
avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
d_video->pos=video_chunk_pos;
// ------------ STEP 2: seek audio, find the right chunk & pos ------------
@ -419,28 +533,28 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
int skip_audio_bytes=0;
int curr_audio_pos=-1;
int audio_chunk_pos=-1;
int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:demuxer->idx_size;
int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;
if(sh_audio->audio.dwSampleSize){
// constant rate audio stream
#if 0
int align;
curr_audio_pos=(avi_video_pts) * sh_audio->wf->nAvgBytesPerSec;
curr_audio_pos=(priv->avi_video_pts) * sh_audio->wf->nAvgBytesPerSec;
if(curr_audio_pos<0)curr_audio_pos=0;
align=sh_audio->audio.dwSampleSize;
if(sh_audio->wf->nBlockAlign>align) align=sh_audio->wf->nBlockAlign;
curr_audio_pos/=align;
curr_audio_pos*=align;
#else
curr_audio_pos=(avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
curr_audio_pos=(priv->avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
curr_audio_pos*=sh_audio->audio.dwSampleSize;
#endif
// find audio chunk pos:
for(i=0;i<chunk_max;i++){
int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid;
int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
if(avi_stream_id(id)==d_audio->id){
len=((AVIINDEXENTRY *)demuxer->idx)[i].dwChunkLength;
len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
audio_chunk_pos=i; ++d_audio->pack_no;
if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){
//if(verbose)printf("break;\n");
@ -453,14 +567,14 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
} else {
// VBR audio
int chunks=(avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
int chunks=(priv->avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
audio_chunk_pos=0;
// find audio chunk pos:
for(i=0;i<demuxer->idx_size && chunks>0;i++){
int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid;
for(i=0;i<priv->idx_size && chunks>0;i++){
int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
if(avi_stream_id(id)==d_audio->id){
len=((AVIINDEXENTRY *)demuxer->idx)[i].dwChunkLength;
len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
if(i>chunk_max){
skip_audio_bytes+=len;
} else {
@ -474,7 +588,7 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
//if(audio_chunk_pos>chunk_max) audio_chunk_pos=chunk_max;
// printf("VBR seek: %5.3f -> chunk_no %d -> chunk_idx %d + skip %d \n",
// avi_video_pts, audio_chunk_pos, );
// priv->avi_video_pts, audio_chunk_pos, );
}
@ -493,25 +607,25 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
if(demuxer->type==DEMUXER_TYPE_AVI){
// interleaved stream:
if(audio_chunk_pos<video_chunk_pos){
// calc skip_video_frames & adjust video pts counter:
// calc priv->skip_video_frames & adjust video pts counter:
for(i=audio_chunk_pos;i<video_chunk_pos;i++){
int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid;
if(avi_stream_id(id)==d_video->id) ++skip_video_frames;
int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;
}
// requires for correct audio pts calculation (demuxer):
avi_video_pts-=skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
demuxer->idx_pos_a=demuxer->idx_pos_v=demuxer->idx_pos=audio_chunk_pos;
priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos;
}
} else {
// non-interleaved stream:
demuxer->idx_pos_a=audio_chunk_pos;
demuxer->idx_pos_v=video_chunk_pos;
demuxer->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos;
priv->idx_pos_a=audio_chunk_pos;
priv->idx_pos_v=video_chunk_pos;
priv->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos;
}
if(verbose) printf("SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n",
demuxer->idx_pos,audio_chunk_pos,video_chunk_pos,
skip_video_frames,skip_audio_bytes,skip_audio_secs);
priv->idx_pos,audio_chunk_pos,video_chunk_pos,
priv->skip_video_frames,skip_audio_bytes,skip_audio_secs);
if(skip_audio_bytes){
demux_read_data(d_audio,NULL,skip_audio_bytes);

105
demuxer.c
View File

@ -294,7 +294,6 @@ extern int num_elementary_packetsPES;
// commandline options, flags:
extern int seek_to_byte;
extern int index_mode; // -1=untouched 0=don't use index 1=use (geneate) index
extern int force_ni;
extern int pts_from_bps;
@ -391,8 +390,8 @@ if(file_format==DEMUXER_TYPE_MPEG_ES){ // little hack, see above!
printf("Detected MPEG-ES file format!\n");
}
}
#ifdef MOV
//=============== Try to open as MOV file: =================
#if 0
if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MOV){
stream_reset(stream);
demuxer=new_demuxer(stream,DEMUXER_TYPE_MOV,audio_id,video_id,dvdsub_id);
@ -416,110 +415,19 @@ d_audio=demuxer->audio;
d_video=demuxer->video;
//d_dvdsub=demuxer->sub;
demuxer->file_format=file_format;
switch(file_format){
case DEMUXER_TYPE_AVI: {
//---- AVI header:
read_avi_header(demuxer,(stream->type!=STREAMTYPE_STREAM)?index_mode:-2);
stream_reset(demuxer->stream);
stream_seek(demuxer->stream,demuxer->movi_start);
demuxer->idx_pos=0;
demuxer->idx_pos_a=0;
demuxer->idx_pos_v=0;
if(demuxer->idx_size>0){
// decide index format:
if(((AVIINDEXENTRY *)demuxer->idx)[0].dwChunkOffset<demuxer->movi_start)
demuxer->idx_offset=demuxer->movi_start-4;
else
demuxer->idx_offset=0;
if(verbose) printf("AVI index offset: %d\n",demuxer->idx_offset);
}
// demuxer->endpos=avi_header.movi_end;
if(demuxer->idx_size>0){
// check that file is non-interleaved:
int i;
int a_pos=-1;
int v_pos=-1;
for(i=0;i<demuxer->idx_size;i++){
AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)demuxer->idx)[i];
demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
int pos=idx->dwChunkOffset+demuxer->idx_offset;
if(a_pos==-1 && ds==demuxer->audio){
a_pos=pos;
if(v_pos!=-1) break;
}
if(v_pos==-1 && ds==demuxer->video){
v_pos=pos;
if(a_pos!=-1) break;
}
}
if(v_pos==-1){
fprintf(stderr,"AVI_NI: missing video stream!? contact the author, it may be a bug :(\n");
return NULL;
// GUI_MSG( mplErrorAVINI )
// exit(1);
}
if(a_pos==-1){
printf("AVI_NI: No audio stream found -> nosound\n");
sh_audio=NULL;
} else {
if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
printf("%s NON-INTERLEAVED AVI file-format!\n",force_ni?"Forced":"Detected");
demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
pts_from_bps=1; // force BPS sync!
}
}
} else {
// no index
if(force_ni){
printf("Using NON-INTERLEAVED Broken AVI file-format!\n");
demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
demuxer->idx_pos_a=
demuxer->idx_pos_v=demuxer->movi_start;
pts_from_bps=1; // force BPS sync!
}
}
if(!ds_fill_buffer(d_video)){
fprintf(stderr,"AVI: missing video stream!? contact the author, it may be a bug :(\n");
return NULL;
// GUI_MSG( mplAVIErrorMissingVideoStream )
// exit(1);
}
sh_video=d_video->sh;sh_video->ds=d_video;
if(audio_id!=-2){
if(verbose) printf("AVI: Searching for audio stream (id:%d)\n",d_audio->id);
if(!ds_fill_buffer(d_audio)){
printf("AVI: No Audio stream found... ->nosound\n");
sh_audio=NULL;
} else {
sh_audio=d_audio->sh;sh_audio->ds=d_audio;
sh_audio->format=sh_audio->wf->wFormatTag;
}
}
// calc. FPS:
sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
// calculating video bitrate:
sh_video->i_bps=demuxer->movi_end-demuxer->movi_start-demuxer->idx_size*8;
if(sh_audio) sh_video->i_bps-=sh_audio->audio.dwLength;
if(verbose) printf("AVI video length=%d\n",sh_video->i_bps);
sh_video->i_bps=((float)sh_video->i_bps/(float)sh_video->video.dwLength)*sh_video->fps;
printf("VIDEO: [%.4s] %ldx%ld %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
(char *)&sh_video->bih->biCompression,
sh_video->bih->biWidth,
sh_video->bih->biHeight,
sh_video->bih->biBitCount,
sh_video->fps,
sh_video->i_bps*0.008f,
sh_video->i_bps/1024.0f );
break;
return demux_open_avi(demuxer);
// break;
}
case DEMUXER_TYPE_ASF: {
//---- ASF header:
read_asf_header(demuxer);
stream_reset(demuxer->stream);
stream_seek(demuxer->stream,demuxer->movi_start);
demuxer->idx_pos=0;
// demuxer->idx_pos=0;
// demuxer->endpos=avi_header.movi_end;
if(!ds_fill_buffer(d_video)){
printf("ASF: no video stream found!\n");
@ -575,6 +483,5 @@ switch(file_format){
}
} // switch(file_format)
demuxer->file_format=file_format;
return demuxer;
}

View File

@ -22,7 +22,7 @@
typedef struct demux_packet_st {
int len;
float pts;
off_t pos; // pozicio indexben (AVI) ill. fileban (MPG)
off_t pos; // position in index (AVI) or file (MPG)
unsigned char* buffer;
int flags; // keyframe, etc
struct demux_packet_st* next;
@ -59,30 +59,19 @@ typedef struct demuxer_st {
off_t filepos; // input stream current pos.
int type; // demuxer type: mpeg PS, mpeg ES, avi, avi-ni, avi-nini, asf
int file_format; // file format: mpeg/avi/asf
// int time_src;// time source (pts/file/bps)
off_t movi_start;
off_t movi_end;
//
demux_stream_t *audio;
demux_stream_t *video;
demux_stream_t *sub;
// index:
// AVIINDEXENTRY* idx;
// FIXME: off_t???
void* idx;
int idx_size;
int idx_pos;
int idx_pos_a;
int idx_pos_v;
int idx_offset; // ennyit kell hozzaadni az index offset ertekekhez
demux_stream_t *audio; // audio buffer/demuxer
demux_stream_t *video; // video buffer/demuxer
demux_stream_t *sub; // dvd subtitle buffer/demuxer
// stream headers:
// sh_audio_t* a_streams[256];
// sh_video_t* v_streams[256];
void* a_streams[256];
void* v_streams[256];
char s_streams[32]; // dvd subtitles
void* a_streams[256]; // audio streams (sh_audio_t)
void* v_streams[256]; // video sterams (sh_video_t)
char s_streams[32]; // dvd subtitles (flag)
void* priv; // fileformat-dependent data
} demuxer_t;
inline static demux_packet_t* new_demux_packet(int len){

View File

@ -150,11 +150,6 @@ int encode_bitrate=0;
extern int asf_packetsize; // for seeking
extern float avi_audio_pts;
extern float avi_video_pts;
extern float avi_video_ftime;
extern int skip_video_frames;
void read_avi_header(demuxer_t *demuxer,int index_mode);
demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id);
@ -1362,7 +1357,7 @@ if(1)
else // VBR:
a_pts=d_audio->pack_no*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate;
v_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
if(verbose)printf("%5.3f|",v_pts-d_video->pts);
// if(verbose)printf("%5.3f|",v_pts-d_video->pts);
} else {
if(!delay_corrected && d_audio->pts){
// float x=d_audio->pts-d_video->pts-(delay);

13
seek.c
View File

@ -22,11 +22,6 @@
//extern int asf_packetsize; // for seeking
//extern float avi_audio_pts;
//extern float avi_video_pts;
//extern float avi_video_ftime;
//extern int skip_video_frames;
//extern int seek_to_byte;
//extern char* current_module; // for debugging
// flags:
@ -44,10 +39,10 @@ int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags){
sh_video_t *sh_video=d_video->sh;
// float skip_audio_secs=0;
if(demuxer->file_format==DEMUXER_TYPE_AVI && demuxer->idx_size<=0){
printf("Can't seek in raw .AVI streams! (index required, try with the -idx switch!) \n");
return 0;
}
//if(demuxer->file_format==DEMUXER_TYPE_AVI && demuxer->idx_size<=0){
// printf("Can't seek in raw .AVI streams! (index required, try with the -idx switch!) \n");
// return 0;
//}
// current_module="seek";