From 4aed347e68a7eadbb8785792f6be3fabaa78236e Mon Sep 17 00:00:00 2001 From: arpi Date: Mon, 5 Aug 2002 17:21:35 +0000 Subject: [PATCH] raw .dv stream demuxer by Alexander Neundorf git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@6926 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libmpdemux/Makefile | 2 +- libmpdemux/demux_rawdv.c | 221 +++++++++++++++++++++++++++++++++++++++ libmpdemux/demuxer.c | 44 +++++++- libmpdemux/demuxer.h | 3 +- 4 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 libmpdemux/demux_rawdv.c diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile index b2cb029c1a..87ba120257 100644 --- a/libmpdemux/Makefile +++ b/libmpdemux/Makefile @@ -3,7 +3,7 @@ LIBNAME = libmpdemux.a include ../config.mak -SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c opt-reg.c mpdemux.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c cddb.c +SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c parse_mp4.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c dvdnav_stream.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c tvi_bsdbt848.c frequencies.c demux_fli.c demux_real.c demux_y4m.c yuv4mpeg.c yuv4mpeg_ratio.c demux_nuv.c demux_film.c demux_roq.c mf.c demux_mf.c demux_audio.c demux_demuxers.c opt-reg.c mpdemux.c demux_ogg.c demux_bmp.c cdda.c demux_rawaudio.c cddb.c demux_rawdv.c ifeq ($(STREAMING),yes) SRCS += asf_streaming.c url.c http.c network.c asf_mmst_streaming.c ifeq ($(STREAMING_LIVE_DOT_COM),yes) diff --git a/libmpdemux/demux_rawdv.c b/libmpdemux/demux_rawdv.c new file mode 100644 index 0000000000..27c7e5601e --- /dev/null +++ b/libmpdemux/demux_rawdv.c @@ -0,0 +1,221 @@ +/* + raw dv file parser for MPlayer + by Alexander Neundorf + based on the fli demuxer + + LGPL +*/ + +#include +#include +#include + +#include "config.h" + +#ifdef HAVE_LIBDV095 + +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" +#include "demuxer.h" +#include "stheader.h" + +#include +#include + +#define DV_PAL_FRAME_SIZE 144000 +#define DV_NTSC_FRAME_SIZE 122000 + +typedef struct +{ + int current_frame; + int frame_size; + int current_filepos; + int frame_number; + dv_decoder_t *decoder; +} rawdv_frames_t; + +void demux_seek_rawdv(demuxer_t *demuxer,float rel_seek_secs,int flags) +{ + rawdv_frames_t *frames = (rawdv_frames_t *)demuxer->priv; + sh_video_t *sh_video = demuxer->video->sh; + int newpos=(flags&1)?0:frames->current_frame; + if(flags&2) + { + // float 0..1 + newpos+=rel_seek_secs*frames->frame_number; + } + else + { + // secs + newpos+=rel_seek_secs*sh_video->fps; + } + if(newpos<0) + newpos=0; + else if(newpos>frames->frame_number) + newpos=frames->frame_number; + frames->current_frame=newpos; + frames->current_filepos=newpos*frames->frame_size; +} + +int check_file_rawdv(demuxer_t *demuxer) +{ + unsigned char tmp_buffer[DV_PAL_FRAME_SIZE]; + int bytes_read=0; + int result=0; + dv_decoder_t *td; + stream_reset(demuxer->stream); + stream_seek(demuxer->stream, 0); + bytes_read=stream_read(demuxer->stream,tmp_buffer,DV_PAL_FRAME_SIZE); + if ((bytes_read!=DV_PAL_FRAME_SIZE) && (bytes_read!=DV_NTSC_FRAME_SIZE)) + return 0; + + td=dv_decoder_new(TRUE,TRUE,FALSE); + td->quality=DV_QUALITY_BEST; + dv_parse_header(td, tmp_buffer); + if ((( td->num_dif_seqs==10) || (td->num_dif_seqs==12)) + && (td->width==720) + && ((td->height==576) || (td->height==480))) + result=1; + dv_decoder_free(td); + return result; +} + +// return value: +// 0 = EOF or no stream found +// 1 = successfully read a packet +int demux_rawdv_fill_buffer(demuxer_t *demuxer) +{ + rawdv_frames_t *frames = (rawdv_frames_t *)demuxer->priv; + demux_packet_t* dp_video=NULL; + sh_video_t *sh_video = demuxer->video->sh; + int bytes_read=0; +// fprintf(stderr,"demux_rawdv_fill_buffer() seek to %d, size: %d\n",frames->current_filepos,frames->frame_size); + // fetch the frame from the file + // first, position the file properly since ds_read_packet() doesn't + // seem to do it, even though it takes a file offset as a parameter + stream_seek(demuxer->stream, frames->current_filepos); + + dp_video=new_demux_packet(frames->frame_size); + bytes_read=stream_read(demuxer->stream,dp_video->buffer,frames->frame_size); + if (bytes_readframe_size) + return 0; + dp_video->pts=frames->current_frame/sh_video->fps; + dp_video->pos=frames->current_filepos; + dp_video->flags=0; + + if (demuxer->audio) + { + demux_packet_t* dp_audio=clone_demux_packet(dp_video); + ds_add_packet(demuxer->audio,dp_audio); + } + ds_add_packet(demuxer->video,dp_video); + // get the next frame ready + frames->current_filepos+=frames->frame_size; + frames->current_frame++; +// fprintf(stderr," audio->packs: %d , video->packs: %d \n",demuxer->audio->packs, demuxer->video->packs); + return 1; +} + +demuxer_t* demux_open_rawdv(demuxer_t* demuxer) +{ + unsigned char dv_frame[DV_PAL_FRAME_SIZE]; + sh_video_t *sh_video = NULL; + rawdv_frames_t *frames = (rawdv_frames_t *)malloc(sizeof(rawdv_frames_t)); + dv_decoder_t *dv_decoder=NULL; + + mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() end_pos %d\n",demuxer->stream->end_pos); + + // go back to the beginning + stream_reset(demuxer->stream); + stream_seek(demuxer->stream, 0); + + //get the first frame + stream_read(demuxer->stream, dv_frame, DV_PAL_FRAME_SIZE); + + //read params from this frame + dv_decoder=dv_decoder_new(TRUE,TRUE,FALSE); + dv_decoder->quality=DV_QUALITY_BEST; + + dv_parse_header(dv_decoder, dv_frame); + + // create a new video stream header + sh_video = new_sh_video(demuxer, 0); + + // make sure the demuxer knows about the new video stream header + // (even though new_sh_video() ought to take care of it) + demuxer->seekable = 1; + demuxer->video->sh = sh_video; + + // make sure that the video demuxer stream header knows about its + // parent video demuxer stream (this is getting wacky), or else + // video_read_properties() will choke + sh_video->ds = demuxer->video; + + // custom fourcc for internal MPlayer use +// sh_video->format = mmioFOURCC('R', 'A', 'D', 'V'); + sh_video->format = mmioFOURCC('D', 'V', 'S', 'D'); + + sh_video->disp_w = dv_decoder->width; + sh_video->disp_h = dv_decoder->height; + mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() frame_size: %d w: %d h: %d dif_seq: %d system: %d\n",dv_decoder->frame_size,dv_decoder->width, dv_decoder->height,dv_decoder->num_dif_seqs,dv_decoder->system); + + sh_video->fps= (dv_decoder->system==e_dv_system_525_60?29.97:25); + sh_video->frametime = 1.0/sh_video->fps; + + // emulate BITMAPINFOHEADER for win32 decoders: + sh_video->bih=malloc(sizeof(BITMAPINFOHEADER)); + memset(sh_video->bih,0,sizeof(BITMAPINFOHEADER)); + sh_video->bih->biSize=40; + sh_video->bih->biWidth = dv_decoder->width; + sh_video->bih->biHeight = dv_decoder->height; + sh_video->bih->biPlanes=1; + sh_video->bih->biBitCount=24; + sh_video->bih->biCompression=sh_video->format; // "DVSD" + sh_video->bih->biSizeImage=sh_video->bih->biWidth*sh_video->bih->biHeight*3; + + + frames->current_filepos=0; + frames->current_frame=0; + frames->frame_size=dv_decoder->frame_size; + frames->frame_number=demuxer->stream->end_pos/frames->frame_size; + + mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() seek to %d, size: %d, dv_dec->frame_size: %d\n",frames->current_filepos,frames->frame_size, dv_decoder->frame_size); + if (dv_decoder->audio != NULL){ + sh_audio_t *sh_audio = new_sh_audio(demuxer, 0); + demuxer->audio->sh = sh_audio; + sh_audio->ds = demuxer->audio; + mp_msg(MSGT_DEMUXER,MSGL_V,"demux_open_rawdv() chan: %d samplerate: %d\n",dv_decoder->audio->num_channels,dv_decoder->audio->frequency ); + // custom fourcc for internal MPlayer use + sh_audio->format = mmioFOURCC('R', 'A', 'D', 'V'); + + sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); + memset(sh_audio->wf, 0, sizeof(WAVEFORMATEX)); + sh_audio->wf->wFormatTag = sh_audio->format; + sh_audio->wf->nChannels = dv_decoder->audio->num_channels; + sh_audio->wf->wBitsPerSample = 16; + sh_audio->wf->nSamplesPerSec = dv_decoder->audio->frequency; + // info about the input stream: + sh_audio->wf->nAvgBytesPerSec = sh_video->fps*dv_decoder->frame_size; + sh_audio->wf->nBlockAlign = dv_decoder->frame_size; + +// sh_audio->context=(void*)dv_decoder; + } + stream_reset(demuxer->stream); + stream_seek(demuxer->stream, 0); + dv_decoder_free(dv_decoder); //we keep this in the context of both stream headers + demuxer->priv=frames; + return demuxer; +} + +void demux_close_rawdv(demuxer_t* demuxer) +{ + rawdv_frames_t *frames = (rawdv_frames_t *)demuxer->priv; + + if(frames==0) + return; + free(frames); +} + +#endif diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index 826293ff3d..495ae09e35 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -153,6 +153,7 @@ extern void demux_close_ogg(demuxer_t* demuxer); extern void demux_close_rtp(demuxer_t* demuxer); extern void demux_close_demuxers(demuxer_t* demuxer); extern void demux_close_avi(demuxer_t *demuxer); +extern void demux_close_rawdv(demuxer_t* demuxer); void free_demuxer(demuxer_t *demuxer){ int i; @@ -176,6 +177,10 @@ void free_demuxer(demuxer_t *demuxer){ demux_close_fli(demuxer); break; case DEMUXER_TYPE_NUV: demux_close_nuv(demuxer); break; +#ifdef HAVE_LIBDV095 + case DEMUXER_TYPE_RAWDV: + demux_close_rawdv(demuxer); break; +#endif case DEMUXER_TYPE_AUDIO: demux_close_audio(demuxer); break; case DEMUXER_TYPE_OGG: @@ -261,6 +266,8 @@ int demux_vivo_fill_buffer(demuxer_t *demux); int demux_real_fill_buffer(demuxer_t *demuxer); int demux_nuv_fill_buffer(demuxer_t *demux); int demux_rtp_fill_buffer(demuxer_t *demux, demux_stream_t* ds); +int demux_rawdv_fill_buffer(demuxer_t *demuxer); + #ifdef USE_TV #include "tv.h" extern tvi_handle_t *tv_handler; @@ -292,6 +299,9 @@ int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){ case DEMUXER_TYPE_ASF: return demux_asf_fill_buffer(demux); case DEMUXER_TYPE_MOV: return demux_mov_fill_buffer(demux,ds); case DEMUXER_TYPE_VIVO: return demux_vivo_fill_buffer(demux); +#ifdef HAVE_LIBDV095 + case DEMUXER_TYPE_RAWDV: return demux_rawdv_fill_buffer(demux); +#endif case DEMUXER_TYPE_REAL: return demux_real_fill_buffer(demux); case DEMUXER_TYPE_NUV: return demux_nuv_fill_buffer(demux); #ifdef USE_TV @@ -506,6 +516,10 @@ int demux_open_mf(demuxer_t* demuxer); int demux_open_film(demuxer_t* demuxer); int demux_open_bmp(demuxer_t* demuxer); int demux_open_roq(demuxer_t* demuxer); +#ifdef HAVE_LIBDV095 +int demux_open_rawdv(demuxer_t* demuxer); +extern int check_file_rawdv(demuxer_t *demuxer); +#endif extern int vivo_check_file(demuxer_t *demuxer); extern void demux_open_vivo(demuxer_t *demuxer); @@ -780,6 +794,20 @@ if(file_format==DEMUXER_TYPE_MPEG_ES){ // little hack, see above! mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGESfile); } } +#ifdef HAVE_LIBDV095 +//=============== Try to open raw DV file, as produced by dvgrab --format raw ================= +if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_RAWDV) +{ + demuxer=new_demuxer(stream,DEMUXER_TYPE_RAWDV,audio_id,video_id,dvdsub_id); + if(check_file_rawdv(demuxer)) + { + mp_msg(MSGT_DEMUXER,MSGL_INFO,"Detected RAWDV file format!\n"); + file_format=DEMUXER_TYPE_RAWDV; + } + else + free_demuxer(demuxer); +} +#endif //=============== Try to open as multi file: ================= if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MF){ demuxer=new_demuxer(stream,DEMUXER_TYPE_MF,audio_id,video_id,dvdsub_id); @@ -821,6 +849,13 @@ d_video=demuxer->video; demuxer->file_format=file_format; switch(file_format){ +#ifdef HAVE_LIBDV095 + case DEMUXER_TYPE_RAWDV: + { + if (!demux_open_rawdv(demuxer)) return NULL; + break; + } +#endif case DEMUXER_TYPE_RAWAUDIO: { demux_rawaudio_open(demuxer); break; @@ -1025,7 +1060,6 @@ demuxer_t* demux_open(stream_t *vs,int file_format,int audio_id,int video_id,int return vd; } - int demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags); int demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags); int demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,int flags); @@ -1036,6 +1070,10 @@ int demux_seek_mf(demuxer_t *demuxer,float rel_seek_secs,int flags); int demux_seek_nuv(demuxer_t *demuxer,float rel_seek_secs,int flags); void demux_seek_mov(demuxer_t *demuxer,float pts,int flags); int demux_seek_real(demuxer_t *demuxer,float rel_seek_secs,int flags); +#ifdef HAVE_LIBDV095 +int demux_seek_rawdv(demuxer_t *demuxer, float pts, int flags); +#endif + extern void demux_audio_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); extern void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); #ifdef HAVE_OGGVORBIS @@ -1078,6 +1116,10 @@ if(!demuxer->seekable){ switch(demuxer->file_format){ +#ifdef HAVE_LIBDV095 + case DEMUXER_TYPE_RAWDV: + demux_seek_rawdv(demuxer,rel_seek_secs,flags); break; +#endif case DEMUXER_TYPE_AVI: demux_seek_avi(demuxer,rel_seek_secs,flags); break; diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 6f8b9c5aa6..42305cf65b 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -30,10 +30,11 @@ #define DEMUXER_TYPE_BMP 19 #define DEMUXER_TYPE_RAWAUDIO 20 #define DEMUXER_TYPE_RTP 21 +#define DEMUXER_TYPE_RAWDV 22 // This should always match the higest demuxer type number. // Unless you want to disallow users to force the demuxer to some types #define DEMUXER_TYPE_MIN 0 -#define DEMUXER_TYPE_MAX 21 +#define DEMUXER_TYPE_MAX 22 #define DEMUXER_TYPE_DEMUXERS (1<<16) // A virtual demuxer type for the network code