From 22329987616780494b4d4f5fc85b8c40b592d724 Mon Sep 17 00:00:00 2001 From: Thibaut Mattern Date: Sun, 12 May 2002 12:13:28 +0000 Subject: Fix seeking problem after demuxer finished Change get_status to return thread_running instead of demux status. Replace by 2 spaces. CVS patchset: 1871 CVS date: 2002/05/12 12:13:28 --- src/demuxers/demux_avi.c | 647 ++++++++++++++++++++++++----------------------- 1 file changed, 327 insertions(+), 320 deletions(-) (limited to 'src') diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index e71d2687f..47acd0d21 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000-2002 the xine project * * This file is part of xine, a free video player. @@ -17,11 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_avi.c,v 1.82 2002/05/04 17:26:15 f1rmb Exp $ + * $Id: demux_avi.c,v 1.83 2002/05/12 12:13:28 tmattern Exp $ * * demultiplexer for avi streams * - * part of the code is taken from + * part of the code is taken from * avilib (C) 1999 Rainer Johanni * */ @@ -97,7 +97,7 @@ typedef struct long height; /* Height of a video frame */ long dwScale, dwRate; double fps; /* Frames per second */ - + char compressor[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ long video_strn; /* Video stream number */ long video_frames; /* Number of video frames */ @@ -105,11 +105,11 @@ typedef struct long video_posf; /* Number of next frame to be read (if index present) */ long video_posb; /* Video position: byte within frame */ - + avi_audio_t *audio[MAX_AUDIO_STREAMS]; int n_audio; - + uint32_t video_type; /* BUF_VIDEO_xxx type */ long pos; /* position in file */ @@ -136,6 +136,7 @@ typedef struct demux_avi_s { avi_t *avi; pthread_t thread; + int thread_running; pthread_mutex_t mutex; int status; @@ -144,7 +145,7 @@ typedef struct demux_avi_s { int have_spu; uint32_t video_step; - uint32_t AVI_errno; + uint32_t AVI_errno; int send_end_buffers; @@ -238,13 +239,13 @@ static int avi_sampsize(avi_t *AVI, int track) { int s; s = ((AVI->audio[track]->a_bits+7)/8)*AVI->audio[track]->a_chans; - if (s==0) + if (s==0) s=1; /* avoid possible zero divisions */ return s; } -static int avi_add_index_entry(demux_avi_t *this, avi_t *AVI, unsigned char *tag, - long flags, long pos, long len) +static int avi_add_index_entry(demux_avi_t *this, avi_t *AVI, unsigned char *tag, + long flags, long pos, long len) { void *ptr; @@ -257,7 +258,7 @@ static int avi_add_index_entry(demux_avi_t *this, avi_t *AVI, unsigned char *tag AVI->max_idx += 4096; AVI->idx = (unsigned char((*)[16]) ) ptr; } - + /* Add index entry */ memcpy(AVI->idx[AVI->n_idx],tag,4); @@ -281,7 +282,7 @@ static void gen_index_show_progress (demux_avi_t *this, int percent) { this->xine->osd_renderer->filled_rect (this->xine->osd, 0, 0, 299, 99, 0); this->xine->osd_renderer->render_text (this->xine->osd, 5, 30, str, OSD_TEXT1); this->xine->osd_renderer->show (this->xine->osd, 0); - + } @@ -315,175 +316,174 @@ static avi_t *AVI_init(demux_avi_t *this) { this->input->seek(this->input, 0, SEEK_SET); if( this->input->read(this->input, data,12) != 12 ) ERR_EXIT(AVI_ERR_READ) ; - + if( strncasecmp(data ,"RIFF",4) !=0 || - strncasecmp(data+8,"AVI ",4) !=0 ) + strncasecmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI) ; /* Go through the AVI file and extract the header list, the start position of the 'movi' list and an optionally present idx1 tag */ - + hdrl_data = NULL; - + while(1) { - if (this->input->read(this->input, data,8) != 8 ) + if (this->input->read(this->input, data,8) != 8 ) break; /* We assume it's EOF */ - + n = str2ulong(data+4); n = PAD_EVEN(n); - + if(strncasecmp(data,"LIST",4) == 0) { if( this->input->read(this->input, data,4) != 4 ) ERR_EXIT(AVI_ERR_READ); n -= 4; if(strncasecmp(data,"hdrl",4) == 0) { - hdrl_len = n; - hdrl_data = (unsigned char *) xine_xmalloc(n); - if(hdrl_data==0) - ERR_EXIT(AVI_ERR_NO_MEM); - if (this->input->read(this->input, hdrl_data,n) != n ) - ERR_EXIT(AVI_ERR_READ); + hdrl_len = n; + hdrl_data = (unsigned char *) xine_xmalloc(n); + if(hdrl_data==0) + ERR_EXIT(AVI_ERR_NO_MEM); + if (this->input->read(this->input, hdrl_data,n) != n ) + ERR_EXIT(AVI_ERR_READ); } else if(strncasecmp(data,"movi",4) == 0) { - AVI->movi_start = this->input->seek(this->input, 0,SEEK_CUR); - this->input->seek(this->input, n, SEEK_CUR); - } else - this->input->seek(this->input, n, SEEK_CUR); + AVI->movi_start = this->input->seek(this->input, 0,SEEK_CUR); + this->input->seek(this->input, n, SEEK_CUR); + } else + this->input->seek(this->input, n, SEEK_CUR); - } else if(strncasecmp(data,"idx1",4) == 0 || + } else if(strncasecmp(data,"idx1",4) == 0 || strncasecmp(data,"iddx",4) == 0) { /* n must be a multiple of 16, but the reading does not - break if this is not the case */ - + break if this is not the case */ + AVI->n_idx = AVI->max_idx = n/16; AVI->idx = (unsigned char((*)[16]) ) xine_xmalloc(n); - if (AVI->idx==0) - ERR_EXIT(AVI_ERR_NO_MEM); + if (AVI->idx==0) + ERR_EXIT(AVI_ERR_NO_MEM); - if (this->input->read(this->input, (char *)AVI->idx, n) != n ) + if (this->input->read(this->input, (char *)AVI->idx, n) != n ) { xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: avi index is broken\n")); - free (AVI->idx); /* Index is broken, reconstruct */ - AVI->idx = NULL; - AVI->n_idx = AVI->max_idx = 0; - break; /* EOF */ + free (AVI->idx); /* Index is broken, reconstruct */ + AVI->idx = NULL; + AVI->n_idx = AVI->max_idx = 0; + break; /* EOF */ } } else this->input->seek(this->input, n, SEEK_CUR); - } - + if(!hdrl_data) ERR_EXIT(AVI_ERR_NO_HDRL) ; if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI) ; /* Interpret the header list */ - + for (i=0;icompressor,hdrl_data+i+4,4); - AVI->compressor[4] = 0; - AVI->dwScale = str2ulong(hdrl_data+i+20); - AVI->dwRate = str2ulong(hdrl_data+i+24); - - if(AVI->dwScale!=0) - AVI->fps = (double)AVI->dwRate/(double)AVI->dwScale; - - this->video_step = (long) (90000.0 / AVI->fps); - - AVI->video_frames = str2ulong(hdrl_data+i+32); - AVI->video_strn = num_stream; - vids_strh_seen = 1; - lasttag = 1; /* vids */ + memcpy(AVI->compressor,hdrl_data+i+4,4); + AVI->compressor[4] = 0; + AVI->dwScale = str2ulong(hdrl_data+i+20); + AVI->dwRate = str2ulong(hdrl_data+i+24); + + if(AVI->dwScale!=0) + AVI->fps = (double)AVI->dwRate/(double)AVI->dwScale; + + this->video_step = (long) (90000.0 / AVI->fps); + + AVI->video_frames = str2ulong(hdrl_data+i+32); + AVI->video_strn = num_stream; + vids_strh_seen = 1; + lasttag = 1; /* vids */ } else if (strncasecmp (hdrl_data+i,"auds",4) ==0 /* && ! auds_strh_seen*/) { - if(AVI->n_audio < MAX_AUDIO_STREAMS) { - avi_audio_t *a = (avi_audio_t *) xine_xmalloc(sizeof(avi_audio_t)); - if(a==NULL) { - this->AVI_errno = AVI_ERR_NO_MEM; - return 0; - } - memset((void *)a,0,sizeof(avi_audio_t)); - AVI->audio[AVI->n_audio] = a; - - a->audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, AVI->n_audio); - a->audio_strn = num_stream; - a->dwScale_audio = str2ulong(hdrl_data+i+20); - a->dwRate_audio = str2ulong(hdrl_data+i+24); - a->dwSampleSize = str2ulong(hdrl_data+i+44); - auds_strh_seen = 1; - lasttag = 2; /* auds */ - AVI->n_audio++; - } + if(AVI->n_audio < MAX_AUDIO_STREAMS) { + avi_audio_t *a = (avi_audio_t *) xine_xmalloc(sizeof(avi_audio_t)); + if(a==NULL) { + this->AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + memset((void *)a,0,sizeof(avi_audio_t)); + AVI->audio[AVI->n_audio] = a; + + a->audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, AVI->n_audio); + a->audio_strn = num_stream; + a->dwScale_audio = str2ulong(hdrl_data+i+20); + a->dwRate_audio = str2ulong(hdrl_data+i+24); + a->dwSampleSize = str2ulong(hdrl_data+i+44); + auds_strh_seen = 1; + lasttag = 2; /* auds */ + AVI->n_audio++; + } } else - lasttag = 0; + lasttag = 0; num_stream++; } else if(strncasecmp(hdrl_data+i,"strf",4)==0) { i += 8; if(lasttag == 1) { - /* printf ("size : %d\n",sizeof(AVI->bih)); */ - memcpy (&AVI->bih, hdrl_data+i, sizeof(AVI->bih)); - /* stream_read(demuxer->stream,(char*) &avi_header.bih,MIN(size2,sizeof(avi_header.bih))); */ - AVI->width = str2ulong(hdrl_data+i+4); - AVI->height = str2ulong(hdrl_data+i+8); - - /* - printf ("size : %d x %d (%d x %d)\n", AVI->width, AVI->height, AVI->bih.biWidth, AVI->bih.biHeight); - printf(" biCompression %d='%.4s'\n", AVI->bih.biCompression, - &AVI->bih.biCompression); - */ - vids_strf_seen = 1; + /* printf ("size : %d\n",sizeof(AVI->bih)); */ + memcpy (&AVI->bih, hdrl_data+i, sizeof(AVI->bih)); + /* stream_read(demuxer->stream,(char*) &avi_header.bih,MIN(size2,sizeof(avi_header.bih))); */ + AVI->width = str2ulong(hdrl_data+i+4); + AVI->height = str2ulong(hdrl_data+i+8); + + /* + printf ("size : %d x %d (%d x %d)\n", AVI->width, AVI->height, AVI->bih.biWidth, AVI->bih.biHeight); + printf(" biCompression %d='%.4s'\n", AVI->bih.biCompression, + &AVI->bih.biCompression); + */ + vids_strf_seen = 1; } else if(lasttag == 2) { - AVI->audio[AVI->n_audio-1]->wavex=malloc(n); - memcpy(AVI->audio[AVI->n_audio-1]->wavex, hdrl_data+i, n); - AVI->audio[AVI->n_audio-1]->wavex_len=n; - AVI->audio[AVI->n_audio-1]->a_fmt = str2ushort(hdrl_data+i ); - AVI->audio[AVI->n_audio-1]->a_chans = str2ushort(hdrl_data+i+2); - AVI->audio[AVI->n_audio-1]->a_rate = str2ulong (hdrl_data+i+4); - AVI->audio[AVI->n_audio-1]->a_bits = str2ushort(hdrl_data+i+14); - - auds_strf_seen = 1; + AVI->audio[AVI->n_audio-1]->wavex=malloc(n); + memcpy(AVI->audio[AVI->n_audio-1]->wavex, hdrl_data+i, n); + AVI->audio[AVI->n_audio-1]->wavex_len=n; + AVI->audio[AVI->n_audio-1]->a_fmt = str2ushort(hdrl_data+i ); + AVI->audio[AVI->n_audio-1]->a_chans = str2ushort(hdrl_data+i+2); + AVI->audio[AVI->n_audio-1]->a_rate = str2ulong (hdrl_data+i+4); + AVI->audio[AVI->n_audio-1]->a_bits = str2ushort(hdrl_data+i+14); + + auds_strf_seen = 1; } lasttag = 0; } else { i += 8; lasttag = 0; } - + i += n; } - + if( hdrl_data ) free( hdrl_data ); hdrl_data = NULL; - + /* somehow ffmpeg doesn't specify the number of frames here */ /* if (!vids_strh_seen || !vids_strf_seen || AVI->video_frames==0) { */ - if (!vids_strh_seen || !vids_strf_seen) - ERR_EXIT(AVI_ERR_NO_VIDS); + if (!vids_strh_seen || !vids_strf_seen) + ERR_EXIT(AVI_ERR_NO_VIDS); + - AVI->video_tag[0] = AVI->video_strn/10 + '0'; AVI->video_tag[1] = AVI->video_strn%10 + '0'; AVI->video_tag[2] = 'd'; @@ -512,79 +512,79 @@ static avi_t *AVI_init(demux_avi_t *this) { /* Search the first videoframe in the idx1 and look where it is in the file */ - + for(i=0;in_idx;i++) if( strncasecmp(AVI->idx[i],AVI->video_tag,3)==0 ) break; if (i>=AVI->n_idx) { ERR_EXIT(AVI_ERR_NO_VIDS); } - + pos = str2ulong(AVI->idx[i]+ 8); len = str2ulong(AVI->idx[i]+12); - + this->input->seek(this->input, pos, SEEK_SET); if(this->input->read(this->input, data, 8)!=8) ERR_EXIT(AVI_ERR_READ) ; - + if( strncasecmp(data,AVI->idx[i],4)==0 && str2ulong(data+4)==len ) { idx_type = 1; /* Index from start of file */ - + } else { - + this->input->seek(this->input, pos+AVI->movi_start-4, SEEK_SET); - if(this->input->read(this->input, data, 8)!=8) - ERR_EXIT(AVI_ERR_READ) ; + if(this->input->read(this->input, data, 8)!=8) + ERR_EXIT(AVI_ERR_READ) ; if( strncasecmp(data,AVI->idx[i],4)==0 && str2ulong(data+4)==len ) { - idx_type = 2; /* Index from start of movi list */ + idx_type = 2; /* Index from start of movi list */ } } /* idx_type remains 0 if neither of the two tests above succeeds */ } - + if(idx_type == 0) { /* we must search through the file to get the index */ - + this->input->seek(this->input, AVI->movi_start, SEEK_SET); - + AVI->n_idx = 0; i=0; - + printf ("demux_avi: reconstructing index"); fflush (stdout); - + gen_index_show_progress (this, 0); file_length = this->input->get_length (this->input); while(1) { - if( this->input->read(this->input, data,8) != 8 ) - break; + if( this->input->read(this->input, data,8) != 8 ) + break; n = str2ulong(data+4); - + i++; if (i>1000) { - off_t pos; + off_t pos; - pos = this->input->get_current_pos (this->input); - gen_index_show_progress (this, 100*pos/file_length); + pos = this->input->get_current_pos (this->input); + gen_index_show_progress (this, 100*pos/file_length); - printf ("."); - i = 0; fflush (stdout); + printf ("."); + i = 0; fflush (stdout); } - + /* The movi list may contain sub-lists, ignore them */ - + if(strncasecmp(data,"LIST",4)==0) { - this->input->seek(this->input, 4,SEEK_CUR); - continue; + this->input->seek(this->input, 4,SEEK_CUR); + continue; } - + /* Check if we got a tag ##db, ##dc or ##wb */ - + if( ( (data[2]=='d' || data[2]=='D') && - (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) - || ( (data[2]=='w' || data[2]=='W') && - (data[3]=='b' || data[3]=='B') ) ) { - avi_add_index_entry(this, AVI, data, AVIIF_KEYFRAME, this->input->seek(this->input, 0, SEEK_CUR)-8, n); + (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) + || ( (data[2]=='w' || data[2]=='W') && + (data[3]=='b' || data[3]=='B') ) ) { + avi_add_index_entry(this, AVI, data, AVIIF_KEYFRAME, this->input->seek(this->input, 0, SEEK_CUR)-8, n); } - + this->input->seek(this->input, PAD_EVEN(n), SEEK_CUR); } @@ -594,7 +594,7 @@ static avi_t *AVI_init(demux_avi_t *this) { } /* Now generate the video index and audio index arrays */ - + nvi = 0; memset((void *)nai,0,sizeof(long) * MAX_AUDIO_STREAMS); @@ -611,7 +611,7 @@ static avi_t *AVI_init(demux_avi_t *this) { if (AVI->video_frames==0) { ERR_EXIT(AVI_ERR_NO_VIDS) ; } - + AVI->video_index = (video_index_entry_t *) xine_xmalloc(nvi*sizeof(video_index_entry_t)); if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM) ; @@ -621,7 +621,7 @@ static avi_t *AVI_init(demux_avi_t *this) { AVI->audio[n]->audio_index = (audio_index_entry_t *) xine_xmalloc(nai[n] * sizeof(audio_index_entry_t)); if(AVI->audio[n]->audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM) ; } - + nvi = 0; memset((void *)nai,0,sizeof(long) * MAX_AUDIO_STREAMS); tot = 0; @@ -636,12 +636,12 @@ static avi_t *AVI_init(demux_avi_t *this) { } for(n = 0; n < AVI->n_audio; n++) if(strncasecmp(AVI->idx[i],AVI->audio[n]->audio_tag,4) == 0) { - AVI->audio[n]->audio_index[nai[n]].pos = str2ulong(AVI->idx[i]+ 8)+ioff; - AVI->audio[n]->audio_index[nai[n]].len = str2ulong(AVI->idx[i]+12); - AVI->audio[n]->audio_index[nai[n]].tot = tot; - AVI->audio[n]->audio_bytes += AVI->audio[n]->audio_index[nai[n]].len; - tot += AVI->audio[n]->audio_index[nai[n]].len; - nai[n]++; + AVI->audio[n]->audio_index[nai[n]].pos = str2ulong(AVI->idx[i]+ 8)+ioff; + AVI->audio[n]->audio_index[nai[n]].len = str2ulong(AVI->idx[i]+12); + AVI->audio[n]->audio_index[nai[n]].tot = tot; + AVI->audio[n]->audio_bytes += AVI->audio[n]->audio_index[nai[n]].len; + tot += AVI->audio[n]->audio_index[nai[n]].len; + nai[n]++; } } @@ -668,13 +668,13 @@ static void AVI_seek_start(avi_t *AVI) } } -static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf, - long bytes, int *buf_flags) { +static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf, + long bytes, int *buf_flags) { long nr, pos, left, todo; - if(!AVI_A->audio_index) { - this->AVI_errno = AVI_ERR_NO_IDX; return -1; + if(!AVI_A->audio_index) { + this->AVI_errno = AVI_ERR_NO_IDX; return -1; } nr = 0; /* total number of bytes read */ @@ -688,8 +688,8 @@ static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf, AVI_A->audio_posc++; AVI_A->audio_posb = 0; if (nr>0) { - *buf_flags = BUF_FLAG_FRAME_END; - return nr; + *buf_flags = BUF_FLAG_FRAME_END; + return nr; } left = AVI_A->audio_index[AVI_A->audio_posc].len - AVI_A->audio_posb; } @@ -720,28 +720,28 @@ static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf, return nr; } -static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, - long bytes, int *buf_flags) { +static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, + long bytes, int *buf_flags) { long nr, pos, left, todo; - if (!AVI->video_index) { - this->AVI_errno = AVI_ERR_NO_IDX; - return -1; + if (!AVI->video_index) { + this->AVI_errno = AVI_ERR_NO_IDX; + return -1; } nr = 0; /* total number of bytes read */ while(bytes>0) { - + left = AVI->video_index[AVI->video_posf].len - AVI->video_posb; - + if(left==0) { AVI->video_posf++; AVI->video_posb = 0; if (nr>0) { - *buf_flags = BUF_FLAG_FRAME_END; - return nr; + *buf_flags = BUF_FLAG_FRAME_END; + return nr; } left = AVI->video_index[AVI->video_posf].len - AVI->video_posb; } @@ -751,7 +751,7 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, todo = left; pos = AVI->video_index[AVI->video_posf].pos + AVI->video_posb; /* printf ("demux_avi: read video from %d\n", pos); */ - if (this->input->seek (this->input, pos, SEEK_SET)<0) + if (this->input->seek (this->input, pos, SEEK_SET)<0) return -1; if (this->input->read(this->input, vidbuf+nr,todo) != todo) { this->AVI_errno = AVI_ERR_READ; @@ -768,18 +768,18 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, *buf_flags = BUF_FLAG_FRAME_END; else *buf_flags = 0; - + return nr; } static int64_t get_audio_pts (demux_avi_t *this, int track, long posc, long posb) { if (this->avi->audio[track]->dwSampleSize==0) - return posc * (double) this->avi->audio[track]->dwScale_audio / + return posc * (double) this->avi->audio[track]->dwScale_audio / this->avi->audio[track]->dwRate_audio * 90000.0; - else - return (this->avi->audio[track]->audio_index[posc].tot+posb)/ - this->avi->audio[track]->dwSampleSize * (double) this->avi->audio[track]->dwScale_audio / + else + return (this->avi->audio[track]->audio_index[posc].tot+posb)/ + this->avi->audio[track]->dwSampleSize * (double) this->avi->audio[track]->dwScale_audio / this->avi->audio[track]->dwRate_audio * 90000.0; } @@ -819,8 +819,8 @@ static int demux_avi_next (demux_avi_t *this) { buf->size = AVI_read_audio (this, audio, buf->mem, 2048, &buf->decoder_flags); if (buf->size<0) { - buf->free_buffer (buf); - return 0; + buf->free_buffer (buf); + return 0; } buf->input_pos = 0; @@ -830,11 +830,11 @@ static int demux_avi_next (demux_avi_t *this) { buf->decoder_info[1] = audio->a_rate; /* audio Rate */ buf->decoder_info[2] = audio->a_bits; /* audio bits */ buf->decoder_info[3] = audio->a_chans; /* audio channels */ - + if(this->audio_fifo) { - this->audio_fifo->put (this->audio_fifo, buf); + this->audio_fifo->put (this->audio_fifo, buf); } else { - buf->free_buffer (buf); + buf->free_buffer (buf); } } else do_read_video = 1; @@ -850,7 +850,7 @@ static int demux_avi_next (demux_avi_t *this) { buf->pts = video_pts; buf->size = AVI_read_video (this, this->avi, buf->mem, 2048, &buf->decoder_flags); buf->type = this->avi->video_type; - + buf->input_time = video_pts / 90000; buf->input_pos = this->input->get_current_pos(this->input); @@ -860,7 +860,7 @@ static int demux_avi_next (demux_avi_t *this) { } /* - printf ("demux_avi: adding buf %d to video fifo, decoder_info[0]: %d\n", + printf ("demux_avi: adding buf %d to video fifo, decoder_info[0]: %d\n", buf, buf->decoder_info[0]); */ @@ -873,13 +873,13 @@ static int demux_avi_next (demux_avi_t *this) { if (this->have_spu && (buf->decoder_flags & BUF_FLAG_FRAME_END)) { buf_element_t *buf; buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - + buf->decoder_flags = BUF_FLAG_FRAME_END; buf->type = BUF_SPU_TEXT; buf->pts = video_pts; - + buf->decoder_info[1] = this->avi->video_posf; - + this->video_fifo->put (this->video_fifo, buf); } } @@ -895,28 +895,37 @@ static void *demux_avi_loop (void *this_gen) { buf_element_t *buf = NULL; demux_avi_t *this = (demux_avi_t *) this_gen; - this->send_end_buffers = 1; + pthread_mutex_lock( &this->mutex ); + /* do-while needed to seek after demux finished */ + do { - while(1) { - - pthread_mutex_lock( &this->mutex ); - - if( this->status != DEMUX_OK) - break; - - if (!demux_avi_next(this)) - this->status = DEMUX_FINISHED; - - pthread_mutex_unlock( &this->mutex ); - - } + /* main demuxer loop */ + while(this->status == DEMUX_OK) { + + if (!demux_avi_next(this)) + this->status = DEMUX_FINISHED; + + /* someone may want to interrupt us */ + pthread_mutex_unlock( &this->mutex ); + pthread_mutex_lock( &this->mutex ); + } + + /* wait before sending end buffers: user might want to do a new seek */ + while(this->send_end_buffers && this->video_fifo->size(this->video_fifo) && + this->status != DEMUX_OK){ + pthread_mutex_unlock( &this->mutex ); + xine_usec_sleep(100000); + pthread_mutex_lock( &this->mutex ); + } + + } while( this->status == DEMUX_OK ); if (this->send_end_buffers) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_END; buf->decoder_flags = BUF_FLAG_END_STREAM; this->video_fifo->put (this->video_fifo, buf); - + if(this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_CONTROL_END; @@ -927,21 +936,23 @@ static void *demux_avi_loop (void *this_gen) { printf ("demux_avi: demux loop finished.\n"); + this->thread_running = 0; pthread_mutex_unlock( &this->mutex ); + pthread_exit(NULL); return NULL; } static void demux_avi_stop (demux_plugin_t *this_gen) { - + demux_avi_t *this = (demux_avi_t *) this_gen; buf_element_t *buf; void *p; - + pthread_mutex_lock( &this->mutex ); - if (this->status != DEMUX_OK) { + if (!this->thread_running) { printf ("demux_avi: stop...ignored\n"); pthread_mutex_unlock( &this->mutex ); return; @@ -949,7 +960,7 @@ static void demux_avi_stop (demux_plugin_t *this_gen) { this->send_end_buffers = 0; this->status = DEMUX_FINISHED; - + pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); @@ -970,13 +981,13 @@ static void demux_avi_stop (demux_plugin_t *this_gen) { buf->decoder_flags = BUF_FLAG_END_USER; /* user finished */ this->audio_fifo->put (this->audio_fifo, buf); } - + } static void demux_avi_close (demux_plugin_t *this_gen) { demux_avi_t *this = (demux_avi_t *) this_gen; - if (this->avi) + if (this->avi) AVI_close (this->avi); free(this); @@ -984,57 +995,57 @@ static void demux_avi_close (demux_plugin_t *this_gen) { static int demux_avi_get_status (demux_plugin_t *this_gen) { demux_avi_t *this = (demux_avi_t *) this_gen; - return this->status; + + return (this->thread_running?DEMUX_OK:DEMUX_FINISHED); } static void demux_avi_start (demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, - off_t start_pos, int start_time) { - int i; - buf_element_t *buf; + fifo_buffer_t *video_fifo, + fifo_buffer_t *audio_fifo, + off_t start_pos, int start_time) { + demux_avi_t *this = (demux_avi_t *) this_gen; + int i; + buf_element_t *buf; uint32_t video_pts = 0; int err; unsigned char *sub; - int starting; - + pthread_mutex_lock( &this->mutex ); - starting = (this->status != DEMUX_OK); this->status = DEMUX_OK; - - if( starting ) { + + if( !this->thread_running ) { this->audio_fifo = audio_fifo; this->video_fifo = video_fifo; - + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video format = %s\n"), - this->avi->compressor); + this->avi->compressor); xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video frame size %ld x %ld\n"), - this->avi->width, this->avi->height); + this->avi->width, this->avi->height); for(i=0; i < this->avi->n_audio; i++) xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: audio format[%d] = 0x%lx\n"), - i, this->avi->audio[i]->a_fmt); + i, this->avi->audio[i]->a_fmt); this->no_audio = 0; - + for(i=0; i < this->avi->n_audio; i++) { this->avi->audio[i]->audio_type = formattag_to_buf_audio (this->avi->audio[i]->a_fmt); - + if( !this->avi->audio[i]->audio_type ) { - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown audio type 0x%lx\n"), - this->avi->audio[i]->a_fmt); + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown audio type 0x%lx\n"), + this->avi->audio[i]->a_fmt); this->no_audio = 1; this->avi->audio[i]->audio_type = BUF_CONTROL_NOP; } else xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: audio type %s (wFormatTag 0x%x)\n"), - buf_audio_name(this->avi->audio[i]->audio_type), - (int)this->avi->audio[i]->a_fmt); + buf_audio_name(this->avi->audio[i]->audio_type), + (int)this->avi->audio[i]->a_fmt); } } - + AVI_seek_start (this->avi); - + /* * seek to start pos / time */ @@ -1044,30 +1055,30 @@ static void demux_avi_start (demux_plugin_t *this_gen, /* seek video */ if (start_pos) { while ( (this->avi->video_index[this->avi->video_posf].pos < start_pos) - || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) { + || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) { this->avi->video_posf++; if (this->avi->video_posf>this->avi->video_frames) { - this->status = DEMUX_FINISHED; + this->status = DEMUX_FINISHED; - printf ("demux_avi: video seek to start failed\n"); - break; + printf ("demux_avi: video seek to start failed\n"); + break; } } - - video_pts = get_video_pts (this, this->avi->video_posf); + + video_pts = get_video_pts (this, this->avi->video_posf); } else if (start_time) { video_pts = start_time * 90000; while ( (get_video_pts (this, this->avi->video_posf) < video_pts) - || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) { + || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) { this->avi->video_posf++; if (this->avi->video_posf>this->avi->video_frames) { - this->status = DEMUX_FINISHED; + this->status = DEMUX_FINISHED; - printf ("demux_avi: video seek to start failed\n"); - break; + printf ("demux_avi: video seek to start failed\n"); + break; } } @@ -1079,21 +1090,21 @@ static void demux_avi_start (demux_plugin_t *this_gen, if (!this->no_audio && this->status == DEMUX_OK) { for(i=0; i < this->avi->n_audio; i++) { while (get_audio_pts (this, i, this->avi->audio[i]->audio_posc, 0) < video_pts) { - this->avi->audio[i]->audio_posc++; - if (this->avi->audio[i]->audio_posc>this->avi->audio[i]->audio_chunks) { - this->status = DEMUX_FINISHED; - - printf ("demux_avi: audio seek to start failed\n"); - break; - } + this->avi->audio[i]->audio_posc++; + if (this->avi->audio[i]->audio_posc>this->avi->audio[i]->audio_chunks) { + this->status = DEMUX_FINISHED; + + printf ("demux_avi: audio seek to start failed\n"); + break; + } } } } - /* + /* * send start buffers */ - if( starting && this->status == DEMUX_OK ) { + if( !this->thread_running && (this->status == DEMUX_OK) ) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_CONTROL_START; buf->decoder_flags = 0; @@ -1105,10 +1116,9 @@ static void demux_avi_start (demux_plugin_t *this_gen, buf->decoder_flags = 0; this->audio_fifo->put (this->audio_fifo, buf); } - } - else { + } else { xine_flush_engine(this->xine); - } + } if( this->status == DEMUX_OK ) { @@ -1124,8 +1134,8 @@ static void demux_avi_start (demux_plugin_t *this_gen, this->audio_fifo->put (this->audio_fifo, buf); } } - - if( starting && this->status == DEMUX_OK ) { + + if( !this->thread_running && (this->status == DEMUX_OK) ) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->content = buf->mem; buf->decoder_flags = BUF_FLAG_HEADER; @@ -1134,24 +1144,23 @@ static void demux_avi_start (demux_plugin_t *this_gen, buf->size = sizeof (this->avi->bih); this->avi->video_type = fourcc_to_buf_video((void*)&this->avi->bih.biCompression); - + if( !this->avi->video_type ) this->avi->video_type = fourcc_to_buf_video((void*)&this->avi->compressor); - + if ( !this->avi->video_type ) { xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: unknown video codec '%.4s'\n"), - (char*)&this->avi->bih.biCompression); + (char*)&this->avi->bih.biCompression); buf->free_buffer (buf); - + this->status = DEMUX_FINISHED; - } - else { + } else { buf->type = this->avi->video_type; - xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video codec is '%s'\n"), - buf_video_name(buf->type)); + xine_log (this->xine, XINE_LOG_FORMAT, _("demux_avi: video codec is '%s'\n"), + buf_video_name(buf->type)); this->video_fifo->put (this->video_fifo, buf); - + if(this->audio_fifo) { for(i=0; iavi->n_audio; i++) { avi_audio_t *a = this->avi->audio[i]; @@ -1169,8 +1178,8 @@ static void demux_avi_start (demux_plugin_t *this_gen, this->audio_fifo->put (this->audio_fifo, buf); } } - - /* + + /* * send external spu file pointer, if present */ @@ -1180,7 +1189,7 @@ static void demux_avi_start (demux_plugin_t *this_gen, buf->content = sub; buf->type = BUF_SPU_TEXT; - + buf->decoder_flags = BUF_FLAG_HEADER; buf->decoder_info[1] = this->avi->width; buf->decoder_info[2] = this->avi->height; @@ -1190,37 +1199,34 @@ static void demux_avi_start (demux_plugin_t *this_gen, this->have_spu = 1; printf ("demux_avi: text subtitle file available\n"); - + } else this->have_spu = 0; - + + this->send_end_buffers = 1; + this->thread_running = 1; if ((err = pthread_create (&this->thread, NULL, demux_avi_loop, this)) != 0) { printf ("demux_avi: can't create new thread (%s)\n", - strerror(err)); + strerror(err)); abort(); } } - } - - pthread_mutex_unlock( &this->mutex ); - - if( !starting && this->status != DEMUX_OK ) { - void *p; - pthread_join (this->thread, &p); } + + pthread_mutex_unlock( &this->mutex ); } static void demux_avi_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time) { + off_t start_pos, int start_time) { demux_avi_t *this = (demux_avi_t *) this_gen; - demux_avi_start (this_gen, this->video_fifo, this->audio_fifo, - start_pos, start_time); + demux_avi_start (this_gen, this->video_fifo, this->audio_fifo, + start_pos, start_time); } -static int demux_avi_open(demux_plugin_t *this_gen, - input_plugin_t *input, int stage) { +static int demux_avi_open(demux_plugin_t *this_gen, + input_plugin_t *input, int stage) { demux_avi_t *this = (demux_avi_t *) this_gen; @@ -1234,7 +1240,7 @@ static int demux_avi_open(demux_plugin_t *this_gen, return DEMUX_CANNOT_HANDLE; input->seek(input, 0, SEEK_SET); - + this->input = input; if (this->avi) @@ -1249,59 +1255,60 @@ static int demux_avi_open(demux_plugin_t *this_gen, strncpy(this->last_mrl, input->get_mrl (input), 1024); return DEMUX_CAN_HANDLE; - } else + } else printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", this->AVI_errno); return DEMUX_CANNOT_HANDLE; } break; - + case STAGE_BY_EXTENSION: { char *ending, *mrl; char *m, *valid_ends; mrl = input->get_mrl (input); - + ending = strrchr(mrl, '.'); - + if(ending) { - xine_strdupa(valid_ends, (this->config->register_string(this->config, - "mrl.ends_avi", VALID_ENDS, - "valid mrls ending for avi demuxer", - NULL, NULL, NULL))); - while((m = xine_strsep(&valid_ends, ",")) != NULL) { - - while(*m == ' ' || *m == '\t') m++; - - if(!strcasecmp((ending + 1), m)) { - - this->input = input; - - if (this->avi) - AVI_close (this->avi); - - this->avi = AVI_init (this); - - if (this->avi) { - strncpy(this->last_mrl, input->get_mrl (input), 1024); - return DEMUX_CAN_HANDLE; - } else { - printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", - this->AVI_errno); - return DEMUX_CANNOT_HANDLE; - } - } + xine_strdupa(valid_ends, + this->config->register_string(this->config, + "mrl.ends_avi", VALID_ENDS, + "valid mrls ending for avi demuxer", + NULL, NULL, NULL)); + while((m = xine_strsep(&valid_ends, ",")) != NULL) { + + while(*m == ' ' || *m == '\t') m++; + + if(!strcasecmp((ending + 1), m)) { + + this->input = input; + + if (this->avi) + AVI_close (this->avi); + + this->avi = AVI_init (this); + + if (this->avi) { + strncpy(this->last_mrl, input->get_mrl (input), 1024); + return DEMUX_CAN_HANDLE; + } else { + printf ("demux_avi: AVI_init failed (AVI_errno: %d)\n", + this->AVI_errno); + return DEMUX_CANNOT_HANDLE; + } + } } } return DEMUX_CANNOT_HANDLE; } break; - + default: return DEMUX_CANNOT_HANDLE; break; } - + return DEMUX_CANNOT_HANDLE; } @@ -1320,7 +1327,7 @@ static int demux_avi_get_stream_length (demux_plugin_t *this_gen) { if (this->avi) { return get_video_pts(this, this->avi->video_frames) / 90000 ; - } + } return 0; } @@ -1331,10 +1338,10 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { if (iface != 7) { xine_log (xine, XINE_LOG_PLUGIN, - _("demux_avi: this plugin doesn't support plugin API version %d.\n" - "demux_avi: this means there's a version mismatch between xine and this " - "demux_avi: demuxer plugin.\nInstalling current demuxer plugins should help.\n"), - iface); + _("demux_avi: this plugin doesn't support plugin API version %d.\n" + "demux_avi: this means there's a version mismatch between xine and this " + "demux_avi: demuxer plugin.\nInstalling current demuxer plugins should help.\n"), + iface); return NULL; } @@ -1343,9 +1350,9 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->xine = xine; (void*) this->config->register_string(this->config, - "mrl.ends_avi", VALID_ENDS, - "valid mrls ending for avi demuxer", - NULL, NULL, NULL); + "mrl.ends_avi", VALID_ENDS, + "valid mrls ending for avi demuxer", + NULL, NULL, NULL); this->demux_plugin.interface_version = DEMUXER_PLUGIN_IFACE_VERSION; this->demux_plugin.open = demux_avi_open; @@ -1357,9 +1364,9 @@ demux_plugin_t *init_demuxer_plugin(int iface, xine_t *xine) { this->demux_plugin.get_identifier = demux_avi_get_id; this->demux_plugin.get_stream_length = demux_avi_get_stream_length; this->demux_plugin.get_mimetypes = demux_avi_get_mimetypes; - + this->status = DEMUX_FINISHED; pthread_mutex_init( &this->mutex, NULL ); - + return (demux_plugin_t *) this; } -- cgit v1.2.3