Mercurial > mplayer.hg
changeset 2310:9e059416eea6
libdemuxer...
line wrap: on
line diff
--- a/Makefile Sat Oct 20 18:05:30 2001 +0000 +++ b/Makefile Sat Oct 20 18:49:08 2001 +0000 @@ -16,13 +16,13 @@ #prefix = /usr/local BINDIR = ${prefix}/bin # BINDIR = /usr/local/bin -SRCS = cpudetect.c postproc/swscale.c postproc/postprocess.c mp_msg.c open.c parse_es.c ac3-iec958.c find_sub.c aviprint.c dec_audio.c dec_video.c aviwrite.c aviheader.c asfheader.c demux_avi.c demux_asf.c demux_mpg.c demux_mov.c demuxer.c stream.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c xa/rle8.c lirc_mp.c cfgparser.c mixer.c dvdauth.c spudec.c $(STREAM_SRCS) +SRCS = cpudetect.c postproc/swscale.c postproc/postprocess.c mp_msg.c ac3-iec958.c find_sub.c dec_audio.c dec_video.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c xa/rle8.c lirc_mp.c cfgparser.c mixer.c spudec.c OBJS = $(SRCS:.c=.o) -CFLAGS = $(OPTFLAGS) -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) # -Wall +CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) # -Wall A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(ESD_LIB) VO_LIBS = -Llibvo -lvo $(MLIB_LIB) $(X_LIBS) -PARTS = mp3lib libac3 libmpeg2 opendivx libavcodec encore libvo libao2 drivers drivers/syncfb +PARTS = libmpdemux mp3lib libac3 libmpeg2 opendivx libavcodec encore libvo libao2 drivers drivers/syncfb ifeq ($(GUI),yes) PARTS += Gui endif @@ -50,11 +50,14 @@ .c.o: $(CC) -c $(CFLAGS) -o $@ $< -COMMONLIBS = libvo/libvo.a libao2/libao2.a libac3/libac3.a mp3lib/libMP3.a libmpeg2/libmpeg2.a opendivx/libdecore.a encore/libencore.a +COMMONLIBS = libmpdemux/libmpdemux.a libvo/libvo.a libao2/libao2.a libac3/libac3.a mp3lib/libMP3.a libmpeg2/libmpeg2.a opendivx/libdecore.a encore/libencore.a loader/libloader.a: $(MAKE) -C loader +libmpdemux/libmpdemux.a: + $(MAKE) -C libmpdemux + loader/DirectShow/libDS_Filter.a: $(MAKE) -C loader/DirectShow @@ -93,7 +96,7 @@ @for a in $(PARTS); do $(MAKE) -C $$a all ; done $(PRG): $(MPLAYER_DEP) - $(CC) $(CFLAGS) -o $(PRG) mplayer.o $(OBJS) $(XMM_LIBS) $(LIRC_LIBS) $(A_LIBS) -lm $(TERMCAP_LIB) $(LIB_LOADER) $(AV_LIB) -Llibmpeg2 -lmpeg2 -Llibao2 -lao2 $(VO_LIBS) $(CSS_LIB) -Lencore -lencore $(DECORE_LIBS) $(GUI_LIBS) $(ARCH_LIBS) + $(CC) $(CFLAGS) -o $(PRG) mplayer.o -Llibmpdemux -lmpdemux $(OBJS) $(XMM_LIBS) $(LIRC_LIBS) $(A_LIBS) -lm $(TERMCAP_LIB) $(LIB_LOADER) $(AV_LIB) -Llibmpeg2 -lmpeg2 -Llibao2 -lao2 $(VO_LIBS) $(CSS_LIB) -Lencore -lencore $(DECORE_LIBS) $(GUI_LIBS) $(ARCH_LIBS) $(PRG_FIBMAP): fibmap_mplayer.o $(CC) -o $(PRG_FIBMAP) fibmap_mplayer.o
--- a/asf.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -#ifndef __ASF_H -#define __ASF_H - -#include "config.h" /* for WORDS_BIGENDIAN */ -#include <inttypes.h> -#include "bswap.h" -#ifdef STREAMING -#include "network.h" -#endif - -#ifndef MIN -#define MIN(a,b) ((a<b)?a:b) -#endif - -/////////////////////// -// MS GUID definition -/////////////////////// -#ifndef GUID_DEFINED -#define GUID_DEFINED -// Size of GUID is 16 bytes! -typedef struct __attribute__((packed)) { - uint32_t Data1; // 4 bytes - uint16_t Data2; // 2 bytes - uint16_t Data3; // 2 bytes - uint8_t Data4[8]; // 8 bytes -} GUID_t; -#endif - -/////////////////////// -// ASF Object Header -/////////////////////// -typedef struct __attribute__((packed)) { - uint8_t guid[16]; - uint64_t size; -} ASF_obj_header_t; - -//////////////// -// ASF Header -//////////////// -typedef struct __attribute__((packed)) { - ASF_obj_header_t objh; - uint32_t cno; // number of subchunks - uint8_t v1; // unknown (0x01) - uint8_t v2; // unknown (0x02) -} ASF_header_t; - -///////////////////// -// ASF File Header -///////////////////// -typedef struct __attribute__((packed)) { - uint8_t client[16]; // Client GUID - uint64_t file_size; - uint64_t creat_time; //File creation time FILETIME 8 - uint64_t packets; //Number of packets UINT64 8 - uint64_t end_timestamp; //Timestamp of the end position UINT64 8 - uint64_t duration; //Duration of the playback UINT64 8 - uint32_t start_timestamp; //Timestamp of the start position UINT32 4 - uint32_t unk1; //Unknown, maybe reserved ( usually contains 0 ) UINT32 4 - uint32_t flags; //Unknown, maybe flags ( usually contains 2 ) UINT32 4 - uint32_t packetsize; //Size of packet, in bytes UINT32 4 - uint32_t packetsize2; //Size of packet ( confirm ) UINT32 4 - uint32_t frame_size; //Size of uncompressed video frame UINT32 4 -} ASF_file_header_t; - -/////////////////////// -// ASF Stream Header -/////////////////////// -typedef struct __attribute__((packed)) { - uint8_t type[16]; // Stream type (audio/video) GUID 16 - uint8_t concealment[16]; // Audio error concealment type GUID 16 - uint64_t unk1; // Unknown, maybe reserved ( usually contains 0 ) UINT64 8 - uint32_t type_size; //Total size of type-specific data UINT32 4 - uint32_t stream_size; //Size of stream-specific data UINT32 4 - uint16_t stream_no; //Stream number UINT16 2 - uint32_t unk2; //Unknown UINT32 4 -} ASF_stream_header_t; - -/////////////////////////// -// ASF Content Description -/////////////////////////// -typedef struct __attribute__((packed)) { - uint16_t title_size; - uint16_t author_size; - uint16_t copyright_size; - uint16_t comment_size; - uint16_t rating_size; -} ASF_content_description_t; - -//////////////////////// -// ASF Segment Header -//////////////////////// -typedef struct __attribute__((packed)) { - uint8_t streamno; - uint8_t seq; - uint32_t x; - uint8_t flag; -} ASF_segmhdr_t; - -////////////////////// -// ASF Stream Chunck -////////////////////// -typedef struct __attribute__((packed)) { - uint16_t type; - uint16_t size; - uint32_t sequence_number; - uint16_t unknown; - uint16_t size_confirm; -} ASF_stream_chunck_t; - - -// Definition of the differents type of ASF streaming -typedef enum { - ASF_Unknown_e, - ASF_Live_e, - ASF_Prerecorded_e, - ASF_Redirector_e -} ASF_StreamType_e; - - -/* - * Some macros to swap little endian structures read from an ASF file - * into machine endian format - */ -#ifdef WORDS_BIGENDIAN -#define le2me_ASF_obj_header_t(h) { \ - (h)->size = le2me_64((h)->size); \ -} -#define le2me_ASF_header_t(h) { \ - le2me_ASF_obj_header_t(&(h)->objh); \ - (h)->cno = le2me_32((h)->cno); \ -} -#define le2me_ASF_stream_header_t(h) { \ - (h)->unk1 = le2me_64((h)->unk1); \ - (h)->type_size = le2me_32((h)->type_size); \ - (h)->stream_size = le2me_32((h)->stream_size); \ - (h)->stream_no = le2me_16((h)->stream_no); \ - (h)->unk2 = le2me_32((h)->unk2); \ -} -#define le2me_ASF_file_header_t(h) { \ - (h)->file_size = le2me_64((h)->file_size); \ - (h)->creat_time = le2me_64((h)->creat_time); \ - (h)->packets = le2me_64((h)->packets); \ - (h)->end_timestamp = le2me_64((h)->end_timestamp); \ - (h)->duration = le2me_64((h)->duration); \ - (h)->start_timestamp = le2me_32((h)->start_timestamp); \ - (h)->unk1 = le2me_32((h)->unk1); \ - (h)->flags = le2me_32((h)->flags); \ - (h)->packetsize = le2me_32((h)->packetsize); \ - (h)->packetsize2 = le2me_32((h)->packetsize2); \ - (h)->frame_size = le2me_32((h)->frame_size); \ -} -#define le2me_ASF_content_description_t(h) { \ - (h)->title_size = le2me_16((h)->title_size); \ - (h)->author_size = le2me_16((h)->author_size); \ - (h)->copyright_size = le2me_16((h)->copyright_size); \ - (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 - - -#ifdef STREAMING -int asf_http_streaming_type(char *content_type, char *features); -int asf_http_streaming_start( streaming_ctrl_t *streaming_ctrl ); -int asf_http_streaming_read( streaming_ctrl_t *streaming_ctrl ); - -int asf_streaming(char *data, int length, int *drop_packet ); -#endif - -#endif
--- a/asf_streaming.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,353 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "url.h" -#include "http.h" -#include "asf.h" -#include "network.h" - -#include "stream.h" -//#include "demuxer.h" - -//extern demuxer_t *demuxer; - -static ASF_StreamType_e streaming_type = ASF_Unknown_e; - -int -asf_http_streaming_read( streaming_ctrl_t *streaming_ctrl ) { - char *buffer; - int drop_packet; - int ret; -printf("asf_streaming_read\n"); - ret = asf_streaming( streaming_ctrl->buffer->buffer, streaming_ctrl->buffer->length, &drop_packet ); -printf("ret: %d\n", ret); - if( ret<0 ) return -1; - if( ret>streaming_ctrl->buffer->length ) return 0; - buffer = (char*)malloc(ret); - if( buffer==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } -printf("buffer length: %d\n", streaming_ctrl->buffer->length ); - net_fifo_pop( streaming_ctrl->buffer, buffer, ret ); -printf(" pop: 0x%02X\n", *((unsigned int*)buffer) ); -printf("buffer length: %d\n", streaming_ctrl->buffer->length ); -printf("0x%02X\n", *((unsigned int*)(buffer+sizeof(ASF_stream_chunck_t))) ); - if( !drop_packet ) { - write( streaming_ctrl->fd_pipe_in, buffer+sizeof(ASF_stream_chunck_t), ret-sizeof(ASF_stream_chunck_t) ); - } - free( buffer ); - return ret; -} - -int -asf_streaming(char *data, int length, int *drop_packet ) { - ASF_stream_chunck_t *stream_chunck=(ASF_stream_chunck_t*)data; - printf("ASF stream chunck size=%d\n", stream_chunck->size); -printf("length: %d\n", length ); -printf("0x%02X\n", stream_chunck->type ); - - if( drop_packet!=NULL ) *drop_packet = 0; - if( data==NULL || length<=0 ) return -1; - - if( stream_chunck->size<8 ) { - printf("Ahhhh, stream_chunck size is too small: %d\n", stream_chunck->size); - return -1; - } - if( stream_chunck->size!=stream_chunck->size_confirm ) { - printf("size_confirm mismatch!: %d %d\n", stream_chunck->size, stream_chunck->size_confirm); - return -1; - } - - printf(" type: 0x%02X\n", stream_chunck->type ); - printf(" size: %d (0x%02X)\n", stream_chunck->size, stream_chunck->size ); - printf(" sequence_number: 0x%04X\n", stream_chunck->sequence_number ); - printf(" unknown: 0x%02X\n", stream_chunck->unknown ); - printf(" size_confirm: 0x%02X\n", stream_chunck->size_confirm ); - - - switch(stream_chunck->type) { - case 0x4324: // Clear ASF configuration - printf("=====> Clearing ASF stream configuration!\n"); - if( drop_packet!=NULL ) *drop_packet = 1; - return stream_chunck->size; - break; - case 0x4424: // Data follows - printf("=====> Data follows\n"); - break; - case 0x4524: // Transfer complete - printf("=====> Transfer complete\n"); - if( drop_packet!=NULL ) *drop_packet = 1; - return stream_chunck->size; - break; - case 0x4824: // ASF header chunk follows - printf("=====> ASF header chunk follows\n"); - break; - default: - printf("=====> Unknown stream type 0x%x\n", stream_chunck->type ); - } - return stream_chunck->size+4; -} - -int -asf_http_streaming_type(char *content_type, char *features) { - if( content_type==NULL ) return ASF_Unknown_e; - if( !strcasecmp(content_type, "application/octet-stream") ) { - if( features==NULL ) { - printf("=====> ASF Prerecorded\n"); - return ASF_Prerecorded_e; - } else if( strstr(features, "broadcast")) { - printf("=====> ASF Live stream\n"); - return ASF_Live_e; - } else { - printf("=====> ASF Prerecorded\n"); - return ASF_Prerecorded_e; - } - } else { - if( (!strcasecmp(content_type, "audio/x-ms-wax")) || - (!strcasecmp(content_type, "audio/x-ms-wma")) || - (!strcasecmp(content_type, "video/x-ms-asf")) || - (!strcasecmp(content_type, "video/x-ms-afs")) || - (!strcasecmp(content_type, "video/x-ms-wvx")) || - (!strcasecmp(content_type, "video/x-ms-wmv")) || - (!strcasecmp(content_type, "video/x-ms-wma")) ) { - printf("=====> ASF Redirector\n"); - return ASF_Redirector_e; - } else { - printf("=====> ASF unknown content-type: %s\n", content_type ); - return ASF_Unknown_e; - } - } - return ASF_Unknown_e; -} - -HTTP_header_t * -asf_http_request(URL_t *url) { - HTTP_header_t *http_hdr; - char str[250]; - char *ptr; - char *request; - int i; - - int offset_hi=0, offset_lo=0, req_nb=1, length=0; - int asf_nb_stream; - - // Common header for all requests. - http_hdr = http_new_header(); - http_set_uri( http_hdr, url->file ); - http_set_field( http_hdr, "Accept: */*" ); - http_set_field( http_hdr, "User-Agent: NSPlayer/4.1.0.3856" ); - sprintf( str, "Host: %s:%d", url->hostname, url->port ); - http_set_field( http_hdr, str ); - http_set_field( http_hdr, "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" ); - sprintf(str, - "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u", - offset_hi, offset_lo, req_nb, length ); - http_set_field( http_hdr, str ); - - switch( streaming_type ) { - case ASF_Live_e: - case ASF_Prerecorded_e: - http_set_field( http_hdr, "Pragma: xPlayStrm=1" ); - ptr = str; - ptr += sprintf( ptr, "Pragma: stream-switch-entry="); - -// FIXME: why do you need demuxer here? if you really need it, pass it as -// parameter. -- A'rpi - -#if 0 - for( i=0, asf_nb_stream=0 ; i<256 ; i++ ) { - // FIXME START - if( demuxer==NULL ) { - ptr += sprintf( ptr, " ffff:1:0" ); - asf_nb_stream = 1; - break; - } - // FIXME END - if( demuxer->a_streams[i] ) { - ptr += sprintf( ptr, " ffff:%d:0", i ); - asf_nb_stream++; - } - if( demuxer->v_streams[i] ) { - ptr += sprintf( ptr, " ffff:%d:0", i ); - asf_nb_stream++; - } - } -#endif - http_set_field( http_hdr, str ); - sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream ); - http_set_field( http_hdr, str ); - break; - case ASF_Redirector_e: - break; - case ASF_Unknown_e: - // First request goes here. - break; - default: - printf("Unknown asf stream type\n"); - } - - http_set_field( http_hdr, "Connection: Close" ); - http_build_request( http_hdr ); - - return http_hdr; -} - -int -asf_http_parse_response( HTTP_header_t *http_hdr ) { - char *content_type, *pragma; - char features[64] = "\0"; - int len; - if( http_response_parse(http_hdr)<0 ) { - printf("Failed to parse HTTP response\n"); - return -1; - } - if( http_hdr->status_code!=200 ) { - printf("Server return %d:%s\n", http_hdr->status_code, http_hdr->reason_phrase); - return -1; - } - - content_type = http_get_field( http_hdr, "Content-Type"); - - pragma = http_get_field( http_hdr, "Pragma"); - while( pragma!=NULL ) { - char *comma_ptr=NULL; - char *end; - // The pragma line can get severals attributes - // separeted with a comma ','. - do { - if( !strncasecmp( pragma, "features=", 9) ) { - pragma += 9; - end = strstr( pragma, "," ); - if( end==NULL ) { - len = strlen(pragma); - } - len = MIN(end-pragma,sizeof(features)); - strncpy( features, pragma, len ); - features[len]='\0'; - break; - } - comma_ptr = strstr( pragma, "," ); - if( comma_ptr!=NULL ) { - pragma = comma_ptr+1; - if( pragma[0]==' ' ) pragma++; - } - } while( comma_ptr!=NULL ); - pragma = http_get_next_field( http_hdr ); - } - - streaming_type = asf_http_streaming_type( content_type, features ); - - if( http_hdr->body_size>0 ) { - asf_streaming( http_hdr->body, http_hdr->body_size, NULL); - } - - return 0; -} - -URL_t * -asf_http_ASX_redirect( HTTP_header_t *http_hdr ) { - URL_t *url_redirect=NULL; - printf("=========>> ASX parser not yet implemented <<==========\n"); - - printf("ASX=[%s]\n", http_hdr->body ); - - return url_redirect; -} - -int -asf_http_streaming_start( streaming_ctrl_t *streaming_ctrl ) { - HTTP_header_t *http_hdr=NULL; - URL_t *url_next=NULL; - URL_t *url = *(streaming_ctrl->url); - char buffer[BUFFER_SIZE]; - int i; - int fd = streaming_ctrl->fd_net; - int done=1; - -streaming_type = ASF_Live_e; - do { - if( fd>0 ) close( fd ); - - fd = connect2Server( url->hostname, url->port ); - if( fd<0 ) return -1; - - http_hdr = asf_http_request( url ); -printf("[%s]\n", http_hdr->buffer ); - write( fd, http_hdr->buffer, http_hdr->buffer_size ); -// http_free( http_hdr ); - - http_hdr = http_new_header(); - do { - i = readFromServer( fd, buffer, BUFFER_SIZE ); -printf("read: %d\n", i ); - if( i<0 ) { - perror("read"); - http_free( http_hdr ); - return -1; - } - http_response_append( http_hdr, buffer, i ); - } while( !http_is_header_entired( http_hdr ) ); -//http_hdr->buffer[http_hdr->buffer_len]='\0'; -//printf("[%s]\n", http_hdr->buffer ); - if( asf_http_parse_response(http_hdr)<0 ) { - printf("Failed to parse header\n"); - http_free( http_hdr ); - return -1; - } - switch( streaming_type ) { - case ASF_Live_e: - case ASF_Prerecorded_e: - if( http_hdr->body_size>0 ) { -printf("--- 0x%02X\n", streaming_ctrl->buffer ); - net_fifo_push( streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size ); - } else { - ASF_stream_chunck_t *ptr; - int ret; - i = readFromServer( fd, buffer, sizeof(ASF_stream_chunck_t) ); -printf("read: %d\n", i ); - ret = asf_streaming( buffer, i, NULL ); - net_fifo_push( streaming_ctrl->buffer, buffer, i ); - ptr = (ASF_stream_chunck_t*)buffer; - if( ret==ptr->size ) { - } - } -// done = 0; - break; - case ASF_Redirector_e: - url_next = asf_http_ASX_redirect( http_hdr ); - if( url_next==NULL ) { - printf("Failed to parse ASX file\n"); - close(fd); - http_free( http_hdr ); - return -1; - } - if( url_next->port==0 ) url_next->port=80; - url_free( url ); - url = url_next; - *(streaming_ctrl->url) = url_next; - url_next = NULL; - break; - case ASF_Unknown_e: - default: - printf("Unknown ASF streaming type\n"); - close(fd); - http_free( http_hdr ); - return -1; - } - - // Check if we got a redirect. - } while(!done); - - streaming_ctrl->fd_net = fd; - streaming_ctrl->streaming_read = asf_http_streaming_read; - streaming_ctrl->prebuffer_size = 10000; - streaming_ctrl->buffering = 1; - streaming_ctrl->status = streaming_playing_e; - - http_free( http_hdr ); - return fd; -} -
--- a/asfheader.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,279 +0,0 @@ -// .asf fileformat docs from http://divx.euro.ru - - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -extern int verbose; // defined in mplayer.c - -#include "config.h" -#include "mp_msg.h" - -#include "stream.h" -#include "demuxer.h" - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "stheader.h" -//#include "aviheader.h" -#include "asf.h" - -#ifdef ARCH_X86 -#define ASF_LOAD_GUID_PREFIX(guid) (*(uint32_t *)(guid)) -#else -#define ASF_LOAD_GUID_PREFIX(guid) \ - ((guid)[3] << 24 | (guid)[2] << 16 | (guid)[1] << 8 | (guid)[0]) -#endif - -#define ASF_GUID_PREFIX_audio_stream 0xF8699E40 -#define ASF_GUID_PREFIX_video_stream 0xBC19EFC0 -#define ASF_GUID_PREFIX_audio_conceal_none 0x49f1a440 -#define ASF_GUID_PREFIX_audio_conceal_interleave 0xbfc3cd50 -#define ASF_GUID_PREFIX_header 0x75B22630 -#define ASF_GUID_PREFIX_data_chunk 0x75b22636 -#define ASF_GUID_PREFIX_index_chunk 0x33000890 -#define ASF_GUID_PREFIX_stream_header 0xB7DC0791 -#define ASF_GUID_PREFIX_header_2_0 0xD6E229D1 -#define ASF_GUID_PREFIX_file_header 0x8CABDCA1 -#define ASF_GUID_PREFIX_content_desc 0x75b22633 - - -static ASF_header_t asfh; -static ASF_obj_header_t objh; -static ASF_file_header_t fileh; -static ASF_stream_header_t streamh; -static ASF_content_description_t contenth; - -unsigned char* asf_packet=NULL; -int asf_scrambling_h=1; -int asf_scrambling_w=1; -int asf_scrambling_b=1; -int asf_packetsize=0; - -//int i; - -// the variable string is modify in this function -void pack_asf_string(char* string, int length) { - int i,j; - if( string==NULL ) return; - for( i=0, j=0; i<length && string[i]!='\0'; i+=2, j++) { - string[j]=string[i]; - } - string[j]='\0'; -} - -// the variable string is modify in this function -void print_asf_string(const char* name, char* string, int length) { - pack_asf_string(string, length); - mp_msg(MSGT_HEADER,MSGL_V,"%s%s\n", name, string); -} - -static char* asf_chunk_type(unsigned char* guid) { - static char tmp[60]; - char *p; - int i; - - switch(ASF_LOAD_GUID_PREFIX(guid)){ - case ASF_GUID_PREFIX_audio_stream: - return "guid_audio_stream"; - case ASF_GUID_PREFIX_video_stream: - return "guid_video_stream"; - case ASF_GUID_PREFIX_audio_conceal_none: - return "guid_audio_conceal_none"; - case ASF_GUID_PREFIX_audio_conceal_interleave: - return "guid_audio_conceal_interleave"; - case ASF_GUID_PREFIX_header: - return "guid_header"; - case ASF_GUID_PREFIX_data_chunk: - return "guid_data_chunk"; - case ASF_GUID_PREFIX_index_chunk: - return "guid_index_chunk"; - case ASF_GUID_PREFIX_stream_header: - return "guid_stream_header"; - case ASF_GUID_PREFIX_header_2_0: - return "guid_header_2_0"; - case ASF_GUID_PREFIX_file_header: - return "guid_file_header"; - case ASF_GUID_PREFIX_content_desc: - return "guid_content_desc"; - default: - strcpy(tmp, "unknown guid "); - p = tmp + strlen(tmp); - for (i = 0; i < 16; i++) { - if ((1 << i) & ((1<<4) | (1<<6) | (1<<8))) *p++ = '-'; - sprintf(p, "%02x", guid[i]); - p += 2; - } - return tmp; - } -} - -int asf_check_header(demuxer_t *demuxer){ - unsigned char asfhdrguid[16]={0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C}; - stream_read(demuxer->stream,(char*) &asfh,sizeof(asfh)); // header obj - le2me_ASF_header_t(&asfh); // swap to machine endian -// for(i=0;i<16;i++) printf(" %02X",temp[i]);printf("\n"); -// for(i=0;i<16;i++) printf(" %02X",asfhdrguid[i]);printf("\n"); - if(memcmp(asfhdrguid,asfh.objh.guid,16)){ - mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: not ASF guid!\n"); - return 0; // not ASF guid - } - if(asfh.cno>256){ - mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: invalid subchunks_no %d\n",(int) asfh.cno); - return 0; // invalid header??? - } - return 1; -} - -extern void print_wave_header(WAVEFORMATEX *h); -extern void print_video_header(BITMAPINFOHEADER *h); - -int read_asf_header(demuxer_t *demuxer){ - static unsigned char buffer[1024]; - -#if 1 - //printf("ASF file! (subchunks: %d)\n",asfh.cno); -while(!stream_eof(demuxer->stream)){ - int pos,endpos; - pos=stream_tell(demuxer->stream); - stream_read(demuxer->stream,(char*) &objh,sizeof(objh)); - le2me_ASF_obj_header_t(&objh); - if(stream_eof(demuxer->stream)) break; // EOF - endpos=pos+objh.size; -// for(i=0;i<16;i++) printf("%02X ",objh.guid[i]); - //printf("0x%08X [%s] %d\n",pos, asf_chunk_type(objh.guid),(int) objh.size); - switch(ASF_LOAD_GUID_PREFIX(objh.guid)){ - case ASF_GUID_PREFIX_stream_header: - stream_read(demuxer->stream,(char*) &streamh,sizeof(streamh)); - le2me_ASF_stream_header_t(&streamh); - if(verbose){ - mp_msg(MSGT_HEADER,MSGL_V,"stream type: %s\n",asf_chunk_type(streamh.type)); - mp_msg(MSGT_HEADER,MSGL_V,"stream concealment: %s\n",asf_chunk_type(streamh.concealment)); - mp_msg(MSGT_HEADER,MSGL_V,"type: %d bytes, stream: %d bytes ID: %d\n",(int)streamh.type_size,(int)streamh.stream_size,(int)streamh.stream_no); - mp_msg(MSGT_HEADER,MSGL_V,"unk1: %lX unk2: %X\n",(unsigned long)streamh.unk1,(unsigned int)streamh.unk2); - mp_msg(MSGT_HEADER,MSGL_V,"FILEPOS=0x%X\n",stream_tell(demuxer->stream)); - } - if(streamh.type_size>1024 || streamh.stream_size>1024){ - mp_msg(MSGT_HEADER,MSGL_FATAL,"FATAL: header size bigger than 1024 bytes!\n" - "Please contact mplayer authors, and upload/send this file.\n"); - return 0; - } - // type-specific data: - stream_read(demuxer->stream,(char*) buffer,streamh.type_size); - switch(ASF_LOAD_GUID_PREFIX(streamh.type)){ - case ASF_GUID_PREFIX_audio_stream: { - sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh.stream_no & 0x7F); - sh_audio->wf=calloc((streamh.type_size<sizeof(WAVEFORMATEX))?sizeof(WAVEFORMATEX):streamh.type_size,1); - memcpy(sh_audio->wf,buffer,streamh.type_size); - le2me_WAVEFORMATEX(sh_audio->wf); - if(verbose>=1) print_wave_header(sh_audio->wf); - if(ASF_LOAD_GUID_PREFIX(streamh.concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){ - stream_read(demuxer->stream,(char*) buffer,streamh.stream_size); - asf_scrambling_h=buffer[0]; - asf_scrambling_w=(buffer[2]<<8)|buffer[1]; - asf_scrambling_b=(buffer[4]<<8)|buffer[3]; - asf_scrambling_w/=asf_scrambling_b; - } else { - asf_scrambling_b=asf_scrambling_h=asf_scrambling_w=1; - } - mp_msg(MSGT_HEADER,MSGL_V,"ASF: audio scrambling: %d x %d x %d\n",asf_scrambling_h,asf_scrambling_w,asf_scrambling_b); - //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F; - break; - } - case ASF_GUID_PREFIX_video_stream: { - sh_video_t* sh_video=new_sh_video(demuxer,streamh.stream_no & 0x7F); - int len=streamh.type_size-(4+4+1+2); -// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); - sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1); - memcpy(sh_video->bih,&buffer[4+4+1+2],len); - le2me_BITMAPINFOHEADER(sh_video->bih); - //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; - if(verbose>=1) print_video_header(sh_video->bih); - //asf_video_id=streamh.stream_no & 0x7F; - //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F; - break; - } - } - // stream-specific data: - // stream_read(demuxer->stream,(char*) buffer,streamh.stream_size); - break; -// case ASF_GUID_PREFIX_header_2_0: return "guid_header_2_0"; - case ASF_GUID_PREFIX_file_header: // guid_file_header - stream_read(demuxer->stream,(char*) &fileh,sizeof(fileh)); - le2me_ASF_file_header_t(&fileh); - mp_msg(MSGT_HEADER,MSGL_V,"ASF: packets: %d flags: %d pack_size: %d frame_size: %d\n",(int)fileh.packets,(int)fileh.flags,(int)fileh.packetsize,(int)fileh.frame_size); - asf_packetsize=fileh.packetsize; - asf_packet=malloc(asf_packetsize); // !!! - break; - case ASF_GUID_PREFIX_data_chunk: // guid_data_chunk - demuxer->movi_start=stream_tell(demuxer->stream)+26; - demuxer->movi_end=endpos; - mp_msg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end); - break; - -// case ASF_GUID_PREFIX_index_chunk: return "guid_index_chunk"; - - case ASF_GUID_PREFIX_content_desc: // Content description - if(verbose){ - char *string=NULL; - stream_read(demuxer->stream,(char*) &contenth,sizeof(contenth)); - le2me_ASF_content_description_t(&contenth); - mp_msg(MSGT_HEADER,MSGL_V,"\n"); - // extract the title - if( contenth.title_size!=0 ) { - string=(char*)malloc(contenth.title_size); - stream_read(demuxer->stream, string, contenth.title_size); - print_asf_string(" Title: ", string, contenth.title_size); - } - // extract the author - if( contenth.author_size!=0 ) { - string=(char*)realloc((void*)string, contenth.author_size); - stream_read(demuxer->stream, string, contenth.author_size); - print_asf_string(" Author: ", string, contenth.author_size); - } - // extract the copyright - if( contenth.copyright_size!=0 ) { - string=(char*)realloc((void*)string, contenth.copyright_size); - stream_read(demuxer->stream, string, contenth.copyright_size); - print_asf_string(" Copyright: ", string, contenth.copyright_size); - } - // extract the comment - if( contenth.comment_size!=0 ) { - string=(char*)realloc((void*)string, contenth.comment_size); - stream_read(demuxer->stream, string, contenth.comment_size); - print_asf_string(" Comment: ", string, contenth.comment_size); - } - // extract the rating - if( contenth.rating_size!=0 ) { - string=(char*)realloc((void*)string, contenth.rating_size); - stream_read(demuxer->stream, string, contenth.rating_size); - print_asf_string(" Rating: ", string, contenth.rating_size); - } - mp_msg(MSGT_HEADER,MSGL_V,"\n"); - free(string); - } - break; - - } // switch GUID - - if(ASF_LOAD_GUID_PREFIX(objh.guid)==ASF_GUID_PREFIX_data_chunk) break; // movi chunk - - if(!stream_seek(demuxer->stream,endpos)) break; -} // while EOF - -#if 0 -if(verbose){ - printf("ASF duration: %d\n",(int)fileh.duration); - printf("ASF start pts: %d\n",(int)fileh.start_timestamp); - printf("ASF end pts: %d\n",(int)fileh.end_timestamp); -} -#endif - -#endif -return 1; -}
--- a/aviheader.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "config.h" -#include "mp_msg.h" - -#include "stream.h" -#include "demuxer.h" - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "bswap.h" -#include "stheader.h" -#include "aviheader.h" - -#define MIN(a,b) (((a)<(b))?(a):(b)) - - -static MainAVIHeader avih; - -extern void print_avih(MainAVIHeader *h); -extern void print_avih_flags(MainAVIHeader *h); -extern void print_strh(AVIStreamHeader *h); -extern void print_wave_header(WAVEFORMATEX *h); -extern void print_video_header(BITMAPINFOHEADER *h); -extern void print_index(AVIINDEXENTRY *idx,int idx_size); - -void read_avi_header(demuxer_t *demuxer,int index_mode){ -sh_audio_t *sh_audio=NULL; -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: -priv->idx_size=0; -while(1){ - int id=stream_read_dword_le(demuxer->stream); - int chunksize,size2; - static int last_fccType=0; - char* hdr=NULL; - // - if(stream_eof(demuxer->stream)) break; - // - if(id==mmioFOURCC('L','I','S','T')){ - int len=stream_read_dword_le(demuxer->stream)-4; // list size - id=stream_read_dword_le(demuxer->stream); // list type - mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%d\n",(char *) &id,len); - if(id==listtypeAVIMOVIE){ - // found MOVI header - demuxer->movi_start=stream_tell(demuxer->stream); - demuxer->movi_end=demuxer->movi_start+len; - mp_msg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end); - if(index_mode==-2) break; // reading from non-seekable source (stdin) - len=(len+1)&(~1); - stream_skip(demuxer->stream,len); - } - continue; - } - size2=stream_read_dword_le(demuxer->stream); - mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%d\n",(char *) &id,size2); - chunksize=(size2+1)&(~1); - switch(id){ - case mmioFOURCC('I','S','F','T'): hdr="Software";break; - case mmioFOURCC('I','N','A','M'): hdr="Name";break; - case mmioFOURCC('I','S','B','J'): hdr="Title";break; - case mmioFOURCC('I','A','R','T'): hdr="Author";break; - case mmioFOURCC('I','C','O','P'): hdr="Copyright";break; - case mmioFOURCC('I','C','M','T'): hdr="Comment";break; - case ckidAVIMAINHDR: // read 'avih' - stream_read(demuxer->stream,(char*) &avih,MIN(size2,sizeof(avih))); - le2me_MainAVIHeader(&avih); // swap to machine endian - chunksize-=MIN(size2,sizeof(avih)); - if(verbose) print_avih(&avih); else print_avih_flags(&avih); - break; - case ckidSTREAMHEADER: { // read 'strh' - AVIStreamHeader h; - stream_read(demuxer->stream,(char*) &h,MIN(size2,sizeof(h))); - le2me_AVIStreamHeader(&h); // swap to machine endian - chunksize-=MIN(size2,sizeof(h)); - ++stream_id; - if(h.fccType==streamtypeVIDEO){ - sh_video=new_sh_video(demuxer,stream_id); - memcpy(&sh_video->video,&h,sizeof(h)); - } else - if(h.fccType==streamtypeAUDIO){ - sh_audio=new_sh_audio(demuxer,stream_id); - memcpy(&sh_audio->audio,&h,sizeof(h)); - } - last_fccType=h.fccType; - if(verbose>=1) print_strh(&h); - break; } - case ckidSTREAMFORMAT: { // read 'strf' - if(last_fccType==streamtypeVIDEO){ - sh_video->bih=calloc((chunksize<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):chunksize,1); -// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); - mp_msg(MSGT_HEADER,MSGL_V,"found 'bih', %d bytes of %d\n",chunksize,sizeof(BITMAPINFOHEADER)); - stream_read(demuxer->stream,(char*) sh_video->bih,chunksize); - le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian - if(verbose>=1) print_video_header(sh_video->bih); - chunksize=0; -// 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; -// if(demuxer->video->id==-1) demuxer->video->id=stream_id; - // IdxFix: - idxfix_videostream=stream_id; - switch(sh_video->bih->biCompression){ - case mmioFOURCC('D', 'I', 'V', '3'): - case mmioFOURCC('d', 'i', 'v', '3'): - case mmioFOURCC('D', 'I', 'V', '4'): - case mmioFOURCC('d', 'i', 'v', '4'): - case mmioFOURCC('D', 'I', 'V', '5'): - case mmioFOURCC('d', 'i', 'v', '5'): - case mmioFOURCC('D', 'I', 'V', '6'): - case mmioFOURCC('d', 'i', 'v', '6'): - case mmioFOURCC('M', 'P', '4', '3'): - case mmioFOURCC('m', 'p', '4', '3'): - case mmioFOURCC('M', 'P', '4', '2'): - case mmioFOURCC('m', 'p', '4', '2'): - case mmioFOURCC('D', 'I', 'V', '2'): - case mmioFOURCC('A', 'P', '4', '1'): - idxfix_divx=1; // we can fix keyframes only for divx coded files! - } - } else - if(last_fccType==streamtypeAUDIO){ - int wf_size = chunksize<sizeof(WAVEFORMATEX)?sizeof(WAVEFORMATEX):chunksize; - sh_audio->wf=calloc(wf_size,1); -// sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize); - mp_msg(MSGT_HEADER,MSGL_V,"found 'wf', %d bytes of %d\n",chunksize,sizeof(WAVEFORMATEX)); - stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize); - le2me_WAVEFORMATEX(sh_audio->wf); - if (sh_audio->wf->cbSize != 0 && - wf_size < sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize) { - sh_audio->wf=realloc(sh_audio->wf, sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize); - } - chunksize=0; - if(verbose>=1) print_wave_header(sh_audio->wf); -// if(demuxer->audio->id==-1) demuxer->audio->id=stream_id; - } - break; - } - case ckidAVINEWINDEX: if(index_mode){ - int i; - priv->idx_size=size2>>4; - mp_msg(MSGT_HEADER,MSGL_V,"Reading INDEX block, %d chunks for %ld frames\n", - 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; - } - } - if(hdr){ - char buf[256]; - int len=(size2<250)?size2:250; - stream_read(demuxer->stream,buf,len); - chunksize-=len; - buf[len]=0; - mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf); - } - if(chunksize>0) stream_skip(demuxer->stream,chunksize); else - if(chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%d (id=%.4s)\n",chunksize,(char *) &id); - -} - -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); - - priv->idx_pos=0; - priv->idx_size=0; - priv->idx=NULL; - - while(1){ - int id,len,skip; - AVIINDEXENTRY* idx; - unsigned char c; - demuxer->filepos=stream_tell(demuxer->stream); - if(demuxer->filepos>=demuxer->movi_end) break; - id=stream_read_dword_le(demuxer->stream); - len=stream_read_dword_le(demuxer->stream); - if(id==mmioFOURCC('L','I','S','T')){ - id=stream_read_dword_le(demuxer->stream); // list type - continue; - } - if(stream_eof(demuxer->stream)) break; - if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?) - - 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 *)priv->idx)[priv->idx_pos++]; - idx->ckid=id; - idx->dwFlags=AVIIF_KEYFRAME; // FIXME - idx->dwChunkOffset=demuxer->filepos; - idx->dwChunkLength=len; - - c=stream_read_char(demuxer->stream); - - // Fix keyframes for DivX files: - if(idxfix_divx) - if(avi_stream_id(id)==idxfix_videostream){ - if(c&0x40) idx->dwFlags=0; - } - - mp_dbg(MSGT_HEADER,MSGL_DBG2,"%08X %08X %.4s %02X %X\n",demuxer->filepos,id,(char *) &id,c,(unsigned int) idx->dwFlags); -#if 0 - { unsigned char tmp[64]; - int i; - stream_read(demuxer->stream,tmp,64); - printf("%.4s",&id); - for(i=0;i<64;i++) printf(" %02X",tmp[i]); - printf("\n"); - } -#endif -skip_chunk: - skip=(len+1)&(~1); // total bytes in this chunk - stream_seek(demuxer->stream,8+demuxer->filepos+skip); - } - priv->idx_size=priv->idx_pos; - mp_msg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size); -} - -} - -#undef MIN - -
--- a/aviheader.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -#ifndef _aviheader_h -#define _aviheader_h - -//#include "config.h" /* get correct definition WORDS_BIGENDIAN */ -#include "bswap.h" - -/* - * Some macros to swap little endian structures read from an AVI file - * into machine endian format - */ -#ifdef WORDS_BIGENDIAN -#define le2me_MainAVIHeader(h) { \ - (h)->dwMicroSecPerFrame = le2me_32((h)->dwMicroSecPerFrame); \ - (h)->dwMaxBytesPerSec = le2me_32((h)->dwMaxBytesPerSec); \ - (h)->dwPaddingGranularity = le2me_32((h)->dwPaddingGranularity); \ - (h)->dwFlags = le2me_32((h)->dwFlags); \ - (h)->dwTotalFrames = le2me_32((h)->dwTotalFrames); \ - (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \ - (h)->dwStreams = le2me_32((h)->dwStreams); \ - (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \ - (h)->dwWidth = le2me_32((h)->dwWidth); \ - (h)->dwHeight = le2me_32((h)->dwHeight); \ -} - -#define le2me_AVIStreamHeader(h) { \ - (h)->fccType = le2me_32((h)->fccType); \ - (h)->fccHandler = le2me_32((h)->fccHandler); \ - (h)->dwFlags = le2me_32((h)->dwFlags); \ - (h)->wPriority = le2me_16((h)->wPriority); \ - (h)->wLanguage = le2me_16((h)->wLanguage); \ - (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \ - (h)->dwScale = le2me_32((h)->dwScale); \ - (h)->dwRate = le2me_32((h)->dwRate); \ - (h)->dwStart = le2me_32((h)->dwStart); \ - (h)->dwLength = le2me_32((h)->dwLength); \ - (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \ - (h)->dwQuality = le2me_32((h)->dwQuality); \ - (h)->dwSampleSize = le2me_32((h)->dwSampleSize); \ - le2me_RECT(&(h)->rcFrame); \ -} -#define le2me_RECT(h) { \ - (h)->left = le2me_16((h)->left); \ - (h)->top = le2me_16((h)->top); \ - (h)->right = le2me_16((h)->right); \ - (h)->bottom = le2me_16((h)->bottom); \ -} -#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); \ -} -#define le2me_AVIINDEXENTRY(h) { \ - (h)->ckid = le2me_32((h)->ckid); \ - (h)->dwFlags = le2me_32((h)->dwFlags); \ - (h)->dwChunkOffset = le2me_32((h)->dwChunkOffset); \ - (h)->dwChunkLength = le2me_32((h)->dwChunkLength); \ -} -#else -#define le2me_MainAVIHeader(h) /**/ -#define le2me_AVIStreamHeader(h) /**/ -#define le2me_RECT(h) /**/ -#define le2me_BITMAPINFOHEADER(h) /**/ -#define le2me_WAVEFORMATEX(h) /**/ -#define le2me_AVIINDEXENTRY(h) /**/ -#endif - - -#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))
--- a/aviprint.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -//extern int verbose; // defined in mplayer.c - -#include "stream.h" -#include "demuxer.h" - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -//#include "codec-cfg.h" -//#include "stheader.h" - -void print_avih_flags(MainAVIHeader *h){ - printf("MainAVIHeader.dwFlags: (%ld)%s%s%s%s%s%s\n",h->dwFlags, - (h->dwFlags&AVIF_HASINDEX)?" HAS_INDEX":"", - (h->dwFlags&AVIF_MUSTUSEINDEX)?" MUST_USE_INDEX":"", - (h->dwFlags&AVIF_ISINTERLEAVED)?" IS_INTERLEAVED":"", - (h->dwFlags&AVIF_TRUSTCKTYPE)?" TRUST_CKTYPE":"", - (h->dwFlags&AVIF_WASCAPTUREFILE)?" WAS_CAPTUREFILE":"", - (h->dwFlags&AVIF_COPYRIGHTED)?" COPYRIGHTED":"" - ); -} - -void print_avih(MainAVIHeader *h){ - printf("======= AVI Header =======\n"); - printf("us/frame: %ld (fps=%5.3f)\n",h->dwMicroSecPerFrame,1000000.0f/(float)h->dwMicroSecPerFrame); - printf("max bytes/sec: %ld\n",h->dwMaxBytesPerSec); - printf("padding: %ld\n",h->dwPaddingGranularity); - print_avih_flags(h); - printf("frames total: %ld initial: %ld\n",h->dwTotalFrames,h->dwInitialFrames); - printf("streams: %ld\n",h->dwStreams); - printf("Suggested BufferSize: %ld\n",h->dwSuggestedBufferSize); - printf("Size: %ld x %ld\n",h->dwWidth,h->dwHeight); -} - -void print_strh(AVIStreamHeader *h){ - printf("======= STREAM Header =======\n"); - printf("Type: %.4s FCC: %.4s (%X)\n",(char *)&h->fccType,(char *)&h->fccHandler,(unsigned int)h->fccHandler); - printf("Flags: %ld\n",h->dwFlags); - printf("Priority: %d Language: %d\n",h->wPriority,h->wLanguage); - printf("InitialFrames: %ld\n",h->dwInitialFrames); - printf("Rate: %ld/%ld = %5.3f\n",h->dwRate,h->dwScale,(float)h->dwRate/(float)h->dwScale); - printf("Start: %ld Len: %ld\n",h->dwStart,h->dwLength); - printf("Suggested BufferSize: %ld\n",h->dwSuggestedBufferSize); - printf("Quality %ld\n",h->dwQuality); - printf("Sample size: %ld\n",h->dwSampleSize); -} - -void print_wave_header(WAVEFORMATEX *h){ - - printf("======= WAVE Format =======\n"); - printf("Format Tag: %d (0x%X)\n",h->wFormatTag,h->wFormatTag); - printf("Channels: %d\n",h->nChannels); - printf("Samplerate: %ld\n",h->nSamplesPerSec); - printf("avg byte/sec: %ld\n",h->nAvgBytesPerSec); - printf("Block align: %d\n",h->nBlockAlign); - printf("bits/sample: %d\n",h->wBitsPerSample); - printf("cbSize: %d\n",h->cbSize); -} - - -void print_video_header(BITMAPINFOHEADER *h){ - printf("======= VIDEO Format ======\n"); - printf(" biSize %ld\n", h->biSize); - printf(" biWidth %ld\n", h->biWidth); - printf(" biHeight %ld\n", h->biHeight); - printf(" biPlanes %d\n", h->biPlanes); - printf(" biBitCount %d\n", h->biBitCount); - printf(" biCompression %ld='%.4s'\n", h->biCompression, (char *)&h->biCompression); - printf(" biSizeImage %ld\n", h->biSizeImage); - printf("===========================\n"); -} - - -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++){ - 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, - pos[id],(float)pos[id]/18747.0f, - num[id],(float)num[id]/23.976f - ); - pos[id]+=idx[i].dwChunkLength; - ++num[id]; - } -} - -
--- a/aviwrite.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -extern char* encode_name; -extern char* encode_index_name; - -void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){ - -fwrite(&id,4,1,f); -fwrite(&len,4,1,f); -if(len>0){ - if(data){ - // DATA - fwrite(data,len,1,f); - if(len&1){ // padding - unsigned char zerobyte=0; - fwrite(&zerobyte,1,1,f); - } - } else { - // JUNK - char *avi_junk_data="[= MPlayer junk data! =]"; - if(len&1) ++len; // padding - while(len>0){ - int l=strlen(avi_junk_data); - if(l>len) l=len; - fwrite(avi_junk_data,l,1,f); - len-=l; - } - } -} - -} - - -void write_avi_list(FILE *f,unsigned int id,int len){ - unsigned int list_id=FOURCC_LIST; - len+=4; // list fix - fwrite(&list_id,4,1,f); - fwrite(&len,4,1,f); - fwrite(&id,4,1,f); -} - -struct { - MainAVIHeader avih; - AVIStreamHeader video; - BITMAPINFOHEADER bih; - unsigned int movi_start; - unsigned int movi_end; - unsigned int file_end; -} wah; - -void write_avi_header(FILE *f){ - unsigned int riff[3]; - // RIFF header: - riff[0]=mmioFOURCC('R','I','F','F'); - riff[1]=wah.file_end; // filesize - riff[2]=formtypeAVI; // 'AVI ' - fwrite(&riff,12,1,f); - // AVI header: - write_avi_list(f,listtypeAVIHEADER,sizeof(wah.avih)+8+12+sizeof(wah.video)+8+sizeof(wah.bih)+8); - write_avi_chunk(f,ckidAVIMAINHDR,sizeof(wah.avih),&wah.avih); - // stream header: - write_avi_list(f,listtypeSTREAMHEADER,sizeof(wah.video)+8+sizeof(wah.bih)+8); - write_avi_chunk(f,ckidSTREAMHEADER,sizeof(wah.video),&wah.video); - write_avi_chunk(f,ckidSTREAMFORMAT,sizeof(wah.bih),&wah.bih); - // JUNK: - write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL); - // 'movi' header: - write_avi_list(f,listtypeAVIMOVIE,wah.movi_end-ftell(f)-12); - wah.movi_start=ftell(f); -} - -// called _before_ encoding: (write placeholders and video info) -void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height){ - int frames=8*3600*fps; // 8 hours - - wah.file_end= - wah.movi_end=0x7f000000; - - wah.avih.dwMicroSecPerFrame=1000000.0f/fps; - wah.avih.dwMaxBytesPerSec=fps*500000; // ????? - wah.avih.dwPaddingGranularity=1; // padding - wah.avih.dwFlags=AVIF_ISINTERLEAVED; - wah.avih.dwTotalFrames=frames; - wah.avih.dwInitialFrames=0; - wah.avih.dwStreams=1; - wah.avih.dwSuggestedBufferSize=0x10000; // 1MB - wah.avih.dwWidth=width; - wah.avih.dwHeight=height; - wah.avih.dwReserved[0]= - wah.avih.dwReserved[1]= - wah.avih.dwReserved[2]= - wah.avih.dwReserved[3]=0; - - wah.video.fccType=streamtypeVIDEO; - wah.video.fccHandler=fcc; - wah.video.dwFlags=0; - wah.video.wPriority=0; - wah.video.wLanguage=0; - wah.video.dwInitialFrames=0; - wah.video.dwScale=10000; - wah.video.dwRate=fps*10000; - wah.video.dwStart=0; - wah.video.dwLength=frames; - wah.video.dwSuggestedBufferSize=0x100000; // 1MB ???? - wah.video.dwQuality=10000; - wah.video.dwSampleSize=width*height*3; - - wah.bih.biSize=sizeof(wah.bih); // 40 ? - wah.bih.biWidth=width; - wah.bih.biHeight=height; - wah.bih.biPlanes=1; - wah.bih.biBitCount=24; - wah.bih.biCompression=fcc; - wah.bih.biSizeImage=3*width*height; - wah.bih.biXPelsPerMeter= - wah.bih.biYPelsPerMeter= - wah.bih.biClrUsed= - wah.bih.biClrImportant=0; - - write_avi_header(f); -} - -void avi_fixate(){ - // append index and fix avi headers: - FILE *f1=fopen(encode_name,"r+"); - FILE *f2; - - if(!f1) return; // error - - fseek(f1,0,SEEK_END); - wah.file_end=wah.movi_end=ftell(f1); - - // index: - if(encode_index_name && (f2=fopen(encode_index_name,"rb"))){ - AVIINDEXENTRY idx; - unsigned int pos=0; - int frames=0; - write_avi_chunk(f1,ckidAVINEWINDEX,0,NULL); - while(fread(&idx,sizeof(idx),1,f2)>0){ - idx.dwChunkOffset-=wah.movi_start-4; - fwrite(&idx,sizeof(idx),1,f1); - ++frames; - } - fclose(f2); - unlink(encode_index_name); - wah.file_end=ftell(f1); - // re-write idx1 length: - pos=wah.file_end-wah.movi_end-8; - fseek(f1,wah.movi_end+4,SEEK_SET); - fwrite(&pos,4,1,f1); - // fixup frames: - wah.avih.dwTotalFrames=frames; - wah.video.dwLength=frames; - } - - // re-write avi header: - fseek(f1,0,SEEK_SET); - write_avi_header(f1); - - fclose(f1); - -} - - -
--- a/codec-cfg.h Sat Oct 20 18:05:30 2001 +0000 +++ b/codec-cfg.h Sat Oct 20 18:49:08 2001 +0000 @@ -51,7 +51,7 @@ #endif -typedef struct { +typedef struct codecs_st { unsigned int fourcc[CODECS_MAX_FOURCC]; unsigned int fourccmap[CODECS_MAX_FOURCC]; unsigned int outfmt[CODECS_MAX_OUTFMT];
--- a/configure Sat Oct 20 18:05:30 2001 +0000 +++ b/configure Sat Oct 20 18:49:08 2001 +0000 @@ -1734,7 +1734,7 @@ _streamingdef='#undef STREAMING' if test "$_streaming" = yes ; then - _streamingsrcs='asf_streaming.c network.c url.c http.c' +# _streamingsrcs='asf_streaming.c network.c url.c http.c' _streamingdef='#define STREAMING' fi @@ -2271,7 +2271,7 @@ ALSA_LIB = $_alsalib ESD_LIB = $_esdlib ARCH_LIBS = $_archlibs $_iconvlib -STREAM_SRCS = $_streamingsrcs +STREAMING=$_streaming DECORE_LIBS = $_decorelibs DIVX4LINUX=$_divx4linux MLIB_INC = $_mlibinc
--- a/demux_asf.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,367 +0,0 @@ -// ASF file parser for DEMUXER v0.3 by A'rpi/ESP-team - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#include "stream.h" -#include "asf.h" -#include "demuxer.h" - - -/* - * Load 16/32-bit values in little endian byte order - * from an unaligned address - */ -#ifdef ARCH_X86 -#define LOAD_LE32(p) (*(unsigned int*)(p)) -#define LOAD_LE16(p) (*(unsigned short*)(p)) -#else -#define LOAD_LE32(p) (((unsigned char*)(p))[0] | \ - ((unsigned char*)(p))[1]<< 8 | \ - ((unsigned char*)(p))[2]<<16 | \ - ((unsigned char*)(p))[3]<<24 ) -#define LOAD_LE16(p) (((unsigned char*)(p))[0] | \ - ((unsigned char*)(p))[1]<<8) -#endif - -// defined at asfheader.c: -extern unsigned char* asf_packet; -extern int asf_scrambling_h; -extern int asf_scrambling_w; -extern int asf_scrambling_b; -extern int asf_packetsize; - - -// based on asf file-format doc by Eugene [http://divx.euro.ru] - -static void asf_descrambling(unsigned char *src,int len){ - unsigned char *dst=malloc(len); - unsigned char *s2=src; - int i=0,x,y; - while(len-i>=asf_scrambling_h*asf_scrambling_w*asf_scrambling_b){ -// mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d b=%d)\n",w,asf_scrambling_b); - //i+=asf_scrambling_h*asf_scrambling_w; - for(x=0;x<asf_scrambling_w;x++) - for(y=0;y<asf_scrambling_h;y++){ - memcpy(dst+i,s2+(y*asf_scrambling_w+x)*asf_scrambling_b,asf_scrambling_b); - i+=asf_scrambling_b; - } - s2+=asf_scrambling_h*asf_scrambling_w*asf_scrambling_b; - } - //if(i<len) memcpy(dst+i,src+i,len-i); - memcpy(src,dst,i); - free(dst); -} - - -static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,unsigned long time,unsigned short dur,int offs,int keyframe){ - demux_stream_t *ds=NULL; - - mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len); - - if(demux->video->id==-1) - if(demux->v_streams[id]) - demux->video->id=id; - - if(demux->audio->id==-1) - if(demux->a_streams[id]) - demux->audio->id=id; - - if(id==demux->audio->id){ - // audio - ds=demux->audio; - if(!ds->sh){ - ds->sh=demux->a_streams[id]; - mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id); - } - } else - if(id==demux->video->id){ - // video - ds=demux->video; - if(!ds->sh){ - ds->sh=demux->v_streams[id]; - mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id); - } - } - - if(ds){ - if(ds->asf_packet){ - if(ds->asf_seq!=seq){ - // closed segment, finalize packet: - if(ds==demux->audio) - if(asf_scrambling_h>1 && asf_scrambling_w>1) - asf_descrambling(ds->asf_packet->buffer,ds->asf_packet->len); - ds_add_packet(ds,ds->asf_packet); - ds->asf_packet=NULL; - } else { - // append data to it! - demux_packet_t* dp=ds->asf_packet; - if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs); - dp->buffer=realloc(dp->buffer,dp->len+len); - memcpy(dp->buffer+dp->len,data,len); - mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); - dp->len+=len; - // we are ready now. - return 1; - } - } - // create new packet: - { demux_packet_t* dp; - if(offs>0){ - mp_msg(MSGT_DEMUX,MSGL_V,"warning! broken fragment, %d bytes missing \n",offs); - return 0; - } - dp=new_demux_packet(len); - memcpy(dp->buffer,data,len); - dp->pts=time*0.001f; - dp->flags=keyframe; -// if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur); - dp->pos=demux->filepos; - ds->asf_packet=dp; - ds->asf_seq=seq; - // we are ready now. - return 1; - } - } - - return 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_asf_fill_buffer(demuxer_t *demux){ - - demux->filepos=stream_tell(demux->stream); - if(demux->filepos>=demux->movi_end){ - demux->stream->eof=1; - return 0; - } - - stream_read(demux->stream,asf_packet,asf_packetsize); - if(demux->stream->eof) return 0; // EOF - - if(asf_packet[0]==0x82){ - unsigned char flags=asf_packet[3]; - unsigned char segtype=asf_packet[4]; - unsigned char* p=&asf_packet[5]; - unsigned char* p_end=p+asf_packetsize; - unsigned long time; - unsigned short duration; - int segs=1; - unsigned char segsizetype=0x80; - int seg; - int padding=0; - int plen; - - if(verbose>1){ - int i; - for(i=0;i<16;i++) printf(" %02X",asf_packet[i]); - printf("\n"); - } - - //if(segtype!=0x5d) printf("Warning! packet[4] != 0x5d \n"); - - // Calculate packet size (plen): - if(flags&0x40){ - // Explicit (absoulte) packet size - plen=LOAD_LE16(p); p+=2; - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Explicit packet size specified: %d \n",plen); - if(plen>asf_packetsize) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! plen>packetsize! (%d>%d) \n",plen,asf_packetsize); - if(flags&(8|16)){ - padding=p[0];p++; - if(flags&16){ padding|=p[0]<<8; p++;} - mp_msg(MSGT_DEMUX,MSGL_V,"Warning! explicit=%d padding=%d \n",plen,asf_packetsize-padding); - } - } else { - // Padding (relative) size - if(flags&8){ - padding=p[0];++p; - } else - if(flags&16){ - padding=LOAD_LE16(p);p+=2; - } - plen=asf_packetsize-padding; - } - - time = LOAD_LE32(p); p+=4; - duration = LOAD_LE16(p); p+=2; - if(flags&1){ - segsizetype=p[0] & 0xC0; - segs=p[0] & 0x3F; - ++p; - } - mp_dbg(MSGT_DEMUX,MSGL_DBG4,"%08X: flag=%02X segs=%d pad=%d time=%ld dur=%d\n", - demux->filepos,flags,segs,padding,time,duration); - for(seg=0;seg<segs;seg++){ - //ASF_segmhdr_t* sh; - unsigned char streamno; - unsigned char seq; - int len; - unsigned long x; - unsigned char type; - unsigned long time2; - int keyframe=0; - - if(p>=p_end) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! invalid packet 1, sig11 coming soon...\n"); - - if(verbose>1){ - int i; - printf("seg %d:",seg); - for(i=0;i<16;i++) printf(" %02X",p[i]); - printf("\n"); - } - - streamno=p[0]&0x7F; - if(p[0]&0x80) keyframe=1; - seq=p[1]; - p+=2; - - switch(segtype){ - case 0x55: - x=*((unsigned char*)p); - p++; - break; - case 0x59: - x=LOAD_LE16(p); - p+=2; - break; - case 0x5D: - x=LOAD_LE32(p); - p+=4; - break; - default: - mp_msg(MSGT_DEMUX,MSGL_V,"Warning! unknown segtype == 0x%2X \n",segtype); - x=0; - } - - type=p[0]; p++; // 0x01: grouping 0x08: single - - switch(type){ - case 0x01: - //printf("grouping: %02X \n",p[0]); - ++p; // skip unknown byte - break; - case 0x08: - //printf("!!! obj_length = %d\n",*((unsigned long*)p)); - p+=4; - time2=LOAD_LE32(p);p+=4; - break; - default: - mp_msg(MSGT_DEMUX,MSGL_V,"unknown segment type: 0x%02X \n",type); - } - - if(flags&1){ - // multiple segments - if(segsizetype==0x40){ - len=*((unsigned char*)p);p++; // 1 byte - } else { - len=LOAD_LE16(p);p+=2; // 2 byte - } - } else { - // single segment - len=plen-(p-asf_packet); - } - if(len<0 || (p+len)>=p_end){ - mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! segment len=%d\n",len); - } - mp_dbg(MSGT_DEMUX,MSGL_DBG4," seg #%d: streamno=%d seq=%d type=%02X len=%d\n",seg,streamno,seq,type,len); - - switch(type){ - case 0x01: - // GROUPING: - //printf("ASF_parser: warning! grouping (flag=1) not yet supported!\n",len); - //printf(" total: %d \n",len); - while(len>0){ - int len2=p[0]; - p++; - //printf(" group part: %d bytes\n",len2); - demux_asf_read_packet(demux,p,len2,streamno,seq,x,duration,-1,keyframe); - p+=len2; - len-=len2+1; - } - if(len!=0){ - mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! groups total != len\n"); - } - break; - case 0x08: - // NO GROUPING: - //printf("fragment offset: %d \n",sh->x); - demux_asf_read_packet(demux,p,len,streamno,seq,time2,duration,x,keyframe); - p+=len; - break; - } - - } // for segs - return 1; // success - } - - mp_msg(MSGT_DEMUX,MSGL_V,"%08X: UNKNOWN TYPE %02X %02X %02X %02X %02X...\n",demux->filepos,asf_packet[0],asf_packet[1],asf_packet[2],asf_packet[3],asf_packet[4]); - return 0; -} - - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "stheader.h" - - -void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags){ - demux_stream_t *d_audio=demuxer->audio; - demux_stream_t *d_video=demuxer->video; - sh_audio_t *sh_audio=d_audio->sh; -// sh_video_t *sh_video=d_video->sh; - - //FIXME: OFF_T - didn't test ASF case yet (don't have a large asf...) - //FIXME: reports good or bad to steve@daviesfam.org please - - //================= seek in ASF ========================== - float p_rate=10; // packets / sec - off_t rel_seek_packs=(flags&2)? // FIXME: int may be enough? - (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf_packetsize): - (rel_seek_secs*p_rate); - off_t rel_seek_bytes=rel_seek_packs*asf_packetsize; - off_t newpos; - //printf("ASF: packs: %d duration: %d \n",(int)fileh.packets,*((int*)&fileh.duration)); -// printf("ASF_seek: %d secs -> %d packs -> %d bytes \n", -// rel_seek_secs,rel_seek_packs,rel_seek_bytes); - newpos=((flags&1)?demuxer->movi_start:demuxer->filepos)+rel_seek_bytes; - if(newpos<0 || newpos<demuxer->movi_start) newpos=demuxer->movi_start; -// printf("\r -- asf: newpos=%d -- \n",newpos); - stream_seek(demuxer->stream,newpos); - - ds_fill_buffer(d_video); - if(sh_audio){ - ds_fill_buffer(d_audio); - resync_audio_stream(sh_audio); - } - - while(1){ - if(sh_audio && !d_audio->eof){ - float a_pts=d_audio->pts; - a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; - // sync audio: - if (d_video->pts > a_pts){ - skip_audio_frame(sh_audio); -// if(!ds_fill_buffer(d_audio)) sh_audio=NULL; // skip audio. EOF? - continue; - } - } - if(d_video->flags&1) break; // found a keyframe! - if(!ds_fill_buffer(d_video)) break; // skip frame. EOF? - } - - -} -
--- a/demux_avi.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,673 +0,0 @@ -// AVI file parser for DEMUXER v2.9 by A'rpi/ESP-team - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#include "stream.h" -#include "demuxer.h" - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "stheader.h" - -#include "aviheader.h" - -// Select ds from ID -demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){ - int stream_id=avi_stream_id(id); - -// printf("demux_avi_select_stream(%d) {a:%d/v:%d}\n",stream_id, -// demux->audio->id,demux->video->id); - - if(demux->video->id==-1) - if(demux->v_streams[stream_id]) - demux->video->id=stream_id; - - if(demux->audio->id==-1) - if(demux->a_streams[stream_id]) - demux->audio->id=stream_id; - - if(stream_id==demux->audio->id){ - if(!demux->audio->sh){ - demux->audio->sh=demux->a_streams[stream_id]; - mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id); - } - return demux->audio; - } - if(stream_id==demux->video->id){ - if(!demux->video->sh){ - demux->video->sh=demux->v_streams[stream_id]; - mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI video ID = %d\n",demux->video->id); - } - return demux->video; - } - if(id!=mmioFOURCC('J','U','N','K')){ - // unknown - mp_msg(MSGT_DEMUX,MSGL_DBG2,"Unknown chunk: %.4s (%X)\n",(char *) &id,id); - } - return NULL; -} - -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); - - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id); - - if(ds==demux->audio){ - - 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)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec; - mp_msg(MSGT_DEMUX,MSGL_V,"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 - priv->pts_corr_bytes+=len; - } - pts=priv->avi_audio_pts; //+priv->pts_correction; - priv->avi_audio_pts=0; - } else - if(ds==demux->video){ - // video - if(priv->skip_video_frames>0){ - // drop frame (seeking) - --priv->skip_video_frames; - ds=NULL; -// } else { -// pts=priv->avi_video_pts; - } - // ezt a 2 sort lehet hogy fell kell majd cserelni: - //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); - 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 - 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",priv->avi_audio_pts,priv->avi_video_pts); - priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction; - priv->pts_has_video=1; - - pts=priv->avi_video_pts; - - //printf("read pack_no: %d pts %5.3f \n",demux->video->pack_no+demux->video->packs,pts); - - } - -// len=stream_read_dword_le(demux->stream); - skip=(len+1)&(~1); // total bytes in this chunk - - if(ds){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id); - ds_read_packet(ds,demux->stream,len,pts,idxpos,flags); - skip-=len; - } - if(skip){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Skipping %d bytes from packet %04X\n",skip,id); - stream_skip(demux->stream,skip); - } - return ds?1: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; -int ret=0; - -do{ - int flags=0; - AVIINDEXENTRY *idx=NULL; -#if 0 - demux->filepos=stream_tell(demux->stream); - if(demux->filepos>=demux->movi_end){ - demux->stream->eof=1; - return 0; - } - if(stream_eof(demux->stream)) return 0; -#endif - if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){ - unsigned int pos; - - //if(priv->idx_pos<0) printf("Fatal! idx_pos=%d\n",priv->idx_pos); - - idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++]; - - //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, - // pos-4,idx->dwChunkLength,idx->dwFlags); - if(idx->dwFlags&AVIIF_LIST){ - // LIST - continue; - } - if(!demux_avi_select_stream(demux,idx->ckid)){ - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid); - continue; // skip this chunk - } - - pos=idx->dwChunkOffset+priv->idx_offset; - if(pos<demux->movi_start || pos>=demux->movi_end){ - mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! idx=0x%X \n",pos); - continue; - } -#if 0 - if(pos!=demux->filepos){ - mp_msg(MSGT_DEMUX,MSGL_V,"Warning! pos=0x%X idx.pos=0x%X diff=%d \n",demux->filepos,pos,pos-demux->filepos); - } -#endif - stream_seek(demux->stream,pos); - demux->filepos=stream_tell(demux->stream); - id=stream_read_dword_le(demux->stream); - if(stream_eof(demux->stream)) return 0; // EOF! - - if(id!=idx->ckid){ - mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid); - id=idx->ckid; -// continue; - } - len=stream_read_dword_le(demux->stream); -// if((len&(~1))!=(idx->dwChunkLength&(~1))){ -// if((len)!=(idx->dwChunkLength)){ - if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ - mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength); - len=idx->dwChunkLength; -// continue; - } - if(idx->dwFlags&AVIIF_KEYFRAME) flags=1; - } else { - demux->filepos=stream_tell(demux->stream); - if(demux->filepos>=demux->movi_end){ - demux->stream->eof=1; - return 0; - } - id=stream_read_dword_le(demux->stream); - len=stream_read_dword_le(demux->stream); - if(stream_eof(demux->stream)) return 0; // EOF! - - if(id==mmioFOURCC('L','I','S','T')){ - id=stream_read_dword_le(demux->stream); // list type - continue; - } - } - 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; -// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream); -// return 0; -// } -} while(ret!=1); - return 1; -} - - -// return value: -// 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; -int ret=0; - -do{ - int flags=0; - AVIINDEXENTRY *idx=NULL; - int idx_pos=0; - demux->filepos=stream_tell(demux->stream); - - 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(priv->idx_size>0 && idx_pos<priv->idx_size){ - unsigned int pos; - idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos]; -// idx=&priv->idx[idx_pos]; - - if(idx->dwFlags&AVIIF_LIST){ - // LIST - continue; - } - if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){ - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid); - continue; // skip this chunk - } - - pos=idx->dwChunkOffset+priv->idx_offset; - if(pos<demux->movi_start || pos>=demux->movi_end){ - mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos); - continue; - } -#if 0 - if(pos!=demux->filepos){ - mp_msg(MSGT_DEMUX,MSGL_V,"Warning! pos=0x%X idx.pos=0x%X diff=%d \n",demux->filepos,pos,pos-demux->filepos); - } -#endif - stream_seek(demux->stream,pos); - - id=stream_read_dword_le(demux->stream); - - if(stream_eof(demux->stream)) return 0; - - if(id!=idx->ckid){ - mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid); - id=idx->ckid; -// continue; - } - len=stream_read_dword_le(demux->stream); -// if((len&(~1))!=(idx->dwChunkLength&(~1))){ -// if((len)!=(idx->dwChunkLength)){ - if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ - mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength); - len=idx->dwChunkLength; -// continue; - } - if(idx->dwFlags&AVIIF_KEYFRAME) flags=1; - } else return 0; - ret=demux_avi_read_packet(demux,id,len,idx_pos,flags); -// if(!ret && priv->skip_video_frames<=0) -// if(--max_packs==0){ -// demux->stream->eof=1; -// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream); -// return 0; -// } -} while(ret!=1); - return 1; -} - - -// return value: -// 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=&priv->idx_pos_v; else - if(ds==demux->audio) fpos=&priv->idx_pos_a; else - return 0; - - stream_seek(demux->stream,fpos[0]); - -do{ - - demux->filepos=stream_tell(demux->stream); - if(demux->filepos>=demux->movi_end){ - demux->stream->eof=1; - return 0; - } - if(stream_eof(demux->stream)) return 0; - - id=stream_read_dword_le(demux->stream); - len=stream_read_dword_le(demux->stream); - if(id==mmioFOURCC('L','I','S','T')){ - id=stream_read_dword_le(demux->stream); // list type - continue; - } - - if(ds==demux_avi_select_stream(demux,id)){ - // read it! - 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 - stream_skip(demux->stream,skip); - } - -} while(ret!=1); - fpos[0]=stream_tell(demux->stream); - return 1; -} - -//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; - -void read_avi_header(demuxer_t *demuxer,int index_mode); - -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; - mp_msg(MSGT_DEMUX,MSGL_V,"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){ - mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI_NI: " MSGTR_MissingVideoStream); - return NULL; -// GUI_MSG( mplErrorAVINI ) - } - if(a_pos==-1){ - mp_msg(MSGT_DEMUX,MSGL_INFO,"AVI_NI: " MSGTR_MissingAudioStream); - sh_audio=NULL; - } else { - if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB - mp_msg(MSGT_DEMUX,MSGL_INFO,MSGTR_NI_Message,force_ni?MSGTR_NI_Forced:MSGTR_NI_Detected); - demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!! - pts_from_bps=1; // force BPS sync! - } - } - } else { - // no index - if(force_ni){ - mp_msg(MSGT_DEMUX,MSGL_INFO,MSGTR_UsingNINI); - 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! - } - demuxer->seekable=0; - } - if(!ds_fill_buffer(d_video)){ - mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI: " MSGTR_MissingVideoStreamBug); - return NULL; -// GUI_MSG( mplAVIErrorMissingVideoStream ) - } - sh_video=d_video->sh;sh_video->ds=d_video; - if(d_audio->id!=-2){ - mp_msg(MSGT_DEMUX,MSGL_V,"AVI: Searching for audio stream (id:%d)\n",d_audio->id); - if(!ds_fill_buffer(d_audio)){ - mp_msg(MSGT_DEMUX,MSGL_INFO,"AVI: " MSGTR_MissingAudioStream); - 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; - mp_msg(MSGT_DEMUX,MSGL_V,"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; - mp_msg(MSGT_DEMUX,MSGL_INFO,"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; - sh_video_t *sh_video=d_video->sh; - float skip_audio_secs=0; - - //FIXME: OFF_T - Didn't check AVI case yet (avi files can't be >2G anyway?) - //================= seek in AVI ========================== - int rel_seek_frames=rel_seek_secs*sh_video->fps; - int video_chunk_pos=d_video->pos; - int i; - - if(flags&1){ - // seek absolute - video_chunk_pos=0; - } - - if(flags&2){ - // float 0..1 - int total=sh_video->video.dwLength; - if(total<=1){ - // bad video header, try to get it from audio - if(sh_audio) total=sh_video->fps*sh_audio->audio.dwLength/sh_audio->wf->nAvgBytesPerSec; - if(total<=1){ - mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CouldntDetFNo); - total=0; - } - } - rel_seek_frames=rel_seek_secs*total; - } - - 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<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 *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break; - } - ++video_chunk_pos; - } - } else { - // seek backward - while(video_chunk_pos>0){ - 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 *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break; - } - --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 *)priv->idx)[i].ckid; - if(avi_stream_id(id)==d_video->id) ++d_video->pack_no; - } - sh_video->num_frames=sh_video->num_frames_decoded=d_video->pack_no; - priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; - d_video->pos=video_chunk_pos; - - mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK: pack=%d pts=%5.3f chunk=%d \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos); - -// ------------ STEP 2: seek audio, find the right chunk & pos ------------ - - d_audio->pack_no=0; - d_audio->dpos=0; - - if(sh_audio){ - int i; -// int apos=0; - int last=0; - int len=0; - 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:priv->idx_size; - - if(sh_audio->audio.dwSampleSize){ - // constant rate audio stream -#if 0 - int align; - 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=(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 *)priv->idx)[i].ckid; - if(avi_stream_id(id)==d_audio->id){ - 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"); - break; - } - d_audio->dpos+=len; - } - } - skip_audio_bytes=curr_audio_pos-d_audio->dpos; - - } else { - // VBR audio - 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<priv->idx_size && chunks>0;i++){ - int id=((AVIINDEXENTRY *)priv->idx)[i].ckid; - if(avi_stream_id(id)==d_audio->id){ - len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength; - if(i>chunk_max){ - skip_audio_bytes+=len; - } else { - ++d_audio->pack_no; - d_audio->dpos+=len; - audio_chunk_pos=i; - } - --chunks; - } - } - //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", -// priv->avi_video_pts, audio_chunk_pos, ); - - } - - // Now we have: - // audio_chunk_pos = chunk no in index table (it's <=chunk_max) - // skip_audio_bytes = bytes to be skipped after chunk seek - // d-audio->pack_no = chunk_no in stream at audio_chunk_pos - // d_audio->dpos = bytepos in stream at audio_chunk_pos - // let's seek! - - // update stream position: - d_audio->pos=audio_chunk_pos; -// d_audio->dpos=apos; -// d_audio->pts=initial_pts_delay+(float)apos/(float)sh_audio->wf->nAvgBytesPerSec; - - if(demuxer->type==DEMUXER_TYPE_AVI){ - // interleaved stream: - if(audio_chunk_pos<video_chunk_pos){ - // calc priv->skip_video_frames & adjust video pts counter: - for(i=audio_chunk_pos;i<video_chunk_pos;i++){ - 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): - 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: - 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; - } - - - - mp_msg(MSGT_SEEK,MSGL_V,"SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n", - 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); - //d_audio->pts=0; // PTS is outdated because of the raw data skipping - } - resync_audio_stream(sh_audio); - -// sh_audio->timer=-skip_audio_secs; - - } - d_video->pts=priv->avi_video_pts; // OSD - -} - - -
--- a/demux_mov.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,613 +0,0 @@ -// QuickTime MOV file parser by A'rpi -// based on TOOLS/movinfo.c by me & Al3x -// compressed header support from moov.c of the openquicktime lib. - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "config.h" - -#ifdef HAVE_PNG -// should be detected by ./configure... -#define HAVE_ZLIB -#endif - -#include "mp_msg.h" -#include "help_mp.h" - -#include "stream.h" -#include "demuxer.h" - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "stheader.h" - -#ifdef HAVE_ZLIB -#include <zlib.h> -#endif - -typedef struct { - unsigned int pts; // duration - unsigned int size; - off_t pos; -} mov_sample_t; - -typedef struct { - unsigned int sample; // number of the first sample in teh chunk - unsigned int size; // number of samples in the chunk - int desc; // for multiple codecs mode - not used - off_t pos; -} mov_chunk_t; - -typedef struct { - unsigned int first; - unsigned int spc; - unsigned int sdid; -} mov_chunkmap_t; - -typedef struct { - unsigned int num; - unsigned int dur; -} mov_durmap_t; - -typedef struct { - int id; - int type; - int pos; - // - int timescale; - unsigned int length; - int samplesize; // 0 = variable - int duration; // 0 = variable - int width,height; // for video - unsigned int fourcc; - // - int tkdata_len; // track data - unsigned char* tkdata; - int stdata_len; // stream data - unsigned char* stdata; - int samples_size; - mov_sample_t* samples; - int chunks_size; - mov_chunk_t* chunks; - int chunkmap_size; - mov_chunkmap_t* chunkmap; - int durmap_size; - mov_durmap_t* durmap; -} mov_track_t; - -void mov_build_index(mov_track_t* trak){ - int i,j,s; - int last=trak->chunks_size; - unsigned int pts=0; - printf("MOV track: %d chunks, %d samples\n",trak->chunks_size,trak->samples_size); - printf("pts=%d scale=%d time=%5.3f\n",trak->length,trak->timescale,(float)trak->length/(float)trak->timescale); - // process chunkmap: - i=trak->chunkmap_size; - while(i>0){ - --i; - for(j=trak->chunkmap[i].first;j<last;j++){ - trak->chunks[j].desc=trak->chunkmap[i].sdid; - trak->chunks[j].size=trak->chunkmap[i].spc; - } - last=trak->chunkmap[i].first; - } - - // calc pts of chunks: - s=0; - for(j=0;j<trak->chunks_size;j++){ - trak->chunks[j].sample=s; - s+=trak->chunks[j].size; - } - - if(!trak->samples_size){ - // constant sampesize - if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){ - trak->duration=trak->durmap[0].dur; - } else printf("*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n"); - return; - } - - // calc pts: - s=0; - for(j=0;j<trak->durmap_size;j++){ - for(i=0;i<trak->durmap[j].num;i++){ - trak->samples[s].pts=pts; - ++s; - pts+=trak->durmap[j].dur; - } - } - - // calc sample offsets - s=0; - for(j=0;j<trak->chunks_size;j++){ - off_t pos=trak->chunks[j].pos; - for(i=0;i<trak->chunks[j].size;i++){ - trak->samples[s].pos=pos; -#if 0 - printf("Sample %5d: pts=%8d off=0x%08X size=%d\n",s, - trak->samples[s].pts, - (int)trak->samples[s].pos, - trak->samples[s].size); -#endif - pos+=trak->samples[s].size; - ++s; - } - } - -} - -#define MOV_MAX_TRACKS 256 - -#define MOV_TRAK_UNKNOWN 0 -#define MOV_TRAK_VIDEO 1 -#define MOV_TRAK_AUDIO 2 - -typedef struct { - off_t moov_start; - off_t moov_end; - off_t mdat_start; - off_t mdat_end; - int track_db; - mov_track_t* tracks[MOV_MAX_TRACKS]; -} mov_priv_t; - -#define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d)) - -int mov_check_file(demuxer_t* demuxer){ - int flags=0; - mov_priv_t* priv=malloc(sizeof(mov_priv_t)); - - mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n"); - - memset(priv,0,sizeof(mov_priv_t)); - demuxer->priv=priv; - - while(1){ - off_t len=stream_read_dword(demuxer->stream); - unsigned int id=stream_read_dword(demuxer->stream); - if(stream_eof(demuxer->stream)) break; // EOF - if(len<8) break; // invalid chunk - switch(id){ - case MOV_FOURCC('m','o','o','v'): - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie header found!\n"); - priv->moov_start=stream_tell(demuxer->stream); - priv->moov_end=priv->moov_start+len-8; - flags|=1; - break; - case MOV_FOURCC('m','d','a','t'): - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie DATA found!\n"); - priv->mdat_start=stream_tell(demuxer->stream); - priv->mdat_end=priv->mdat_start+len-8; - flags|=2; - break; - default: - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",&id,(int)len); - } - if(!stream_skip(demuxer->stream,len-8)) break; - } - - if(flags==1) - mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing data (mdat) chunk! Maybe broken file...\n"); - else if(flags==2) - mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing header (moov/cmov) chunk! Maybe broken file...\n"); - -return (flags==3); -} - -static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ - mov_priv_t* priv=demuxer->priv; - while(1){ - off_t pos; - off_t len; - unsigned int id; - // - pos=stream_tell(demuxer->stream); -// printf("stream_tell==%d\n",pos); - if(pos>=endpos) return; // END - len=stream_read_dword(demuxer->stream); -// printf("len==%d\n",len); - if(len<8) return; // error - len-=8; - id=stream_read_dword(demuxer->stream); - // - mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",&id,(int)len); - // - if(trak){ - switch(id){ - case MOV_FOURCC('t','k','h','d'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sTrack header!\n",level,""); - // read codec data - trak->tkdata_len=len; - trak->tkdata=malloc(trak->tkdata_len); - stream_read(demuxer->stream,trak->tkdata,trak->tkdata_len); - break; - } - case MOV_FOURCC('m','d','h','d'): { - unsigned int tmp; - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia header!\n",level,""); -#if 0 - tmp=stream_read_dword(demuxer->stream); - printf("dword1: 0x%08X (%d)\n",tmp,tmp); - tmp=stream_read_dword(demuxer->stream); - printf("dword2: 0x%08X (%d)\n",tmp,tmp); - tmp=stream_read_dword(demuxer->stream); - printf("dword3: 0x%08X (%d)\n",tmp,tmp); - tmp=stream_read_dword(demuxer->stream); - printf("dword4: 0x%08X (%d)\n",tmp,tmp); - tmp=stream_read_dword(demuxer->stream); - printf("dword5: 0x%08X (%d)\n",tmp,tmp); - tmp=stream_read_dword(demuxer->stream); - printf("dword6: 0x%08X (%d)\n",tmp,tmp); -#endif - stream_skip(demuxer->stream,12); - // read timescale - trak->timescale=stream_read_dword(demuxer->stream); - // read length - trak->length=stream_read_dword(demuxer->stream); - break; - } - case MOV_FOURCC('v','m','h','d'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sVideo header!\n",level,""); - trak->type=MOV_TRAK_VIDEO; - // read video data - break; - } - case MOV_FOURCC('s','m','h','d'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSound header!\n",level,""); - trak->type=MOV_TRAK_AUDIO; - // read audio data - break; - } - case MOV_FOURCC('s','t','s','d'): { - int i=stream_read_dword(demuxer->stream); // temp! - int count=stream_read_dword(demuxer->stream); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sDescription list! (cnt:%d)\n",level,"",count); - for(i=0;i<count;i++){ - off_t pos=stream_tell(demuxer->stream); - off_t len=stream_read_dword(demuxer->stream); - unsigned int fourcc=stream_read_dword_le(demuxer->stream); - if(len<8) break; // error - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*s desc #%d: %.4s",level,"",i,&fourcc); - if(!i){ - trak->fourcc=fourcc; - // read codec data - trak->stdata_len=len-8; - trak->stdata=malloc(trak->stdata_len); - stream_read(demuxer->stream,trak->stdata,trak->stdata_len); - if(trak->type==MOV_TRAK_VIDEO && trak->stdata_len>43){ - mp_msg(MSGT_DEMUX,MSGL_V," '%.*s'",trak->stdata_len-43,trak->stdata+43); - } - } - mp_msg(MSGT_DEMUX,MSGL_V,"\n"); - if(fourcc!=trak->fourcc && i) - mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVvariableFourCC); - if(!stream_seek(demuxer->stream,pos+len)) break; - } - break; - } - case MOV_FOURCC('s','t','t','s'): { - int temp=stream_read_dword(demuxer->stream); - int len=stream_read_dword(demuxer->stream); - int i; - int x=0; - unsigned int pts=0; - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample duration table! (%d blocks)\n",level,"",len); - trak->durmap=malloc(sizeof(mov_durmap_t)*len); - memset(trak->durmap,0,sizeof(mov_durmap_t)*len); - trak->durmap_size=len; - for(i=0;i<len;i++){ - trak->durmap[i].num=stream_read_dword(demuxer->stream); - trak->durmap[i].dur=stream_read_dword(demuxer->stream); - pts+=trak->durmap[i].num*trak->durmap[i].dur; - } - if(trak->length!=pts) printf("Warning! pts=%d length=%d\n",pts,trak->length); - break; - } - case MOV_FOURCC('s','t','s','c'): { - int temp=stream_read_dword(demuxer->stream); - int len=stream_read_dword(demuxer->stream); - int i; - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample->Chunk mapping table! (%d blocks)\n",level,"",len); - // read data: - trak->chunkmap_size=len; - trak->chunkmap=malloc(sizeof(mov_chunkmap_t)*len); - for(i=0;i<len;i++){ - trak->chunkmap[i].first=stream_read_dword(demuxer->stream)-1; - trak->chunkmap[i].spc=stream_read_dword(demuxer->stream); - trak->chunkmap[i].sdid=stream_read_dword(demuxer->stream); - } - break; - } - case MOV_FOURCC('s','t','s','z'): { - int temp=stream_read_dword(demuxer->stream); - int ss=stream_read_dword(demuxer->stream); - int len=stream_read_dword(demuxer->stream); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample size table! len=%d ss=%d\n",level,"",len,ss); - trak->samplesize=ss; - if(!ss){ - // variable samplesize - int i; - trak->samples=realloc(trak->samples,sizeof(mov_sample_t)*len); - trak->samples_size=len; - for(i=0;i<len;i++) - trak->samples[i].size=stream_read_dword(demuxer->stream); - } - break; - } - case MOV_FOURCC('s','t','c','o'): { - int temp=stream_read_dword(demuxer->stream); - int len=stream_read_dword(demuxer->stream); - int i; - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sChunk offset table! (%d chunks)\n",level,"",len); - // extend array if needed: - if(len>trak->chunks_size){ - trak->chunks=realloc(trak->chunks,sizeof(mov_chunk_t)*len); - trak->chunks_size=len; - } - // read elements: - for(i=0;i<len;i++) trak->chunks[i].pos=stream_read_dword(demuxer->stream); - break; - } - case MOV_FOURCC('m','d','i','a'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia stream!\n",level,""); - lschunks(demuxer,level+1,pos+len,trak); - break; - } - case MOV_FOURCC('m','i','n','f'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia info!\n",level,""); - lschunks(demuxer,level+1,pos+len,trak); - break; - } - case MOV_FOURCC('s','t','b','l'): { - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample info!\n",level,""); - lschunks(demuxer,level+1,pos+len,trak); - break; - } - }//switch(id) - } else - if(id==MOV_FOURCC('t','r','a','k')){ -// if(trak) printf("MOV: Warning! trak in trak?\n"); - if(priv->track_db>=MOV_MAX_TRACKS){ - mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk); - return; - } - trak=malloc(sizeof(mov_track_t)); - memset(trak,0,sizeof(mov_track_t)); - mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db); - trak->id=priv->track_db; - priv->tracks[priv->track_db]=trak; - lschunks(demuxer,level+1,pos+len,trak); - mov_build_index(trak); - switch(trak->type){ - case MOV_TRAK_AUDIO: { - sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); - sh->format=trak->fourcc; - printf("!!! audio bits: %d chans: %d\n",trak->stdata[19],trak->stdata[17]); - printf("Fourcc: %.4s\n",&trak->fourcc); - // Emulate WAVEFORMATEX struct: - sh->wf=malloc(sizeof(WAVEFORMATEX)); - memset(sh->wf,0,sizeof(WAVEFORMATEX)); - sh->wf->nChannels=trak->stdata[17]; - sh->wf->wBitsPerSample=trak->stdata[19]; - sh->wf->nSamplesPerSec=trak->timescale; - sh->wf->nAvgBytesPerSec=sh->wf->nChannels*((sh->wf->wBitsPerSample+7)/8)*sh->wf->nSamplesPerSec; - // Selection: - if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ - // (auto)selected audio track: - demuxer->audio->id=priv->track_db; - demuxer->audio->sh=sh; sh->ds=demuxer->audio; - } - break; - } - case MOV_TRAK_VIDEO: { - sh_video_t* sh=new_sh_video(demuxer,priv->track_db); - sh->format=trak->fourcc; - sh->fps=trak->timescale; - sh->frametime=1.0f/sh->fps; - sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); - sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); - - // emulate BITMAPINFOHEADER: - sh->bih=malloc(sizeof(BITMAPINFOHEADER)); - memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); - sh->bih->biSize=40; - sh->bih->biWidth=sh->disp_w; - sh->bih->biHeight=sh->disp_h; - sh->bih->biPlanes=0; - sh->bih->biBitCount=16; - sh->bih->biCompression=trak->fourcc; - sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; - - printf("Image size: %d x %d\n",sh->disp_w,sh->disp_h); - printf("Fourcc: %.4s Codec: '%.*s'\n",&trak->fourcc,trak->stdata_len-43,trak->stdata+43); - - if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ - // (auto)selected video track: - demuxer->video->id=priv->track_db; - demuxer->video->sh=sh; sh->ds=demuxer->video; - } - break; - } - } - printf("--------------\n"); - priv->track_db++; - trak=NULL; - } else -#ifndef HAVE_ZLIB - if(id==MOV_FOURCC('c','m','o','v')){ - mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); - return; - } -#else - if(id==MOV_FOURCC('c','m','o','v')){ -// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); - lschunks(demuxer,level+1,pos+len,NULL); - } else - if(id==MOV_FOURCC('d','c','o','m')){ -// int temp=stream_read_dword(demuxer->stream); - unsigned int len=stream_read_dword(demuxer->stream); - printf("Compressed header uses %.4s algo!\n",&len); - } else - if(id==MOV_FOURCC('c','m','v','d')){ -// int temp=stream_read_dword(demuxer->stream); - unsigned int moov_sz=stream_read_dword(demuxer->stream); - unsigned int cmov_sz=len-4; - unsigned char* cmov_buf=malloc(cmov_sz); - unsigned char* moov_buf=malloc(moov_sz+16); - int zret; - z_stream zstrm; - stream_t* backup; - - printf("Compressed header size: %d / %d\n",cmov_sz,moov_sz); - - stream_read(demuxer->stream,cmov_buf,cmov_sz); - - zstrm.zalloc = (alloc_func)0; - zstrm.zfree = (free_func)0; - zstrm.opaque = (voidpf)0; - zstrm.next_in = cmov_buf; - zstrm.avail_in = cmov_sz; - zstrm.next_out = moov_buf; - zstrm.avail_out = moov_sz; - - zret = inflateInit(&zstrm); - if (zret != Z_OK) - { fprintf(stderr,"QT cmov: inflateInit err %d\n",zret); - return; - } - zret = inflate(&zstrm, Z_NO_FLUSH); - if ((zret != Z_OK) && (zret != Z_STREAM_END)) - { fprintf(stderr,"QT cmov inflate: ERR %d\n",zret); - return; - } -#if 0 - else { - FILE *DecOut; - DecOut = fopen("Out.bin", "w"); - fwrite(moov_buf, 1, moov_sz, DecOut); - fclose(DecOut); - } -#endif - if(moov_sz != zstrm.total_out) printf("Warning! moov size differs cmov: %d zlib: %d\n",moov_sz,zstrm.total_out); - zret = inflateEnd(&zstrm); - - backup=demuxer->stream; - demuxer->stream=new_memory_stream(moov_buf,moov_sz); - stream_skip(demuxer->stream,8); - lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' - //free_stream(demuxer->stream); - demuxer->stream=backup; - - } -#endif - - pos+=len+8; - if(pos>=endpos) break; - if(!stream_seek(demuxer->stream,pos)) break; - } -} - -int mov_read_header(demuxer_t* demuxer){ - mov_priv_t* priv=demuxer->priv; - - printf("mov_read_header!\n"); - - // Parse header: - stream_reset(demuxer->stream); - if(!stream_seek(demuxer->stream,priv->moov_start)) return 0; // ??? - lschunks(demuxer, 0, priv->moov_end, NULL); - -#if 1 - return 1; -#else - mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVnotyetsupp); - return 0; -#endif -} - -// return value: -// 0 = EOF or no stream found -// 1 = successfully read a packet -int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){ - mov_priv_t* priv=demuxer->priv; - mov_track_t* trak=NULL; - float pts; - - if(ds->id<0 || ds->id>=priv->track_db) return 0; - trak=priv->tracks[ds->id]; - -if(trak->samplesize){ - // read chunk: - if(trak->pos>=trak->chunks_size) return 0; // EOF - stream_seek(demuxer->stream,trak->chunks[trak->pos].pos); - pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; - ds_read_packet(ds,demuxer->stream,trak->chunks[trak->pos].size*trak->samplesize,pts,trak->chunks[trak->pos].pos,0); -} else { - // read sample: - if(trak->pos>=trak->samples_size) return 0; // EOF - stream_seek(demuxer->stream,trak->samples[trak->pos].pos); - pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; - ds_read_packet(ds,demuxer->stream,trak->samples[trak->pos].size,pts,trak->samples[trak->pos].pos,0); -} - ++trak->pos; - - return 1; - -} - -static float mov_seek_track(mov_track_t* trak,float pts,int flags){ - -// printf("MOV track seek called %5.3f \n",pts); - if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale; - -if(trak->samplesize){ - int sample=pts/trak->duration; -// printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration); - if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative - trak->pos=0; - while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos; - pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; -} else { - unsigned int ipts=pts; -// printf("MOV track seek - sample: %d \n",ipts); - if(!(flags&1)) ipts+=trak->samples[trak->pos].pts; - trak->pos=0; - while(trak->pos<trak->samples_size && trak->samples[trak->pos].pts<ipts) ++trak->pos; - pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; -} - -// printf("MOV track seek done: %5.3f \n",pts); - -return pts; -} - -void demux_seek_mov(demuxer_t *demuxer,float pts,int flags){ - mov_priv_t* priv=demuxer->priv; - demux_stream_t* ds; - -// printf("MOV seek called %5.3f flag=%d \n",pts,flags); - - ds=demuxer->video; - if(ds && ds->id>=0 && ds->id<priv->track_db){ - mov_track_t* trak=priv->tracks[ds->id]; - //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; - //if(!(flags&1)) pts+=ds->pts; - pts=ds->pts=mov_seek_track(trak,pts,flags); - flags=1; // absolute seconds - } - - ds=demuxer->audio; - if(ds && ds->id>=0 && ds->id<priv->track_db){ - mov_track_t* trak=priv->tracks[ds->id]; - //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; - //if(!(flags&1)) pts+=ds->pts; - ds->pts=mov_seek_track(trak,pts,flags); - } - -} -
--- a/demux_mpg.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,403 +0,0 @@ -// MPG/VOB file parser for DEMUXER v2.5 by A'rpi/ESP-team - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#include "config.h" -#include "dvdauth.h" -#include "stream.h" -#include "demuxer.h" -#include "parse_es.h" - -//#define MAX_PS_PACKETSIZE 2048 -#define MAX_PS_PACKETSIZE (224*1024) - -static int mpeg_pts_error=0; - -static unsigned int read_mpeg_timestamp(stream_t *s,int c){ - int d,e; - unsigned int pts; - d=stream_read_word(s); - e=stream_read_word(s); - if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){ - ++mpeg_pts_error; - return 0; // invalid pts - } - pts=(((c>>1)&7)<<30)|((d>>1)<<15)|(e>>1); - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"{%d}",pts); - return pts; -} - -//static unsigned int packet_start_pos=0; - -//extern void *new_sh_audio(demuxer_t *demux,int id); -//extern void *new_sh_video(demuxer_t *demux,int id); -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "stheader.h" - -static int demux_mpg_read_packet(demuxer_t *demux,int id){ - int d; - int len; -#ifdef HAVE_LIBCSS - int css=0; -#endif - unsigned char c=0; - unsigned int pts=0; - unsigned int dts=0; - demux_stream_t *ds=NULL; - - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id); - -// if(id==0x1F0){ -// demux->synced=0; // force resync after 0x1F0 -// return -1; -//} - -// if(id==0x1BA) packet_start_pos=stream_tell(demux->stream); - if(id<0x1BC || id>=0x1F0) return -1; - if(id==0x1BE) return -1; // padding stream - if(id==0x1BF) return -1; // private2 - - len=stream_read_word(demux->stream); - mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len); -// if(len==62480){ demux->synced=0;return -1;} /* :) */ - if(len==0 || len>MAX_PS_PACKETSIZE){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len); - return -2; // invalid packet !!!!!! - } - - mpeg_pts_error=0; - - while(len>0){ // Skip stuFFing bytes - c=stream_read_char(demux->stream);--len; - if(c!=0xFF)break; - } - if((c>>6)==1){ // Read (skip) STD scale & size value -// printf(" STD_scale=%d",(c>>5)&1); - d=((c&0x1F)<<8)|stream_read_char(demux->stream); - len-=2; -// printf(" STD_size=%d",d); - c=stream_read_char(demux->stream); - } - // Read System-1 stream timestamps: - if((c>>4)==2){ - pts=read_mpeg_timestamp(demux->stream,c); - len-=4; - } else - if((c>>4)==3){ - pts=read_mpeg_timestamp(demux->stream,c); - c=stream_read_char(demux->stream); - if((c>>4)!=1) pts=0; //printf("{ERROR4}"); - dts=read_mpeg_timestamp(demux->stream,c); - len-=4+1+4; - } else - if((c>>6)==2){ - int pts_flags; - int hdrlen; - // System-2 (.VOB) stream: - if((c>>4)&3) { -#ifdef HAVE_LIBCSS - css=1; -#else - mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_EncryptedVOB); -#endif - } - c=stream_read_char(demux->stream); pts_flags=c>>6; - c=stream_read_char(demux->stream); hdrlen=c; - len-=2; - mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len); - if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;} - if(pts_flags==2){ - c=stream_read_char(demux->stream); - pts=read_mpeg_timestamp(demux->stream,c); - len-=5;hdrlen-=5; - } else - if(pts_flags==3){ - c=stream_read_char(demux->stream); - pts=read_mpeg_timestamp(demux->stream,c); - c=stream_read_char(demux->stream); - dts=read_mpeg_timestamp(demux->stream,c); - len-=10;hdrlen-=10; - } - len-=hdrlen; - if(hdrlen>0) stream_skip(demux->stream,hdrlen); // skip header bytes - - //============== DVD Audio sub-stream ====================== - if(id==0x1BD){ - int aid=stream_read_char(demux->stream);--len; - if(len<3) return -1; // invalid audio packet - - // AID: - // 0x20..0x3F subtitle - // 0x80..0x9F AC3 audio - // 0xA0..0xBF PCM audio - - if((aid & 0xE0) == 0x20){ - // subtitle: - aid&=0x1F; - - if(!demux->s_streams[aid]){ - mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid); - demux->s_streams[aid]=1; - } - - if(demux->sub->id==aid){ - ds=demux->sub; - } - - } else if((aid & 0xC0) == 0x80) { - -// aid=128+(aid&0x7F); - // aid=0x80..0xBF - - if(!demux->a_streams[aid]) new_sh_audio(demux,aid); - if(demux->audio->id==-1) demux->audio->id=aid; - - if(demux->audio->id==aid){ -// int type; - ds=demux->audio; - if(!ds->sh) ds->sh=demux->a_streams[aid]; - // READ Packet: Skip additional audio header data: - c=stream_read_char(demux->stream);//type=c; - c=stream_read_char(demux->stream);//type|=c<<8; - c=stream_read_char(demux->stream);//type|=c<<16; -// printf("[%06X]",type); - len-=3; - if((aid&0xE0)==0xA0 && len>=2){ - // read PCM header - int head; - head=stream_read_char(demux->stream); head=c<<8; - c=stream_read_char(demux->stream); head|=c; len-=2; - while(len>0 && head!=0x180){ - head=c<<8; - c=stream_read_char(demux->stream); - head|=c;--len; - } - if(!len) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n"); - } - } // if(demux->audio->id==aid) - - } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid); - - } //if(id==0x1BD) - - } else { - if(c!=0x0f){ - mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c); - return -1; // invalid packet !!!!!! - } - } - if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error); - mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len); - -// if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size - if(len<=0 || len>MAX_PS_PACKETSIZE){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len); - return -1; // invalid packet !!!!!! - } - - if(id>=0x1C0 && id<=0x1DF){ - // mpeg audio - int aid=id-0x1C0; - if(!demux->a_streams[aid]) new_sh_audio(demux,aid); - if(demux->audio->id==-1) demux->audio->id=aid; - if(demux->audio->id==aid){ - ds=demux->audio; - if(!ds->sh) ds->sh=demux->a_streams[aid]; - } - } else - if(id>=0x1E0 && id<=0x1EF){ - // mpeg video - int aid=id-0x1E0; - if(!demux->v_streams[aid]) new_sh_video(demux,aid); - if(demux->video->id==-1) demux->video->id=aid; - if(demux->video->id==aid){ - ds=demux->video; - if(!ds->sh) ds->sh=demux->v_streams[aid]; - } - } - - if(ds){ - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id); -// printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos); -#ifdef HAVE_LIBCSS - if (css) { - if (descrambling) CSSDescramble(demux->stream->buffer,key_title); else - mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_EncryptedVOBauth); - } -#endif - ds_read_packet(ds,demux->stream,len,pts/90000.0f,demux->filepos,0); -// if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len); - return 1; - } - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id); - if(len<=2356) stream_skip(demux->stream,len); - return 0; -} - -int num_elementary_packets100=0; -int num_elementary_packets101=0; -int num_elementary_packets1B6=0; -int num_elementary_packetsPES=0; - -int demux_mpg_es_fill_buffer(demuxer_t *demux){ - // Elementary video stream - if(demux->stream->eof) return 0; - demux->filepos=stream_tell(demux->stream); - ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0); - return 1; -} - -int demux_mpg_fill_buffer(demuxer_t *demux){ -unsigned int head=0; -int skipped=0; -int max_packs=128; -int ret=0; - -// System stream -do{ - demux->filepos=stream_tell(demux->stream); - head=stream_read_dword(demux->stream); - if((head&0xFFFFFF00)!=0x100){ - // sync... - demux->filepos-=skipped; - while(1){ - int c=stream_read_char(demux->stream); - if(c<0) break; //EOF - head<<=8; - if(head!=0x100){ - head|=c; - ++skipped; //++demux->filepos; - continue; - } - head|=c; - break; - } - demux->filepos+=skipped; - } - if(stream_eof(demux->stream)) break; - // sure: head=0x000001XX - mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head); - if(demux->synced==0){ - if(head==0x1BA) demux->synced=1; -#if 0 - else if(head>=0x1C0 && head<=0x1EF){ - demux->synced=2; - mp_msg(MSGT_DEMUX,MSGL_V,"Mpeg PES stream synced at 0x%X (%d)!\n",demux->filepos,demux->filepos); - num_elementary_packets100=0; // requires for re-sync! - num_elementary_packets101=0; // requires for re-sync! - } -#endif - } else - if(demux->synced==1){ - if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){ - demux->synced=2; - mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%X (%d)!\n",demux->filepos,demux->filepos); - num_elementary_packets100=0; // requires for re-sync! - num_elementary_packets101=0; // requires for re-sync! - } else demux->synced=0; - } // else - if(demux->synced==2){ - ret=demux_mpg_read_packet(demux,head); - if(!ret) - if(--max_packs==0){ - demux->stream->eof=1; - mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream); - return 0; - } - } else { - if(head>=0x100 && head<0x1B0){ - if(head==0x100) ++num_elementary_packets100; else - if(head==0x101) ++num_elementary_packets101; - mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head); - } else - if(head>=0x1C0 && head<0x1F0){ - ++num_elementary_packetsPES; - mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head); - } else - if(head==0x1B6) ++num_elementary_packets1B6; -#if 1 - if( ( (num_elementary_packets100>50 && num_elementary_packets101>50) || - (num_elementary_packetsPES>50) ) && skipped>4000000){ - mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n"); - demux->stream->eof=1; - break; - } -#endif - } -} while(ret!=1); - mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped); - if(demux->stream->eof){ - mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n"); - return 0; - } - return 1; -} - -//extern off_t seek_to_byte; - -void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,int flags){ - demux_stream_t *d_audio=demuxer->audio; - demux_stream_t *d_video=demuxer->video; - sh_audio_t *sh_audio=d_audio->sh; - sh_video_t *sh_video=d_video->sh; - - //================= seek in MPEG ========================== - off_t newpos=(flags&1)?demuxer->movi_start:demuxer->filepos; - - if(flags&2){ - // float seek 0..1 - newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs; - } else { - // time seek (secs) - if(!sh_video->i_bps) // unspecified or VBR - newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec - else - newpos+=sh_video->i_bps*rel_seek_secs; - } - - if(newpos<demuxer->movi_start) newpos=demuxer->movi_start; - -#ifdef _LARGEFILE_SOURCE - newpos&=~((long long)STREAM_BUFFER_SIZE-1); /* sector boundary */ -#else - newpos&=~(STREAM_BUFFER_SIZE-1); /* sector boundary */ -#endif - stream_seek(demuxer->stream,newpos); - - // re-sync video: - videobuf_code_len=0; // reset ES stream buffer - - ds_fill_buffer(d_video); - if(sh_audio){ - ds_fill_buffer(d_audio); - resync_audio_stream(sh_audio); - } - - while(1){ - int i; - if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){ - float a_pts=d_audio->pts; - a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; - if(d_video->pts>a_pts){ - skip_audio_frame(sh_audio); // sync audio - continue; - } - } - i=sync_video_packet(d_video); - if(i==0x1B3 || i==0x1B8) break; // found it! - if(!i || !skip_video_packet(d_video)) break; // EOF? - } - - -} -
--- a/demuxer.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,580 +0,0 @@ -//=================== DEMUXER v2.5 ========================= - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/stat.h> - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#include "stream.h" -#include "demuxer.h" - -#include "wine/mmreg.h" -#include "wine/avifmt.h" -#include "wine/vfw.h" - -#include "codec-cfg.h" -#include "stheader.h" - -void free_demuxer_stream(demux_stream_t *ds){ - ds_free_packs(ds); - free(ds); -} - -demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id){ - demux_stream_t* ds=malloc(sizeof(demux_stream_t)); - ds->buffer_pos=ds->buffer_size=0; - ds->buffer=NULL; - ds->pts=0; - ds->pts_bytes=0; - ds->eof=0; - ds->pos=0; - ds->dpos=0; - ds->pack_no=0; -//--------------- - ds->packs=0; - ds->bytes=0; - ds->first=ds->last=NULL; - ds->id=id; - ds->demuxer=demuxer; -//---------------- - ds->asf_seq=-1; - ds->asf_packet=NULL; -//---------------- - ds->sh=NULL; - return ds; -} - -demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id){ - demuxer_t *d=malloc(sizeof(demuxer_t)); - memset(d,0,sizeof(demuxer_t)); - d->stream=stream; - d->movi_start=stream->start_pos; - d->movi_end=stream->end_pos; - d->seekable=1; - d->synced=0; - d->filepos=0; - d->audio=new_demuxer_stream(d,a_id); - d->video=new_demuxer_stream(d,v_id); - d->sub=new_demuxer_stream(d,s_id); - d->type=type; - stream_reset(stream); - stream_seek(stream,stream->start_pos); - return d; -} - -sh_audio_t* new_sh_audio(demuxer_t *demuxer,int id){ - if(demuxer->a_streams[id]){ - mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_AudioStreamRedefined,id); - } else { - mp_msg(MSGT_DEMUXER,MSGL_V,"==> Found audio stream: %d\n",id); - demuxer->a_streams[id]=malloc(sizeof(sh_audio_t)); - memset(demuxer->a_streams[id],0,sizeof(sh_audio_t)); - } - return demuxer->a_streams[id]; -} - -void free_sh_audio(sh_audio_t* sh){ - if(sh->a_in_buffer) free(sh->a_in_buffer); - if(sh->a_buffer) free(sh->a_buffer); - if(sh->wf) free(sh->wf); - free(sh); -} - -sh_video_t* new_sh_video(demuxer_t *demuxer,int id){ - if(demuxer->v_streams[id]){ - mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_VideoStreamRedefined,id); - } else { - mp_msg(MSGT_DEMUXER,MSGL_V,"==> Found video stream: %d\n",id); - demuxer->v_streams[id]=malloc(sizeof(sh_video_t)); - memset(demuxer->v_streams[id],0,sizeof(sh_video_t)); - } - return demuxer->v_streams[id]; -} - -void free_sh_video(sh_video_t* sh){ - if(sh->our_out_buffer) free(sh->our_out_buffer); - if(sh->bih) free(sh->bih); - free(sh); -} - -void free_demuxer(demuxer_t *demuxer){ - int i; - // free streams: - for(i=0;i<256;i++){ - if(demuxer->a_streams[i]) free_sh_audio(demuxer->a_streams[i]); - if(demuxer->v_streams[i]) free_sh_video(demuxer->v_streams[i]); - } - //if(sh_audio) free_sh_audio(sh_audio); - //if(sh_video) free_sh_video(sh_video); - // free demuxers: - free_demuxer_stream(demuxer->audio); - free_demuxer_stream(demuxer->video); - free(demuxer); -} - - -void ds_add_packet(demux_stream_t *ds,demux_packet_t* dp){ -// demux_packet_t* dp=new_demux_packet(len); -// stream_read(stream,dp->buffer,len); -// dp->pts=pts; //(float)pts/90000.0f; -// dp->pos=pos; - // append packet to DS stream: - ++ds->packs; - ds->bytes+=dp->len; - if(ds->last){ - // next packet in stream - ds->last->next=dp; - ds->last=dp; - } else { - // first packet in stream - ds->first=ds->last=dp; - } - mp_dbg(MSGT_DEMUXER,MSGL_DBG2,"DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%u [packs: A=%d V=%d]\n", - (ds==ds->demuxer->audio)?"d_audio":"d_video", - dp->len,dp->pts,(unsigned int)dp->pos,ds->demuxer->audio->packs,ds->demuxer->video->packs); -} - -void ds_read_packet(demux_stream_t *ds,stream_t *stream,int len,float pts,off_t pos,int flags){ - demux_packet_t* dp=new_demux_packet(len); - stream_read(stream,dp->buffer,len); - dp->pts=pts; //(float)pts/90000.0f; - dp->pos=pos; - dp->flags=flags; - // append packet to DS stream: - ds_add_packet(ds,dp); -} - -// return value: -// 0 = EOF or no stream found or invalid type -// 1 = successfully read a packet -int demux_mpg_es_fill_buffer(demuxer_t *demux); -int demux_mpg_fill_buffer(demuxer_t *demux); -int demux_avi_fill_buffer(demuxer_t *demux); -int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t *ds); -int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t *ds); -int demux_asf_fill_buffer(demuxer_t *demux); -int demux_mov_fill_buffer(demuxer_t *demux,demux_stream_t* ds); - -int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){ - // Note: parameter 'ds' can be NULL! -// printf("demux->type=%d\n",demux->type); - switch(demux->type){ - case DEMUXER_TYPE_MPEG_ES: return demux_mpg_es_fill_buffer(demux); - case DEMUXER_TYPE_MPEG_PS: return demux_mpg_fill_buffer(demux); - case DEMUXER_TYPE_AVI: return demux_avi_fill_buffer(demux); - case DEMUXER_TYPE_AVI_NI: return demux_avi_fill_buffer_ni(demux,ds); - case DEMUXER_TYPE_AVI_NINI: return demux_avi_fill_buffer_nini(demux,ds); - case DEMUXER_TYPE_ASF: return demux_asf_fill_buffer(demux); - case DEMUXER_TYPE_MOV: return demux_mov_fill_buffer(demux,ds); - } - return 0; -} - -// return value: -// 0 = EOF -// 1 = succesfull -int ds_fill_buffer(demux_stream_t *ds){ - demuxer_t *demux=ds->demuxer; - if(ds->buffer) free(ds->buffer); - if(verbose>2){ - if(ds==demux->audio) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_audio) called\n");else - if(ds==demux->video) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_video) called\n");else - mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(unknown 0x%X) called\n",(unsigned int)ds); - } - while(1){ - if(ds->packs){ - demux_packet_t *p=ds->first; - // copy useful data: - ds->buffer=p->buffer; - ds->buffer_pos=0; - ds->buffer_size=p->len; - ds->pos=p->pos; - ds->dpos+=p->len; // !!! - ++ds->pack_no; - if(p->pts){ - ds->pts=p->pts; - ds->pts_bytes=0; - } - ds->pts_bytes+=p->len; // !!! - ds->flags=p->flags; - // free packet: - ds->bytes-=p->len; - ds->first=p->next; - if(!ds->first) ds->last=NULL; - free(p); - --ds->packs; - return 1; //ds->buffer_size; - } - if(demux->audio->packs>=MAX_PACKS || demux->audio->bytes>=MAX_PACK_BYTES){ - mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyAudioInBuffer,demux->audio->packs,demux->audio->bytes); - mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI); - break; - } - if(demux->video->packs>=MAX_PACKS || demux->video->bytes>=MAX_PACK_BYTES){ - mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyVideoInBuffer,demux->video->packs,demux->video->bytes); - mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI); - break; - } - if(!demux_fill_buffer(demux,ds)){ - mp_dbg(MSGT_DEMUXER,MSGL_DBG2,"ds_fill_buffer()->demux_fill_buffer() failed\n"); - break; // EOF - } - } - ds->buffer_pos=ds->buffer_size=0; - ds->buffer=NULL; - mp_msg(MSGT_DEMUXER,MSGL_V,"ds_fill_buffer: EOF reached (stream: %s) \n",ds==demux->audio?"audio":"video"); - ds->eof=1; - return 0; -} - -int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len){ -int x; -int bytes=0; -while(len>0){ - x=ds->buffer_size-ds->buffer_pos; - if(x==0){ - if(!ds_fill_buffer(ds)) return bytes; - } else { - if(x>len) x=len; - if(mem) memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x); - bytes+=x;len-=x;ds->buffer_pos+=x; - } -} -return bytes; -} - -int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len){ -int x; -int bytes=0; -while(len>0){ - x=ds->buffer_size-ds->buffer_pos; - if(x==0){ - if(!ds_fill_buffer(ds)) return bytes; - } else { - if(x>len) x=len; - if(mem) memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x); - bytes+=x;len-=x;ds->buffer_pos+=x; - return bytes; // stop at end of package! (for correct timestamping) - } -} -return bytes; -} - - -void ds_free_packs(demux_stream_t *ds){ - demux_packet_t *dp=ds->first; - while(dp){ - demux_packet_t *dn=dp->next; - free(dp->buffer); - free(dp); - dp=dn; - } - if(ds->asf_packet){ - // free unfinished .asf fragments: - free(ds->asf_packet->buffer); - free(ds->asf_packet); - ds->asf_packet=NULL; - } - ds->first=ds->last=NULL; - ds->packs=0; // !!!!! - ds->bytes=0; - if(ds->buffer) free(ds->buffer); - ds->buffer=NULL; - ds->buffer_pos=ds->buffer_size; - ds->pts=0; ds->pts_bytes=0; -} - -int ds_get_packet(demux_stream_t *ds,unsigned char **start){ - while(1){ - int len; - if(ds->buffer_pos>=ds->buffer_size){ - if(!ds_fill_buffer(ds)){ - // EOF - *start = NULL; - return -1; - } - } - len=ds->buffer_size-ds->buffer_pos; - *start = &ds->buffer[ds->buffer_pos]; - ds->buffer_pos+=len; - return len; - } -} - -int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start){ - while(1){ - int len; - if(ds->buffer_pos>=ds->buffer_size){ - *start = NULL; - if(!ds->packs) return -1; // no sub - if(!ds_fill_buffer(ds)) return -1; // EOF - } - len=ds->buffer_size-ds->buffer_pos; - *start = &ds->buffer[ds->buffer_pos]; - ds->buffer_pos+=len; - return len; - } -} - -// ==================================================================== - -// feed-back from demuxers: -extern int num_elementary_packets100; // for MPEG-ES fileformat detection -extern int num_elementary_packets101; -extern int num_elementary_packetsPES; -extern int num_elementary_packets1B6; - -// commandline options, flags: -//extern int seek_to_byte; -extern int force_ni; -extern int pts_from_bps; - -extern int audio_id; -extern int video_id; -extern int dvdsub_id; - -void read_avi_header(demuxer_t *demuxer,int index_mode); -int asf_check_header(demuxer_t *demuxer); -int read_asf_header(demuxer_t *demuxer); -demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id); -demuxer_t* demux_open_avi(demuxer_t* demuxer); -int mov_check_file(demuxer_t* demuxer); -int mov_read_header(demuxer_t* demuxer); - - -demuxer_t* demux_open(stream_t *stream,int file_format,int audio_id,int video_id,int dvdsub_id){ - -//int file_format=(*file_format_ptr); - -demuxer_t *demuxer=NULL; - -demux_stream_t *d_audio=NULL; -demux_stream_t *d_video=NULL; - -sh_audio_t *sh_audio=NULL; -sh_video_t *sh_video=NULL; - -//printf("demux_open(%p,%d,%d,%d,%d) \n",stream,file_format,audio_id,video_id,dvdsub_id); - -//=============== Try to open as AVI file: ================= -if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_AVI){ - demuxer=new_demuxer(stream,DEMUXER_TYPE_AVI,audio_id,video_id,dvdsub_id); - { //---- RIFF header: - int id=stream_read_dword_le(demuxer->stream); // "RIFF" - if(id==mmioFOURCC('R','I','F','F')){ - stream_read_dword_le(demuxer->stream); //filesize - id=stream_read_dword_le(demuxer->stream); // "AVI " - if(id==formtypeAVI){ - mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedAVIfile); - file_format=DEMUXER_TYPE_AVI; - } - } - } -} -//=============== Try to open as ASF file: ================= -if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_ASF){ - demuxer=new_demuxer(stream,DEMUXER_TYPE_ASF,audio_id,video_id,dvdsub_id); - if(asf_check_header(demuxer)){ - mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedASFfile); - file_format=DEMUXER_TYPE_ASF; - } -} -//=============== Try to open as MPEG-PS file: ================= -if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPEG_PS){ - int pes=1; - while(pes>=0){ - demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_PS,audio_id,video_id,dvdsub_id); - if(!pes) demuxer->synced=1; // hack! - num_elementary_packets100=0; - num_elementary_packets101=0; - num_elementary_packets1B6=0; - num_elementary_packetsPES=0; - - if(ds_fill_buffer(demuxer->video)){ - if(!pes) - mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGPESfile); - else - mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGPSfile); - file_format=DEMUXER_TYPE_MPEG_PS; - } else { - // some hack to get meaningfull error messages to our unhappy users: - if(num_elementary_packets100>=2 && num_elementary_packets101>=2 && - abs(num_elementary_packets101-num_elementary_packets100)<8){ - if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4){ - --pes;continue; // tricky... - } - file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :) - } else { - if(demuxer->synced==2) - mp_msg(MSGT_DEMUXER,MSGL_ERR,"MPEG: " MSGTR_MissingVideoStreamBug); - else - mp_msg(MSGT_DEMUXER,MSGL_V,"Not MPEG System Stream format... (maybe Transport Stream?)\n"); - } - } - break; - } -} -//=============== Try to open as MPEG-ES file: ================= -if(file_format==DEMUXER_TYPE_MPEG_ES){ // little hack, see above! - demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_ES,audio_id,video_id,dvdsub_id); - if(!ds_fill_buffer(demuxer->video)){ - mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_InvalidMPEGES); - file_format=DEMUXER_TYPE_UNKNOWN; - } else { - mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGESfile); - } -} -//=============== Try to open as MOV file: ================= -#if 1 -if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MOV){ - demuxer=new_demuxer(stream,DEMUXER_TYPE_MOV,audio_id,video_id,dvdsub_id); - if(mov_check_file(demuxer)){ - mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedQTMOVfile); - file_format=DEMUXER_TYPE_MOV; - } -} -#endif -//=============== Unknown, exiting... =========================== -if(file_format==DEMUXER_TYPE_UNKNOWN){ - mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_FormatNotRecognized); - return NULL; -// GUI_MSG( mplUnknowFileType ) -} -//====== File format recognized, set up these for compatibility: ========= -d_audio=demuxer->audio; -d_video=demuxer->video; -//d_dvdsub=demuxer->sub; - -demuxer->file_format=file_format; - -switch(file_format){ - case DEMUXER_TYPE_MOV: { - if(!mov_read_header(demuxer)) return NULL; -// sh_video=d_video->sh;if(sh_video) sh_video->ds=d_video; -// sh_audio=d_audio->sh;if(sh_audio) sh_audio->ds=d_audio; - break; - } - case DEMUXER_TYPE_AVI: { - return (demuxer_t*) 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->endpos=avi_header.movi_end; - if(!ds_fill_buffer(d_video)){ - mp_msg(MSGT_DEMUXER,MSGL_WARN,"ASF: " MSGTR_MissingVideoStream); - sh_video=NULL; - //printf("ASF: missing video stream!? contact the author, it may be a bug :(\n"); - //GUI_MSG( mplASFErrorMissingVideoStream ) - } else { - sh_video=d_video->sh;sh_video->ds=d_video; - sh_video->fps=1000.0f; sh_video->frametime=0.001f; // 1ms - mp_msg(MSGT_DEMUXER,MSGL_INFO,"VIDEO: [%.4s] %ldx%ld %dbpp\n", - (char *)&sh_video->bih->biCompression, - sh_video->bih->biWidth, - sh_video->bih->biHeight, - sh_video->bih->biBitCount); -// sh_video->i_bps=10*asf_packetsize; // FIXME! - } - if(audio_id!=-2){ - mp_msg(MSGT_DEMUXER,MSGL_V,"ASF: Searching for audio stream (id:%d)\n",d_audio->id); - if(!ds_fill_buffer(d_audio)){ - mp_msg(MSGT_DEMUXER,MSGL_INFO,"ASF: " MSGTR_MissingAudioStream); - sh_audio=NULL; - } else { - sh_audio=d_audio->sh;sh_audio->ds=d_audio; - sh_audio->format=sh_audio->wf->wFormatTag; - } - } - break; - } - case DEMUXER_TYPE_MPEG_ES: { - sh_audio=NULL; // ES streams has no audio channel - d_video->sh=new_sh_video(demuxer,0); // create dummy video stream header, id=0 - sh_video=d_video->sh;sh_video->ds=d_video; - break; - } - case DEMUXER_TYPE_MPEG_PS: { - sh_video=d_video->sh;sh_video->ds=d_video; - if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD - - if(audio_id!=-2) { - if(!ds_fill_buffer(d_audio)){ - mp_msg(MSGT_DEMUXER,MSGL_INFO,"MPEG: " MSGTR_MissingAudioStream); - sh_audio=NULL; - } else { - sh_audio=d_audio->sh;sh_audio->ds=d_audio; - switch(d_audio->id & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id) - case 0x00: sh_audio->format=0x50;break; // mpeg - case 0xA0: sh_audio->format=0x10001;break; // dvd pcm - case 0x80: sh_audio->format=0x2000;break; // ac3 - default: sh_audio=NULL; // unknown type - } - } - } - break; - } -} // switch(file_format) - -return demuxer; -} - -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); -void demux_seek_mov(demuxer_t *demuxer,float pts,int flags); - -int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags){ - demux_stream_t *d_audio=demuxer->audio; - demux_stream_t *d_video=demuxer->video; - sh_audio_t *sh_audio=d_audio->sh; - sh_video_t *sh_video=d_video->sh; - -if(!demuxer->seekable){ - if(demuxer->file_format==DEMUXER_TYPE_AVI) - mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CantSeekRawAVI); - else - mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CantSeekFile); - return 0; -} - - // clear demux buffers: - if(sh_audio){ ds_free_packs(d_audio);sh_audio->a_buffer_len=0;} - ds_free_packs(d_video); - - demuxer->stream->eof=0; // clear eof flag - - if(sh_audio) sh_audio->timer=0; - sh_video->timer=0; // !!!!!! - -switch(demuxer->file_format){ - - case DEMUXER_TYPE_AVI: - demux_seek_avi(demuxer,rel_seek_secs,flags); break; - - case DEMUXER_TYPE_ASF: - demux_seek_asf(demuxer,rel_seek_secs,flags); break; - - case DEMUXER_TYPE_MPEG_ES: - case DEMUXER_TYPE_MPEG_PS: - demux_seek_mpg(demuxer,rel_seek_secs,flags); break; - - case DEMUXER_TYPE_MOV: - demux_seek_mov(demuxer,rel_seek_secs,flags); break; - -} // switch(demuxer->file_format) - -return 1; -} - -
--- a/demuxer.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ - -#include "config.h" - -#define MAX_PACKS 4096 -#define MAX_PACK_BYTES 0x800000 - -#define DEMUXER_TYPE_UNKNOWN 0 -#define DEMUXER_TYPE_MPEG_ES 1 -#define DEMUXER_TYPE_MPEG_PS 2 -#define DEMUXER_TYPE_AVI 3 -#define DEMUXER_TYPE_AVI_NI 4 -#define DEMUXER_TYPE_AVI_NINI 5 -#define DEMUXER_TYPE_ASF 6 -#define DEMUXER_TYPE_MOV 7 - -#define DEMUXER_TIME_NONE 0 -#define DEMUXER_TIME_PTS 1 -#define DEMUXER_TIME_FILE 2 -#define DEMUXER_TIME_BPS 3 - - -// Holds one packet/frame/whatever -typedef struct demux_packet_st { - int len; - float pts; - off_t pos; // position in index (AVI) or file (MPG) - unsigned char* buffer; - int flags; // keyframe, etc - struct demux_packet_st* next; -} demux_packet_t; - -typedef struct { - int buffer_pos; // current buffer position - int buffer_size; // current buffer size - unsigned char* buffer; // current buffer - float pts; // current buffer's pts - int pts_bytes; // number of bytes read after last pts stamp - int eof; // end of demuxed stream? (true if all buffer empty) - off_t pos; // position in the input stream (file) - off_t dpos; // position in the demuxed stream - int pack_no; // serial number of packet - int flags; // flags of current packet (keyframe etc) -//--------------- - int packs; // number of packets in buffer - int bytes; // total bytes of packets in buffer - demux_packet_t *first; // read to current buffer from here - demux_packet_t *last; // append new packets from input stream to here - int id; // stream ID (for multiple audio/video streams) - struct demuxer_st *demuxer; // parent demuxer structure (stream handler) -// ---- asf ----- - demux_packet_t *asf_packet; // read asf fragments here - int asf_seq; -// ---- stream header ---- - void* sh; -} demux_stream_t; - -typedef struct demuxer_st { - stream_t *stream; - int synced; // stream synced (used by mpeg) - 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 - off_t movi_start; - off_t movi_end; - int seekable; // flag - // - demux_stream_t *audio; // audio buffer/demuxer - demux_stream_t *video; // video buffer/demuxer - demux_stream_t *sub; // dvd subtitle buffer/demuxer - - // stream headers: - 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){ - demux_packet_t* dp=malloc(sizeof(demux_packet_t)); - dp->len=len; - dp->buffer=malloc(len); - dp->next=NULL; - dp->pts=0; - dp->pos=0; - dp->flags=0; - return dp; -} - -inline static void free_demux_packet(demux_packet_t* dp){ - free(dp->buffer); - free(dp); -} - -demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id); -demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id); -void free_demuxer_stream(demux_stream_t *ds); -void free_demuxer(demuxer_t *demuxer); - -void ds_add_packet(demux_stream_t *ds,demux_packet_t* dp); -void ds_read_packet(demux_stream_t *ds,stream_t *stream,int len,float pts,off_t pos,int flags); - -int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds); -int ds_fill_buffer(demux_stream_t *ds); - -inline static off_t ds_tell(demux_stream_t *ds){ - return (ds->dpos-ds->buffer_size)+ds->buffer_pos; -} - -inline static int ds_tell_pts(demux_stream_t *ds){ - return (ds->pts_bytes-ds->buffer_size)+ds->buffer_pos; -} - -int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len); -int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len); - -#if 1 -#define demux_getc(ds) (\ - (ds->buffer_pos<ds->buffer_size) ? ds->buffer[ds->buffer_pos++] \ - :((!ds_fill_buffer(ds))? (-1) : ds->buffer[ds->buffer_pos++] ) ) -#else -inline static int demux_getc(demux_stream_t *ds){ - if(ds->buffer_pos>=ds->buffer_size){ - if(!ds_fill_buffer(ds)){ -// printf("DEMUX_GETC: EOF reached!\n"); - return -1; // EOF - } - } -// printf("[%02X]",ds->buffer[ds->buffer_pos]); - return ds->buffer[ds->buffer_pos++]; -} -#endif - -void ds_free_packs(demux_stream_t *ds); -int ds_get_packet(demux_stream_t *ds,unsigned char **start); -int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start); - - -static inline int avi_stream_id(unsigned int id){ - unsigned char *p=(unsigned char *)&id; - unsigned char a,b; -#if WORDS_BIGENDIAN - a=p[3]-'0'; b=p[2]-'0'; -#else - a=p[0]-'0'; b=p[1]-'0'; -#endif - if(a>9 || b>9) return 100; // invalid ID - return a*10+b; -} - -demuxer_t* demux_open(stream_t *stream,int file_format,int aid,int vid,int sid); -int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); - - -
--- a/dvdauth.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -/* (C)2001 by LGB (Gabor Lenart), based on example programs in libcss - lgb@lgb.hu */ - -/* don't do anything with this source if css support was not requested */ -#include "config.h" -#ifdef HAVE_LIBCSS - -#include <stdio.h> -#include <stdlib.h> -//#include <string.h> // FIXME: conflicts with fs.h -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <css.h> -#if CSS_MAJOR_VERSION > 0 || (CSS_MAJOR_VERSION == 0 && CSS_MINOR_VERSION > 1) -# include <dvd.h> -# undef OLD_CSS_API -#else -# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) -# include <sys/dvdio.h> -# elif defined(__linux__) -# include <linux/cdrom.h> -# elif defined(__sun) -# include <sun/dvdio.h> -# else -# error "Need the DVD ioctls" -# endif -# define OLD_CSS_API 1 -#endif - -#include "dvdauth.h" - - -#if OLD_CSS_API -/* - * provide some backward compatibiliy macros to compile this - * code using the old libcss-0.1 - */ -#define DVDHandle int -#define DVDOpenFailed (-1) - -#define DVDAuth(hdl, s) ioctl(hdl, DVD_AUTH, s) -#define DVDOpenDevice(path) open(path, O_RDONLY) -#define DVDCloseDevice(hdl) close(hdl) -#define CSSDVDisEncrypted(hdl) CSSisEncrypted(hdl) -#define CSSDVDAuthDisc CSSAuthDisc -/* Arghhh! Please think before you commit! You forget to check the return - value of path_to_lba (-1 for error) in this way ... - LGB */ -//#define CSSDVDAuthTitlePath(hdl,key_title,path) \ -// CSSAuthTitle(hdl,key_title,path_to_lba(path)) - -#else /*OLD_CSS_API*/ - -#define DVDHandle struct dvd_device * -#define DVDOpenFailed NULL - -#endif /*OLD_CSS_API*/ - - -char *dvd_auth_device=NULL; -char *dvd_device=NULL; -char *dvd_raw_device=NULL; -unsigned char key_disc[2048]; -unsigned char key_title[5]; -unsigned char *dvdimportkey=NULL; -int descrambling=0; - - -#if OLD_CSS_API -/* - * With the old libcss-0.1 api, we have to find out the LBA for - * a title for title authentication. - */ -#ifdef __linux__ -#include <linux/fs.h> - -#ifndef FIBMAP -#define FIBMAP 1 -#endif - -static int path_to_lba (char *path) -{ - int lba = 0; - char cmd[100]; - FILE *fp; - - snprintf(cmd,sizeof(cmd),"fibmap_mplayer %s",path); - fp=popen(cmd,"r"); - if (fp) { - int ret; - bzero(cmd,sizeof(cmd)); - fgets(cmd,99,fp); - if ((ret=pclose(fp))) - fprintf(stderr,"fibmap_mplayer: %s\n",*cmd?cmd:"no error info"); - if(WIFEXITED(ret) && !WEXITSTATUS(ret)) - lba=atoi(cmd); - else - fp=NULL; - } - if (!fp) { - int fd; - printf("fibmap_mplayer could not run, trying with ioctl() ...\n"); - if ((fd = open(path, O_RDONLY)) == -1) { - fprintf(stderr, "Cannot open file %s: %s", - path ? path : "(NULL)", strerror(errno)); - return -1; - } - if (ioctl(fd, FIBMAP, &lba) != 0) { - perror ("ioctl FIBMAP"); - fprintf(stderr,"Hint: run mplayer as root (or better to install fibmap_mplayer as suid root)!\n"); - close(fd); - return -1; - } - close(fd); - } - printf("LBA: %d\n",lba); - return lba; -} - - -int CSSDVDAuthTitlePath(DVDHandle hdl,unsigned char *key_title,char *path) -{ - int lba=path_to_lba(path); - if (lba==-1) return -1; - return CSSAuthTitle(hdl,key_title,lba); -} - - -#else /*linux*/ -static int path_to_lba (char *path) -{ -#warning translating pathname to iso9660 LBA is not supported on this platform - fprintf(stderr, "Translating pathname to iso9660 LBA is not supported on this platform\n"); - return -1; -} -#endif /*linux*/ -#endif /*OLD_CSS_API*/ - - -static void reset_agids ( DVDHandle dvd ) -{ - dvd_authinfo ai; - int i; - for (i = 0; i < 4; i++) { - memset(&ai, 0, sizeof(ai)); - ai.type = DVD_INVALIDATE_AGID; - ai.lsa.agid = i; - DVDAuth(dvd, &ai); - } -} - - -int dvd_import_key ( unsigned char *hexkey ) -{ - unsigned char *t=key_title; - int digit=4,len; - bzero(key_title,sizeof(key_title)); -// printf("DVD key: %s\n",hexkey); - for (len=0;len<10;len++) { -// printf("-> %c\n",*hexkey); - if (!*hexkey) return 1; - if (*hexkey>='A'&&*hexkey<='F') *t|=(*hexkey-'A'+10)<<digit; - else if (*hexkey>='0'&&*hexkey<='9') *t|=(*hexkey-'0')<<digit; - else return 1; - if (digit) digit=0; else { - digit=4; - t++; - } - hexkey++; - } - if (*hexkey) return 1; - printf("DVD key (requested): %02X%02X%02X%02X%02X\n",key_title[0],key_title[1],key_title[2],key_title[3],key_title[4]); - descrambling=1; - return 0; -} - - - -int dvd_auth ( char *dev , char *filename ) -{ - DVDHandle dvd; /* DVD device handle */ - - if ((dvd=DVDOpenDevice(dev)) == DVDOpenFailed) { - fprintf(stderr,"DVD: cannot open DVD device \"%s\": %s.\n", - dev, strerror(errno)); - return 1; - } - - if (!CSSDVDisEncrypted(dvd)) { - printf("DVD is unencrypted! Skipping authentication!\n(note: you should not use -dvd switch for unencrypted discs!)\n"); - DVDCloseDevice(dvd); - return 0; - } else printf("DVD is encrypted, issuing authentication ...\n"); - - /* reset AGIDs */ - reset_agids(dvd); - - /* authenticate disc */ - if (CSSDVDAuthDisc(dvd,key_disc)) { - fprintf(stderr,"DVD: CSSDVDAuthDisc() failed.\n"); - DVDCloseDevice(dvd); - return 1; - } - - if (CSSDVDAuthTitlePath(dvd,key_title,filename)) { - fprintf(stderr,"DVD: CSSDVDAuthTitle() failed.\n"); - DVDCloseDevice(dvd); - return 1; - } - - /* decrypting title */ - if (CSSDecryptTitleKey (key_title, key_disc) < 0) { - fprintf(stderr,"DVD: CSSDecryptTitleKey() failed.\n"); - DVDCloseDevice(dvd); - return 1; - } - - DVDCloseDevice(dvd); - printf("DVD title key is: %02X%02X%02X%02X%02X\n",key_title[0],key_title[1],key_title[2],key_title[3],key_title[4]); - descrambling=1; - return 0; -} - - -#endif
--- a/dvdauth.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -//#include "config.h" -#ifdef HAVE_LIBCSS -#ifndef _MPLAYER_CSS_H -#define _MPLAYER_CSS_H - -extern char *dvd_auth_device; -extern unsigned char key_disc[]; -extern unsigned char key_title[]; -extern unsigned char *dvdimportkey; -extern int descrambling; - -int dvd_auth ( char *, char * ); -int dvd_import_key ( unsigned char * ); - -#endif -#endif
--- a/http.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,296 +0,0 @@ -/* - * HTTP Helper - * by Bertrand Baudet <bertrand_baudet@yahoo.com> - * (C) 2001, MPlayer team. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "http.h" - -HTTP_header_t * -http_new_header() { - HTTP_header_t *http_hdr; - - http_hdr = (HTTP_header_t*)malloc(sizeof(HTTP_header_t)); - if( http_hdr==NULL ) return NULL; - memset( http_hdr, 0, sizeof(HTTP_header_t) ); - - return http_hdr; -} - -void -http_free( HTTP_header_t *http_hdr ) { - int i; - if( http_hdr==NULL ) return; - if( http_hdr->protocol!=NULL ) free( http_hdr->protocol ); - if( http_hdr->uri!=NULL ) free( http_hdr->uri ); - if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase ); - if( http_hdr->body!=NULL ) free( http_hdr->body ); - if( http_hdr->field_search!=NULL ) free( http_hdr->field_search ); - if( http_hdr->method!=NULL ) free( http_hdr->method ); - if( http_hdr->buffer!=NULL ) free( http_hdr->buffer ); - for( i=0 ; i<http_hdr->field_nb ; i++ ) - if( http_hdr->fields[i]!=NULL ) free( http_hdr->fields[i] ); - free( http_hdr ); -} - -int -http_response_append( HTTP_header_t *http_hdr, char *response, int length ) { - char *ptr = NULL; - if( http_hdr==NULL || response==NULL || length<0 ) return -1; - ptr = (char*)malloc( http_hdr->buffer_size+length ); - if( ptr==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - if( http_hdr->buffer_size==0 ) { - // Buffer empty, copy response into it. - memcpy( ptr, response, length ); - http_hdr->buffer_size = length; - } else { - // Buffer not empty, grow buffer, copy and append the response. - memcpy( ptr, http_hdr->buffer, http_hdr->buffer_size ); - free( http_hdr->buffer ); - memcpy( ptr+http_hdr->buffer_size, response, length ); - http_hdr->buffer_size += length; - } - http_hdr->buffer = ptr; - return http_hdr->buffer_size; -} - -int -http_is_header_entired( HTTP_header_t *http_hdr ) { - if( http_hdr==NULL ) return -1; - - if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL ) return 0; - else return 1; -} - -int -http_response_parse( HTTP_header_t *http_hdr ) { - char *hdr_ptr, *ptr; - char *field=NULL; - int pos_hdr_sep, len; - if( http_hdr==NULL ) return -1; - if( http_hdr->is_parsed ) return 0; - - // Get the protocol - hdr_ptr = strstr( http_hdr->buffer, " " ); - if( hdr_ptr==NULL ) { - printf("Malformed answer. No space separator found.\n"); - return -1; - } - len = hdr_ptr-http_hdr->buffer; - http_hdr->protocol = (char*)malloc(len+1); - if( http_hdr->protocol==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - strncpy( http_hdr->protocol, http_hdr->buffer, len ); - http_hdr->protocol[len]='\0'; - if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) { - if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) { - printf("Malformed answer. Unable to get HTTP minor version.\n"); - return -1; - } - } - - // Get the status code - if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) { - printf("Malformed answer. Unable to get status code.\n"); - return -1; - } - hdr_ptr += 4; - - // Get the reason phrase - ptr = strstr( hdr_ptr, "\r\n" ); - if( hdr_ptr==NULL ) { - printf("Malformed answer. Unable to get the reason phrase.\n"); - return -1; - } - len = ptr-hdr_ptr; - http_hdr->reason_phrase = (char*)malloc(len+1); - if( http_hdr->reason_phrase==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - strncpy( http_hdr->reason_phrase, hdr_ptr, len ); - http_hdr->reason_phrase[len]='\0'; - - // Set the position of the header separator: \r\n\r\n - ptr = strstr( http_hdr->buffer, "\r\n\r\n" ); - if( ptr==NULL ) { - printf("Header may be incomplete. No CRLF CRLF found.\n"); - return -1; - } - pos_hdr_sep = ptr-http_hdr->buffer; - - hdr_ptr = strstr( http_hdr->buffer, "\r\n" )+2; - do { - ptr = strstr( hdr_ptr, "\r\n"); - if( ptr==NULL ) { - printf("No CRLF found\n"); - return -1; - } - len = ptr-hdr_ptr; - field = (char*)realloc(field, len+1); - if( field==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - strncpy( field, hdr_ptr, len ); - field[len]='\0'; - http_set_field( http_hdr, field ); - hdr_ptr = ptr+2; - } while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) ); - - if( field!=NULL ) free( field ); - - if( pos_hdr_sep+4<http_hdr->buffer_size ) { - // Response has data! - int data_length = http_hdr->buffer_size-(pos_hdr_sep+4); - http_hdr->body = (char*)malloc( data_length ); - if( http_hdr->body==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - memcpy( http_hdr->body, http_hdr->buffer+pos_hdr_sep+4, data_length ); - http_hdr->body_size = data_length; - } - - http_hdr->is_parsed = 1; - return 0; -} - -char * -http_build_request( HTTP_header_t *http_hdr ) { - char *ptr; - int i; - int len; - if( http_hdr==NULL ) return NULL; - - if( http_hdr->method==NULL ) http_set_method( http_hdr, "GET"); - if( http_hdr->uri==NULL ) http_set_uri( http_hdr, "/"); - - // Compute the request length - len = strlen(http_hdr->method)+strlen(http_hdr->uri)+12; // Method line - for( i=0 ; i<http_hdr->field_nb ; i++ ) // Fields - len += strlen(http_hdr->fields[i])+2; - len += 2; // CRLF - if( http_hdr->body!=NULL ) { - len += http_hdr->body_size; - } - if( http_hdr->buffer!=NULL ) { - free( http_hdr->buffer ); - http_hdr->buffer = NULL; - } - http_hdr->buffer = (char*)malloc(len); - if( http_hdr->buffer==NULL ) { - printf("Memory allocation failed\n"); - return NULL; - } - http_hdr->buffer_size = len; - - ptr = http_hdr->buffer; - ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, http_hdr->uri, http_hdr->http_minor_version ); - for( i=0 ; i<http_hdr->field_nb ; i++ ) - ptr += sprintf( ptr, "%s\r\n", http_hdr->fields[i] ); - ptr += sprintf( ptr, "\r\n" ); - if( http_hdr->body!=NULL ) { - memcpy( ptr, http_hdr->body, http_hdr->body_size ); - } - return http_hdr->buffer; -} - -char * -http_get_field( HTTP_header_t *http_hdr, const char *field_name ) { - if( http_hdr==NULL || field_name==NULL ) return NULL; - http_hdr->search_pos = 0; - if( http_hdr->field_search!=NULL ) free( http_hdr->field_search ); - http_hdr->field_search = (char*)malloc(strlen(field_name)+1); - if( http_hdr->field_search==NULL ) { - printf("Memory allocation failed\n"); - return NULL; - } - strcpy( http_hdr->field_search, field_name ); - return http_get_next_field( http_hdr ); -} - -char * -http_get_next_field( HTTP_header_t *http_hdr ) { - char *ptr; - int i; - if( http_hdr==NULL ) return NULL; - - for( i=http_hdr->search_pos ; i<http_hdr->field_nb ; i++ ) { - ptr = strstr( http_hdr->fields[i], ":" ); - if( ptr==NULL ) return NULL; - if( !strncasecmp( http_hdr->fields[i], http_hdr->field_search, ptr-http_hdr->fields[i] ) ) { - ptr++; // Skip the column - while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some - http_hdr->search_pos = i+1; - return ptr; // return the value without the field name - } - } - return NULL; -} - -void -http_set_field( HTTP_header_t *http_hdr, const char *field ) { - int pos; - if( http_hdr==NULL || field==NULL ) return; - - pos = http_hdr->field_nb; - - http_hdr->fields[pos] = (char*)malloc(strlen(field)+1); - if( http_hdr->fields[pos]==NULL ) { - printf("Memory allocation failed\n"); - return; - } - http_hdr->field_nb++; - strcpy( http_hdr->fields[pos], field ); -} - -void -http_set_method( HTTP_header_t *http_hdr, const char *method ) { - if( http_hdr==NULL || method==NULL ) return; - - http_hdr->method = (char*)malloc(strlen(method)+1); - if( http_hdr->method==NULL ) { - printf("Memory allocation failed\n"); - return; - } - strcpy( http_hdr->method, method ); -} - -void -http_set_uri( HTTP_header_t *http_hdr, const char *uri ) { - if( http_hdr==NULL || uri==NULL ) return; - - http_hdr->uri = (char*)malloc(strlen(uri)+1); - if( http_hdr->uri==NULL ) { - printf("Memory allocation failed\n"); - return; - } - strcpy( http_hdr->uri, uri ); -} - -void -http_debug_hdr( HTTP_header_t *http_hdr ) { - int i; - if( http_hdr==NULL ) return; - - printf("protocol: %s\n", http_hdr->protocol ); - printf("http minor version: %d\n", http_hdr->http_minor_version ); - printf("uri: %s\n", http_hdr->uri ); - printf("method: %s\n", http_hdr->method ); - printf("status code: %d\n", http_hdr->status_code ); - printf("reason phrase: %s\n", http_hdr->reason_phrase ); - - printf("Fields:\n"); - for( i=0 ; i<http_hdr->field_nb ; i++ ) - printf(" %d - %s\n", i, http_hdr->fields[i] ); -}
--- a/http.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * HTTP Helper - * by Bertrand Baudet <bertrand_baudet@yahoo.com> - * (C) 2001, MPlayer team. - */ - -#ifndef __HTTP_H -#define __HTTP_H - -#define HTTP_FIELD_MAX 20 - -typedef struct { - char *protocol; - char *method; - char *uri; - int status_code; - char *reason_phrase; - int http_minor_version; - char *fields[HTTP_FIELD_MAX]; - int field_nb; - char *field_search; - int search_pos; - char *body; - int body_size; - char *buffer; - int buffer_size; - int is_parsed; -} HTTP_header_t; - -HTTP_header_t* http_new_header(); -void http_free( HTTP_header_t *http_hdr ); -int http_response_append( HTTP_header_t *http_hdr, char *data, int length ); -int http_response_parse( HTTP_header_t *http_hdr ); -int http_is_header_entired( HTTP_header_t *http_hdr ); -char* http_build_request( HTTP_header_t *http_hdr ); -char* http_get_field( HTTP_header_t *http_hdr, const char *field_name ); -char* http_get_next_field( HTTP_header_t *http_hdr ); -void http_set_field( HTTP_header_t *http_hdr, const char *field ); -void http_set_method( HTTP_header_t *http_hdr, const char *method ); -void http_set_uri( HTTP_header_t *http_hdr, const char *uri ); - -void http_debug_hdr( HTTP_header_t *http_hdr ); - -#endif // __HTTP_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/asf.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,200 @@ +#ifndef __ASF_H +#define __ASF_H + +#include "config.h" /* for WORDS_BIGENDIAN */ +#include <inttypes.h> +#include "bswap.h" +#ifdef STREAMING +#include "network.h" +#endif + +#ifndef MIN +#define MIN(a,b) ((a<b)?a:b) +#endif + +/////////////////////// +// MS GUID definition +/////////////////////// +#ifndef GUID_DEFINED +#define GUID_DEFINED +// Size of GUID is 16 bytes! +typedef struct __attribute__((packed)) { + uint32_t Data1; // 4 bytes + uint16_t Data2; // 2 bytes + uint16_t Data3; // 2 bytes + uint8_t Data4[8]; // 8 bytes +} GUID_t; +#endif + +/////////////////////// +// ASF Object Header +/////////////////////// +typedef struct __attribute__((packed)) { + uint8_t guid[16]; + uint64_t size; +} ASF_obj_header_t; + +//////////////// +// ASF Header +//////////////// +typedef struct __attribute__((packed)) { + ASF_obj_header_t objh; + uint32_t cno; // number of subchunks + uint8_t v1; // unknown (0x01) + uint8_t v2; // unknown (0x02) +} ASF_header_t; + +///////////////////// +// ASF File Header +///////////////////// +typedef struct __attribute__((packed)) { + uint8_t client[16]; // Client GUID + uint64_t file_size; + uint64_t creat_time; //File creation time FILETIME 8 + uint64_t packets; //Number of packets UINT64 8 + uint64_t end_timestamp; //Timestamp of the end position UINT64 8 + uint64_t duration; //Duration of the playback UINT64 8 + uint32_t start_timestamp; //Timestamp of the start position UINT32 4 + uint32_t unk1; //Unknown, maybe reserved ( usually contains 0 ) UINT32 4 + uint32_t flags; //Unknown, maybe flags ( usually contains 2 ) UINT32 4 + uint32_t packetsize; //Size of packet, in bytes UINT32 4 + uint32_t packetsize2; //Size of packet ( confirm ) UINT32 4 + uint32_t frame_size; //Size of uncompressed video frame UINT32 4 +} ASF_file_header_t; + +/////////////////////// +// ASF Stream Header +/////////////////////// +typedef struct __attribute__((packed)) { + uint8_t type[16]; // Stream type (audio/video) GUID 16 + uint8_t concealment[16]; // Audio error concealment type GUID 16 + uint64_t unk1; // Unknown, maybe reserved ( usually contains 0 ) UINT64 8 + uint32_t type_size; //Total size of type-specific data UINT32 4 + uint32_t stream_size; //Size of stream-specific data UINT32 4 + uint16_t stream_no; //Stream number UINT16 2 + uint32_t unk2; //Unknown UINT32 4 +} ASF_stream_header_t; + +/////////////////////////// +// ASF Content Description +/////////////////////////// +typedef struct __attribute__((packed)) { + uint16_t title_size; + uint16_t author_size; + uint16_t copyright_size; + uint16_t comment_size; + uint16_t rating_size; +} ASF_content_description_t; + +//////////////////////// +// ASF Segment Header +//////////////////////// +typedef struct __attribute__((packed)) { + uint8_t streamno; + uint8_t seq; + uint32_t x; + uint8_t flag; +} ASF_segmhdr_t; + +////////////////////// +// ASF Stream Chunck +////////////////////// +typedef struct __attribute__((packed)) { + uint16_t type; + uint16_t size; + uint32_t sequence_number; + uint16_t unknown; + uint16_t size_confirm; +} ASF_stream_chunck_t; + + +// Definition of the differents type of ASF streaming +typedef enum { + ASF_Unknown_e, + ASF_Live_e, + ASF_Prerecorded_e, + ASF_Redirector_e +} ASF_StreamType_e; + + +/* + * Some macros to swap little endian structures read from an ASF file + * into machine endian format + */ +#ifdef WORDS_BIGENDIAN +#define le2me_ASF_obj_header_t(h) { \ + (h)->size = le2me_64((h)->size); \ +} +#define le2me_ASF_header_t(h) { \ + le2me_ASF_obj_header_t(&(h)->objh); \ + (h)->cno = le2me_32((h)->cno); \ +} +#define le2me_ASF_stream_header_t(h) { \ + (h)->unk1 = le2me_64((h)->unk1); \ + (h)->type_size = le2me_32((h)->type_size); \ + (h)->stream_size = le2me_32((h)->stream_size); \ + (h)->stream_no = le2me_16((h)->stream_no); \ + (h)->unk2 = le2me_32((h)->unk2); \ +} +#define le2me_ASF_file_header_t(h) { \ + (h)->file_size = le2me_64((h)->file_size); \ + (h)->creat_time = le2me_64((h)->creat_time); \ + (h)->packets = le2me_64((h)->packets); \ + (h)->end_timestamp = le2me_64((h)->end_timestamp); \ + (h)->duration = le2me_64((h)->duration); \ + (h)->start_timestamp = le2me_32((h)->start_timestamp); \ + (h)->unk1 = le2me_32((h)->unk1); \ + (h)->flags = le2me_32((h)->flags); \ + (h)->packetsize = le2me_32((h)->packetsize); \ + (h)->packetsize2 = le2me_32((h)->packetsize2); \ + (h)->frame_size = le2me_32((h)->frame_size); \ +} +#define le2me_ASF_content_description_t(h) { \ + (h)->title_size = le2me_16((h)->title_size); \ + (h)->author_size = le2me_16((h)->author_size); \ + (h)->copyright_size = le2me_16((h)->copyright_size); \ + (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 + + +#ifdef STREAMING +int asf_http_streaming_type(char *content_type, char *features); +int asf_http_streaming_start( streaming_ctrl_t *streaming_ctrl ); +int asf_http_streaming_read( streaming_ctrl_t *streaming_ctrl ); + +int asf_streaming(char *data, int length, int *drop_packet ); +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/asf_streaming.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,353 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "url.h" +#include "http.h" +#include "asf.h" +#include "network.h" + +#include "stream.h" +//#include "demuxer.h" + +//extern demuxer_t *demuxer; + +static ASF_StreamType_e streaming_type = ASF_Unknown_e; + +int +asf_http_streaming_read( streaming_ctrl_t *streaming_ctrl ) { + char *buffer; + int drop_packet; + int ret; +printf("asf_streaming_read\n"); + ret = asf_streaming( streaming_ctrl->buffer->buffer, streaming_ctrl->buffer->length, &drop_packet ); +printf("ret: %d\n", ret); + if( ret<0 ) return -1; + if( ret>streaming_ctrl->buffer->length ) return 0; + buffer = (char*)malloc(ret); + if( buffer==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } +printf("buffer length: %d\n", streaming_ctrl->buffer->length ); + net_fifo_pop( streaming_ctrl->buffer, buffer, ret ); +printf(" pop: 0x%02X\n", *((unsigned int*)buffer) ); +printf("buffer length: %d\n", streaming_ctrl->buffer->length ); +printf("0x%02X\n", *((unsigned int*)(buffer+sizeof(ASF_stream_chunck_t))) ); + if( !drop_packet ) { + write( streaming_ctrl->fd_pipe_in, buffer+sizeof(ASF_stream_chunck_t), ret-sizeof(ASF_stream_chunck_t) ); + } + free( buffer ); + return ret; +} + +int +asf_streaming(char *data, int length, int *drop_packet ) { + ASF_stream_chunck_t *stream_chunck=(ASF_stream_chunck_t*)data; + printf("ASF stream chunck size=%d\n", stream_chunck->size); +printf("length: %d\n", length ); +printf("0x%02X\n", stream_chunck->type ); + + if( drop_packet!=NULL ) *drop_packet = 0; + if( data==NULL || length<=0 ) return -1; + + if( stream_chunck->size<8 ) { + printf("Ahhhh, stream_chunck size is too small: %d\n", stream_chunck->size); + return -1; + } + if( stream_chunck->size!=stream_chunck->size_confirm ) { + printf("size_confirm mismatch!: %d %d\n", stream_chunck->size, stream_chunck->size_confirm); + return -1; + } + + printf(" type: 0x%02X\n", stream_chunck->type ); + printf(" size: %d (0x%02X)\n", stream_chunck->size, stream_chunck->size ); + printf(" sequence_number: 0x%04X\n", stream_chunck->sequence_number ); + printf(" unknown: 0x%02X\n", stream_chunck->unknown ); + printf(" size_confirm: 0x%02X\n", stream_chunck->size_confirm ); + + + switch(stream_chunck->type) { + case 0x4324: // Clear ASF configuration + printf("=====> Clearing ASF stream configuration!\n"); + if( drop_packet!=NULL ) *drop_packet = 1; + return stream_chunck->size; + break; + case 0x4424: // Data follows + printf("=====> Data follows\n"); + break; + case 0x4524: // Transfer complete + printf("=====> Transfer complete\n"); + if( drop_packet!=NULL ) *drop_packet = 1; + return stream_chunck->size; + break; + case 0x4824: // ASF header chunk follows + printf("=====> ASF header chunk follows\n"); + break; + default: + printf("=====> Unknown stream type 0x%x\n", stream_chunck->type ); + } + return stream_chunck->size+4; +} + +int +asf_http_streaming_type(char *content_type, char *features) { + if( content_type==NULL ) return ASF_Unknown_e; + if( !strcasecmp(content_type, "application/octet-stream") ) { + if( features==NULL ) { + printf("=====> ASF Prerecorded\n"); + return ASF_Prerecorded_e; + } else if( strstr(features, "broadcast")) { + printf("=====> ASF Live stream\n"); + return ASF_Live_e; + } else { + printf("=====> ASF Prerecorded\n"); + return ASF_Prerecorded_e; + } + } else { + if( (!strcasecmp(content_type, "audio/x-ms-wax")) || + (!strcasecmp(content_type, "audio/x-ms-wma")) || + (!strcasecmp(content_type, "video/x-ms-asf")) || + (!strcasecmp(content_type, "video/x-ms-afs")) || + (!strcasecmp(content_type, "video/x-ms-wvx")) || + (!strcasecmp(content_type, "video/x-ms-wmv")) || + (!strcasecmp(content_type, "video/x-ms-wma")) ) { + printf("=====> ASF Redirector\n"); + return ASF_Redirector_e; + } else { + printf("=====> ASF unknown content-type: %s\n", content_type ); + return ASF_Unknown_e; + } + } + return ASF_Unknown_e; +} + +HTTP_header_t * +asf_http_request(URL_t *url) { + HTTP_header_t *http_hdr; + char str[250]; + char *ptr; + char *request; + int i; + + int offset_hi=0, offset_lo=0, req_nb=1, length=0; + int asf_nb_stream; + + // Common header for all requests. + http_hdr = http_new_header(); + http_set_uri( http_hdr, url->file ); + http_set_field( http_hdr, "Accept: */*" ); + http_set_field( http_hdr, "User-Agent: NSPlayer/4.1.0.3856" ); + sprintf( str, "Host: %s:%d", url->hostname, url->port ); + http_set_field( http_hdr, str ); + http_set_field( http_hdr, "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}" ); + sprintf(str, + "Pragma: no-cache,rate=1.000000,stream-time=0,stream-offset=%u:%u,request-context=%d,max-duration=%u", + offset_hi, offset_lo, req_nb, length ); + http_set_field( http_hdr, str ); + + switch( streaming_type ) { + case ASF_Live_e: + case ASF_Prerecorded_e: + http_set_field( http_hdr, "Pragma: xPlayStrm=1" ); + ptr = str; + ptr += sprintf( ptr, "Pragma: stream-switch-entry="); + +// FIXME: why do you need demuxer here? if you really need it, pass it as +// parameter. -- A'rpi + +#if 0 + for( i=0, asf_nb_stream=0 ; i<256 ; i++ ) { + // FIXME START + if( demuxer==NULL ) { + ptr += sprintf( ptr, " ffff:1:0" ); + asf_nb_stream = 1; + break; + } + // FIXME END + if( demuxer->a_streams[i] ) { + ptr += sprintf( ptr, " ffff:%d:0", i ); + asf_nb_stream++; + } + if( demuxer->v_streams[i] ) { + ptr += sprintf( ptr, " ffff:%d:0", i ); + asf_nb_stream++; + } + } +#endif + http_set_field( http_hdr, str ); + sprintf( str, "Pragma: stream-switch-count=%d", asf_nb_stream ); + http_set_field( http_hdr, str ); + break; + case ASF_Redirector_e: + break; + case ASF_Unknown_e: + // First request goes here. + break; + default: + printf("Unknown asf stream type\n"); + } + + http_set_field( http_hdr, "Connection: Close" ); + http_build_request( http_hdr ); + + return http_hdr; +} + +int +asf_http_parse_response( HTTP_header_t *http_hdr ) { + char *content_type, *pragma; + char features[64] = "\0"; + int len; + if( http_response_parse(http_hdr)<0 ) { + printf("Failed to parse HTTP response\n"); + return -1; + } + if( http_hdr->status_code!=200 ) { + printf("Server return %d:%s\n", http_hdr->status_code, http_hdr->reason_phrase); + return -1; + } + + content_type = http_get_field( http_hdr, "Content-Type"); + + pragma = http_get_field( http_hdr, "Pragma"); + while( pragma!=NULL ) { + char *comma_ptr=NULL; + char *end; + // The pragma line can get severals attributes + // separeted with a comma ','. + do { + if( !strncasecmp( pragma, "features=", 9) ) { + pragma += 9; + end = strstr( pragma, "," ); + if( end==NULL ) { + len = strlen(pragma); + } + len = MIN(end-pragma,sizeof(features)); + strncpy( features, pragma, len ); + features[len]='\0'; + break; + } + comma_ptr = strstr( pragma, "," ); + if( comma_ptr!=NULL ) { + pragma = comma_ptr+1; + if( pragma[0]==' ' ) pragma++; + } + } while( comma_ptr!=NULL ); + pragma = http_get_next_field( http_hdr ); + } + + streaming_type = asf_http_streaming_type( content_type, features ); + + if( http_hdr->body_size>0 ) { + asf_streaming( http_hdr->body, http_hdr->body_size, NULL); + } + + return 0; +} + +URL_t * +asf_http_ASX_redirect( HTTP_header_t *http_hdr ) { + URL_t *url_redirect=NULL; + printf("=========>> ASX parser not yet implemented <<==========\n"); + + printf("ASX=[%s]\n", http_hdr->body ); + + return url_redirect; +} + +int +asf_http_streaming_start( streaming_ctrl_t *streaming_ctrl ) { + HTTP_header_t *http_hdr=NULL; + URL_t *url_next=NULL; + URL_t *url = *(streaming_ctrl->url); + char buffer[BUFFER_SIZE]; + int i; + int fd = streaming_ctrl->fd_net; + int done=1; + +streaming_type = ASF_Live_e; + do { + if( fd>0 ) close( fd ); + + fd = connect2Server( url->hostname, url->port ); + if( fd<0 ) return -1; + + http_hdr = asf_http_request( url ); +printf("[%s]\n", http_hdr->buffer ); + write( fd, http_hdr->buffer, http_hdr->buffer_size ); +// http_free( http_hdr ); + + http_hdr = http_new_header(); + do { + i = readFromServer( fd, buffer, BUFFER_SIZE ); +printf("read: %d\n", i ); + if( i<0 ) { + perror("read"); + http_free( http_hdr ); + return -1; + } + http_response_append( http_hdr, buffer, i ); + } while( !http_is_header_entired( http_hdr ) ); +//http_hdr->buffer[http_hdr->buffer_len]='\0'; +//printf("[%s]\n", http_hdr->buffer ); + if( asf_http_parse_response(http_hdr)<0 ) { + printf("Failed to parse header\n"); + http_free( http_hdr ); + return -1; + } + switch( streaming_type ) { + case ASF_Live_e: + case ASF_Prerecorded_e: + if( http_hdr->body_size>0 ) { +printf("--- 0x%02X\n", streaming_ctrl->buffer ); + net_fifo_push( streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size ); + } else { + ASF_stream_chunck_t *ptr; + int ret; + i = readFromServer( fd, buffer, sizeof(ASF_stream_chunck_t) ); +printf("read: %d\n", i ); + ret = asf_streaming( buffer, i, NULL ); + net_fifo_push( streaming_ctrl->buffer, buffer, i ); + ptr = (ASF_stream_chunck_t*)buffer; + if( ret==ptr->size ) { + } + } +// done = 0; + break; + case ASF_Redirector_e: + url_next = asf_http_ASX_redirect( http_hdr ); + if( url_next==NULL ) { + printf("Failed to parse ASX file\n"); + close(fd); + http_free( http_hdr ); + return -1; + } + if( url_next->port==0 ) url_next->port=80; + url_free( url ); + url = url_next; + *(streaming_ctrl->url) = url_next; + url_next = NULL; + break; + case ASF_Unknown_e: + default: + printf("Unknown ASF streaming type\n"); + close(fd); + http_free( http_hdr ); + return -1; + } + + // Check if we got a redirect. + } while(!done); + + streaming_ctrl->fd_net = fd; + streaming_ctrl->streaming_read = asf_http_streaming_read; + streaming_ctrl->prebuffer_size = 10000; + streaming_ctrl->buffering = 1; + streaming_ctrl->status = streaming_playing_e; + + http_free( http_hdr ); + return fd; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/asfheader.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,279 @@ +// .asf fileformat docs from http://divx.euro.ru + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +extern int verbose; // defined in mplayer.c + +#include "config.h" +#include "mp_msg.h" + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "stheader.h" +//#include "aviheader.h" +#include "asf.h" + +#ifdef ARCH_X86 +#define ASF_LOAD_GUID_PREFIX(guid) (*(uint32_t *)(guid)) +#else +#define ASF_LOAD_GUID_PREFIX(guid) \ + ((guid)[3] << 24 | (guid)[2] << 16 | (guid)[1] << 8 | (guid)[0]) +#endif + +#define ASF_GUID_PREFIX_audio_stream 0xF8699E40 +#define ASF_GUID_PREFIX_video_stream 0xBC19EFC0 +#define ASF_GUID_PREFIX_audio_conceal_none 0x49f1a440 +#define ASF_GUID_PREFIX_audio_conceal_interleave 0xbfc3cd50 +#define ASF_GUID_PREFIX_header 0x75B22630 +#define ASF_GUID_PREFIX_data_chunk 0x75b22636 +#define ASF_GUID_PREFIX_index_chunk 0x33000890 +#define ASF_GUID_PREFIX_stream_header 0xB7DC0791 +#define ASF_GUID_PREFIX_header_2_0 0xD6E229D1 +#define ASF_GUID_PREFIX_file_header 0x8CABDCA1 +#define ASF_GUID_PREFIX_content_desc 0x75b22633 + + +static ASF_header_t asfh; +static ASF_obj_header_t objh; +static ASF_file_header_t fileh; +static ASF_stream_header_t streamh; +static ASF_content_description_t contenth; + +unsigned char* asf_packet=NULL; +int asf_scrambling_h=1; +int asf_scrambling_w=1; +int asf_scrambling_b=1; +int asf_packetsize=0; + +//int i; + +// the variable string is modify in this function +void pack_asf_string(char* string, int length) { + int i,j; + if( string==NULL ) return; + for( i=0, j=0; i<length && string[i]!='\0'; i+=2, j++) { + string[j]=string[i]; + } + string[j]='\0'; +} + +// the variable string is modify in this function +void print_asf_string(const char* name, char* string, int length) { + pack_asf_string(string, length); + mp_msg(MSGT_HEADER,MSGL_V,"%s%s\n", name, string); +} + +static char* asf_chunk_type(unsigned char* guid) { + static char tmp[60]; + char *p; + int i; + + switch(ASF_LOAD_GUID_PREFIX(guid)){ + case ASF_GUID_PREFIX_audio_stream: + return "guid_audio_stream"; + case ASF_GUID_PREFIX_video_stream: + return "guid_video_stream"; + case ASF_GUID_PREFIX_audio_conceal_none: + return "guid_audio_conceal_none"; + case ASF_GUID_PREFIX_audio_conceal_interleave: + return "guid_audio_conceal_interleave"; + case ASF_GUID_PREFIX_header: + return "guid_header"; + case ASF_GUID_PREFIX_data_chunk: + return "guid_data_chunk"; + case ASF_GUID_PREFIX_index_chunk: + return "guid_index_chunk"; + case ASF_GUID_PREFIX_stream_header: + return "guid_stream_header"; + case ASF_GUID_PREFIX_header_2_0: + return "guid_header_2_0"; + case ASF_GUID_PREFIX_file_header: + return "guid_file_header"; + case ASF_GUID_PREFIX_content_desc: + return "guid_content_desc"; + default: + strcpy(tmp, "unknown guid "); + p = tmp + strlen(tmp); + for (i = 0; i < 16; i++) { + if ((1 << i) & ((1<<4) | (1<<6) | (1<<8))) *p++ = '-'; + sprintf(p, "%02x", guid[i]); + p += 2; + } + return tmp; + } +} + +int asf_check_header(demuxer_t *demuxer){ + unsigned char asfhdrguid[16]={0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C}; + stream_read(demuxer->stream,(char*) &asfh,sizeof(asfh)); // header obj + le2me_ASF_header_t(&asfh); // swap to machine endian +// for(i=0;i<16;i++) printf(" %02X",temp[i]);printf("\n"); +// for(i=0;i<16;i++) printf(" %02X",asfhdrguid[i]);printf("\n"); + if(memcmp(asfhdrguid,asfh.objh.guid,16)){ + mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: not ASF guid!\n"); + return 0; // not ASF guid + } + if(asfh.cno>256){ + mp_msg(MSGT_HEADER,MSGL_V,"ASF_check: invalid subchunks_no %d\n",(int) asfh.cno); + return 0; // invalid header??? + } + return 1; +} + +extern void print_wave_header(WAVEFORMATEX *h); +extern void print_video_header(BITMAPINFOHEADER *h); + +int read_asf_header(demuxer_t *demuxer){ + static unsigned char buffer[1024]; + +#if 1 + //printf("ASF file! (subchunks: %d)\n",asfh.cno); +while(!stream_eof(demuxer->stream)){ + int pos,endpos; + pos=stream_tell(demuxer->stream); + stream_read(demuxer->stream,(char*) &objh,sizeof(objh)); + le2me_ASF_obj_header_t(&objh); + if(stream_eof(demuxer->stream)) break; // EOF + endpos=pos+objh.size; +// for(i=0;i<16;i++) printf("%02X ",objh.guid[i]); + //printf("0x%08X [%s] %d\n",pos, asf_chunk_type(objh.guid),(int) objh.size); + switch(ASF_LOAD_GUID_PREFIX(objh.guid)){ + case ASF_GUID_PREFIX_stream_header: + stream_read(demuxer->stream,(char*) &streamh,sizeof(streamh)); + le2me_ASF_stream_header_t(&streamh); + if(verbose){ + mp_msg(MSGT_HEADER,MSGL_V,"stream type: %s\n",asf_chunk_type(streamh.type)); + mp_msg(MSGT_HEADER,MSGL_V,"stream concealment: %s\n",asf_chunk_type(streamh.concealment)); + mp_msg(MSGT_HEADER,MSGL_V,"type: %d bytes, stream: %d bytes ID: %d\n",(int)streamh.type_size,(int)streamh.stream_size,(int)streamh.stream_no); + mp_msg(MSGT_HEADER,MSGL_V,"unk1: %lX unk2: %X\n",(unsigned long)streamh.unk1,(unsigned int)streamh.unk2); + mp_msg(MSGT_HEADER,MSGL_V,"FILEPOS=0x%X\n",stream_tell(demuxer->stream)); + } + if(streamh.type_size>1024 || streamh.stream_size>1024){ + mp_msg(MSGT_HEADER,MSGL_FATAL,"FATAL: header size bigger than 1024 bytes!\n" + "Please contact mplayer authors, and upload/send this file.\n"); + return 0; + } + // type-specific data: + stream_read(demuxer->stream,(char*) buffer,streamh.type_size); + switch(ASF_LOAD_GUID_PREFIX(streamh.type)){ + case ASF_GUID_PREFIX_audio_stream: { + sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh.stream_no & 0x7F); + sh_audio->wf=calloc((streamh.type_size<sizeof(WAVEFORMATEX))?sizeof(WAVEFORMATEX):streamh.type_size,1); + memcpy(sh_audio->wf,buffer,streamh.type_size); + le2me_WAVEFORMATEX(sh_audio->wf); + if(verbose>=1) print_wave_header(sh_audio->wf); + if(ASF_LOAD_GUID_PREFIX(streamh.concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){ + stream_read(demuxer->stream,(char*) buffer,streamh.stream_size); + asf_scrambling_h=buffer[0]; + asf_scrambling_w=(buffer[2]<<8)|buffer[1]; + asf_scrambling_b=(buffer[4]<<8)|buffer[3]; + asf_scrambling_w/=asf_scrambling_b; + } else { + asf_scrambling_b=asf_scrambling_h=asf_scrambling_w=1; + } + mp_msg(MSGT_HEADER,MSGL_V,"ASF: audio scrambling: %d x %d x %d\n",asf_scrambling_h,asf_scrambling_w,asf_scrambling_b); + //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F; + break; + } + case ASF_GUID_PREFIX_video_stream: { + sh_video_t* sh_video=new_sh_video(demuxer,streamh.stream_no & 0x7F); + int len=streamh.type_size-(4+4+1+2); +// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); + sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1); + memcpy(sh_video->bih,&buffer[4+4+1+2],len); + le2me_BITMAPINFOHEADER(sh_video->bih); + //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; + if(verbose>=1) print_video_header(sh_video->bih); + //asf_video_id=streamh.stream_no & 0x7F; + //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F; + break; + } + } + // stream-specific data: + // stream_read(demuxer->stream,(char*) buffer,streamh.stream_size); + break; +// case ASF_GUID_PREFIX_header_2_0: return "guid_header_2_0"; + case ASF_GUID_PREFIX_file_header: // guid_file_header + stream_read(demuxer->stream,(char*) &fileh,sizeof(fileh)); + le2me_ASF_file_header_t(&fileh); + mp_msg(MSGT_HEADER,MSGL_V,"ASF: packets: %d flags: %d pack_size: %d frame_size: %d\n",(int)fileh.packets,(int)fileh.flags,(int)fileh.packetsize,(int)fileh.frame_size); + asf_packetsize=fileh.packetsize; + asf_packet=malloc(asf_packetsize); // !!! + break; + case ASF_GUID_PREFIX_data_chunk: // guid_data_chunk + demuxer->movi_start=stream_tell(demuxer->stream)+26; + demuxer->movi_end=endpos; + mp_msg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end); + break; + +// case ASF_GUID_PREFIX_index_chunk: return "guid_index_chunk"; + + case ASF_GUID_PREFIX_content_desc: // Content description + if(verbose){ + char *string=NULL; + stream_read(demuxer->stream,(char*) &contenth,sizeof(contenth)); + le2me_ASF_content_description_t(&contenth); + mp_msg(MSGT_HEADER,MSGL_V,"\n"); + // extract the title + if( contenth.title_size!=0 ) { + string=(char*)malloc(contenth.title_size); + stream_read(demuxer->stream, string, contenth.title_size); + print_asf_string(" Title: ", string, contenth.title_size); + } + // extract the author + if( contenth.author_size!=0 ) { + string=(char*)realloc((void*)string, contenth.author_size); + stream_read(demuxer->stream, string, contenth.author_size); + print_asf_string(" Author: ", string, contenth.author_size); + } + // extract the copyright + if( contenth.copyright_size!=0 ) { + string=(char*)realloc((void*)string, contenth.copyright_size); + stream_read(demuxer->stream, string, contenth.copyright_size); + print_asf_string(" Copyright: ", string, contenth.copyright_size); + } + // extract the comment + if( contenth.comment_size!=0 ) { + string=(char*)realloc((void*)string, contenth.comment_size); + stream_read(demuxer->stream, string, contenth.comment_size); + print_asf_string(" Comment: ", string, contenth.comment_size); + } + // extract the rating + if( contenth.rating_size!=0 ) { + string=(char*)realloc((void*)string, contenth.rating_size); + stream_read(demuxer->stream, string, contenth.rating_size); + print_asf_string(" Rating: ", string, contenth.rating_size); + } + mp_msg(MSGT_HEADER,MSGL_V,"\n"); + free(string); + } + break; + + } // switch GUID + + if(ASF_LOAD_GUID_PREFIX(objh.guid)==ASF_GUID_PREFIX_data_chunk) break; // movi chunk + + if(!stream_seek(demuxer->stream,endpos)) break; +} // while EOF + +#if 0 +if(verbose){ + printf("ASF duration: %d\n",(int)fileh.duration); + printf("ASF start pts: %d\n",(int)fileh.start_timestamp); + printf("ASF end pts: %d\n",(int)fileh.end_timestamp); +} +#endif + +#endif +return 1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/aviheader.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,241 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "config.h" +#include "mp_msg.h" + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "bswap.h" +#include "stheader.h" +#include "aviheader.h" + +#define MIN(a,b) (((a)<(b))?(a):(b)) + + +static MainAVIHeader avih; + +extern void print_avih(MainAVIHeader *h); +extern void print_avih_flags(MainAVIHeader *h); +extern void print_strh(AVIStreamHeader *h); +extern void print_wave_header(WAVEFORMATEX *h); +extern void print_video_header(BITMAPINFOHEADER *h); +extern void print_index(AVIINDEXENTRY *idx,int idx_size); + +void read_avi_header(demuxer_t *demuxer,int index_mode){ +sh_audio_t *sh_audio=NULL; +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: +priv->idx_size=0; +while(1){ + int id=stream_read_dword_le(demuxer->stream); + int chunksize,size2; + static int last_fccType=0; + char* hdr=NULL; + // + if(stream_eof(demuxer->stream)) break; + // + if(id==mmioFOURCC('L','I','S','T')){ + int len=stream_read_dword_le(demuxer->stream)-4; // list size + id=stream_read_dword_le(demuxer->stream); // list type + mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%d\n",(char *) &id,len); + if(id==listtypeAVIMOVIE){ + // found MOVI header + demuxer->movi_start=stream_tell(demuxer->stream); + demuxer->movi_end=demuxer->movi_start+len; + mp_msg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end); + if(index_mode==-2) break; // reading from non-seekable source (stdin) + len=(len+1)&(~1); + stream_skip(demuxer->stream,len); + } + continue; + } + size2=stream_read_dword_le(demuxer->stream); + mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%d\n",(char *) &id,size2); + chunksize=(size2+1)&(~1); + switch(id){ + case mmioFOURCC('I','S','F','T'): hdr="Software";break; + case mmioFOURCC('I','N','A','M'): hdr="Name";break; + case mmioFOURCC('I','S','B','J'): hdr="Title";break; + case mmioFOURCC('I','A','R','T'): hdr="Author";break; + case mmioFOURCC('I','C','O','P'): hdr="Copyright";break; + case mmioFOURCC('I','C','M','T'): hdr="Comment";break; + case ckidAVIMAINHDR: // read 'avih' + stream_read(demuxer->stream,(char*) &avih,MIN(size2,sizeof(avih))); + le2me_MainAVIHeader(&avih); // swap to machine endian + chunksize-=MIN(size2,sizeof(avih)); + if(verbose) print_avih(&avih); else print_avih_flags(&avih); + break; + case ckidSTREAMHEADER: { // read 'strh' + AVIStreamHeader h; + stream_read(demuxer->stream,(char*) &h,MIN(size2,sizeof(h))); + le2me_AVIStreamHeader(&h); // swap to machine endian + chunksize-=MIN(size2,sizeof(h)); + ++stream_id; + if(h.fccType==streamtypeVIDEO){ + sh_video=new_sh_video(demuxer,stream_id); + memcpy(&sh_video->video,&h,sizeof(h)); + } else + if(h.fccType==streamtypeAUDIO){ + sh_audio=new_sh_audio(demuxer,stream_id); + memcpy(&sh_audio->audio,&h,sizeof(h)); + } + last_fccType=h.fccType; + if(verbose>=1) print_strh(&h); + break; } + case ckidSTREAMFORMAT: { // read 'strf' + if(last_fccType==streamtypeVIDEO){ + sh_video->bih=calloc((chunksize<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):chunksize,1); +// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); + mp_msg(MSGT_HEADER,MSGL_V,"found 'bih', %d bytes of %d\n",chunksize,sizeof(BITMAPINFOHEADER)); + stream_read(demuxer->stream,(char*) sh_video->bih,chunksize); + le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian + if(verbose>=1) print_video_header(sh_video->bih); + chunksize=0; +// 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; +// if(demuxer->video->id==-1) demuxer->video->id=stream_id; + // IdxFix: + idxfix_videostream=stream_id; + switch(sh_video->bih->biCompression){ + case mmioFOURCC('D', 'I', 'V', '3'): + case mmioFOURCC('d', 'i', 'v', '3'): + case mmioFOURCC('D', 'I', 'V', '4'): + case mmioFOURCC('d', 'i', 'v', '4'): + case mmioFOURCC('D', 'I', 'V', '5'): + case mmioFOURCC('d', 'i', 'v', '5'): + case mmioFOURCC('D', 'I', 'V', '6'): + case mmioFOURCC('d', 'i', 'v', '6'): + case mmioFOURCC('M', 'P', '4', '3'): + case mmioFOURCC('m', 'p', '4', '3'): + case mmioFOURCC('M', 'P', '4', '2'): + case mmioFOURCC('m', 'p', '4', '2'): + case mmioFOURCC('D', 'I', 'V', '2'): + case mmioFOURCC('A', 'P', '4', '1'): + idxfix_divx=1; // we can fix keyframes only for divx coded files! + } + } else + if(last_fccType==streamtypeAUDIO){ + int wf_size = chunksize<sizeof(WAVEFORMATEX)?sizeof(WAVEFORMATEX):chunksize; + sh_audio->wf=calloc(wf_size,1); +// sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize); + mp_msg(MSGT_HEADER,MSGL_V,"found 'wf', %d bytes of %d\n",chunksize,sizeof(WAVEFORMATEX)); + stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize); + le2me_WAVEFORMATEX(sh_audio->wf); + if (sh_audio->wf->cbSize != 0 && + wf_size < sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize) { + sh_audio->wf=realloc(sh_audio->wf, sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize); + } + chunksize=0; + if(verbose>=1) print_wave_header(sh_audio->wf); +// if(demuxer->audio->id==-1) demuxer->audio->id=stream_id; + } + break; + } + case ckidAVINEWINDEX: if(index_mode){ + int i; + priv->idx_size=size2>>4; + mp_msg(MSGT_HEADER,MSGL_V,"Reading INDEX block, %d chunks for %ld frames\n", + 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; + } + } + if(hdr){ + char buf[256]; + int len=(size2<250)?size2:250; + stream_read(demuxer->stream,buf,len); + chunksize-=len; + buf[len]=0; + mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf); + } + if(chunksize>0) stream_skip(demuxer->stream,chunksize); else + if(chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%d (id=%.4s)\n",chunksize,(char *) &id); + +} + +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); + + priv->idx_pos=0; + priv->idx_size=0; + priv->idx=NULL; + + while(1){ + int id,len,skip; + AVIINDEXENTRY* idx; + unsigned char c; + demuxer->filepos=stream_tell(demuxer->stream); + if(demuxer->filepos>=demuxer->movi_end) break; + id=stream_read_dword_le(demuxer->stream); + len=stream_read_dword_le(demuxer->stream); + if(id==mmioFOURCC('L','I','S','T')){ + id=stream_read_dword_le(demuxer->stream); // list type + continue; + } + if(stream_eof(demuxer->stream)) break; + if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?) + + 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 *)priv->idx)[priv->idx_pos++]; + idx->ckid=id; + idx->dwFlags=AVIIF_KEYFRAME; // FIXME + idx->dwChunkOffset=demuxer->filepos; + idx->dwChunkLength=len; + + c=stream_read_char(demuxer->stream); + + // Fix keyframes for DivX files: + if(idxfix_divx) + if(avi_stream_id(id)==idxfix_videostream){ + if(c&0x40) idx->dwFlags=0; + } + + mp_dbg(MSGT_HEADER,MSGL_DBG2,"%08X %08X %.4s %02X %X\n",demuxer->filepos,id,(char *) &id,c,(unsigned int) idx->dwFlags); +#if 0 + { unsigned char tmp[64]; + int i; + stream_read(demuxer->stream,tmp,64); + printf("%.4s",&id); + for(i=0;i<64;i++) printf(" %02X",tmp[i]); + printf("\n"); + } +#endif +skip_chunk: + skip=(len+1)&(~1); // total bytes in this chunk + stream_seek(demuxer->stream,8+demuxer->filepos+skip); + } + priv->idx_size=priv->idx_pos; + mp_msg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size); +} + +} + +#undef MIN + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/aviheader.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,106 @@ +#ifndef _aviheader_h +#define _aviheader_h + +//#include "config.h" /* get correct definition WORDS_BIGENDIAN */ +#include "bswap.h" + +/* + * Some macros to swap little endian structures read from an AVI file + * into machine endian format + */ +#ifdef WORDS_BIGENDIAN +#define le2me_MainAVIHeader(h) { \ + (h)->dwMicroSecPerFrame = le2me_32((h)->dwMicroSecPerFrame); \ + (h)->dwMaxBytesPerSec = le2me_32((h)->dwMaxBytesPerSec); \ + (h)->dwPaddingGranularity = le2me_32((h)->dwPaddingGranularity); \ + (h)->dwFlags = le2me_32((h)->dwFlags); \ + (h)->dwTotalFrames = le2me_32((h)->dwTotalFrames); \ + (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \ + (h)->dwStreams = le2me_32((h)->dwStreams); \ + (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \ + (h)->dwWidth = le2me_32((h)->dwWidth); \ + (h)->dwHeight = le2me_32((h)->dwHeight); \ +} + +#define le2me_AVIStreamHeader(h) { \ + (h)->fccType = le2me_32((h)->fccType); \ + (h)->fccHandler = le2me_32((h)->fccHandler); \ + (h)->dwFlags = le2me_32((h)->dwFlags); \ + (h)->wPriority = le2me_16((h)->wPriority); \ + (h)->wLanguage = le2me_16((h)->wLanguage); \ + (h)->dwInitialFrames = le2me_32((h)->dwInitialFrames); \ + (h)->dwScale = le2me_32((h)->dwScale); \ + (h)->dwRate = le2me_32((h)->dwRate); \ + (h)->dwStart = le2me_32((h)->dwStart); \ + (h)->dwLength = le2me_32((h)->dwLength); \ + (h)->dwSuggestedBufferSize = le2me_32((h)->dwSuggestedBufferSize); \ + (h)->dwQuality = le2me_32((h)->dwQuality); \ + (h)->dwSampleSize = le2me_32((h)->dwSampleSize); \ + le2me_RECT(&(h)->rcFrame); \ +} +#define le2me_RECT(h) { \ + (h)->left = le2me_16((h)->left); \ + (h)->top = le2me_16((h)->top); \ + (h)->right = le2me_16((h)->right); \ + (h)->bottom = le2me_16((h)->bottom); \ +} +#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); \ +} +#define le2me_AVIINDEXENTRY(h) { \ + (h)->ckid = le2me_32((h)->ckid); \ + (h)->dwFlags = le2me_32((h)->dwFlags); \ + (h)->dwChunkOffset = le2me_32((h)->dwChunkOffset); \ + (h)->dwChunkLength = le2me_32((h)->dwChunkLength); \ +} +#else +#define le2me_MainAVIHeader(h) /**/ +#define le2me_AVIStreamHeader(h) /**/ +#define le2me_RECT(h) /**/ +#define le2me_BITMAPINFOHEADER(h) /**/ +#define le2me_WAVEFORMATEX(h) /**/ +#define le2me_AVIINDEXENTRY(h) /**/ +#endif + + +#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))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/aviprint.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,102 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +//extern int verbose; // defined in mplayer.c + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +//#include "codec-cfg.h" +//#include "stheader.h" + +void print_avih_flags(MainAVIHeader *h){ + printf("MainAVIHeader.dwFlags: (%ld)%s%s%s%s%s%s\n",h->dwFlags, + (h->dwFlags&AVIF_HASINDEX)?" HAS_INDEX":"", + (h->dwFlags&AVIF_MUSTUSEINDEX)?" MUST_USE_INDEX":"", + (h->dwFlags&AVIF_ISINTERLEAVED)?" IS_INTERLEAVED":"", + (h->dwFlags&AVIF_TRUSTCKTYPE)?" TRUST_CKTYPE":"", + (h->dwFlags&AVIF_WASCAPTUREFILE)?" WAS_CAPTUREFILE":"", + (h->dwFlags&AVIF_COPYRIGHTED)?" COPYRIGHTED":"" + ); +} + +void print_avih(MainAVIHeader *h){ + printf("======= AVI Header =======\n"); + printf("us/frame: %ld (fps=%5.3f)\n",h->dwMicroSecPerFrame,1000000.0f/(float)h->dwMicroSecPerFrame); + printf("max bytes/sec: %ld\n",h->dwMaxBytesPerSec); + printf("padding: %ld\n",h->dwPaddingGranularity); + print_avih_flags(h); + printf("frames total: %ld initial: %ld\n",h->dwTotalFrames,h->dwInitialFrames); + printf("streams: %ld\n",h->dwStreams); + printf("Suggested BufferSize: %ld\n",h->dwSuggestedBufferSize); + printf("Size: %ld x %ld\n",h->dwWidth,h->dwHeight); +} + +void print_strh(AVIStreamHeader *h){ + printf("======= STREAM Header =======\n"); + printf("Type: %.4s FCC: %.4s (%X)\n",(char *)&h->fccType,(char *)&h->fccHandler,(unsigned int)h->fccHandler); + printf("Flags: %ld\n",h->dwFlags); + printf("Priority: %d Language: %d\n",h->wPriority,h->wLanguage); + printf("InitialFrames: %ld\n",h->dwInitialFrames); + printf("Rate: %ld/%ld = %5.3f\n",h->dwRate,h->dwScale,(float)h->dwRate/(float)h->dwScale); + printf("Start: %ld Len: %ld\n",h->dwStart,h->dwLength); + printf("Suggested BufferSize: %ld\n",h->dwSuggestedBufferSize); + printf("Quality %ld\n",h->dwQuality); + printf("Sample size: %ld\n",h->dwSampleSize); +} + +void print_wave_header(WAVEFORMATEX *h){ + + printf("======= WAVE Format =======\n"); + printf("Format Tag: %d (0x%X)\n",h->wFormatTag,h->wFormatTag); + printf("Channels: %d\n",h->nChannels); + printf("Samplerate: %ld\n",h->nSamplesPerSec); + printf("avg byte/sec: %ld\n",h->nAvgBytesPerSec); + printf("Block align: %d\n",h->nBlockAlign); + printf("bits/sample: %d\n",h->wBitsPerSample); + printf("cbSize: %d\n",h->cbSize); +} + + +void print_video_header(BITMAPINFOHEADER *h){ + printf("======= VIDEO Format ======\n"); + printf(" biSize %ld\n", h->biSize); + printf(" biWidth %ld\n", h->biWidth); + printf(" biHeight %ld\n", h->biHeight); + printf(" biPlanes %d\n", h->biPlanes); + printf(" biBitCount %d\n", h->biBitCount); + printf(" biCompression %ld='%.4s'\n", h->biCompression, (char *)&h->biCompression); + printf(" biSizeImage %ld\n", h->biSizeImage); + printf("===========================\n"); +} + + +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++){ + 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, + pos[id],(float)pos[id]/18747.0f, + num[id],(float)num[id]/23.976f + ); + pos[id]+=idx[i].dwChunkLength; + ++num[id]; + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/aviwrite.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,172 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +extern char* encode_name; +extern char* encode_index_name; + +void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){ + +fwrite(&id,4,1,f); +fwrite(&len,4,1,f); +if(len>0){ + if(data){ + // DATA + fwrite(data,len,1,f); + if(len&1){ // padding + unsigned char zerobyte=0; + fwrite(&zerobyte,1,1,f); + } + } else { + // JUNK + char *avi_junk_data="[= MPlayer junk data! =]"; + if(len&1) ++len; // padding + while(len>0){ + int l=strlen(avi_junk_data); + if(l>len) l=len; + fwrite(avi_junk_data,l,1,f); + len-=l; + } + } +} + +} + + +void write_avi_list(FILE *f,unsigned int id,int len){ + unsigned int list_id=FOURCC_LIST; + len+=4; // list fix + fwrite(&list_id,4,1,f); + fwrite(&len,4,1,f); + fwrite(&id,4,1,f); +} + +struct { + MainAVIHeader avih; + AVIStreamHeader video; + BITMAPINFOHEADER bih; + unsigned int movi_start; + unsigned int movi_end; + unsigned int file_end; +} wah; + +void write_avi_header(FILE *f){ + unsigned int riff[3]; + // RIFF header: + riff[0]=mmioFOURCC('R','I','F','F'); + riff[1]=wah.file_end; // filesize + riff[2]=formtypeAVI; // 'AVI ' + fwrite(&riff,12,1,f); + // AVI header: + write_avi_list(f,listtypeAVIHEADER,sizeof(wah.avih)+8+12+sizeof(wah.video)+8+sizeof(wah.bih)+8); + write_avi_chunk(f,ckidAVIMAINHDR,sizeof(wah.avih),&wah.avih); + // stream header: + write_avi_list(f,listtypeSTREAMHEADER,sizeof(wah.video)+8+sizeof(wah.bih)+8); + write_avi_chunk(f,ckidSTREAMHEADER,sizeof(wah.video),&wah.video); + write_avi_chunk(f,ckidSTREAMFORMAT,sizeof(wah.bih),&wah.bih); + // JUNK: + write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL); + // 'movi' header: + write_avi_list(f,listtypeAVIMOVIE,wah.movi_end-ftell(f)-12); + wah.movi_start=ftell(f); +} + +// called _before_ encoding: (write placeholders and video info) +void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height){ + int frames=8*3600*fps; // 8 hours + + wah.file_end= + wah.movi_end=0x7f000000; + + wah.avih.dwMicroSecPerFrame=1000000.0f/fps; + wah.avih.dwMaxBytesPerSec=fps*500000; // ????? + wah.avih.dwPaddingGranularity=1; // padding + wah.avih.dwFlags=AVIF_ISINTERLEAVED; + wah.avih.dwTotalFrames=frames; + wah.avih.dwInitialFrames=0; + wah.avih.dwStreams=1; + wah.avih.dwSuggestedBufferSize=0x10000; // 1MB + wah.avih.dwWidth=width; + wah.avih.dwHeight=height; + wah.avih.dwReserved[0]= + wah.avih.dwReserved[1]= + wah.avih.dwReserved[2]= + wah.avih.dwReserved[3]=0; + + wah.video.fccType=streamtypeVIDEO; + wah.video.fccHandler=fcc; + wah.video.dwFlags=0; + wah.video.wPriority=0; + wah.video.wLanguage=0; + wah.video.dwInitialFrames=0; + wah.video.dwScale=10000; + wah.video.dwRate=fps*10000; + wah.video.dwStart=0; + wah.video.dwLength=frames; + wah.video.dwSuggestedBufferSize=0x100000; // 1MB ???? + wah.video.dwQuality=10000; + wah.video.dwSampleSize=width*height*3; + + wah.bih.biSize=sizeof(wah.bih); // 40 ? + wah.bih.biWidth=width; + wah.bih.biHeight=height; + wah.bih.biPlanes=1; + wah.bih.biBitCount=24; + wah.bih.biCompression=fcc; + wah.bih.biSizeImage=3*width*height; + wah.bih.biXPelsPerMeter= + wah.bih.biYPelsPerMeter= + wah.bih.biClrUsed= + wah.bih.biClrImportant=0; + + write_avi_header(f); +} + +void avi_fixate(){ + // append index and fix avi headers: + FILE *f1=fopen(encode_name,"r+"); + FILE *f2; + + if(!f1) return; // error + + fseek(f1,0,SEEK_END); + wah.file_end=wah.movi_end=ftell(f1); + + // index: + if(encode_index_name && (f2=fopen(encode_index_name,"rb"))){ + AVIINDEXENTRY idx; + unsigned int pos=0; + int frames=0; + write_avi_chunk(f1,ckidAVINEWINDEX,0,NULL); + while(fread(&idx,sizeof(idx),1,f2)>0){ + idx.dwChunkOffset-=wah.movi_start-4; + fwrite(&idx,sizeof(idx),1,f1); + ++frames; + } + fclose(f2); + unlink(encode_index_name); + wah.file_end=ftell(f1); + // re-write idx1 length: + pos=wah.file_end-wah.movi_end-8; + fseek(f1,wah.movi_end+4,SEEK_SET); + fwrite(&pos,4,1,f1); + // fixup frames: + wah.avih.dwTotalFrames=frames; + wah.video.dwLength=frames; + } + + // re-write avi header: + fseek(f1,0,SEEK_SET); + write_avi_header(f1); + + fclose(f1); + +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/bswap.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,2 @@ +/* Let it be for now*/ +#include "../bswap.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/config.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,2 @@ +/* Let it be for now*/ +#include "../config.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/demux_asf.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,367 @@ +// ASF file parser for DEMUXER v0.3 by A'rpi/ESP-team + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" +#include "asf.h" +#include "demuxer.h" + + +/* + * Load 16/32-bit values in little endian byte order + * from an unaligned address + */ +#ifdef ARCH_X86 +#define LOAD_LE32(p) (*(unsigned int*)(p)) +#define LOAD_LE16(p) (*(unsigned short*)(p)) +#else +#define LOAD_LE32(p) (((unsigned char*)(p))[0] | \ + ((unsigned char*)(p))[1]<< 8 | \ + ((unsigned char*)(p))[2]<<16 | \ + ((unsigned char*)(p))[3]<<24 ) +#define LOAD_LE16(p) (((unsigned char*)(p))[0] | \ + ((unsigned char*)(p))[1]<<8) +#endif + +// defined at asfheader.c: +extern unsigned char* asf_packet; +extern int asf_scrambling_h; +extern int asf_scrambling_w; +extern int asf_scrambling_b; +extern int asf_packetsize; + + +// based on asf file-format doc by Eugene [http://divx.euro.ru] + +static void asf_descrambling(unsigned char *src,int len){ + unsigned char *dst=malloc(len); + unsigned char *s2=src; + int i=0,x,y; + while(len-i>=asf_scrambling_h*asf_scrambling_w*asf_scrambling_b){ +// mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d b=%d)\n",w,asf_scrambling_b); + //i+=asf_scrambling_h*asf_scrambling_w; + for(x=0;x<asf_scrambling_w;x++) + for(y=0;y<asf_scrambling_h;y++){ + memcpy(dst+i,s2+(y*asf_scrambling_w+x)*asf_scrambling_b,asf_scrambling_b); + i+=asf_scrambling_b; + } + s2+=asf_scrambling_h*asf_scrambling_w*asf_scrambling_b; + } + //if(i<len) memcpy(dst+i,src+i,len-i); + memcpy(src,dst,i); + free(dst); +} + + +static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,unsigned long time,unsigned short dur,int offs,int keyframe){ + demux_stream_t *ds=NULL; + + mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len); + + if(demux->video->id==-1) + if(demux->v_streams[id]) + demux->video->id=id; + + if(demux->audio->id==-1) + if(demux->a_streams[id]) + demux->audio->id=id; + + if(id==demux->audio->id){ + // audio + ds=demux->audio; + if(!ds->sh){ + ds->sh=demux->a_streams[id]; + mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id); + } + } else + if(id==demux->video->id){ + // video + ds=demux->video; + if(!ds->sh){ + ds->sh=demux->v_streams[id]; + mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id); + } + } + + if(ds){ + if(ds->asf_packet){ + if(ds->asf_seq!=seq){ + // closed segment, finalize packet: + if(ds==demux->audio) + if(asf_scrambling_h>1 && asf_scrambling_w>1) + asf_descrambling(ds->asf_packet->buffer,ds->asf_packet->len); + ds_add_packet(ds,ds->asf_packet); + ds->asf_packet=NULL; + } else { + // append data to it! + demux_packet_t* dp=ds->asf_packet; + if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs); + dp->buffer=realloc(dp->buffer,dp->len+len); + memcpy(dp->buffer+dp->len,data,len); + mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); + dp->len+=len; + // we are ready now. + return 1; + } + } + // create new packet: + { demux_packet_t* dp; + if(offs>0){ + mp_msg(MSGT_DEMUX,MSGL_V,"warning! broken fragment, %d bytes missing \n",offs); + return 0; + } + dp=new_demux_packet(len); + memcpy(dp->buffer,data,len); + dp->pts=time*0.001f; + dp->flags=keyframe; +// if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur); + dp->pos=demux->filepos; + ds->asf_packet=dp; + ds->asf_seq=seq; + // we are ready now. + return 1; + } + } + + return 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_asf_fill_buffer(demuxer_t *demux){ + + demux->filepos=stream_tell(demux->stream); + if(demux->filepos>=demux->movi_end){ + demux->stream->eof=1; + return 0; + } + + stream_read(demux->stream,asf_packet,asf_packetsize); + if(demux->stream->eof) return 0; // EOF + + if(asf_packet[0]==0x82){ + unsigned char flags=asf_packet[3]; + unsigned char segtype=asf_packet[4]; + unsigned char* p=&asf_packet[5]; + unsigned char* p_end=p+asf_packetsize; + unsigned long time; + unsigned short duration; + int segs=1; + unsigned char segsizetype=0x80; + int seg; + int padding=0; + int plen; + + if(verbose>1){ + int i; + for(i=0;i<16;i++) printf(" %02X",asf_packet[i]); + printf("\n"); + } + + //if(segtype!=0x5d) printf("Warning! packet[4] != 0x5d \n"); + + // Calculate packet size (plen): + if(flags&0x40){ + // Explicit (absoulte) packet size + plen=LOAD_LE16(p); p+=2; + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Explicit packet size specified: %d \n",plen); + if(plen>asf_packetsize) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! plen>packetsize! (%d>%d) \n",plen,asf_packetsize); + if(flags&(8|16)){ + padding=p[0];p++; + if(flags&16){ padding|=p[0]<<8; p++;} + mp_msg(MSGT_DEMUX,MSGL_V,"Warning! explicit=%d padding=%d \n",plen,asf_packetsize-padding); + } + } else { + // Padding (relative) size + if(flags&8){ + padding=p[0];++p; + } else + if(flags&16){ + padding=LOAD_LE16(p);p+=2; + } + plen=asf_packetsize-padding; + } + + time = LOAD_LE32(p); p+=4; + duration = LOAD_LE16(p); p+=2; + if(flags&1){ + segsizetype=p[0] & 0xC0; + segs=p[0] & 0x3F; + ++p; + } + mp_dbg(MSGT_DEMUX,MSGL_DBG4,"%08X: flag=%02X segs=%d pad=%d time=%ld dur=%d\n", + demux->filepos,flags,segs,padding,time,duration); + for(seg=0;seg<segs;seg++){ + //ASF_segmhdr_t* sh; + unsigned char streamno; + unsigned char seq; + int len; + unsigned long x; + unsigned char type; + unsigned long time2; + int keyframe=0; + + if(p>=p_end) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! invalid packet 1, sig11 coming soon...\n"); + + if(verbose>1){ + int i; + printf("seg %d:",seg); + for(i=0;i<16;i++) printf(" %02X",p[i]); + printf("\n"); + } + + streamno=p[0]&0x7F; + if(p[0]&0x80) keyframe=1; + seq=p[1]; + p+=2; + + switch(segtype){ + case 0x55: + x=*((unsigned char*)p); + p++; + break; + case 0x59: + x=LOAD_LE16(p); + p+=2; + break; + case 0x5D: + x=LOAD_LE32(p); + p+=4; + break; + default: + mp_msg(MSGT_DEMUX,MSGL_V,"Warning! unknown segtype == 0x%2X \n",segtype); + x=0; + } + + type=p[0]; p++; // 0x01: grouping 0x08: single + + switch(type){ + case 0x01: + //printf("grouping: %02X \n",p[0]); + ++p; // skip unknown byte + break; + case 0x08: + //printf("!!! obj_length = %d\n",*((unsigned long*)p)); + p+=4; + time2=LOAD_LE32(p);p+=4; + break; + default: + mp_msg(MSGT_DEMUX,MSGL_V,"unknown segment type: 0x%02X \n",type); + } + + if(flags&1){ + // multiple segments + if(segsizetype==0x40){ + len=*((unsigned char*)p);p++; // 1 byte + } else { + len=LOAD_LE16(p);p+=2; // 2 byte + } + } else { + // single segment + len=plen-(p-asf_packet); + } + if(len<0 || (p+len)>=p_end){ + mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! segment len=%d\n",len); + } + mp_dbg(MSGT_DEMUX,MSGL_DBG4," seg #%d: streamno=%d seq=%d type=%02X len=%d\n",seg,streamno,seq,type,len); + + switch(type){ + case 0x01: + // GROUPING: + //printf("ASF_parser: warning! grouping (flag=1) not yet supported!\n",len); + //printf(" total: %d \n",len); + while(len>0){ + int len2=p[0]; + p++; + //printf(" group part: %d bytes\n",len2); + demux_asf_read_packet(demux,p,len2,streamno,seq,x,duration,-1,keyframe); + p+=len2; + len-=len2+1; + } + if(len!=0){ + mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! groups total != len\n"); + } + break; + case 0x08: + // NO GROUPING: + //printf("fragment offset: %d \n",sh->x); + demux_asf_read_packet(demux,p,len,streamno,seq,time2,duration,x,keyframe); + p+=len; + break; + } + + } // for segs + return 1; // success + } + + mp_msg(MSGT_DEMUX,MSGL_V,"%08X: UNKNOWN TYPE %02X %02X %02X %02X %02X...\n",demux->filepos,asf_packet[0],asf_packet[1],asf_packet[2],asf_packet[3],asf_packet[4]); + return 0; +} + + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "stheader.h" + + +void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags){ + demux_stream_t *d_audio=demuxer->audio; + demux_stream_t *d_video=demuxer->video; + sh_audio_t *sh_audio=d_audio->sh; +// sh_video_t *sh_video=d_video->sh; + + //FIXME: OFF_T - didn't test ASF case yet (don't have a large asf...) + //FIXME: reports good or bad to steve@daviesfam.org please + + //================= seek in ASF ========================== + float p_rate=10; // packets / sec + off_t rel_seek_packs=(flags&2)? // FIXME: int may be enough? + (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf_packetsize): + (rel_seek_secs*p_rate); + off_t rel_seek_bytes=rel_seek_packs*asf_packetsize; + off_t newpos; + //printf("ASF: packs: %d duration: %d \n",(int)fileh.packets,*((int*)&fileh.duration)); +// printf("ASF_seek: %d secs -> %d packs -> %d bytes \n", +// rel_seek_secs,rel_seek_packs,rel_seek_bytes); + newpos=((flags&1)?demuxer->movi_start:demuxer->filepos)+rel_seek_bytes; + if(newpos<0 || newpos<demuxer->movi_start) newpos=demuxer->movi_start; +// printf("\r -- asf: newpos=%d -- \n",newpos); + stream_seek(demuxer->stream,newpos); + + ds_fill_buffer(d_video); + if(sh_audio){ + ds_fill_buffer(d_audio); + resync_audio_stream(sh_audio); + } + + while(1){ + if(sh_audio && !d_audio->eof){ + float a_pts=d_audio->pts; + a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + // sync audio: + if (d_video->pts > a_pts){ + skip_audio_frame(sh_audio); +// if(!ds_fill_buffer(d_audio)) sh_audio=NULL; // skip audio. EOF? + continue; + } + } + if(d_video->flags&1) break; // found a keyframe! + if(!ds_fill_buffer(d_video)) break; // skip frame. EOF? + } + + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/demux_avi.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,673 @@ +// AVI file parser for DEMUXER v2.9 by A'rpi/ESP-team + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "stheader.h" + +#include "aviheader.h" + +// Select ds from ID +demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){ + int stream_id=avi_stream_id(id); + +// printf("demux_avi_select_stream(%d) {a:%d/v:%d}\n",stream_id, +// demux->audio->id,demux->video->id); + + if(demux->video->id==-1) + if(demux->v_streams[stream_id]) + demux->video->id=stream_id; + + if(demux->audio->id==-1) + if(demux->a_streams[stream_id]) + demux->audio->id=stream_id; + + if(stream_id==demux->audio->id){ + if(!demux->audio->sh){ + demux->audio->sh=demux->a_streams[stream_id]; + mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id); + } + return demux->audio; + } + if(stream_id==demux->video->id){ + if(!demux->video->sh){ + demux->video->sh=demux->v_streams[stream_id]; + mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI video ID = %d\n",demux->video->id); + } + return demux->video; + } + if(id!=mmioFOURCC('J','U','N','K')){ + // unknown + mp_msg(MSGT_DEMUX,MSGL_DBG2,"Unknown chunk: %.4s (%X)\n",(char *) &id,id); + } + return NULL; +} + +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); + + mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id); + + if(ds==demux->audio){ + + 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)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec; + mp_msg(MSGT_DEMUX,MSGL_V,"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 + priv->pts_corr_bytes+=len; + } + pts=priv->avi_audio_pts; //+priv->pts_correction; + priv->avi_audio_pts=0; + } else + if(ds==demux->video){ + // video + if(priv->skip_video_frames>0){ + // drop frame (seeking) + --priv->skip_video_frames; + ds=NULL; +// } else { +// pts=priv->avi_video_pts; + } + // ezt a 2 sort lehet hogy fell kell majd cserelni: + //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); + 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 + 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",priv->avi_audio_pts,priv->avi_video_pts); + priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction; + priv->pts_has_video=1; + + pts=priv->avi_video_pts; + + //printf("read pack_no: %d pts %5.3f \n",demux->video->pack_no+demux->video->packs,pts); + + } + +// len=stream_read_dword_le(demux->stream); + skip=(len+1)&(~1); // total bytes in this chunk + + if(ds){ + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id); + ds_read_packet(ds,demux->stream,len,pts,idxpos,flags); + skip-=len; + } + if(skip){ + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Skipping %d bytes from packet %04X\n",skip,id); + stream_skip(demux->stream,skip); + } + return ds?1: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; +int ret=0; + +do{ + int flags=0; + AVIINDEXENTRY *idx=NULL; +#if 0 + demux->filepos=stream_tell(demux->stream); + if(demux->filepos>=demux->movi_end){ + demux->stream->eof=1; + return 0; + } + if(stream_eof(demux->stream)) return 0; +#endif + if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){ + unsigned int pos; + + //if(priv->idx_pos<0) printf("Fatal! idx_pos=%d\n",priv->idx_pos); + + idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++]; + + //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, + // pos-4,idx->dwChunkLength,idx->dwFlags); + if(idx->dwFlags&AVIIF_LIST){ + // LIST + continue; + } + if(!demux_avi_select_stream(demux,idx->ckid)){ + mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid); + continue; // skip this chunk + } + + pos=idx->dwChunkOffset+priv->idx_offset; + if(pos<demux->movi_start || pos>=demux->movi_end){ + mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! idx=0x%X \n",pos); + continue; + } +#if 0 + if(pos!=demux->filepos){ + mp_msg(MSGT_DEMUX,MSGL_V,"Warning! pos=0x%X idx.pos=0x%X diff=%d \n",demux->filepos,pos,pos-demux->filepos); + } +#endif + stream_seek(demux->stream,pos); + demux->filepos=stream_tell(demux->stream); + id=stream_read_dword_le(demux->stream); + if(stream_eof(demux->stream)) return 0; // EOF! + + if(id!=idx->ckid){ + mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid); + id=idx->ckid; +// continue; + } + len=stream_read_dword_le(demux->stream); +// if((len&(~1))!=(idx->dwChunkLength&(~1))){ +// if((len)!=(idx->dwChunkLength)){ + if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ + mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength); + len=idx->dwChunkLength; +// continue; + } + if(idx->dwFlags&AVIIF_KEYFRAME) flags=1; + } else { + demux->filepos=stream_tell(demux->stream); + if(demux->filepos>=demux->movi_end){ + demux->stream->eof=1; + return 0; + } + id=stream_read_dword_le(demux->stream); + len=stream_read_dword_le(demux->stream); + if(stream_eof(demux->stream)) return 0; // EOF! + + if(id==mmioFOURCC('L','I','S','T')){ + id=stream_read_dword_le(demux->stream); // list type + continue; + } + } + 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; +// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream); +// return 0; +// } +} while(ret!=1); + return 1; +} + + +// return value: +// 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; +int ret=0; + +do{ + int flags=0; + AVIINDEXENTRY *idx=NULL; + int idx_pos=0; + demux->filepos=stream_tell(demux->stream); + + 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(priv->idx_size>0 && idx_pos<priv->idx_size){ + unsigned int pos; + idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos]; +// idx=&priv->idx[idx_pos]; + + if(idx->dwFlags&AVIIF_LIST){ + // LIST + continue; + } + if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){ + mp_dbg(MSGT_DEMUX,MSGL_DBG3,"Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid); + continue; // skip this chunk + } + + pos=idx->dwChunkOffset+priv->idx_offset; + if(pos<demux->movi_start || pos>=demux->movi_end){ + mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos); + continue; + } +#if 0 + if(pos!=demux->filepos){ + mp_msg(MSGT_DEMUX,MSGL_V,"Warning! pos=0x%X idx.pos=0x%X diff=%d \n",demux->filepos,pos,pos-demux->filepos); + } +#endif + stream_seek(demux->stream,pos); + + id=stream_read_dword_le(demux->stream); + + if(stream_eof(demux->stream)) return 0; + + if(id!=idx->ckid){ + mp_msg(MSGT_DEMUX,MSGL_V,"ChunkID mismatch! raw=%.4s idx=%.4s \n",(char *)&id,(char *)&idx->ckid); + id=idx->ckid; +// continue; + } + len=stream_read_dword_le(demux->stream); +// if((len&(~1))!=(idx->dwChunkLength&(~1))){ +// if((len)!=(idx->dwChunkLength)){ + if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ + mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength); + len=idx->dwChunkLength; +// continue; + } + if(idx->dwFlags&AVIIF_KEYFRAME) flags=1; + } else return 0; + ret=demux_avi_read_packet(demux,id,len,idx_pos,flags); +// if(!ret && priv->skip_video_frames<=0) +// if(--max_packs==0){ +// demux->stream->eof=1; +// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream); +// return 0; +// } +} while(ret!=1); + return 1; +} + + +// return value: +// 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=&priv->idx_pos_v; else + if(ds==demux->audio) fpos=&priv->idx_pos_a; else + return 0; + + stream_seek(demux->stream,fpos[0]); + +do{ + + demux->filepos=stream_tell(demux->stream); + if(demux->filepos>=demux->movi_end){ + demux->stream->eof=1; + return 0; + } + if(stream_eof(demux->stream)) return 0; + + id=stream_read_dword_le(demux->stream); + len=stream_read_dword_le(demux->stream); + if(id==mmioFOURCC('L','I','S','T')){ + id=stream_read_dword_le(demux->stream); // list type + continue; + } + + if(ds==demux_avi_select_stream(demux,id)){ + // read it! + 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 + stream_skip(demux->stream,skip); + } + +} while(ret!=1); + fpos[0]=stream_tell(demux->stream); + return 1; +} + +//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; + +void read_avi_header(demuxer_t *demuxer,int index_mode); + +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; + mp_msg(MSGT_DEMUX,MSGL_V,"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){ + mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI_NI: " MSGTR_MissingVideoStream); + return NULL; +// GUI_MSG( mplErrorAVINI ) + } + if(a_pos==-1){ + mp_msg(MSGT_DEMUX,MSGL_INFO,"AVI_NI: " MSGTR_MissingAudioStream); + sh_audio=NULL; + } else { + if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB + mp_msg(MSGT_DEMUX,MSGL_INFO,MSGTR_NI_Message,force_ni?MSGTR_NI_Forced:MSGTR_NI_Detected); + demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!! + pts_from_bps=1; // force BPS sync! + } + } + } else { + // no index + if(force_ni){ + mp_msg(MSGT_DEMUX,MSGL_INFO,MSGTR_UsingNINI); + 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! + } + demuxer->seekable=0; + } + if(!ds_fill_buffer(d_video)){ + mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI: " MSGTR_MissingVideoStreamBug); + return NULL; +// GUI_MSG( mplAVIErrorMissingVideoStream ) + } + sh_video=d_video->sh;sh_video->ds=d_video; + if(d_audio->id!=-2){ + mp_msg(MSGT_DEMUX,MSGL_V,"AVI: Searching for audio stream (id:%d)\n",d_audio->id); + if(!ds_fill_buffer(d_audio)){ + mp_msg(MSGT_DEMUX,MSGL_INFO,"AVI: " MSGTR_MissingAudioStream); + 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; + mp_msg(MSGT_DEMUX,MSGL_V,"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; + mp_msg(MSGT_DEMUX,MSGL_INFO,"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; + sh_video_t *sh_video=d_video->sh; + float skip_audio_secs=0; + + //FIXME: OFF_T - Didn't check AVI case yet (avi files can't be >2G anyway?) + //================= seek in AVI ========================== + int rel_seek_frames=rel_seek_secs*sh_video->fps; + int video_chunk_pos=d_video->pos; + int i; + + if(flags&1){ + // seek absolute + video_chunk_pos=0; + } + + if(flags&2){ + // float 0..1 + int total=sh_video->video.dwLength; + if(total<=1){ + // bad video header, try to get it from audio + if(sh_audio) total=sh_video->fps*sh_audio->audio.dwLength/sh_audio->wf->nAvgBytesPerSec; + if(total<=1){ + mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CouldntDetFNo); + total=0; + } + } + rel_seek_frames=rel_seek_secs*total; + } + + 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<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 *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break; + } + ++video_chunk_pos; + } + } else { + // seek backward + while(video_chunk_pos>0){ + 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 *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break; + } + --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 *)priv->idx)[i].ckid; + if(avi_stream_id(id)==d_video->id) ++d_video->pack_no; + } + sh_video->num_frames=sh_video->num_frames_decoded=d_video->pack_no; + priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; + d_video->pos=video_chunk_pos; + + mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK: pack=%d pts=%5.3f chunk=%d \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos); + +// ------------ STEP 2: seek audio, find the right chunk & pos ------------ + + d_audio->pack_no=0; + d_audio->dpos=0; + + if(sh_audio){ + int i; +// int apos=0; + int last=0; + int len=0; + 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:priv->idx_size; + + if(sh_audio->audio.dwSampleSize){ + // constant rate audio stream +#if 0 + int align; + 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=(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 *)priv->idx)[i].ckid; + if(avi_stream_id(id)==d_audio->id){ + 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"); + break; + } + d_audio->dpos+=len; + } + } + skip_audio_bytes=curr_audio_pos-d_audio->dpos; + + } else { + // VBR audio + 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<priv->idx_size && chunks>0;i++){ + int id=((AVIINDEXENTRY *)priv->idx)[i].ckid; + if(avi_stream_id(id)==d_audio->id){ + len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength; + if(i>chunk_max){ + skip_audio_bytes+=len; + } else { + ++d_audio->pack_no; + d_audio->dpos+=len; + audio_chunk_pos=i; + } + --chunks; + } + } + //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", +// priv->avi_video_pts, audio_chunk_pos, ); + + } + + // Now we have: + // audio_chunk_pos = chunk no in index table (it's <=chunk_max) + // skip_audio_bytes = bytes to be skipped after chunk seek + // d-audio->pack_no = chunk_no in stream at audio_chunk_pos + // d_audio->dpos = bytepos in stream at audio_chunk_pos + // let's seek! + + // update stream position: + d_audio->pos=audio_chunk_pos; +// d_audio->dpos=apos; +// d_audio->pts=initial_pts_delay+(float)apos/(float)sh_audio->wf->nAvgBytesPerSec; + + if(demuxer->type==DEMUXER_TYPE_AVI){ + // interleaved stream: + if(audio_chunk_pos<video_chunk_pos){ + // calc priv->skip_video_frames & adjust video pts counter: + for(i=audio_chunk_pos;i<video_chunk_pos;i++){ + 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): + 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: + 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; + } + + + + mp_msg(MSGT_SEEK,MSGL_V,"SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n", + 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); + //d_audio->pts=0; // PTS is outdated because of the raw data skipping + } + resync_audio_stream(sh_audio); + +// sh_audio->timer=-skip_audio_secs; + + } + d_video->pts=priv->avi_video_pts; // OSD + +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/demux_mov.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,613 @@ +// QuickTime MOV file parser by A'rpi +// based on TOOLS/movinfo.c by me & Al3x +// compressed header support from moov.c of the openquicktime lib. + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "config.h" + +#ifdef HAVE_PNG +// should be detected by ./configure... +#define HAVE_ZLIB +#endif + +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "stheader.h" + +#ifdef HAVE_ZLIB +#include <zlib.h> +#endif + +typedef struct { + unsigned int pts; // duration + unsigned int size; + off_t pos; +} mov_sample_t; + +typedef struct { + unsigned int sample; // number of the first sample in teh chunk + unsigned int size; // number of samples in the chunk + int desc; // for multiple codecs mode - not used + off_t pos; +} mov_chunk_t; + +typedef struct { + unsigned int first; + unsigned int spc; + unsigned int sdid; +} mov_chunkmap_t; + +typedef struct { + unsigned int num; + unsigned int dur; +} mov_durmap_t; + +typedef struct { + int id; + int type; + int pos; + // + int timescale; + unsigned int length; + int samplesize; // 0 = variable + int duration; // 0 = variable + int width,height; // for video + unsigned int fourcc; + // + int tkdata_len; // track data + unsigned char* tkdata; + int stdata_len; // stream data + unsigned char* stdata; + int samples_size; + mov_sample_t* samples; + int chunks_size; + mov_chunk_t* chunks; + int chunkmap_size; + mov_chunkmap_t* chunkmap; + int durmap_size; + mov_durmap_t* durmap; +} mov_track_t; + +void mov_build_index(mov_track_t* trak){ + int i,j,s; + int last=trak->chunks_size; + unsigned int pts=0; + printf("MOV track: %d chunks, %d samples\n",trak->chunks_size,trak->samples_size); + printf("pts=%d scale=%d time=%5.3f\n",trak->length,trak->timescale,(float)trak->length/(float)trak->timescale); + // process chunkmap: + i=trak->chunkmap_size; + while(i>0){ + --i; + for(j=trak->chunkmap[i].first;j<last;j++){ + trak->chunks[j].desc=trak->chunkmap[i].sdid; + trak->chunks[j].size=trak->chunkmap[i].spc; + } + last=trak->chunkmap[i].first; + } + + // calc pts of chunks: + s=0; + for(j=0;j<trak->chunks_size;j++){ + trak->chunks[j].sample=s; + s+=trak->chunks[j].size; + } + + if(!trak->samples_size){ + // constant sampesize + if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){ + trak->duration=trak->durmap[0].dur; + } else printf("*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n"); + return; + } + + // calc pts: + s=0; + for(j=0;j<trak->durmap_size;j++){ + for(i=0;i<trak->durmap[j].num;i++){ + trak->samples[s].pts=pts; + ++s; + pts+=trak->durmap[j].dur; + } + } + + // calc sample offsets + s=0; + for(j=0;j<trak->chunks_size;j++){ + off_t pos=trak->chunks[j].pos; + for(i=0;i<trak->chunks[j].size;i++){ + trak->samples[s].pos=pos; +#if 0 + printf("Sample %5d: pts=%8d off=0x%08X size=%d\n",s, + trak->samples[s].pts, + (int)trak->samples[s].pos, + trak->samples[s].size); +#endif + pos+=trak->samples[s].size; + ++s; + } + } + +} + +#define MOV_MAX_TRACKS 256 + +#define MOV_TRAK_UNKNOWN 0 +#define MOV_TRAK_VIDEO 1 +#define MOV_TRAK_AUDIO 2 + +typedef struct { + off_t moov_start; + off_t moov_end; + off_t mdat_start; + off_t mdat_end; + int track_db; + mov_track_t* tracks[MOV_MAX_TRACKS]; +} mov_priv_t; + +#define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d)) + +int mov_check_file(demuxer_t* demuxer){ + int flags=0; + mov_priv_t* priv=malloc(sizeof(mov_priv_t)); + + mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n"); + + memset(priv,0,sizeof(mov_priv_t)); + demuxer->priv=priv; + + while(1){ + off_t len=stream_read_dword(demuxer->stream); + unsigned int id=stream_read_dword(demuxer->stream); + if(stream_eof(demuxer->stream)) break; // EOF + if(len<8) break; // invalid chunk + switch(id){ + case MOV_FOURCC('m','o','o','v'): + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie header found!\n"); + priv->moov_start=stream_tell(demuxer->stream); + priv->moov_end=priv->moov_start+len-8; + flags|=1; + break; + case MOV_FOURCC('m','d','a','t'): + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie DATA found!\n"); + priv->mdat_start=stream_tell(demuxer->stream); + priv->mdat_end=priv->mdat_start+len-8; + flags|=2; + break; + default: + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",&id,(int)len); + } + if(!stream_skip(demuxer->stream,len-8)) break; + } + + if(flags==1) + mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing data (mdat) chunk! Maybe broken file...\n"); + else if(flags==2) + mp_msg(MSGT_DEMUX,MSGL_WARN,"MOV: missing header (moov/cmov) chunk! Maybe broken file...\n"); + +return (flags==3); +} + +static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ + mov_priv_t* priv=demuxer->priv; + while(1){ + off_t pos; + off_t len; + unsigned int id; + // + pos=stream_tell(demuxer->stream); +// printf("stream_tell==%d\n",pos); + if(pos>=endpos) return; // END + len=stream_read_dword(demuxer->stream); +// printf("len==%d\n",len); + if(len<8) return; // error + len-=8; + id=stream_read_dword(demuxer->stream); + // + mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",&id,(int)len); + // + if(trak){ + switch(id){ + case MOV_FOURCC('t','k','h','d'): { + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sTrack header!\n",level,""); + // read codec data + trak->tkdata_len=len; + trak->tkdata=malloc(trak->tkdata_len); + stream_read(demuxer->stream,trak->tkdata,trak->tkdata_len); + break; + } + case MOV_FOURCC('m','d','h','d'): { + unsigned int tmp; + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia header!\n",level,""); +#if 0 + tmp=stream_read_dword(demuxer->stream); + printf("dword1: 0x%08X (%d)\n",tmp,tmp); + tmp=stream_read_dword(demuxer->stream); + printf("dword2: 0x%08X (%d)\n",tmp,tmp); + tmp=stream_read_dword(demuxer->stream); + printf("dword3: 0x%08X (%d)\n",tmp,tmp); + tmp=stream_read_dword(demuxer->stream); + printf("dword4: 0x%08X (%d)\n",tmp,tmp); + tmp=stream_read_dword(demuxer->stream); + printf("dword5: 0x%08X (%d)\n",tmp,tmp); + tmp=stream_read_dword(demuxer->stream); + printf("dword6: 0x%08X (%d)\n",tmp,tmp); +#endif + stream_skip(demuxer->stream,12); + // read timescale + trak->timescale=stream_read_dword(demuxer->stream); + // read length + trak->length=stream_read_dword(demuxer->stream); + break; + } + case MOV_FOURCC('v','m','h','d'): { + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sVideo header!\n",level,""); + trak->type=MOV_TRAK_VIDEO; + // read video data + break; + } + case MOV_FOURCC('s','m','h','d'): { + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSound header!\n",level,""); + trak->type=MOV_TRAK_AUDIO; + // read audio data + break; + } + case MOV_FOURCC('s','t','s','d'): { + int i=stream_read_dword(demuxer->stream); // temp! + int count=stream_read_dword(demuxer->stream); + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sDescription list! (cnt:%d)\n",level,"",count); + for(i=0;i<count;i++){ + off_t pos=stream_tell(demuxer->stream); + off_t len=stream_read_dword(demuxer->stream); + unsigned int fourcc=stream_read_dword_le(demuxer->stream); + if(len<8) break; // error + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*s desc #%d: %.4s",level,"",i,&fourcc); + if(!i){ + trak->fourcc=fourcc; + // read codec data + trak->stdata_len=len-8; + trak->stdata=malloc(trak->stdata_len); + stream_read(demuxer->stream,trak->stdata,trak->stdata_len); + if(trak->type==MOV_TRAK_VIDEO && trak->stdata_len>43){ + mp_msg(MSGT_DEMUX,MSGL_V," '%.*s'",trak->stdata_len-43,trak->stdata+43); + } + } + mp_msg(MSGT_DEMUX,MSGL_V,"\n"); + if(fourcc!=trak->fourcc && i) + mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVvariableFourCC); + if(!stream_seek(demuxer->stream,pos+len)) break; + } + break; + } + case MOV_FOURCC('s','t','t','s'): { + int temp=stream_read_dword(demuxer->stream); + int len=stream_read_dword(demuxer->stream); + int i; + int x=0; + unsigned int pts=0; + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample duration table! (%d blocks)\n",level,"",len); + trak->durmap=malloc(sizeof(mov_durmap_t)*len); + memset(trak->durmap,0,sizeof(mov_durmap_t)*len); + trak->durmap_size=len; + for(i=0;i<len;i++){ + trak->durmap[i].num=stream_read_dword(demuxer->stream); + trak->durmap[i].dur=stream_read_dword(demuxer->stream); + pts+=trak->durmap[i].num*trak->durmap[i].dur; + } + if(trak->length!=pts) printf("Warning! pts=%d length=%d\n",pts,trak->length); + break; + } + case MOV_FOURCC('s','t','s','c'): { + int temp=stream_read_dword(demuxer->stream); + int len=stream_read_dword(demuxer->stream); + int i; + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample->Chunk mapping table! (%d blocks)\n",level,"",len); + // read data: + trak->chunkmap_size=len; + trak->chunkmap=malloc(sizeof(mov_chunkmap_t)*len); + for(i=0;i<len;i++){ + trak->chunkmap[i].first=stream_read_dword(demuxer->stream)-1; + trak->chunkmap[i].spc=stream_read_dword(demuxer->stream); + trak->chunkmap[i].sdid=stream_read_dword(demuxer->stream); + } + break; + } + case MOV_FOURCC('s','t','s','z'): { + int temp=stream_read_dword(demuxer->stream); + int ss=stream_read_dword(demuxer->stream); + int len=stream_read_dword(demuxer->stream); + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample size table! len=%d ss=%d\n",level,"",len,ss); + trak->samplesize=ss; + if(!ss){ + // variable samplesize + int i; + trak->samples=realloc(trak->samples,sizeof(mov_sample_t)*len); + trak->samples_size=len; + for(i=0;i<len;i++) + trak->samples[i].size=stream_read_dword(demuxer->stream); + } + break; + } + case MOV_FOURCC('s','t','c','o'): { + int temp=stream_read_dword(demuxer->stream); + int len=stream_read_dword(demuxer->stream); + int i; + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sChunk offset table! (%d chunks)\n",level,"",len); + // extend array if needed: + if(len>trak->chunks_size){ + trak->chunks=realloc(trak->chunks,sizeof(mov_chunk_t)*len); + trak->chunks_size=len; + } + // read elements: + for(i=0;i<len;i++) trak->chunks[i].pos=stream_read_dword(demuxer->stream); + break; + } + case MOV_FOURCC('m','d','i','a'): { + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia stream!\n",level,""); + lschunks(demuxer,level+1,pos+len,trak); + break; + } + case MOV_FOURCC('m','i','n','f'): { + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia info!\n",level,""); + lschunks(demuxer,level+1,pos+len,trak); + break; + } + case MOV_FOURCC('s','t','b','l'): { + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample info!\n",level,""); + lschunks(demuxer,level+1,pos+len,trak); + break; + } + }//switch(id) + } else + if(id==MOV_FOURCC('t','r','a','k')){ +// if(trak) printf("MOV: Warning! trak in trak?\n"); + if(priv->track_db>=MOV_MAX_TRACKS){ + mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk); + return; + } + trak=malloc(sizeof(mov_track_t)); + memset(trak,0,sizeof(mov_track_t)); + mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db); + trak->id=priv->track_db; + priv->tracks[priv->track_db]=trak; + lschunks(demuxer,level+1,pos+len,trak); + mov_build_index(trak); + switch(trak->type){ + case MOV_TRAK_AUDIO: { + sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); + sh->format=trak->fourcc; + printf("!!! audio bits: %d chans: %d\n",trak->stdata[19],trak->stdata[17]); + printf("Fourcc: %.4s\n",&trak->fourcc); + // Emulate WAVEFORMATEX struct: + sh->wf=malloc(sizeof(WAVEFORMATEX)); + memset(sh->wf,0,sizeof(WAVEFORMATEX)); + sh->wf->nChannels=trak->stdata[17]; + sh->wf->wBitsPerSample=trak->stdata[19]; + sh->wf->nSamplesPerSec=trak->timescale; + sh->wf->nAvgBytesPerSec=sh->wf->nChannels*((sh->wf->wBitsPerSample+7)/8)*sh->wf->nSamplesPerSec; + // Selection: + if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ + // (auto)selected audio track: + demuxer->audio->id=priv->track_db; + demuxer->audio->sh=sh; sh->ds=demuxer->audio; + } + break; + } + case MOV_TRAK_VIDEO: { + sh_video_t* sh=new_sh_video(demuxer,priv->track_db); + sh->format=trak->fourcc; + sh->fps=trak->timescale; + sh->frametime=1.0f/sh->fps; + sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); + sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); + + // emulate BITMAPINFOHEADER: + sh->bih=malloc(sizeof(BITMAPINFOHEADER)); + memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); + sh->bih->biSize=40; + sh->bih->biWidth=sh->disp_w; + sh->bih->biHeight=sh->disp_h; + sh->bih->biPlanes=0; + sh->bih->biBitCount=16; + sh->bih->biCompression=trak->fourcc; + sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; + + printf("Image size: %d x %d\n",sh->disp_w,sh->disp_h); + printf("Fourcc: %.4s Codec: '%.*s'\n",&trak->fourcc,trak->stdata_len-43,trak->stdata+43); + + if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ + // (auto)selected video track: + demuxer->video->id=priv->track_db; + demuxer->video->sh=sh; sh->ds=demuxer->video; + } + break; + } + } + printf("--------------\n"); + priv->track_db++; + trak=NULL; + } else +#ifndef HAVE_ZLIB + if(id==MOV_FOURCC('c','m','o','v')){ + mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); + return; + } +#else + if(id==MOV_FOURCC('c','m','o','v')){ +// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); + lschunks(demuxer,level+1,pos+len,NULL); + } else + if(id==MOV_FOURCC('d','c','o','m')){ +// int temp=stream_read_dword(demuxer->stream); + unsigned int len=stream_read_dword(demuxer->stream); + printf("Compressed header uses %.4s algo!\n",&len); + } else + if(id==MOV_FOURCC('c','m','v','d')){ +// int temp=stream_read_dword(demuxer->stream); + unsigned int moov_sz=stream_read_dword(demuxer->stream); + unsigned int cmov_sz=len-4; + unsigned char* cmov_buf=malloc(cmov_sz); + unsigned char* moov_buf=malloc(moov_sz+16); + int zret; + z_stream zstrm; + stream_t* backup; + + printf("Compressed header size: %d / %d\n",cmov_sz,moov_sz); + + stream_read(demuxer->stream,cmov_buf,cmov_sz); + + zstrm.zalloc = (alloc_func)0; + zstrm.zfree = (free_func)0; + zstrm.opaque = (voidpf)0; + zstrm.next_in = cmov_buf; + zstrm.avail_in = cmov_sz; + zstrm.next_out = moov_buf; + zstrm.avail_out = moov_sz; + + zret = inflateInit(&zstrm); + if (zret != Z_OK) + { fprintf(stderr,"QT cmov: inflateInit err %d\n",zret); + return; + } + zret = inflate(&zstrm, Z_NO_FLUSH); + if ((zret != Z_OK) && (zret != Z_STREAM_END)) + { fprintf(stderr,"QT cmov inflate: ERR %d\n",zret); + return; + } +#if 0 + else { + FILE *DecOut; + DecOut = fopen("Out.bin", "w"); + fwrite(moov_buf, 1, moov_sz, DecOut); + fclose(DecOut); + } +#endif + if(moov_sz != zstrm.total_out) printf("Warning! moov size differs cmov: %d zlib: %d\n",moov_sz,zstrm.total_out); + zret = inflateEnd(&zstrm); + + backup=demuxer->stream; + demuxer->stream=new_memory_stream(moov_buf,moov_sz); + stream_skip(demuxer->stream,8); + lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' + //free_stream(demuxer->stream); + demuxer->stream=backup; + + } +#endif + + pos+=len+8; + if(pos>=endpos) break; + if(!stream_seek(demuxer->stream,pos)) break; + } +} + +int mov_read_header(demuxer_t* demuxer){ + mov_priv_t* priv=demuxer->priv; + + printf("mov_read_header!\n"); + + // Parse header: + stream_reset(demuxer->stream); + if(!stream_seek(demuxer->stream,priv->moov_start)) return 0; // ??? + lschunks(demuxer, 0, priv->moov_end, NULL); + +#if 1 + return 1; +#else + mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVnotyetsupp); + return 0; +#endif +} + +// return value: +// 0 = EOF or no stream found +// 1 = successfully read a packet +int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){ + mov_priv_t* priv=demuxer->priv; + mov_track_t* trak=NULL; + float pts; + + if(ds->id<0 || ds->id>=priv->track_db) return 0; + trak=priv->tracks[ds->id]; + +if(trak->samplesize){ + // read chunk: + if(trak->pos>=trak->chunks_size) return 0; // EOF + stream_seek(demuxer->stream,trak->chunks[trak->pos].pos); + pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; + ds_read_packet(ds,demuxer->stream,trak->chunks[trak->pos].size*trak->samplesize,pts,trak->chunks[trak->pos].pos,0); +} else { + // read sample: + if(trak->pos>=trak->samples_size) return 0; // EOF + stream_seek(demuxer->stream,trak->samples[trak->pos].pos); + pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; + ds_read_packet(ds,demuxer->stream,trak->samples[trak->pos].size,pts,trak->samples[trak->pos].pos,0); +} + ++trak->pos; + + return 1; + +} + +static float mov_seek_track(mov_track_t* trak,float pts,int flags){ + +// printf("MOV track seek called %5.3f \n",pts); + if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale; + +if(trak->samplesize){ + int sample=pts/trak->duration; +// printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration); + if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative + trak->pos=0; + while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos; + pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; +} else { + unsigned int ipts=pts; +// printf("MOV track seek - sample: %d \n",ipts); + if(!(flags&1)) ipts+=trak->samples[trak->pos].pts; + trak->pos=0; + while(trak->pos<trak->samples_size && trak->samples[trak->pos].pts<ipts) ++trak->pos; + pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; +} + +// printf("MOV track seek done: %5.3f \n",pts); + +return pts; +} + +void demux_seek_mov(demuxer_t *demuxer,float pts,int flags){ + mov_priv_t* priv=demuxer->priv; + demux_stream_t* ds; + +// printf("MOV seek called %5.3f flag=%d \n",pts,flags); + + ds=demuxer->video; + if(ds && ds->id>=0 && ds->id<priv->track_db){ + mov_track_t* trak=priv->tracks[ds->id]; + //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; + //if(!(flags&1)) pts+=ds->pts; + pts=ds->pts=mov_seek_track(trak,pts,flags); + flags=1; // absolute seconds + } + + ds=demuxer->audio; + if(ds && ds->id>=0 && ds->id<priv->track_db){ + mov_track_t* trak=priv->tracks[ds->id]; + //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; + //if(!(flags&1)) pts+=ds->pts; + ds->pts=mov_seek_track(trak,pts,flags); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/demux_mpg.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,403 @@ +// MPG/VOB file parser for DEMUXER v2.5 by A'rpi/ESP-team + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "config.h" +#include "dvdauth.h" +#include "stream.h" +#include "demuxer.h" +#include "parse_es.h" + +//#define MAX_PS_PACKETSIZE 2048 +#define MAX_PS_PACKETSIZE (224*1024) + +static int mpeg_pts_error=0; + +static unsigned int read_mpeg_timestamp(stream_t *s,int c){ + int d,e; + unsigned int pts; + d=stream_read_word(s); + e=stream_read_word(s); + if( ((c&1)!=1) || ((d&1)!=1) || ((e&1)!=1) ){ + ++mpeg_pts_error; + return 0; // invalid pts + } + pts=(((c>>1)&7)<<30)|((d>>1)<<15)|(e>>1); + mp_dbg(MSGT_DEMUX,MSGL_DBG3,"{%d}",pts); + return pts; +} + +//static unsigned int packet_start_pos=0; + +//extern void *new_sh_audio(demuxer_t *demux,int id); +//extern void *new_sh_video(demuxer_t *demux,int id); +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "stheader.h" + +static int demux_mpg_read_packet(demuxer_t *demux,int id){ + int d; + int len; +#ifdef HAVE_LIBCSS + int css=0; +#endif + unsigned char c=0; + unsigned int pts=0; + unsigned int dts=0; + demux_stream_t *ds=NULL; + + mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_read_packet: %X\n",id); + +// if(id==0x1F0){ +// demux->synced=0; // force resync after 0x1F0 +// return -1; +//} + +// if(id==0x1BA) packet_start_pos=stream_tell(demux->stream); + if(id<0x1BC || id>=0x1F0) return -1; + if(id==0x1BE) return -1; // padding stream + if(id==0x1BF) return -1; // private2 + + len=stream_read_word(demux->stream); + mp_dbg(MSGT_DEMUX,MSGL_DBG3,"PACKET len=%d",len); +// if(len==62480){ demux->synced=0;return -1;} /* :) */ + if(len==0 || len>MAX_PS_PACKETSIZE){ + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS packet len: %d\n",len); + return -2; // invalid packet !!!!!! + } + + mpeg_pts_error=0; + + while(len>0){ // Skip stuFFing bytes + c=stream_read_char(demux->stream);--len; + if(c!=0xFF)break; + } + if((c>>6)==1){ // Read (skip) STD scale & size value +// printf(" STD_scale=%d",(c>>5)&1); + d=((c&0x1F)<<8)|stream_read_char(demux->stream); + len-=2; +// printf(" STD_size=%d",d); + c=stream_read_char(demux->stream); + } + // Read System-1 stream timestamps: + if((c>>4)==2){ + pts=read_mpeg_timestamp(demux->stream,c); + len-=4; + } else + if((c>>4)==3){ + pts=read_mpeg_timestamp(demux->stream,c); + c=stream_read_char(demux->stream); + if((c>>4)!=1) pts=0; //printf("{ERROR4}"); + dts=read_mpeg_timestamp(demux->stream,c); + len-=4+1+4; + } else + if((c>>6)==2){ + int pts_flags; + int hdrlen; + // System-2 (.VOB) stream: + if((c>>4)&3) { +#ifdef HAVE_LIBCSS + css=1; +#else + mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_EncryptedVOB); +#endif + } + c=stream_read_char(demux->stream); pts_flags=c>>6; + c=stream_read_char(demux->stream); hdrlen=c; + len-=2; + mp_dbg(MSGT_DEMUX,MSGL_DBG3," hdrlen=%d (len=%d)",hdrlen,len); + if(hdrlen>len){ mp_msg(MSGT_DEMUX,MSGL_V,"demux_mpg: invalid header length \n"); return -1;} + if(pts_flags==2){ + c=stream_read_char(demux->stream); + pts=read_mpeg_timestamp(demux->stream,c); + len-=5;hdrlen-=5; + } else + if(pts_flags==3){ + c=stream_read_char(demux->stream); + pts=read_mpeg_timestamp(demux->stream,c); + c=stream_read_char(demux->stream); + dts=read_mpeg_timestamp(demux->stream,c); + len-=10;hdrlen-=10; + } + len-=hdrlen; + if(hdrlen>0) stream_skip(demux->stream,hdrlen); // skip header bytes + + //============== DVD Audio sub-stream ====================== + if(id==0x1BD){ + int aid=stream_read_char(demux->stream);--len; + if(len<3) return -1; // invalid audio packet + + // AID: + // 0x20..0x3F subtitle + // 0x80..0x9F AC3 audio + // 0xA0..0xBF PCM audio + + if((aid & 0xE0) == 0x20){ + // subtitle: + aid&=0x1F; + + if(!demux->s_streams[aid]){ + mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid); + demux->s_streams[aid]=1; + } + + if(demux->sub->id==aid){ + ds=demux->sub; + } + + } else if((aid & 0xC0) == 0x80) { + +// aid=128+(aid&0x7F); + // aid=0x80..0xBF + + if(!demux->a_streams[aid]) new_sh_audio(demux,aid); + if(demux->audio->id==-1) demux->audio->id=aid; + + if(demux->audio->id==aid){ +// int type; + ds=demux->audio; + if(!ds->sh) ds->sh=demux->a_streams[aid]; + // READ Packet: Skip additional audio header data: + c=stream_read_char(demux->stream);//type=c; + c=stream_read_char(demux->stream);//type|=c<<8; + c=stream_read_char(demux->stream);//type|=c<<16; +// printf("[%06X]",type); + len-=3; + if((aid&0xE0)==0xA0 && len>=2){ + // read PCM header + int head; + head=stream_read_char(demux->stream); head=c<<8; + c=stream_read_char(demux->stream); head|=c; len-=2; + while(len>0 && head!=0x180){ + head=c<<8; + c=stream_read_char(demux->stream); + head|=c;--len; + } + if(!len) mp_msg(MSGT_DEMUX,MSGL_V,"End of packet while searching for PCM header\n"); + } + } // if(demux->audio->id==aid) + + } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown 0x1BD substream: 0x%02X \n",aid); + + } //if(id==0x1BD) + + } else { + if(c!=0x0f){ + mp_msg(MSGT_DEMUX,MSGL_V," {ERROR5,c=%d} \n",c); + return -1; // invalid packet !!!!!! + } + } + if(mpeg_pts_error) mp_msg(MSGT_DEMUX,MSGL_V," {PTS_err:%d} \n",mpeg_pts_error); + mp_dbg(MSGT_DEMUX,MSGL_DBG3," => len=%d\n",len); + +// if(len<=0 || len>MAX_PS_PACKETSIZE) return -1; // Invalid packet size + if(len<=0 || len>MAX_PS_PACKETSIZE){ + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Invalid PS data len: %d\n",len); + return -1; // invalid packet !!!!!! + } + + if(id>=0x1C0 && id<=0x1DF){ + // mpeg audio + int aid=id-0x1C0; + if(!demux->a_streams[aid]) new_sh_audio(demux,aid); + if(demux->audio->id==-1) demux->audio->id=aid; + if(demux->audio->id==aid){ + ds=demux->audio; + if(!ds->sh) ds->sh=demux->a_streams[aid]; + } + } else + if(id>=0x1E0 && id<=0x1EF){ + // mpeg video + int aid=id-0x1E0; + if(!demux->v_streams[aid]) new_sh_video(demux,aid); + if(demux->video->id==-1) demux->video->id=aid; + if(demux->video->id==aid){ + ds=demux->video; + if(!ds->sh) ds->sh=demux->v_streams[aid]; + } + } + + if(ds){ + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Read %d data bytes from packet %04X\n",len,id); +// printf("packet start = 0x%X \n",stream_tell(demux->stream)-packet_start_pos); +#ifdef HAVE_LIBCSS + if (css) { + if (descrambling) CSSDescramble(demux->stream->buffer,key_title); else + mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_EncryptedVOBauth); + } +#endif + ds_read_packet(ds,demux->stream,len,pts/90000.0f,demux->filepos,0); +// if(ds==demux->sub) parse_dvdsub(ds->last->buffer,ds->last->len); + return 1; + } + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_MPG: Skipping %d data bytes from packet %04X\n",len,id); + if(len<=2356) stream_skip(demux->stream,len); + return 0; +} + +int num_elementary_packets100=0; +int num_elementary_packets101=0; +int num_elementary_packets1B6=0; +int num_elementary_packetsPES=0; + +int demux_mpg_es_fill_buffer(demuxer_t *demux){ + // Elementary video stream + if(demux->stream->eof) return 0; + demux->filepos=stream_tell(demux->stream); + ds_read_packet(demux->video,demux->stream,STREAM_BUFFER_SIZE,0,demux->filepos,0); + return 1; +} + +int demux_mpg_fill_buffer(demuxer_t *demux){ +unsigned int head=0; +int skipped=0; +int max_packs=128; +int ret=0; + +// System stream +do{ + demux->filepos=stream_tell(demux->stream); + head=stream_read_dword(demux->stream); + if((head&0xFFFFFF00)!=0x100){ + // sync... + demux->filepos-=skipped; + while(1){ + int c=stream_read_char(demux->stream); + if(c<0) break; //EOF + head<<=8; + if(head!=0x100){ + head|=c; + ++skipped; //++demux->filepos; + continue; + } + head|=c; + break; + } + demux->filepos+=skipped; + } + if(stream_eof(demux->stream)) break; + // sure: head=0x000001XX + mp_dbg(MSGT_DEMUX,MSGL_DBG4,"*** head=0x%X\n",head); + if(demux->synced==0){ + if(head==0x1BA) demux->synced=1; +#if 0 + else if(head>=0x1C0 && head<=0x1EF){ + demux->synced=2; + mp_msg(MSGT_DEMUX,MSGL_V,"Mpeg PES stream synced at 0x%X (%d)!\n",demux->filepos,demux->filepos); + num_elementary_packets100=0; // requires for re-sync! + num_elementary_packets101=0; // requires for re-sync! + } +#endif + } else + if(demux->synced==1){ + if(head==0x1BB || head==0x1BD || (head>=0x1C0 && head<=0x1EF)){ + demux->synced=2; + mp_msg(MSGT_DEMUX,MSGL_V,"system stream synced at 0x%X (%d)!\n",demux->filepos,demux->filepos); + num_elementary_packets100=0; // requires for re-sync! + num_elementary_packets101=0; // requires for re-sync! + } else demux->synced=0; + } // else + if(demux->synced==2){ + ret=demux_mpg_read_packet(demux,head); + if(!ret) + if(--max_packs==0){ + demux->stream->eof=1; + mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_DoesntContainSelectedStream); + return 0; + } + } else { + if(head>=0x100 && head<0x1B0){ + if(head==0x100) ++num_elementary_packets100; else + if(head==0x101) ++num_elementary_packets101; + mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... elementary video packet found: %03X\n",head); + } else + if(head>=0x1C0 && head<0x1F0){ + ++num_elementary_packetsPES; + mp_msg(MSGT_DEMUX,MSGL_DBG3,"Opps... PES packet found: %03X\n",head); + } else + if(head==0x1B6) ++num_elementary_packets1B6; +#if 1 + if( ( (num_elementary_packets100>50 && num_elementary_packets101>50) || + (num_elementary_packetsPES>50) ) && skipped>4000000){ + mp_msg(MSGT_DEMUX,MSGL_V,"sync_mpeg_ps: seems to be ES/PES stream...\n"); + demux->stream->eof=1; + break; + } +#endif + } +} while(ret!=1); + mp_dbg(MSGT_DEMUX,MSGL_DBG2,"demux: %d bad bytes skipped\n",skipped); + if(demux->stream->eof){ + mp_msg(MSGT_DEMUX,MSGL_V,"MPEG Stream reached EOF\n"); + return 0; + } + return 1; +} + +//extern off_t seek_to_byte; + +void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,int flags){ + demux_stream_t *d_audio=demuxer->audio; + demux_stream_t *d_video=demuxer->video; + sh_audio_t *sh_audio=d_audio->sh; + sh_video_t *sh_video=d_video->sh; + + //================= seek in MPEG ========================== + off_t newpos=(flags&1)?demuxer->movi_start:demuxer->filepos; + + if(flags&2){ + // float seek 0..1 + newpos+=(demuxer->movi_end-demuxer->movi_start)*rel_seek_secs; + } else { + // time seek (secs) + if(!sh_video->i_bps) // unspecified or VBR + newpos+=2324*75*rel_seek_secs; // 174.3 kbyte/sec + else + newpos+=sh_video->i_bps*rel_seek_secs; + } + + if(newpos<demuxer->movi_start) newpos=demuxer->movi_start; + +#ifdef _LARGEFILE_SOURCE + newpos&=~((long long)STREAM_BUFFER_SIZE-1); /* sector boundary */ +#else + newpos&=~(STREAM_BUFFER_SIZE-1); /* sector boundary */ +#endif + stream_seek(demuxer->stream,newpos); + + // re-sync video: + videobuf_code_len=0; // reset ES stream buffer + + ds_fill_buffer(d_video); + if(sh_audio){ + ds_fill_buffer(d_audio); + resync_audio_stream(sh_audio); + } + + while(1){ + int i; + if(sh_audio && !d_audio->eof && d_video->pts && d_audio->pts){ + float a_pts=d_audio->pts; + a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + if(d_video->pts>a_pts){ + skip_audio_frame(sh_audio); // sync audio + continue; + } + } + i=sync_video_packet(d_video); + if(i==0x1B3 || i==0x1B8) break; // found it! + if(!i || !skip_video_packet(d_video)) break; // EOF? + } + + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/demuxer.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,580 @@ +//=================== DEMUXER v2.5 ========================= + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +#include "codec-cfg.h" +#include "stheader.h" + +void free_demuxer_stream(demux_stream_t *ds){ + ds_free_packs(ds); + free(ds); +} + +demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id){ + demux_stream_t* ds=malloc(sizeof(demux_stream_t)); + ds->buffer_pos=ds->buffer_size=0; + ds->buffer=NULL; + ds->pts=0; + ds->pts_bytes=0; + ds->eof=0; + ds->pos=0; + ds->dpos=0; + ds->pack_no=0; +//--------------- + ds->packs=0; + ds->bytes=0; + ds->first=ds->last=NULL; + ds->id=id; + ds->demuxer=demuxer; +//---------------- + ds->asf_seq=-1; + ds->asf_packet=NULL; +//---------------- + ds->sh=NULL; + return ds; +} + +demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id){ + demuxer_t *d=malloc(sizeof(demuxer_t)); + memset(d,0,sizeof(demuxer_t)); + d->stream=stream; + d->movi_start=stream->start_pos; + d->movi_end=stream->end_pos; + d->seekable=1; + d->synced=0; + d->filepos=0; + d->audio=new_demuxer_stream(d,a_id); + d->video=new_demuxer_stream(d,v_id); + d->sub=new_demuxer_stream(d,s_id); + d->type=type; + stream_reset(stream); + stream_seek(stream,stream->start_pos); + return d; +} + +sh_audio_t* new_sh_audio(demuxer_t *demuxer,int id){ + if(demuxer->a_streams[id]){ + mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_AudioStreamRedefined,id); + } else { + mp_msg(MSGT_DEMUXER,MSGL_V,"==> Found audio stream: %d\n",id); + demuxer->a_streams[id]=malloc(sizeof(sh_audio_t)); + memset(demuxer->a_streams[id],0,sizeof(sh_audio_t)); + } + return demuxer->a_streams[id]; +} + +void free_sh_audio(sh_audio_t* sh){ + if(sh->a_in_buffer) free(sh->a_in_buffer); + if(sh->a_buffer) free(sh->a_buffer); + if(sh->wf) free(sh->wf); + free(sh); +} + +sh_video_t* new_sh_video(demuxer_t *demuxer,int id){ + if(demuxer->v_streams[id]){ + mp_msg(MSGT_DEMUXER,MSGL_WARN,MSGTR_VideoStreamRedefined,id); + } else { + mp_msg(MSGT_DEMUXER,MSGL_V,"==> Found video stream: %d\n",id); + demuxer->v_streams[id]=malloc(sizeof(sh_video_t)); + memset(demuxer->v_streams[id],0,sizeof(sh_video_t)); + } + return demuxer->v_streams[id]; +} + +void free_sh_video(sh_video_t* sh){ + if(sh->our_out_buffer) free(sh->our_out_buffer); + if(sh->bih) free(sh->bih); + free(sh); +} + +void free_demuxer(demuxer_t *demuxer){ + int i; + // free streams: + for(i=0;i<256;i++){ + if(demuxer->a_streams[i]) free_sh_audio(demuxer->a_streams[i]); + if(demuxer->v_streams[i]) free_sh_video(demuxer->v_streams[i]); + } + //if(sh_audio) free_sh_audio(sh_audio); + //if(sh_video) free_sh_video(sh_video); + // free demuxers: + free_demuxer_stream(demuxer->audio); + free_demuxer_stream(demuxer->video); + free(demuxer); +} + + +void ds_add_packet(demux_stream_t *ds,demux_packet_t* dp){ +// demux_packet_t* dp=new_demux_packet(len); +// stream_read(stream,dp->buffer,len); +// dp->pts=pts; //(float)pts/90000.0f; +// dp->pos=pos; + // append packet to DS stream: + ++ds->packs; + ds->bytes+=dp->len; + if(ds->last){ + // next packet in stream + ds->last->next=dp; + ds->last=dp; + } else { + // first packet in stream + ds->first=ds->last=dp; + } + mp_dbg(MSGT_DEMUXER,MSGL_DBG2,"DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%u [packs: A=%d V=%d]\n", + (ds==ds->demuxer->audio)?"d_audio":"d_video", + dp->len,dp->pts,(unsigned int)dp->pos,ds->demuxer->audio->packs,ds->demuxer->video->packs); +} + +void ds_read_packet(demux_stream_t *ds,stream_t *stream,int len,float pts,off_t pos,int flags){ + demux_packet_t* dp=new_demux_packet(len); + stream_read(stream,dp->buffer,len); + dp->pts=pts; //(float)pts/90000.0f; + dp->pos=pos; + dp->flags=flags; + // append packet to DS stream: + ds_add_packet(ds,dp); +} + +// return value: +// 0 = EOF or no stream found or invalid type +// 1 = successfully read a packet +int demux_mpg_es_fill_buffer(demuxer_t *demux); +int demux_mpg_fill_buffer(demuxer_t *demux); +int demux_avi_fill_buffer(demuxer_t *demux); +int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t *ds); +int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t *ds); +int demux_asf_fill_buffer(demuxer_t *demux); +int demux_mov_fill_buffer(demuxer_t *demux,demux_stream_t* ds); + +int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){ + // Note: parameter 'ds' can be NULL! +// printf("demux->type=%d\n",demux->type); + switch(demux->type){ + case DEMUXER_TYPE_MPEG_ES: return demux_mpg_es_fill_buffer(demux); + case DEMUXER_TYPE_MPEG_PS: return demux_mpg_fill_buffer(demux); + case DEMUXER_TYPE_AVI: return demux_avi_fill_buffer(demux); + case DEMUXER_TYPE_AVI_NI: return demux_avi_fill_buffer_ni(demux,ds); + case DEMUXER_TYPE_AVI_NINI: return demux_avi_fill_buffer_nini(demux,ds); + case DEMUXER_TYPE_ASF: return demux_asf_fill_buffer(demux); + case DEMUXER_TYPE_MOV: return demux_mov_fill_buffer(demux,ds); + } + return 0; +} + +// return value: +// 0 = EOF +// 1 = succesfull +int ds_fill_buffer(demux_stream_t *ds){ + demuxer_t *demux=ds->demuxer; + if(ds->buffer) free(ds->buffer); + if(verbose>2){ + if(ds==demux->audio) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_audio) called\n");else + if(ds==demux->video) mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(d_video) called\n");else + mp_dbg(MSGT_DEMUXER,MSGL_DBG3,"ds_fill_buffer(unknown 0x%X) called\n",(unsigned int)ds); + } + while(1){ + if(ds->packs){ + demux_packet_t *p=ds->first; + // copy useful data: + ds->buffer=p->buffer; + ds->buffer_pos=0; + ds->buffer_size=p->len; + ds->pos=p->pos; + ds->dpos+=p->len; // !!! + ++ds->pack_no; + if(p->pts){ + ds->pts=p->pts; + ds->pts_bytes=0; + } + ds->pts_bytes+=p->len; // !!! + ds->flags=p->flags; + // free packet: + ds->bytes-=p->len; + ds->first=p->next; + if(!ds->first) ds->last=NULL; + free(p); + --ds->packs; + return 1; //ds->buffer_size; + } + if(demux->audio->packs>=MAX_PACKS || demux->audio->bytes>=MAX_PACK_BYTES){ + mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyAudioInBuffer,demux->audio->packs,demux->audio->bytes); + mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI); + break; + } + if(demux->video->packs>=MAX_PACKS || demux->video->bytes>=MAX_PACK_BYTES){ + mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_TooManyVideoInBuffer,demux->video->packs,demux->video->bytes); + mp_msg(MSGT_DEMUXER,MSGL_HINT,MSGTR_MaybeNI); + break; + } + if(!demux_fill_buffer(demux,ds)){ + mp_dbg(MSGT_DEMUXER,MSGL_DBG2,"ds_fill_buffer()->demux_fill_buffer() failed\n"); + break; // EOF + } + } + ds->buffer_pos=ds->buffer_size=0; + ds->buffer=NULL; + mp_msg(MSGT_DEMUXER,MSGL_V,"ds_fill_buffer: EOF reached (stream: %s) \n",ds==demux->audio?"audio":"video"); + ds->eof=1; + return 0; +} + +int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len){ +int x; +int bytes=0; +while(len>0){ + x=ds->buffer_size-ds->buffer_pos; + if(x==0){ + if(!ds_fill_buffer(ds)) return bytes; + } else { + if(x>len) x=len; + if(mem) memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x); + bytes+=x;len-=x;ds->buffer_pos+=x; + } +} +return bytes; +} + +int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len){ +int x; +int bytes=0; +while(len>0){ + x=ds->buffer_size-ds->buffer_pos; + if(x==0){ + if(!ds_fill_buffer(ds)) return bytes; + } else { + if(x>len) x=len; + if(mem) memcpy(mem+bytes,&ds->buffer[ds->buffer_pos],x); + bytes+=x;len-=x;ds->buffer_pos+=x; + return bytes; // stop at end of package! (for correct timestamping) + } +} +return bytes; +} + + +void ds_free_packs(demux_stream_t *ds){ + demux_packet_t *dp=ds->first; + while(dp){ + demux_packet_t *dn=dp->next; + free(dp->buffer); + free(dp); + dp=dn; + } + if(ds->asf_packet){ + // free unfinished .asf fragments: + free(ds->asf_packet->buffer); + free(ds->asf_packet); + ds->asf_packet=NULL; + } + ds->first=ds->last=NULL; + ds->packs=0; // !!!!! + ds->bytes=0; + if(ds->buffer) free(ds->buffer); + ds->buffer=NULL; + ds->buffer_pos=ds->buffer_size; + ds->pts=0; ds->pts_bytes=0; +} + +int ds_get_packet(demux_stream_t *ds,unsigned char **start){ + while(1){ + int len; + if(ds->buffer_pos>=ds->buffer_size){ + if(!ds_fill_buffer(ds)){ + // EOF + *start = NULL; + return -1; + } + } + len=ds->buffer_size-ds->buffer_pos; + *start = &ds->buffer[ds->buffer_pos]; + ds->buffer_pos+=len; + return len; + } +} + +int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start){ + while(1){ + int len; + if(ds->buffer_pos>=ds->buffer_size){ + *start = NULL; + if(!ds->packs) return -1; // no sub + if(!ds_fill_buffer(ds)) return -1; // EOF + } + len=ds->buffer_size-ds->buffer_pos; + *start = &ds->buffer[ds->buffer_pos]; + ds->buffer_pos+=len; + return len; + } +} + +// ==================================================================== + +// feed-back from demuxers: +extern int num_elementary_packets100; // for MPEG-ES fileformat detection +extern int num_elementary_packets101; +extern int num_elementary_packetsPES; +extern int num_elementary_packets1B6; + +// commandline options, flags: +//extern int seek_to_byte; +extern int force_ni; +extern int pts_from_bps; + +extern int audio_id; +extern int video_id; +extern int dvdsub_id; + +void read_avi_header(demuxer_t *demuxer,int index_mode); +int asf_check_header(demuxer_t *demuxer); +int read_asf_header(demuxer_t *demuxer); +demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id); +demuxer_t* demux_open_avi(demuxer_t* demuxer); +int mov_check_file(demuxer_t* demuxer); +int mov_read_header(demuxer_t* demuxer); + + +demuxer_t* demux_open(stream_t *stream,int file_format,int audio_id,int video_id,int dvdsub_id){ + +//int file_format=(*file_format_ptr); + +demuxer_t *demuxer=NULL; + +demux_stream_t *d_audio=NULL; +demux_stream_t *d_video=NULL; + +sh_audio_t *sh_audio=NULL; +sh_video_t *sh_video=NULL; + +//printf("demux_open(%p,%d,%d,%d,%d) \n",stream,file_format,audio_id,video_id,dvdsub_id); + +//=============== Try to open as AVI file: ================= +if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_AVI){ + demuxer=new_demuxer(stream,DEMUXER_TYPE_AVI,audio_id,video_id,dvdsub_id); + { //---- RIFF header: + int id=stream_read_dword_le(demuxer->stream); // "RIFF" + if(id==mmioFOURCC('R','I','F','F')){ + stream_read_dword_le(demuxer->stream); //filesize + id=stream_read_dword_le(demuxer->stream); // "AVI " + if(id==formtypeAVI){ + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedAVIfile); + file_format=DEMUXER_TYPE_AVI; + } + } + } +} +//=============== Try to open as ASF file: ================= +if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_ASF){ + demuxer=new_demuxer(stream,DEMUXER_TYPE_ASF,audio_id,video_id,dvdsub_id); + if(asf_check_header(demuxer)){ + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedASFfile); + file_format=DEMUXER_TYPE_ASF; + } +} +//=============== Try to open as MPEG-PS file: ================= +if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPEG_PS){ + int pes=1; + while(pes>=0){ + demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_PS,audio_id,video_id,dvdsub_id); + if(!pes) demuxer->synced=1; // hack! + num_elementary_packets100=0; + num_elementary_packets101=0; + num_elementary_packets1B6=0; + num_elementary_packetsPES=0; + + if(ds_fill_buffer(demuxer->video)){ + if(!pes) + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGPESfile); + else + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGPSfile); + file_format=DEMUXER_TYPE_MPEG_PS; + } else { + // some hack to get meaningfull error messages to our unhappy users: + if(num_elementary_packets100>=2 && num_elementary_packets101>=2 && + abs(num_elementary_packets101-num_elementary_packets100)<8){ + if(num_elementary_packetsPES>=4 && num_elementary_packetsPES>=num_elementary_packets100-4){ + --pes;continue; // tricky... + } + file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :) + } else { + if(demuxer->synced==2) + mp_msg(MSGT_DEMUXER,MSGL_ERR,"MPEG: " MSGTR_MissingVideoStreamBug); + else + mp_msg(MSGT_DEMUXER,MSGL_V,"Not MPEG System Stream format... (maybe Transport Stream?)\n"); + } + } + break; + } +} +//=============== Try to open as MPEG-ES file: ================= +if(file_format==DEMUXER_TYPE_MPEG_ES){ // little hack, see above! + demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_ES,audio_id,video_id,dvdsub_id); + if(!ds_fill_buffer(demuxer->video)){ + mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_InvalidMPEGES); + file_format=DEMUXER_TYPE_UNKNOWN; + } else { + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedMPEGESfile); + } +} +//=============== Try to open as MOV file: ================= +#if 1 +if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MOV){ + demuxer=new_demuxer(stream,DEMUXER_TYPE_MOV,audio_id,video_id,dvdsub_id); + if(mov_check_file(demuxer)){ + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_DetectedQTMOVfile); + file_format=DEMUXER_TYPE_MOV; + } +} +#endif +//=============== Unknown, exiting... =========================== +if(file_format==DEMUXER_TYPE_UNKNOWN){ + mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_FormatNotRecognized); + return NULL; +// GUI_MSG( mplUnknowFileType ) +} +//====== File format recognized, set up these for compatibility: ========= +d_audio=demuxer->audio; +d_video=demuxer->video; +//d_dvdsub=demuxer->sub; + +demuxer->file_format=file_format; + +switch(file_format){ + case DEMUXER_TYPE_MOV: { + if(!mov_read_header(demuxer)) return NULL; +// sh_video=d_video->sh;if(sh_video) sh_video->ds=d_video; +// sh_audio=d_audio->sh;if(sh_audio) sh_audio->ds=d_audio; + break; + } + case DEMUXER_TYPE_AVI: { + return (demuxer_t*) 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->endpos=avi_header.movi_end; + if(!ds_fill_buffer(d_video)){ + mp_msg(MSGT_DEMUXER,MSGL_WARN,"ASF: " MSGTR_MissingVideoStream); + sh_video=NULL; + //printf("ASF: missing video stream!? contact the author, it may be a bug :(\n"); + //GUI_MSG( mplASFErrorMissingVideoStream ) + } else { + sh_video=d_video->sh;sh_video->ds=d_video; + sh_video->fps=1000.0f; sh_video->frametime=0.001f; // 1ms + mp_msg(MSGT_DEMUXER,MSGL_INFO,"VIDEO: [%.4s] %ldx%ld %dbpp\n", + (char *)&sh_video->bih->biCompression, + sh_video->bih->biWidth, + sh_video->bih->biHeight, + sh_video->bih->biBitCount); +// sh_video->i_bps=10*asf_packetsize; // FIXME! + } + if(audio_id!=-2){ + mp_msg(MSGT_DEMUXER,MSGL_V,"ASF: Searching for audio stream (id:%d)\n",d_audio->id); + if(!ds_fill_buffer(d_audio)){ + mp_msg(MSGT_DEMUXER,MSGL_INFO,"ASF: " MSGTR_MissingAudioStream); + sh_audio=NULL; + } else { + sh_audio=d_audio->sh;sh_audio->ds=d_audio; + sh_audio->format=sh_audio->wf->wFormatTag; + } + } + break; + } + case DEMUXER_TYPE_MPEG_ES: { + sh_audio=NULL; // ES streams has no audio channel + d_video->sh=new_sh_video(demuxer,0); // create dummy video stream header, id=0 + sh_video=d_video->sh;sh_video->ds=d_video; + break; + } + case DEMUXER_TYPE_MPEG_PS: { + sh_video=d_video->sh;sh_video->ds=d_video; + if(demuxer->stream->type!=STREAMTYPE_VCD) demuxer->movi_start=0; // for VCD + + if(audio_id!=-2) { + if(!ds_fill_buffer(d_audio)){ + mp_msg(MSGT_DEMUXER,MSGL_INFO,"MPEG: " MSGTR_MissingAudioStream); + sh_audio=NULL; + } else { + sh_audio=d_audio->sh;sh_audio->ds=d_audio; + switch(d_audio->id & 0xE0){ // 1110 0000 b (high 3 bit: type low 5: id) + case 0x00: sh_audio->format=0x50;break; // mpeg + case 0xA0: sh_audio->format=0x10001;break; // dvd pcm + case 0x80: sh_audio->format=0x2000;break; // ac3 + default: sh_audio=NULL; // unknown type + } + } + } + break; + } +} // switch(file_format) + +return demuxer; +} + +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); +void demux_seek_mov(demuxer_t *demuxer,float pts,int flags); + +int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags){ + demux_stream_t *d_audio=demuxer->audio; + demux_stream_t *d_video=demuxer->video; + sh_audio_t *sh_audio=d_audio->sh; + sh_video_t *sh_video=d_video->sh; + +if(!demuxer->seekable){ + if(demuxer->file_format==DEMUXER_TYPE_AVI) + mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CantSeekRawAVI); + else + mp_msg(MSGT_SEEK,MSGL_WARN,MSGTR_CantSeekFile); + return 0; +} + + // clear demux buffers: + if(sh_audio){ ds_free_packs(d_audio);sh_audio->a_buffer_len=0;} + ds_free_packs(d_video); + + demuxer->stream->eof=0; // clear eof flag + + if(sh_audio) sh_audio->timer=0; + sh_video->timer=0; // !!!!!! + +switch(demuxer->file_format){ + + case DEMUXER_TYPE_AVI: + demux_seek_avi(demuxer,rel_seek_secs,flags); break; + + case DEMUXER_TYPE_ASF: + demux_seek_asf(demuxer,rel_seek_secs,flags); break; + + case DEMUXER_TYPE_MPEG_ES: + case DEMUXER_TYPE_MPEG_PS: + demux_seek_mpg(demuxer,rel_seek_secs,flags); break; + + case DEMUXER_TYPE_MOV: + demux_seek_mov(demuxer,rel_seek_secs,flags); break; + +} // switch(demuxer->file_format) + +return 1; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/demuxer.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,155 @@ + +#include "config.h" + +#define MAX_PACKS 4096 +#define MAX_PACK_BYTES 0x800000 + +#define DEMUXER_TYPE_UNKNOWN 0 +#define DEMUXER_TYPE_MPEG_ES 1 +#define DEMUXER_TYPE_MPEG_PS 2 +#define DEMUXER_TYPE_AVI 3 +#define DEMUXER_TYPE_AVI_NI 4 +#define DEMUXER_TYPE_AVI_NINI 5 +#define DEMUXER_TYPE_ASF 6 +#define DEMUXER_TYPE_MOV 7 + +#define DEMUXER_TIME_NONE 0 +#define DEMUXER_TIME_PTS 1 +#define DEMUXER_TIME_FILE 2 +#define DEMUXER_TIME_BPS 3 + + +// Holds one packet/frame/whatever +typedef struct demux_packet_st { + int len; + float pts; + off_t pos; // position in index (AVI) or file (MPG) + unsigned char* buffer; + int flags; // keyframe, etc + struct demux_packet_st* next; +} demux_packet_t; + +typedef struct { + int buffer_pos; // current buffer position + int buffer_size; // current buffer size + unsigned char* buffer; // current buffer + float pts; // current buffer's pts + int pts_bytes; // number of bytes read after last pts stamp + int eof; // end of demuxed stream? (true if all buffer empty) + off_t pos; // position in the input stream (file) + off_t dpos; // position in the demuxed stream + int pack_no; // serial number of packet + int flags; // flags of current packet (keyframe etc) +//--------------- + int packs; // number of packets in buffer + int bytes; // total bytes of packets in buffer + demux_packet_t *first; // read to current buffer from here + demux_packet_t *last; // append new packets from input stream to here + int id; // stream ID (for multiple audio/video streams) + struct demuxer_st *demuxer; // parent demuxer structure (stream handler) +// ---- asf ----- + demux_packet_t *asf_packet; // read asf fragments here + int asf_seq; +// ---- stream header ---- + void* sh; +} demux_stream_t; + +typedef struct demuxer_st { + stream_t *stream; + int synced; // stream synced (used by mpeg) + 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 + off_t movi_start; + off_t movi_end; + int seekable; // flag + // + demux_stream_t *audio; // audio buffer/demuxer + demux_stream_t *video; // video buffer/demuxer + demux_stream_t *sub; // dvd subtitle buffer/demuxer + + // stream headers: + 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){ + demux_packet_t* dp=malloc(sizeof(demux_packet_t)); + dp->len=len; + dp->buffer=malloc(len); + dp->next=NULL; + dp->pts=0; + dp->pos=0; + dp->flags=0; + return dp; +} + +inline static void free_demux_packet(demux_packet_t* dp){ + free(dp->buffer); + free(dp); +} + +demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id); +demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id); +void free_demuxer_stream(demux_stream_t *ds); +void free_demuxer(demuxer_t *demuxer); + +void ds_add_packet(demux_stream_t *ds,demux_packet_t* dp); +void ds_read_packet(demux_stream_t *ds,stream_t *stream,int len,float pts,off_t pos,int flags); + +int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds); +int ds_fill_buffer(demux_stream_t *ds); + +inline static off_t ds_tell(demux_stream_t *ds){ + return (ds->dpos-ds->buffer_size)+ds->buffer_pos; +} + +inline static int ds_tell_pts(demux_stream_t *ds){ + return (ds->pts_bytes-ds->buffer_size)+ds->buffer_pos; +} + +int demux_read_data(demux_stream_t *ds,unsigned char* mem,int len); +int demux_read_data_pack(demux_stream_t *ds,unsigned char* mem,int len); + +#if 1 +#define demux_getc(ds) (\ + (ds->buffer_pos<ds->buffer_size) ? ds->buffer[ds->buffer_pos++] \ + :((!ds_fill_buffer(ds))? (-1) : ds->buffer[ds->buffer_pos++] ) ) +#else +inline static int demux_getc(demux_stream_t *ds){ + if(ds->buffer_pos>=ds->buffer_size){ + if(!ds_fill_buffer(ds)){ +// printf("DEMUX_GETC: EOF reached!\n"); + return -1; // EOF + } + } +// printf("[%02X]",ds->buffer[ds->buffer_pos]); + return ds->buffer[ds->buffer_pos++]; +} +#endif + +void ds_free_packs(demux_stream_t *ds); +int ds_get_packet(demux_stream_t *ds,unsigned char **start); +int ds_get_packet_sub(demux_stream_t *ds,unsigned char **start); + + +static inline int avi_stream_id(unsigned int id){ + unsigned char *p=(unsigned char *)&id; + unsigned char a,b; +#if WORDS_BIGENDIAN + a=p[3]-'0'; b=p[2]-'0'; +#else + a=p[0]-'0'; b=p[1]-'0'; +#endif + if(a>9 || b>9) return 100; // invalid ID + return a*10+b; +} + +demuxer_t* demux_open(stream_t *stream,int file_format,int aid,int vid,int sid); +int demux_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/dvdauth.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,229 @@ +/* (C)2001 by LGB (Gabor Lenart), based on example programs in libcss + lgb@lgb.hu */ + +/* don't do anything with this source if css support was not requested */ +#include "config.h" +#ifdef HAVE_LIBCSS + +#include <stdio.h> +#include <stdlib.h> +//#include <string.h> // FIXME: conflicts with fs.h +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <css.h> +#if CSS_MAJOR_VERSION > 0 || (CSS_MAJOR_VERSION == 0 && CSS_MINOR_VERSION > 1) +# include <dvd.h> +# undef OLD_CSS_API +#else +# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +# include <sys/dvdio.h> +# elif defined(__linux__) +# include <linux/cdrom.h> +# elif defined(__sun) +# include <sun/dvdio.h> +# else +# error "Need the DVD ioctls" +# endif +# define OLD_CSS_API 1 +#endif + +#include "dvdauth.h" + + +#if OLD_CSS_API +/* + * provide some backward compatibiliy macros to compile this + * code using the old libcss-0.1 + */ +#define DVDHandle int +#define DVDOpenFailed (-1) + +#define DVDAuth(hdl, s) ioctl(hdl, DVD_AUTH, s) +#define DVDOpenDevice(path) open(path, O_RDONLY) +#define DVDCloseDevice(hdl) close(hdl) +#define CSSDVDisEncrypted(hdl) CSSisEncrypted(hdl) +#define CSSDVDAuthDisc CSSAuthDisc +/* Arghhh! Please think before you commit! You forget to check the return + value of path_to_lba (-1 for error) in this way ... - LGB */ +//#define CSSDVDAuthTitlePath(hdl,key_title,path) \ +// CSSAuthTitle(hdl,key_title,path_to_lba(path)) + +#else /*OLD_CSS_API*/ + +#define DVDHandle struct dvd_device * +#define DVDOpenFailed NULL + +#endif /*OLD_CSS_API*/ + + +char *dvd_auth_device=NULL; +char *dvd_device=NULL; +char *dvd_raw_device=NULL; +unsigned char key_disc[2048]; +unsigned char key_title[5]; +unsigned char *dvdimportkey=NULL; +int descrambling=0; + + +#if OLD_CSS_API +/* + * With the old libcss-0.1 api, we have to find out the LBA for + * a title for title authentication. + */ +#ifdef __linux__ +#include <linux/fs.h> + +#ifndef FIBMAP +#define FIBMAP 1 +#endif + +static int path_to_lba (char *path) +{ + int lba = 0; + char cmd[100]; + FILE *fp; + + snprintf(cmd,sizeof(cmd),"fibmap_mplayer %s",path); + fp=popen(cmd,"r"); + if (fp) { + int ret; + bzero(cmd,sizeof(cmd)); + fgets(cmd,99,fp); + if ((ret=pclose(fp))) + fprintf(stderr,"fibmap_mplayer: %s\n",*cmd?cmd:"no error info"); + if(WIFEXITED(ret) && !WEXITSTATUS(ret)) + lba=atoi(cmd); + else + fp=NULL; + } + if (!fp) { + int fd; + printf("fibmap_mplayer could not run, trying with ioctl() ...\n"); + if ((fd = open(path, O_RDONLY)) == -1) { + fprintf(stderr, "Cannot open file %s: %s", + path ? path : "(NULL)", strerror(errno)); + return -1; + } + if (ioctl(fd, FIBMAP, &lba) != 0) { + perror ("ioctl FIBMAP"); + fprintf(stderr,"Hint: run mplayer as root (or better to install fibmap_mplayer as suid root)!\n"); + close(fd); + return -1; + } + close(fd); + } + printf("LBA: %d\n",lba); + return lba; +} + + +int CSSDVDAuthTitlePath(DVDHandle hdl,unsigned char *key_title,char *path) +{ + int lba=path_to_lba(path); + if (lba==-1) return -1; + return CSSAuthTitle(hdl,key_title,lba); +} + + +#else /*linux*/ +static int path_to_lba (char *path) +{ +#warning translating pathname to iso9660 LBA is not supported on this platform + fprintf(stderr, "Translating pathname to iso9660 LBA is not supported on this platform\n"); + return -1; +} +#endif /*linux*/ +#endif /*OLD_CSS_API*/ + + +static void reset_agids ( DVDHandle dvd ) +{ + dvd_authinfo ai; + int i; + for (i = 0; i < 4; i++) { + memset(&ai, 0, sizeof(ai)); + ai.type = DVD_INVALIDATE_AGID; + ai.lsa.agid = i; + DVDAuth(dvd, &ai); + } +} + + +int dvd_import_key ( unsigned char *hexkey ) +{ + unsigned char *t=key_title; + int digit=4,len; + bzero(key_title,sizeof(key_title)); +// printf("DVD key: %s\n",hexkey); + for (len=0;len<10;len++) { +// printf("-> %c\n",*hexkey); + if (!*hexkey) return 1; + if (*hexkey>='A'&&*hexkey<='F') *t|=(*hexkey-'A'+10)<<digit; + else if (*hexkey>='0'&&*hexkey<='9') *t|=(*hexkey-'0')<<digit; + else return 1; + if (digit) digit=0; else { + digit=4; + t++; + } + hexkey++; + } + if (*hexkey) return 1; + printf("DVD key (requested): %02X%02X%02X%02X%02X\n",key_title[0],key_title[1],key_title[2],key_title[3],key_title[4]); + descrambling=1; + return 0; +} + + + +int dvd_auth ( char *dev , char *filename ) +{ + DVDHandle dvd; /* DVD device handle */ + + if ((dvd=DVDOpenDevice(dev)) == DVDOpenFailed) { + fprintf(stderr,"DVD: cannot open DVD device \"%s\": %s.\n", + dev, strerror(errno)); + return 1; + } + + if (!CSSDVDisEncrypted(dvd)) { + printf("DVD is unencrypted! Skipping authentication!\n(note: you should not use -dvd switch for unencrypted discs!)\n"); + DVDCloseDevice(dvd); + return 0; + } else printf("DVD is encrypted, issuing authentication ...\n"); + + /* reset AGIDs */ + reset_agids(dvd); + + /* authenticate disc */ + if (CSSDVDAuthDisc(dvd,key_disc)) { + fprintf(stderr,"DVD: CSSDVDAuthDisc() failed.\n"); + DVDCloseDevice(dvd); + return 1; + } + + if (CSSDVDAuthTitlePath(dvd,key_title,filename)) { + fprintf(stderr,"DVD: CSSDVDAuthTitle() failed.\n"); + DVDCloseDevice(dvd); + return 1; + } + + /* decrypting title */ + if (CSSDecryptTitleKey (key_title, key_disc) < 0) { + fprintf(stderr,"DVD: CSSDecryptTitleKey() failed.\n"); + DVDCloseDevice(dvd); + return 1; + } + + DVDCloseDevice(dvd); + printf("DVD title key is: %02X%02X%02X%02X%02X\n",key_title[0],key_title[1],key_title[2],key_title[3],key_title[4]); + descrambling=1; + return 0; +} + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/dvdauth.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,16 @@ +//#include "config.h" +#ifdef HAVE_LIBCSS +#ifndef _MPLAYER_CSS_H +#define _MPLAYER_CSS_H + +extern char *dvd_auth_device; +extern unsigned char key_disc[]; +extern unsigned char key_title[]; +extern unsigned char *dvdimportkey; +extern int descrambling; + +int dvd_auth ( char *, char * ); +int dvd_import_key ( unsigned char * ); + +#endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/help_mp.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,1 @@ +#include "../help_mp.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/http.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,296 @@ +/* + * HTTP Helper + * by Bertrand Baudet <bertrand_baudet@yahoo.com> + * (C) 2001, MPlayer team. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "http.h" + +HTTP_header_t * +http_new_header() { + HTTP_header_t *http_hdr; + + http_hdr = (HTTP_header_t*)malloc(sizeof(HTTP_header_t)); + if( http_hdr==NULL ) return NULL; + memset( http_hdr, 0, sizeof(HTTP_header_t) ); + + return http_hdr; +} + +void +http_free( HTTP_header_t *http_hdr ) { + int i; + if( http_hdr==NULL ) return; + if( http_hdr->protocol!=NULL ) free( http_hdr->protocol ); + if( http_hdr->uri!=NULL ) free( http_hdr->uri ); + if( http_hdr->reason_phrase!=NULL ) free( http_hdr->reason_phrase ); + if( http_hdr->body!=NULL ) free( http_hdr->body ); + if( http_hdr->field_search!=NULL ) free( http_hdr->field_search ); + if( http_hdr->method!=NULL ) free( http_hdr->method ); + if( http_hdr->buffer!=NULL ) free( http_hdr->buffer ); + for( i=0 ; i<http_hdr->field_nb ; i++ ) + if( http_hdr->fields[i]!=NULL ) free( http_hdr->fields[i] ); + free( http_hdr ); +} + +int +http_response_append( HTTP_header_t *http_hdr, char *response, int length ) { + char *ptr = NULL; + if( http_hdr==NULL || response==NULL || length<0 ) return -1; + ptr = (char*)malloc( http_hdr->buffer_size+length ); + if( ptr==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + if( http_hdr->buffer_size==0 ) { + // Buffer empty, copy response into it. + memcpy( ptr, response, length ); + http_hdr->buffer_size = length; + } else { + // Buffer not empty, grow buffer, copy and append the response. + memcpy( ptr, http_hdr->buffer, http_hdr->buffer_size ); + free( http_hdr->buffer ); + memcpy( ptr+http_hdr->buffer_size, response, length ); + http_hdr->buffer_size += length; + } + http_hdr->buffer = ptr; + return http_hdr->buffer_size; +} + +int +http_is_header_entired( HTTP_header_t *http_hdr ) { + if( http_hdr==NULL ) return -1; + + if( strstr(http_hdr->buffer, "\r\n\r\n")==NULL ) return 0; + else return 1; +} + +int +http_response_parse( HTTP_header_t *http_hdr ) { + char *hdr_ptr, *ptr; + char *field=NULL; + int pos_hdr_sep, len; + if( http_hdr==NULL ) return -1; + if( http_hdr->is_parsed ) return 0; + + // Get the protocol + hdr_ptr = strstr( http_hdr->buffer, " " ); + if( hdr_ptr==NULL ) { + printf("Malformed answer. No space separator found.\n"); + return -1; + } + len = hdr_ptr-http_hdr->buffer; + http_hdr->protocol = (char*)malloc(len+1); + if( http_hdr->protocol==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + strncpy( http_hdr->protocol, http_hdr->buffer, len ); + http_hdr->protocol[len]='\0'; + if( !strncasecmp( http_hdr->protocol, "HTTP", 4) ) { + if( sscanf( http_hdr->protocol+5,"1.%d", &(http_hdr->http_minor_version) )!=1 ) { + printf("Malformed answer. Unable to get HTTP minor version.\n"); + return -1; + } + } + + // Get the status code + if( sscanf( ++hdr_ptr, "%d", &(http_hdr->status_code) )!=1 ) { + printf("Malformed answer. Unable to get status code.\n"); + return -1; + } + hdr_ptr += 4; + + // Get the reason phrase + ptr = strstr( hdr_ptr, "\r\n" ); + if( hdr_ptr==NULL ) { + printf("Malformed answer. Unable to get the reason phrase.\n"); + return -1; + } + len = ptr-hdr_ptr; + http_hdr->reason_phrase = (char*)malloc(len+1); + if( http_hdr->reason_phrase==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + strncpy( http_hdr->reason_phrase, hdr_ptr, len ); + http_hdr->reason_phrase[len]='\0'; + + // Set the position of the header separator: \r\n\r\n + ptr = strstr( http_hdr->buffer, "\r\n\r\n" ); + if( ptr==NULL ) { + printf("Header may be incomplete. No CRLF CRLF found.\n"); + return -1; + } + pos_hdr_sep = ptr-http_hdr->buffer; + + hdr_ptr = strstr( http_hdr->buffer, "\r\n" )+2; + do { + ptr = strstr( hdr_ptr, "\r\n"); + if( ptr==NULL ) { + printf("No CRLF found\n"); + return -1; + } + len = ptr-hdr_ptr; + field = (char*)realloc(field, len+1); + if( field==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + strncpy( field, hdr_ptr, len ); + field[len]='\0'; + http_set_field( http_hdr, field ); + hdr_ptr = ptr+2; + } while( hdr_ptr<(http_hdr->buffer+pos_hdr_sep) ); + + if( field!=NULL ) free( field ); + + if( pos_hdr_sep+4<http_hdr->buffer_size ) { + // Response has data! + int data_length = http_hdr->buffer_size-(pos_hdr_sep+4); + http_hdr->body = (char*)malloc( data_length ); + if( http_hdr->body==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + memcpy( http_hdr->body, http_hdr->buffer+pos_hdr_sep+4, data_length ); + http_hdr->body_size = data_length; + } + + http_hdr->is_parsed = 1; + return 0; +} + +char * +http_build_request( HTTP_header_t *http_hdr ) { + char *ptr; + int i; + int len; + if( http_hdr==NULL ) return NULL; + + if( http_hdr->method==NULL ) http_set_method( http_hdr, "GET"); + if( http_hdr->uri==NULL ) http_set_uri( http_hdr, "/"); + + // Compute the request length + len = strlen(http_hdr->method)+strlen(http_hdr->uri)+12; // Method line + for( i=0 ; i<http_hdr->field_nb ; i++ ) // Fields + len += strlen(http_hdr->fields[i])+2; + len += 2; // CRLF + if( http_hdr->body!=NULL ) { + len += http_hdr->body_size; + } + if( http_hdr->buffer!=NULL ) { + free( http_hdr->buffer ); + http_hdr->buffer = NULL; + } + http_hdr->buffer = (char*)malloc(len); + if( http_hdr->buffer==NULL ) { + printf("Memory allocation failed\n"); + return NULL; + } + http_hdr->buffer_size = len; + + ptr = http_hdr->buffer; + ptr += sprintf( ptr, "%s %s HTTP/1.%d\r\n", http_hdr->method, http_hdr->uri, http_hdr->http_minor_version ); + for( i=0 ; i<http_hdr->field_nb ; i++ ) + ptr += sprintf( ptr, "%s\r\n", http_hdr->fields[i] ); + ptr += sprintf( ptr, "\r\n" ); + if( http_hdr->body!=NULL ) { + memcpy( ptr, http_hdr->body, http_hdr->body_size ); + } + return http_hdr->buffer; +} + +char * +http_get_field( HTTP_header_t *http_hdr, const char *field_name ) { + if( http_hdr==NULL || field_name==NULL ) return NULL; + http_hdr->search_pos = 0; + if( http_hdr->field_search!=NULL ) free( http_hdr->field_search ); + http_hdr->field_search = (char*)malloc(strlen(field_name)+1); + if( http_hdr->field_search==NULL ) { + printf("Memory allocation failed\n"); + return NULL; + } + strcpy( http_hdr->field_search, field_name ); + return http_get_next_field( http_hdr ); +} + +char * +http_get_next_field( HTTP_header_t *http_hdr ) { + char *ptr; + int i; + if( http_hdr==NULL ) return NULL; + + for( i=http_hdr->search_pos ; i<http_hdr->field_nb ; i++ ) { + ptr = strstr( http_hdr->fields[i], ":" ); + if( ptr==NULL ) return NULL; + if( !strncasecmp( http_hdr->fields[i], http_hdr->field_search, ptr-http_hdr->fields[i] ) ) { + ptr++; // Skip the column + while( ptr[0]==' ' ) ptr++; // Skip the spaces if there is some + http_hdr->search_pos = i+1; + return ptr; // return the value without the field name + } + } + return NULL; +} + +void +http_set_field( HTTP_header_t *http_hdr, const char *field ) { + int pos; + if( http_hdr==NULL || field==NULL ) return; + + pos = http_hdr->field_nb; + + http_hdr->fields[pos] = (char*)malloc(strlen(field)+1); + if( http_hdr->fields[pos]==NULL ) { + printf("Memory allocation failed\n"); + return; + } + http_hdr->field_nb++; + strcpy( http_hdr->fields[pos], field ); +} + +void +http_set_method( HTTP_header_t *http_hdr, const char *method ) { + if( http_hdr==NULL || method==NULL ) return; + + http_hdr->method = (char*)malloc(strlen(method)+1); + if( http_hdr->method==NULL ) { + printf("Memory allocation failed\n"); + return; + } + strcpy( http_hdr->method, method ); +} + +void +http_set_uri( HTTP_header_t *http_hdr, const char *uri ) { + if( http_hdr==NULL || uri==NULL ) return; + + http_hdr->uri = (char*)malloc(strlen(uri)+1); + if( http_hdr->uri==NULL ) { + printf("Memory allocation failed\n"); + return; + } + strcpy( http_hdr->uri, uri ); +} + +void +http_debug_hdr( HTTP_header_t *http_hdr ) { + int i; + if( http_hdr==NULL ) return; + + printf("protocol: %s\n", http_hdr->protocol ); + printf("http minor version: %d\n", http_hdr->http_minor_version ); + printf("uri: %s\n", http_hdr->uri ); + printf("method: %s\n", http_hdr->method ); + printf("status code: %d\n", http_hdr->status_code ); + printf("reason phrase: %s\n", http_hdr->reason_phrase ); + + printf("Fields:\n"); + for( i=0 ; i<http_hdr->field_nb ; i++ ) + printf(" %d - %s\n", i, http_hdr->fields[i] ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/http.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,44 @@ +/* + * HTTP Helper + * by Bertrand Baudet <bertrand_baudet@yahoo.com> + * (C) 2001, MPlayer team. + */ + +#ifndef __HTTP_H +#define __HTTP_H + +#define HTTP_FIELD_MAX 20 + +typedef struct { + char *protocol; + char *method; + char *uri; + int status_code; + char *reason_phrase; + int http_minor_version; + char *fields[HTTP_FIELD_MAX]; + int field_nb; + char *field_search; + int search_pos; + char *body; + int body_size; + char *buffer; + int buffer_size; + int is_parsed; +} HTTP_header_t; + +HTTP_header_t* http_new_header(); +void http_free( HTTP_header_t *http_hdr ); +int http_response_append( HTTP_header_t *http_hdr, char *data, int length ); +int http_response_parse( HTTP_header_t *http_hdr ); +int http_is_header_entired( HTTP_header_t *http_hdr ); +char* http_build_request( HTTP_header_t *http_hdr ); +char* http_get_field( HTTP_header_t *http_hdr, const char *field_name ); +char* http_get_next_field( HTTP_header_t *http_hdr ); +void http_set_field( HTTP_header_t *http_hdr, const char *field ); +void http_set_method( HTTP_header_t *http_hdr, const char *method ); +void http_set_uri( HTTP_header_t *http_hdr, const char *uri ); + +void http_debug_hdr( HTTP_header_t *http_hdr ); + +#endif // __HTTP_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/mp_msg.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,2 @@ +/* Let it be for now*/ +#include "../mp_msg.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/network.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,592 @@ +/* + * Network layer for MPlayer + * by Bertrand BAUDET <bertrand_baudet@yahoo.com> + * (C) 2001, MPlayer team. + */ + +//#define DUMP2FILE + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#include <pthread.h> + +#include <errno.h> +#include <ctype.h> + +#include "stream.h" +#include "demuxer.h" + +#include "network.h" +#include "http.h" +#include "url.h" +#include "asf.h" + +streaming_ctrl_t *streaming_ctrl; + +static ASF_StreamType_e streaming_type = ASF_Unknown_e; + +Net_Fifo * +net_fifo_new() { + Net_Fifo *net_fifo; + net_fifo = (Net_Fifo*)malloc(sizeof(Net_Fifo)); + if( net_fifo==NULL ) { + printf("Memory allocation failed\n"); + return NULL; + } + memset( net_fifo, 0, sizeof(Net_Fifo) ); + return net_fifo; +} + +void +net_fifo_free( Net_Fifo *net_fifo ) { + if( net_fifo->buffer!=NULL ) free( net_fifo->buffer ); + free( net_fifo ); +} + +int +net_fifo_push(Net_Fifo *net_fifo, char *buffer, int length ) { + char *ptr; + if( net_fifo==NULL || buffer==NULL || length<0 ) return -1; + + ptr = (char*)malloc(length+net_fifo->length); + if( ptr==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + if( net_fifo->buffer!=NULL ) { + memcpy( ptr, net_fifo->buffer, net_fifo->length ); + free( net_fifo->buffer ); + } + memcpy( ptr+net_fifo->length, buffer, length ); + net_fifo->buffer = ptr; + net_fifo->length += length; + return net_fifo->length; +} + +int +net_fifo_pop(Net_Fifo *net_fifo, char *buffer, int length ) { + char *ptr; + int len; + if( net_fifo==NULL || buffer==NULL || length<0 ) return -1; + if( net_fifo->buffer==NULL || net_fifo->length==0 ) return -1; + + len = MIN(net_fifo->length, length); + + ptr = (char*)malloc(net_fifo->length-len); + if( ptr==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + memcpy( buffer, net_fifo->buffer, len ); + if( net_fifo->length-len!=0 ) { + memcpy( ptr, net_fifo->buffer+len, net_fifo->length-len ); + free( net_fifo->buffer ); + net_fifo->buffer = ptr; + net_fifo->length -= len; + } else { + free( net_fifo->buffer ); + net_fifo->buffer = NULL; + net_fifo->length = 0; + } + return len; +} + +streaming_ctrl_t * +streaming_ctrl_new( ) { + streaming_ctrl_t *streaming_ctrl; + streaming_ctrl = (streaming_ctrl_t*)malloc(sizeof(streaming_ctrl_t)); + if( streaming_ctrl==NULL ) { + printf("Failed to allocate memory\n"); + return NULL; + } + memset( streaming_ctrl, 0, sizeof(streaming_ctrl_t) ); + streaming_ctrl->buffer = net_fifo_new(); + return streaming_ctrl; +} + +void +streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ) { + if( streaming_ctrl==NULL ) return; + if( streaming_ctrl->buffer!=NULL ) net_fifo_free( streaming_ctrl->buffer ); + free( streaming_ctrl ); +} + +int +readFromServer(int fd, char *buffer, int length) { + int ret; + int done=0; + fd_set set; + struct timeval tv; + if( buffer==NULL || length<0 ) return -1; + + +// fcntl( fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK ); + return read( fd, buffer, length ); + + do { + tv.tv_sec = 0; + tv.tv_usec = 10000; // 10 milli-seconds timeout + FD_ZERO( &set ); + FD_SET( fd, &set ); + ret = select( fd+1, &set, NULL, NULL, &tv ); + if( ret<0 ) { + perror("select"); + } else if( ret==0 ) { + printf("timeout\n"); + } + if( FD_ISSET(fd, &set) ) { + ret = read( fd, buffer, length ); + if( ret<0 ) { + if( errno!=EINPROGRESS ) { + } + } else { + done = 1; + } + } else { + return -1; + } + } while( !done ); + + return ret; +} + +// Connect to a server using a TCP connection +int +connect2Server(char *host, int port) { + int socket_server_fd; + int err, err_len; + fd_set set; + struct timeval tv; + struct sockaddr_in server_address; + + printf("Connecting to server %s:%d ...\n", host, port ); + + socket_server_fd = socket(AF_INET, SOCK_STREAM, 0); +// fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); + if( socket_server_fd==-1 ) { + perror("Failed to create socket"); + return -1; + } + + if( isalpha(host[0]) ) { + struct hostent *hp =(struct hostent*)gethostbyname( host ); + if( hp==NULL ) { + printf("Counldn't resolve name: %s\n", host); + return -1; + } + memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); + } else { + inet_pton(AF_INET, host, &server_address.sin_addr); + } + server_address.sin_family=AF_INET; + server_address.sin_port=htons(port); + + if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { + if( errno!=EINPROGRESS ) { + perror("Failed to connect to server"); + close(socket_server_fd); + return -1; + } + } + + tv.tv_sec = 0; + tv.tv_usec = 10000; // 10 milli-seconds timeout + FD_ZERO( &set ); + FD_SET( socket_server_fd, &set ); + if( select(socket_server_fd+1, NULL, &set, NULL, &tv)>0 ) { + err_len = sizeof( err ); + getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); + if( err ) { + printf("Couldn't connect to host %s\n", host ); + printf("Socket error: %d\n", err ); + close(socket_server_fd); + return -1; + } + } + return socket_server_fd; +} + +int +http_send_request( URL_t *url ) { + HTTP_header_t *http_hdr; + int fd; + http_hdr = http_new_header(); + http_set_uri( http_hdr, url->file ); + http_set_field( http_hdr, "User-Agent: MPlayer"); + http_set_field( http_hdr, "Connection: closed"); + if( http_build_request( http_hdr )==NULL ) { + return -1; + } + + fd = connect2Server( url->hostname, url->port ); + if( fd<0 ) { + return -1; + } + write( fd, http_hdr->buffer, http_hdr->buffer_size ); + http_free( http_hdr ); + + return fd; +} + +HTTP_header_t * +http_read_response( int fd ) { + HTTP_header_t *http_hdr; + char response[BUFFER_SIZE]; + int i; + + http_hdr = http_new_header(); + if( http_hdr==NULL ) { + return NULL; + } + + do { + i = readFromServer( fd, response, BUFFER_SIZE ); + if( i<0 ) { + printf("Read failed\n"); + } + http_response_append( http_hdr, response, i ); + } while( !http_is_header_entired( http_hdr ) ); + http_response_parse( http_hdr ); + return http_hdr; +} + +// By using the protocol, the extension of the file or the content-type +// we might be able to guess the streaming type. +int +autodetectProtocol(URL_t *url, int *fd_out) { + HTTP_header_t *http_hdr; + int fd=-1; + int i; + int redirect; + char *extension; + char *content_type; + char *next_url; + char response[1024]; + + do { + *fd_out=-1; + next_url = NULL; + extension = NULL; + content_type = NULL; + redirect = 0; + + if( url==NULL ) return DEMUXER_TYPE_UNKNOWN; + + // Get the extension of the file if present + if( url->file!=NULL ) { + for( i=strlen(url->file) ; i>0 ; i-- ) { + if( url->file[i]=='.' ) { + extension=(url->file)+i+1; + break; + } + } + } +// extension=NULL; + if( extension!=NULL ) { + printf("Extension: %s\n", extension ); + if( !strcasecmp(extension, "asf") || + !strcasecmp(extension, "wmv") || + !strcasecmp(extension, "asx") ) { + if( url->port==0 ) url->port = 80; + return DEMUXER_TYPE_ASF; + } + if( !strcasecmp(extension, "mpg") || + !strcasecmp(extension, "mpeg") ) { + if( url->port==0 ) url->port = 80; + return DEMUXER_TYPE_MPEG_PS; + } + if( !strcasecmp(extension, "avi") ) { + if( url->port==0 ) url->port = 80; + return DEMUXER_TYPE_AVI; + } + } + + // Checking for RTSP + if( !strcasecmp(url->protocol, "rtsp") ) { + printf("RTSP protocol not yet implemented!\n"); + return DEMUXER_TYPE_UNKNOWN; + } + + // Checking for ASF + if( !strcasecmp(url->protocol, "mms") ) { + if( url->port==0 ) url->port = 80; + return DEMUXER_TYPE_ASF; + } + + // HTTP based protocol + if( !strcasecmp(url->protocol, "http") ) { + if( url->port==0 ) url->port = 80; + + fd = http_send_request( url ); + if( fd<0 ) { + *fd_out=-1; + return DEMUXER_TYPE_UNKNOWN; + } + + http_hdr = http_read_response( fd ); + if( http_hdr==NULL ) { + close( fd ); + *fd_out=-1; + return DEMUXER_TYPE_UNKNOWN; + } + + *fd_out=fd; + //http_debug_hdr( http_hdr ); + + // Check if the response is an ICY status_code reason_phrase + if( !strcasecmp(http_hdr->protocol, "ICY") ) { + // Ok, we have detected an mp3 streaming + return DEMUXER_TYPE_MPEG_PS; + } + + switch( http_hdr->status_code ) { + case 200: // OK + // Look if we can use the Content-Type + content_type = http_get_field( http_hdr, "Content-Type" ); + if( content_type!=NULL ) { + printf("Content-Type: [%s]\n", content_type ); + printf("Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); + // Check for ASF + if( asf_http_streaming_type(content_type, NULL)!=ASF_Unknown_e ) { + return DEMUXER_TYPE_ASF; + } + // Check for MP3 streaming + // Some MP3 streaming server answer with audio/mpeg + if( !strcasecmp(content_type, "audio/mpeg") ) { + return DEMUXER_TYPE_MPEG_PS; + } + // Check for MPEG streaming + if( !strcasecmp(content_type, "video/mpeg") ) { + return DEMUXER_TYPE_MPEG_PS; + } + // AVI ??? => video/x-msvideo + if( !strcasecmp(content_type, "video/x-msvideo") ) { + return DEMUXER_TYPE_AVI; + } + } + break; + // Redirect + case 301: // Permanently + case 302: // Temporarily + // TODO: RFC 2616, recommand to detect infinite redirection loops + next_url = http_get_field( http_hdr, "Location" ); + if( next_url!=NULL ) { + close( fd ); + url_free( url ); + url = url_new( next_url ); + redirect = 1; + } + break; + default: + printf("Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); + close( fd ); + *fd_out=-1; + return DEMUXER_TYPE_UNKNOWN; + } + } + } while( redirect ); + + return DEMUXER_TYPE_UNKNOWN; +} + +int +nop_streaming_read( streaming_ctrl_t *streaming_ctrl ) { + char *buffer; + int len; + if( streaming_ctrl==NULL ) return -1; + len = streaming_ctrl->buffer->length; + if( len==0 ) return 0; + + buffer = (char*)malloc( len ); + if( buffer==NULL ) { + printf("Memory allocation failed\n"); + return -1; + } + net_fifo_pop( streaming_ctrl->buffer, buffer, len ); + write( streaming_ctrl->fd_pipe_in, buffer, len ); + free( buffer ); + return len; +} + +int +nop_streaming_start( streaming_ctrl_t *streaming_ctrl ) { + HTTP_header_t *http_hdr; + int fd; + if( streaming_ctrl==NULL ) return -1; + + fd = streaming_ctrl->fd_net; + if( fd<0 ) { + fd = http_send_request( *(streaming_ctrl->url) ); + if( fd<0 ) return -1; + http_hdr = http_read_response( fd ); + if( http_hdr==NULL ) return -1; + + switch( http_hdr->status_code ) { + case 200: // OK + printf("Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") ); + printf("Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); + if( http_hdr->body_size>0 ) { + write( streaming_ctrl->fd_pipe_in, http_hdr->body, http_hdr->body_size ); + } + break; + default: + printf("Server return %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); + close( fd ); + fd = -1; + } + streaming_ctrl->fd_net = fd; + } + + http_free( http_hdr ); + + streaming_ctrl->streaming_read = nop_streaming_read; + streaming_ctrl->prebuffer_size = 180000; +// streaming_ctrl->prebuffer_size = 0; + streaming_ctrl->buffering = 1; +// streaming_ctrl->buffering = 0; + streaming_ctrl->status = streaming_playing_e; + return fd; +} + +void +network_streaming(void *arg) { + char buffer[BUFFER_SIZE]; + fd_set fd_net_in; + int ret; + + arg = arg; + + do { + FD_ZERO( &fd_net_in ); + FD_SET( streaming_ctrl->fd_net, &fd_net_in ); + + ret = select( streaming_ctrl->fd_net+1, &fd_net_in, NULL, NULL, NULL ); + if( ret<0 ) { + perror("select"); + return; //exit(1); // FIXME! + } + if( FD_ISSET( streaming_ctrl->fd_net, &fd_net_in ) ) { + ret = readFromServer( streaming_ctrl->fd_net, buffer, BUFFER_SIZE ); + if( ret<=0 ) { + streaming_ctrl->status=streaming_stopped_e; + } else { +//printf(" push: 0x%02X\n", *((unsigned int*)buffer) ); + net_fifo_push( streaming_ctrl->buffer, buffer, ret ); + if( !streaming_ctrl->buffering ) { + do { + ret = streaming_ctrl->streaming_read( streaming_ctrl ); + if( ret<0 && streaming_ctrl->buffer->length<streaming_ctrl->prebuffer_size ) { + // Need buffering + streaming_ctrl->buffering = 1; + } + } while( streaming_ctrl->buffer->length>streaming_ctrl->prebuffer_size ); + } else { + if( streaming_ctrl->buffer->length>streaming_ctrl->prebuffer_size ) { + streaming_ctrl->buffering = 0; + printf("\n"); + } else { + printf(" Buffering: %d \%\r", (int)((float)(((float)streaming_ctrl->buffer->length)/((float)streaming_ctrl->prebuffer_size))*100) ); + fflush(stdout); + } + } + } + } else { + printf("Network fd not set\n"); + } + } while( streaming_ctrl->status==streaming_playing_e ); + + // Flush the buffer + while( streaming_ctrl->buffer->length>0 ) { + ret = streaming_ctrl->streaming_read( streaming_ctrl ); + if( ret<0 ) break; + } + +printf("Network thread done\n"); + + // Close to the pipe to stop mplayer. + close( streaming_ctrl->fd_pipe_in ); + +} + +int +streaming_start(URL_t **url, int fd, int streaming_type) { + int fd_pipe[2]; + // Open the pipe + if( pipe(fd_pipe)<0 ) { + printf("Pipe creation failed\n"); + return -1; + } + + streaming_ctrl = streaming_ctrl_new( ); + if( streaming_ctrl==NULL ) { + return -1; + } + streaming_ctrl->url = url; + streaming_ctrl->fd_pipe_in = fd_pipe[1]; + streaming_ctrl->fd_net = fd; + +#ifdef DUMP2FILE +{ + int fd_file; + fd_file = open("dump.stream", O_WRONLY | O_CREAT ); + if( fd_file<0 ) { + perror("open"); + } + streaming_ctrl->fd_pipe_in = fd_file; +} +#endif + + switch( streaming_type ) { + case DEMUXER_TYPE_ASF: + // Send the appropriate HTTP request + fd = asf_http_streaming_start( streaming_ctrl ); + break; + case DEMUXER_TYPE_AVI: + case DEMUXER_TYPE_MPEG_ES: + case DEMUXER_TYPE_MPEG_PS: + fd = nop_streaming_start( streaming_ctrl ); + break; + case DEMUXER_TYPE_UNKNOWN: + default: + printf("Unable to detect the streaming type\n"); + close( fd ); + free( streaming_ctrl ); + return -1; + } + + if( fd<0 ) { + free( streaming_ctrl ); + return -1; + } + + // Start the network thread + if( pthread_create( &(streaming_ctrl->thread_id), NULL , (void*)network_streaming, (void*)NULL)<0 ) { + printf("Unable to start the network thread.\n"); + close( fd ); + free( streaming_ctrl ); + return -1; + } +printf("Network thread created with id: %d\n", streaming_ctrl->thread_id ); + +// streaming_ctrl->status = streaming_stopped_e; + +// return fd; + return fd_pipe[0]; +} + +int +streaming_stop( ) { + streaming_ctrl->status = streaming_stopped_e; + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/network.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,49 @@ +/* + * Network layer for MPlayer + * by Bertrand BAUDET <bertrand_baudet@yahoo.com> + * (C) 2001, MPlayer team. + */ + +#ifndef __NETWORK_H +#define __NETWORK_H + +#include <pthread.h> + +#include "stream.h" + +#include "url.h" + +#define BUFFER_SIZE 2048 + +typedef enum { + streaming_stopped_e, + streaming_playing_e +} streaming_status; + +typedef struct { + char *buffer; + int length; +} Net_Fifo; + +typedef struct streaming_control { + URL_t **url; + int fd_net; + int fd_pipe_in; + streaming_status status; + pthread_t thread_id; + Net_Fifo *buffer; + int buffering; // boolean + int prebuffer_size; + int (*streaming_read)( struct streaming_control *stream_ctrl ); +} streaming_ctrl_t; + +Net_Fifo* net_fifo_new( ); +void net_fifo_free(Net_Fifo *net_fifo ); +int net_fifo_pop(Net_Fifo *net_fifo, char *buffer, int length ); +int net_fifo_push(Net_Fifo *net_fifo, char *buffer, int length ); + +int connect2Server(char *host, int port); +int readFromServer(int fd, char *buffer, int length ); +int autodetectProtocol( URL_t *url, int *fd_out ); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/open.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,437 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#ifdef __FreeBSD__ +#include <sys/cdrio.h> +#endif + +#include "stream.h" +#include "demuxer.h" + +#ifdef STREAMING +#include "url.h" +#include "network.h" +static URL_t* url; +#endif + +int dvd_title=0; +int dvd_chapter=1; +int dvd_angle=1; + +#ifdef USE_DVDREAD + +#include <dvdread/dvd_reader.h> +#include <dvdread/ifo_types.h> +#include <dvdread/ifo_read.h> +#include <dvdread/nav_read.h> + +#define DVDREAD_VERSION(maj,min,micro) ((maj)*10000 + (min)*100 + (micro)) + +/* + * Try to autodetect the libdvd-0.9.0 library + * (0.9.0 removed the <dvdread/dvd_udf.h> header, and moved the two defines + * DVD_VIDEO_LB_LEN and MAX_UDF_FILE_NAME_LEN from it to + * <dvdread/dvd_reader.h>) + */ +#if defined(DVD_VIDEO_LB_LEN) && defined(MAX_UDF_FILE_NAME_LEN) +#define LIBDVDREAD_VERSION DVDREAD_VERSION(0,9,0) +#else +#define LIBDVDREAD_VERSION DVDREAD_VERSION(0,8,0) +#endif + + +typedef struct { + dvd_reader_t *dvd; + dvd_file_t *title; + ifo_handle_t *vmg_file; + tt_srpt_t *tt_srpt; + ifo_handle_t *vts_file; + vts_ptt_srpt_t *vts_ptt_srpt; + pgc_t *cur_pgc; + // + int cur_cell; + int cur_pack; + int cell_last_pack; + // Navi: + int packs_left; + dsi_t dsi_pack; + int angle_seek; +} dvd_priv_t; + +#endif + +extern int vcd_get_track_end(int fd,int track); + +// Open a new stream (stdin/file/vcd/url) + +stream_t* open_stream(char* filename,int vcd_track,int* file_format){ +stream_t* stream=NULL; +int f=-1; +off_t len; +#ifdef VCD_CACHE +int vcd_cache_size=128; +#endif +#ifdef __FreeBSD__ +int bsize = VCD_SECTOR_SIZE; +#endif + +//============ Open VideoCD track ============== +if(vcd_track){ + int ret,ret2; + if(!filename) filename=DEFAULT_CDROM_DEVICE; + f=open(filename,O_RDONLY); + if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,filename);return NULL; } + vcd_read_toc(f); + ret2=vcd_get_track_end(f,vcd_track); + if(ret2<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");return NULL;} + ret=vcd_seek_to_track(f,vcd_track); + if(ret<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");return NULL;} +// seek_to_byte+=ret; + mp_msg(MSGT_OPEN,MSGL_V,"VCD start byte position: 0x%X end: 0x%X\n",ret,ret2); +#ifdef VCD_CACHE + vcd_cache_init(vcd_cache_size); +#endif +#ifdef __FreeBSD__ + if (ioctl (f, CDRIOCSETBLOCKSIZE, &bsize) == -1) { + perror ( "Error in CDRIOCSETBLOCKSIZE"); + } +#endif + stream=new_stream(f,STREAMTYPE_VCD); + stream->start_pos=ret; + stream->end_pos=ret2; + return stream; +} + +//============ Open DVD title ============== +#ifdef USE_DVDREAD +if(dvd_title){ +// int ret,ret2; + dvd_priv_t *d; + int ttn,pgc_id,pgn; + dvd_reader_t *dvd; + dvd_file_t *title; + ifo_handle_t *vmg_file; + tt_srpt_t *tt_srpt; + ifo_handle_t *vts_file; + /** + * Open the disc. + */ + if(!filename) filename=DEFAULT_DVD_DEVICE; + dvd = DVDOpen(filename); + if( !dvd ) { + mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename); + return NULL; + } + + mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDwait); + + /** + * Load the video manager to find out the information about the titles on + * this disc. + */ + vmg_file = ifoOpen( dvd, 0 ); + if( !vmg_file ) { + mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open VMG info!\n"); + DVDClose( dvd ); + return NULL; + } + tt_srpt = vmg_file->tt_srpt; + /** + * Make sure our title number is valid. + */ + mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumTitles, + tt_srpt->nr_of_srpts ); + if( dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts ) { + mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidTitle, dvd_title); + ifoClose( vmg_file ); + DVDClose( dvd ); + return NULL; + } + --dvd_title; // remap 1.. -> 0.. + /** + * Make sure the chapter number is valid for this title. + */ + mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumChapters, + tt_srpt->title[dvd_title].nr_of_ptts ); + if( dvd_chapter<1 || dvd_chapter>tt_srpt->title[dvd_title].nr_of_ptts ) { + mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidChapter, dvd_chapter); + ifoClose( vmg_file ); + DVDClose( dvd ); + return NULL; + } + --dvd_chapter; // remap 1.. -> 0.. + /** + * Make sure the angle number is valid for this title. + */ + mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumAngles, + tt_srpt->title[dvd_title].nr_of_angles ); + if( dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles ) { + mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidAngle, dvd_angle); + ifoClose( vmg_file ); + DVDClose( dvd ); + return NULL; + } + --dvd_angle; // remap 1.. -> 0.. + /** + * Load the VTS information for the title set our title is in. + */ + vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr ); + if( !vts_file ) { + mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoIFO, + tt_srpt->title[dvd_title].title_set_nr ); + ifoClose( vmg_file ); + DVDClose( dvd ); + return NULL; + } + /** + * We've got enough info, time to open the title set data. + */ + title = DVDOpenFile( dvd, tt_srpt->title[dvd_title].title_set_nr, + DVD_READ_TITLE_VOBS ); + if( !title ) { + mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVOBs, + tt_srpt->title[dvd_title].title_set_nr ); + ifoClose( vts_file ); + ifoClose( vmg_file ); + DVDClose( dvd ); + return NULL; + } + + mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDopenOk); + // store data + d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t)); + d->dvd=dvd; + d->title=title; + d->vmg_file=vmg_file; + d->tt_srpt=tt_srpt; + d->vts_file=vts_file; + + /** + * Determine which program chain we want to watch. This is based on the + * chapter number. + */ + ttn = tt_srpt->title[ dvd_title ].vts_ttn; // local + pgc_id = vts_file->vts_ptt_srpt->title[ttn-1].ptt[dvd_chapter].pgcn; // local + pgn = vts_file->vts_ptt_srpt->title[ttn-1].ptt[dvd_chapter].pgn; // local + d->cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc; + d->cur_cell = d->cur_pgc->program_map[pgn-1] - 1; // start playback here + d->packs_left=-1; // for Navi stuff + d->angle_seek=0; + + if( d->cur_pgc->cell_playback[d->cur_cell].block_type + == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle; + d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; + d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; + mp_msg(MSGT_DVD,MSGL_V, "DVD start cell: %d pack: 0x%X-0x%X \n",d->cur_cell,d->cur_pack,d->cell_last_pack); + + // ... (unimplemented) +// return NULL; + stream=new_stream(-1,STREAMTYPE_DVD); + stream->start_pos=(off_t)d->cur_pack*2048; + //stream->end_pos=0; + stream->priv=(void*)d; + return stream; +} +#endif + +//============ Open STDIN ============ + if(!strcmp(filename,"-")){ + // read from stdin + mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ReadSTDIN); + f=0; // 0=stdin + stream=new_stream(f,STREAMTYPE_STREAM); + return stream; + } + +#ifdef STREAMING + url = url_new(filename); + if(url) { + (*file_format)=autodetectProtocol( url, &f ); + if( (*file_format)==DEMUXER_TYPE_UNKNOWN ) { + mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, filename); + url_free(url); + return NULL; + } + f=streaming_start( &url, f, *file_format ); + if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, url->url); return NULL; } + mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ConnToServer, url->hostname ); + stream=new_stream(f,STREAMTYPE_STREAM); + return NULL; + } +#endif + +//============ Open plain FILE ============ + f=open(filename,O_RDONLY); + if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename);return NULL; } + len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET); + if (len == -1) + perror("Error: lseek failed to obtain video file size"); + else + if(verbose) +#ifdef _LARGEFILE_SOURCE + mp_msg(MSGT_OPEN,MSGL_V,"File size is %lld bytes\n", (long long)len); +#else + mp_msg(MSGT_OPEN,MSGL_V,"File size is %u bytes\n", (unsigned int)len); +#endif + stream=new_stream(f,STREAMTYPE_FILE); + stream->end_pos=len; + return stream; + +} + + +#ifdef USE_DVDREAD + +static int dvd_next_cell(dvd_priv_t *d){ + int next_cell=d->cur_cell; + + mp_msg(MSGT_DVD,MSGL_V, "dvd_next_cell: next1=0x%X \n",next_cell); + + if( d->cur_pgc->cell_playback[ next_cell ].block_type + == BLOCK_TYPE_ANGLE_BLOCK ) { + while(next_cell<d->cur_pgc->nr_of_cells){ + if( d->cur_pgc->cell_playback[next_cell].block_mode + == BLOCK_MODE_LAST_CELL ) break; + ++next_cell; + } + } + mp_msg(MSGT_DVD,MSGL_V, "dvd_next_cell: next2=0x%X \n",next_cell); + + ++next_cell; + if(next_cell>=d->cur_pgc->nr_of_cells) return -1; // EOF + if( d->cur_pgc->cell_playback[next_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ){ + next_cell+=dvd_angle; + if(next_cell>=d->cur_pgc->nr_of_cells) return -1; // EOF + } + mp_msg(MSGT_DVD,MSGL_V, "dvd_next_cell: next3=0x%X \n",next_cell); + return next_cell; +} + +int dvd_read_sector(dvd_priv_t *d,unsigned char* data){ + int len; + + if(d->packs_left==0){ + /** + * If we're not at the end of this cell, we can determine the next + * VOBU to display using the VOBU_SRI information section of the + * DSI. Using this value correctly follows the current angle, + * avoiding the doubled scenes in The Matrix, and makes our life + * really happy. + * + * Otherwise, we set our next address past the end of this cell to + * force the code above to go to the next cell in the program. + */ + if( d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL ) { + d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn + + ( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff ); + mp_msg(MSGT_DVD,MSGL_DBG2, "Navi new pos=0x%X \n",d->cur_pack); + } else { + // end of cell! find next cell! + mp_msg(MSGT_DVD,MSGL_V, "--- END OF CELL !!! ---\n"); + d->cur_pack=d->cell_last_pack+1; + } + } + +read_next: + + if(d->cur_pack>d->cell_last_pack){ + // end of cell! + int next=dvd_next_cell(d); + if(next>=0){ + d->cur_cell=next; + +// if( d->cur_pgc->cell_playback[d->cur_cell].block_type +// == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle; + d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; + d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; + mp_msg(MSGT_DVD,MSGL_V, "DVD next cell: %d pack: 0x%X-0x%X \n",d->cur_cell,d->cur_pack,d->cell_last_pack); + + } else return -1; // EOF + } + + len = DVDReadBlocks( d->title, d->cur_pack, 1, data ); + if(!len) return -1; //error + + if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF && + data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF){ + // found a Navi packet!!! +#if LIBDVDREAD_VERSION >= DVDREAD_VERSION(0,9,0) + navRead_DSI( &d->dsi_pack, &(data[ DSI_START_BYTE ]) ); +#else + navRead_DSI( &d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t) ); +#endif + if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ){ + mp_msg(MSGT_DVD,MSGL_V, "Invalid NAVI packet! lba=0x%X navi=0x%X \n", + d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn); + } else { + // process! + d->packs_left = d->dsi_pack.dsi_gi.vobu_ea; + mp_msg(MSGT_DVD,MSGL_DBG2, "Found NAVI packet! lba=0x%X len=%d \n",d->cur_pack,d->packs_left); + if(d->angle_seek){ + int skip=d->dsi_pack.sml_agli.data[dvd_angle].address; + if(skip) d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+skip; + d->angle_seek=0; + mp_msg(MSGT_DVD,MSGL_V, "Angle-seek synced! skip=%d new_lba=0x%X \n",skip,d->cur_pack); + } + } + ++d->cur_pack; + goto read_next; + } + + ++d->cur_pack; + if(d->packs_left>=0) --d->packs_left; + + if(d->angle_seek) goto read_next; // searching for Navi packet + + return d->cur_pack-1; +} + +void dvd_seek(dvd_priv_t *d,int pos){ + d->packs_left=-1; + d->cur_pack=pos; + +// check if we stay in current cell (speedup things, and avoid angle skip) +if(d->cur_pack>d->cell_last_pack || + d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector){ + + // ok, cell change, find the right cell! + d->cur_cell=0; + if( d->cur_pgc->cell_playback[d->cur_cell].block_type + == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle; + + while(1){ + int next; + d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; + if(d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector){ + d->cur_pack=d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; + break; + } + if(d->cur_pack<=d->cell_last_pack) break; // ok, we find it! :) + next=dvd_next_cell(d); + if(next<0){ +// d->cur_pack=d->cell_last_pack+1; + break; // we're after the last cell + } + d->cur_cell=next; + } + +} + +mp_msg(MSGT_DVD,MSGL_V, "DVD Seek! lba=0x%X cell=%d packs: 0x%X-0x%X \n", + d->cur_pack,d->cur_cell,d->cur_pgc->cell_playback[ d->cur_cell ].first_sector,d->cell_last_pack); + +// if we're in interleaved multi-angle cell, find the right angle chain! +// (read Navi block, and use the seamless angle jump table) +d->angle_seek=1; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/parse_es.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,117 @@ +//=================== MPEG-ES VIDEO PARSER ========================= + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +extern int verbose; // defined in mplayer.c + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" +#include "demuxer.h" + +#include "parse_es.h" + +//static unsigned char videobuffer[MAX_VIDEO_PACKET_SIZE]; +unsigned char* videobuffer=NULL; +int videobuf_len=0; +unsigned char videobuf_code[4]; +int videobuf_code_len=0; + +// sync video stream, and returns next packet code +int sync_video_packet(demux_stream_t *ds){ + int skipped=0; + // we need enough bytes in the buffer: + while(videobuf_code_len<4){ +#if 0 + int c; + c=demux_getc(ds);if(c<0){ return 0;} // EOF + videobuf_code[videobuf_code_len++]=c; +#else + videobuf_code[videobuf_code_len++]=demux_getc(ds); +#endif + } + // sync packet: + while(1){ + int c; + if(videobuf_code[0]==0 && + videobuf_code[1]==0 && + videobuf_code[2]==1) break; // synced + // shift buffer, drop first byte + ++skipped; + videobuf_code[0]=videobuf_code[1]; + videobuf_code[1]=videobuf_code[2]; + videobuf_code[2]=videobuf_code[3]; + c=demux_getc(ds);if(c<0){ return 0;} // EOF + videobuf_code[3]=c; + } + if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped (next: 0x1%02X)\n",skipped,videobuf_code[3]); + return 0x100|videobuf_code[3]; +} + +// return: packet length +int read_video_packet(demux_stream_t *ds){ +int packet_start; + + // SYNC STREAM +// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF) + + // COPY STARTCODE: + packet_start=videobuf_len; + videobuffer[videobuf_len+0]=videobuf_code[0]; + videobuffer[videobuf_len+1]=videobuf_code[1]; + videobuffer[videobuf_len+2]=videobuf_code[2]; + videobuffer[videobuf_len+3]=videobuf_code[3]; + videobuf_len+=4; + + // READ PACKET: + { unsigned int head=-1; + while(videobuf_len<VIDEOBUFFER_SIZE){ + int c=demux_getc(ds); + if(c<0) break; // EOF + videobuffer[videobuf_len++]=c; +#if 1 + head<<=8; + if(head==0x100) break; // synced + head|=c; +#else + if(videobuffer[videobuf_len-4]==0 && + videobuffer[videobuf_len-3]==0 && + videobuffer[videobuf_len-2]==1) break; // synced +#endif + } + } + + if(ds->eof){ + videobuf_code_len=0; // EOF, no next code + return videobuf_len-packet_start; + } + + videobuf_len-=4; + + mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: packet 0x1%02X len=%d (total=%d)\n",videobuffer[packet_start+3],videobuf_len-packet_start,videobuf_len); + + // Save next packet code: + videobuf_code[0]=videobuffer[videobuf_len]; + videobuf_code[1]=videobuffer[videobuf_len+1]; + videobuf_code[2]=videobuffer[videobuf_len+2]; + videobuf_code[3]=videobuffer[videobuf_len+3]; + videobuf_code_len=4; + + return videobuf_len-packet_start; +} + +// return: next packet code +int skip_video_packet(demux_stream_t *ds){ + + // SYNC STREAM +// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF) + + videobuf_code_len=0; // force resync + + // SYNC AGAIN: + return sync_video_packet(ds); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/parse_es.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,18 @@ + +#define MAX_VIDEO_PACKET_SIZE (224*1024+4) +#define VIDEOBUFFER_SIZE 0x100000 + +extern unsigned char* videobuffer; +extern int videobuf_len; +extern unsigned char videobuf_code[4]; +extern int videobuf_code_len; + +// sync video stream, and returns next packet code +int sync_video_packet(demux_stream_t *ds); + +// return: packet length +int read_video_packet(demux_stream_t *ds); + +// return: next packet code +int skip_video_packet(demux_stream_t *ds); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/stheader.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,94 @@ +// Stream headers: + +/* +typedef struct { + int driver; + // codec descriptor from codec.conf +} codecinfo_t; +*/ + +#ifdef HAVE_OGGVORBIS +#include <math.h> +#include <vorbis/codec.h> +typedef struct { + ogg_sync_state oy; /* sync and verify incoming physical bitstream */ + ogg_stream_state os; /* take physical pages, weld into a logical + stream of packets */ + ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ + ogg_packet op; /* one raw packet of data for decode */ + + vorbis_info vi; /* struct that stores all the static vorbis bitstream + settings */ + vorbis_comment vc; /* struct that stores all the bitstream user comments */ + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ +} ov_struct_t; +#endif + +typedef struct { + demux_stream_t *ds; + unsigned int format; + struct codecs_st *codec; + int inited; + // output format: + float timer; // value of old a_frame + int samplerate; + int samplesize; + int channels; + int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec) + int i_bps; // == bitrate (compressed bytes/sec) + // in buffers: + char* a_in_buffer; + int a_in_buffer_len; + int a_in_buffer_size; + // out buffers: + char* a_buffer; + int a_buffer_len; + int a_buffer_size; + int sample_format; + // win32 codec stuff: + AVIStreamHeader audio; + WAVEFORMATEX *wf; +// char wf_ext[64]; // in format + WAVEFORMATEX o_wf; // out format + HACMSTREAM srcstream; // handle + int audio_in_minsize; + int audio_out_minsize; + // other codecs: +// ac3_frame_t *ac3_frame; + void* ac3_frame; + int pcm_bswap; +#ifdef HAVE_OGGVORBIS + ov_struct_t *ov; // should be assigned on init +#endif +} sh_audio_t; + +typedef struct { + demux_stream_t *ds; + unsigned int format; + struct codecs_st *codec; + int inited; + // output format: + float timer; // value of old v_frame + float fps; + float frametime; // 1/fps + int i_bps; // == bitrate (compressed bytes/sec) + int disp_w,disp_h; // display size (filled by fileformat parser) +// int coded_w,coded_h; // coded size (filled by video codec) + float aspect; + unsigned int outfmtidx; +// unsigned int bitrate; + // buffers: + float num_frames; // number of frames played + int num_frames_decoded; // number of frames decoded + char *our_out_buffer; + // win32 codec stuff: + AVIStreamHeader video; + BITMAPINFOHEADER *bih; // in format + BITMAPINFOHEADER o_bih; // out format + HIC hic; // handle +} sh_video_t; + +sh_audio_t* new_sh_audio(demuxer_t *demuxer,int id); +sh_video_t* new_sh_video(demuxer_t *demuxer,int id); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/stream.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,188 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "stream.h" + +extern int verbose; // defined in mplayer.c + +#ifdef __FreeBSD__ +#include "vcd_read_fbsd.h" +#else +#include "vcd_read.h" +#endif + +#ifdef USE_DVDREAD +int dvd_read_sector(void* d,void* p2); +void dvd_seek(void* d,off_t pos); +#endif + +//=================== STREAMER ========================= + +int stream_fill_buffer(stream_t *s){ + int len; + if(s->eof){ s->buf_pos=s->buf_len=0; return 0; } + switch(s->type){ + case STREAMTYPE_FILE: + case STREAMTYPE_STREAM: + len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break; + case STREAMTYPE_VCD: +#ifdef VCD_CACHE + len=vcd_cache_read(s->fd,s->buffer);break; +#else + len=vcd_read(s->fd,s->buffer);break; +#endif +#ifdef USE_DVDREAD + case STREAMTYPE_DVD: { + off_t pos=dvd_read_sector(s->priv,s->buffer); + if(pos>=0){ + len=2048; // full sector + s->pos=2048*pos-len; + } else len=-1; // error + break; + } +#endif + default: len=0; + } + if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; } + s->buf_pos=0; + s->buf_len=len; + s->pos+=len; +// printf("[%d]",len);fflush(stdout); + return len; +} + +int stream_seek_long(stream_t *s,off_t pos){ +off_t newpos; + +// if(verbose>=3) printf("seek_long to 0x%X\n",(unsigned int)pos); + + s->buf_pos=s->buf_len=0; + + switch(s->type){ + case STREAMTYPE_FILE: + case STREAMTYPE_STREAM: +#ifdef _LARGEFILE_SOURCE + newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break; +#else + newpos=pos&(~(STREAM_BUFFER_SIZE-1));break; +#endif + case STREAMTYPE_VCD: + newpos=(pos/VCD_SECTOR_DATA)*VCD_SECTOR_DATA;break; + case STREAMTYPE_DVD: + newpos=pos/2048; newpos*=2048; break; + } + +if(verbose>=3){ +#ifdef _LARGEFILE_SOURCE + printf("s->pos=%llX newpos=%llX new_bufpos=%llX buflen=%X \n", + (long long)s->pos,(long long)newpos,(long long)pos,s->buf_len); +#else + printf("s->pos=%X newpos=%X new_bufpos=%X buflen=%X \n", + (unsigned int)s->pos,newpos,pos,s->buf_len); +#endif +} + + pos-=newpos; + +if(newpos==0 || newpos!=s->pos){ + switch(s->type){ + case STREAMTYPE_FILE: + s->pos=newpos; // real seek + if(lseek(s->fd,s->pos,SEEK_SET)<0) s->eof=1; + break; + case STREAMTYPE_VCD: + s->pos=newpos; // real seek +#ifdef VCD_CACHE + vcd_cache_seek(s->pos/VCD_SECTOR_DATA); +#else + vcd_set_msf(s->pos/VCD_SECTOR_DATA); +#endif + break; +#ifdef USE_DVDREAD + case STREAMTYPE_DVD: + s->pos=newpos; // real seek + dvd_seek(s->priv,s->pos/2048); + break; +#endif + case STREAMTYPE_STREAM: + //s->pos=newpos; // real seek + if(newpos<s->pos){ + mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n"); + return 1; + } + while(s->pos<newpos){ + if(stream_fill_buffer(s)<=0) break; // EOF + } + break; + } +// putchar('.');fflush(stdout); +//} else { +// putchar('%');fflush(stdout); +} + + stream_fill_buffer(s); + if(pos>=0 && pos<=s->buf_len){ + s->buf_pos=pos; // byte position in sector + return 1; + } + +// if(pos==s->buf_len) printf("XXX Seek to last byte of file -> EOF\n"); + +#ifdef _LARGEFILE_SOURCE + mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%llX !\n",(long long)(pos+newpos)); +#else + mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%X !\n",(pos+newpos)); +#endif + return 0; +} + + +void stream_reset(stream_t *s){ + if(s->eof){ + s->pos=0; //ftell(f); +// s->buf_pos=s->buf_len=0; + s->eof=0; + } + //stream_seek(s,0); +} + +stream_t* new_memory_stream(unsigned char* data,int len){ + stream_t *s=malloc(sizeof(stream_t)+len); + s->fd=-1; + s->type=STREAMTYPE_MEMORY; + s->buf_pos=0; s->buf_len=len; + s->start_pos=0; s->end_pos=len; + stream_reset(s); + s->pos=len; + memcpy(s->buffer,data,len); + return s; +} + +stream_t* new_stream(int fd,int type){ + stream_t *s=malloc(sizeof(stream_t)); + s->fd=fd; + s->type=type; + s->buf_pos=s->buf_len=0; + s->start_pos=s->end_pos=0; + s->priv=NULL; + stream_reset(s); + return s; +} + +void free_stream(stream_t *s){ + if(s->priv) free(s->priv); + free(s); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/stream.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,141 @@ +#ifndef __STREAM_H +#define __STREAM_H + +#define STREAM_BUFFER_SIZE 2048 + +#define STREAMTYPE_FILE 0 +#define STREAMTYPE_VCD 1 +#define STREAMTYPE_STREAM 2 // same as FILE but no seeking (for stdin) +#define STREAMTYPE_DVD 3 +#define STREAMTYPE_MEMORY 4 + +#define VCD_SECTOR_SIZE 2352 +#define VCD_SECTOR_OFFS 24 +#define VCD_SECTOR_DATA 2324 + +int vcd_seek_to_track(int fd,int track); +void vcd_read_toc(int fd); + +#ifdef VCD_CACHE +void vcd_cache_init(int s); +#endif + +typedef struct { + int fd; + off_t pos; + int eof; + int type; // 0=file 1=VCD + unsigned int buf_pos,buf_len; + off_t start_pos,end_pos; + void* priv; // used for DVD + unsigned char buffer[STREAM_BUFFER_SIZE>VCD_SECTOR_SIZE?STREAM_BUFFER_SIZE:VCD_SECTOR_SIZE]; +} stream_t; + +int stream_fill_buffer(stream_t *s); + +int stream_seek_long(stream_t *s,off_t pos); + +inline static int stream_read_char(stream_t *s){ + return (s->buf_pos<s->buf_len)?s->buffer[s->buf_pos++]: + (stream_fill_buffer(s)?s->buffer[s->buf_pos++]:-256); +// if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++]; +// stream_fill_buffer(s); +// if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++]; +// return 0; // EOF +} + +inline static unsigned int stream_read_word(stream_t *s){ + int x,y; + x=stream_read_char(s); + y=stream_read_char(s); + return (x<<8)|y; +} + +inline static unsigned int stream_read_dword(stream_t *s){ + unsigned int y; + y=stream_read_char(s); + y=(y<<8)|stream_read_char(s); + y=(y<<8)|stream_read_char(s); + y=(y<<8)|stream_read_char(s); + return y; +} + +inline static unsigned int stream_read_word_le(stream_t *s){ + int x,y; + x=stream_read_char(s); + y=stream_read_char(s); + return (y<<8)|x; +} + +inline static unsigned int stream_read_dword_le(stream_t *s){ + unsigned int y; + y=stream_read_char(s); + y|=stream_read_char(s)<<8; + y|=stream_read_char(s)<<16; + y|=stream_read_char(s)<<24; + return y; +} + +inline static void stream_read(stream_t *s,char* mem,int len){ + while(len>0){ + int x; + x=s->buf_len-s->buf_pos; + if(x==0){ + if(!stream_fill_buffer(s)) return; // EOF + x=s->buf_len-s->buf_pos; + } + if(s->buf_pos>s->buf_len) printf("stream_read: WARNING! s->buf_pos>s->buf_len\n"); + if(x>len) x=len; + memcpy(mem,&s->buffer[s->buf_pos],x); + s->buf_pos+=x; mem+=x; len-=x; + } +} + +inline static int stream_eof(stream_t *s){ + return s->eof; +} + +inline static off_t stream_tell(stream_t *s){ + return s->pos+s->buf_pos-s->buf_len; +} + +inline static int stream_seek(stream_t *s,off_t pos){ + +// if(verbose>=3) printf("seek to 0x%qX\n",(long long)pos); + + if(pos<s->pos){ + off_t x=pos-(s->pos-s->buf_len); + if(x>=0){ + s->buf_pos=x; +// putchar('*');fflush(stdout); + return 1; + } + } + + return stream_seek_long(s,pos); +} + +inline static int stream_skip(stream_t *s,int len){ + if(len<0 || (len>2*STREAM_BUFFER_SIZE && s->type!=STREAMTYPE_STREAM)){ + // negative or big skip! + return stream_seek(s,stream_tell(s)+len); + } + while(len>0){ + int x=s->buf_len-s->buf_pos; + if(x==0){ + if(!stream_fill_buffer(s)) return 0; // EOF + x=s->buf_len-s->buf_pos; + } + if(x>len) x=len; + //memcpy(mem,&s->buf[s->buf_pos],x); + s->buf_pos+=x; len-=x; + } + return 1; +} + +void stream_reset(stream_t *s); +stream_t* new_stream(int fd,int type); +void free_stream(stream_t *s); +stream_t* new_memory_stream(unsigned char* data,int len); + +#endif // __STREAM_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/test.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,66 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "mp_msg.h" + +#include "stream.h" +#include "demuxer.h" + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" +#include "codec-cfg.h" +#include "stheader.h" + +//-------------------------- + +// audio stream skip/resync functions requires only for seeking. +// (they should be implemented in the audio codec layer) +void skip_audio_frame(sh_audio_t *sh_audio){ +} +void resync_audio_stream(sh_audio_t *sh_audio){ +} + +// some globals: +int verbose=1; + +// AVI demuxer parameters: +int index_mode=-1; // -1=untouched 0=don't use index 1=use (geneate) index +int force_ni=0; // force non-interleaved AVI parsing +int pts_from_bps=1; // PTS: 0=interleaved 1=BPS-based + +//--------------- + +extern stream_t* open_stream(char* filename,int vcd_track,int* file_format); + +int main(int argc,char* argv[]){ + +stream_t* stream=NULL; +demuxer_t* demuxer=NULL; +int file_format=DEMUXER_TYPE_UNKNOWN; + + mp_msg_init(verbose+MSGL_STATUS); + + if(argc>1) + stream=open_stream(argv[1],0,&file_format); + else +// stream=open_stream("/3d/divx/405divx_sm_v2[1].avi",0,&file_format); + stream=open_stream("/dev/cdrom",2,&file_format); // VCD track 2 + + if(!stream){ + printf("Cannot open file/device\n"); + exit(1); + } + + printf("success: format: %d data: 0x%X - 0x%X\n",file_format, (int)(stream->start_pos),(int)(stream->end_pos)); + + demuxer=demux_open(stream,file_format,-1,-1,-1); + if(!demuxer){ + printf("Cannot open demuxer\n"); + exit(1); + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/url.c Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,117 @@ +/* + * URL Helper + * by Bertrand Baudet <bertrand_baudet@yahoo.com> + * (C) 2001, MPlayer team. + * + * TODO: + * Extract the username/password if present + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "url.h" + +URL_t* +url_new(char* url) { + int pos1, pos2; + URL_t* Curl; + char *ptr1, *ptr2; + + // Create the URL container + Curl = (URL_t*)malloc(sizeof(URL_t)); + if( Curl==NULL ) { + printf("Memory allocation failed!\n"); + return NULL; + } + // Initialisation of the URL container members + memset( Curl, 0, sizeof(URL_t) ); + + // Copy the url in the URL container + Curl->url = (char*)malloc(strlen(url)+1); + if( Curl->url==NULL ) { + printf("Memory allocation failed!\n"); + return NULL; + } + strcpy(Curl->url, url); + + // extract the protocol + ptr1 = strstr(url, "://"); + if( ptr1==NULL ) { + printf("Not an URL!\n"); + return NULL; + } + pos1 = ptr1-url; + Curl->protocol = (char*)malloc(pos1+1); + strncpy(Curl->protocol, url, pos1); + Curl->protocol[pos1] = '\0'; + + // look if the port is given + ptr2 = strstr(ptr1+3, ":"); + if( ptr2==NULL ) { + // No port is given + // Look if a path is given + ptr2 = strstr(ptr1+3, "/"); + if( ptr2==NULL ) { + // No path/filename + // So we have an URL like http://www.hostname.com + pos2 = strlen(url); + } else { + // We have an URL like http://www.hostname.com/file.txt + pos2 = ptr2-url; + } + } else { + // We have an URL beginning like http://www.hostname.com:1212 + // Get the port number + Curl->port = atoi(ptr2+1); + pos2 = ptr2-url; + } + // copy the hostname in the URL container + Curl->hostname = (char*)malloc(pos2-pos1-3+1); + if( Curl->hostname==NULL ) { + printf("Memory allocation failed!\n"); + return NULL; + } + strncpy(Curl->hostname, ptr1+3, pos2-pos1-3); + Curl->hostname[pos2-pos1-3] = '\0'; + + // Look if a path is given + ptr2 = strstr(ptr1+3, "/"); + if( ptr2!=NULL ) { + // A path/filename is given + // check if it's not a trailing '/' + if( strlen(ptr2)>1 ) { + // copy the path/filename in the URL container + Curl->file = (char*)malloc(strlen(ptr2)+1); + if( Curl->file==NULL ) { + printf("Memory allocation failed!\n"); + return NULL; + } + strcpy(Curl->file, ptr2); + } + } + // Check if a filenme was given or set, else set it with '/' + if( Curl->file==NULL ) { + Curl->file = (char*)malloc(2); + if( Curl->file==NULL ) { + printf("Memory allocation failed!\n"); + return NULL; + } + strcpy(Curl->file, "/"); + } + + return Curl; +} + +void +url_free(URL_t* url) { + if(!url) return; + if(url->url) free(url->url); + if(url->protocol) free(url->protocol); + if(url->hostname) free(url->hostname); + if(url->file) free(url->file); + if(url->username) free(url->username); + if(url->password) free(url->password); + free(url); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/url.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,23 @@ +/* + * URL Helper + * by Bertrand Baudet <bertrand_baudet@yahoo.com> + * (C) 2001, MPlayer team. + */ + +#ifndef __URL_H +#define __URL_H + +typedef struct { + char *url; + char *protocol; + char *hostname; + char *file; + unsigned int port; + char *username; + char *password; +} URL_t; + +URL_t* url_new(char* url); +void url_free(URL_t* url); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/vcd_read.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,280 @@ +//=================== VideoCD ========================== +#if defined(linux) || defined(sun) || defined(__bsdi__) + +#if defined(linux) +#include <linux/cdrom.h> +#elif defined(sun) +#include <sys/cdio.h> +static int sun_vcd_read(int, int*); +#elif defined(__bsdi__) +#include <dvd.h> +#endif + + +static struct cdrom_tocentry vcd_entry; + +static inline void vcd_set_msf(unsigned int sect){ + vcd_entry.cdte_addr.msf.frame=sect%75; + sect=sect/75; + vcd_entry.cdte_addr.msf.second=sect%60; + sect=sect/60; + vcd_entry.cdte_addr.msf.minute=sect; +} + +static inline unsigned int vcd_get_msf(){ + return vcd_entry.cdte_addr.msf.frame + + (vcd_entry.cdte_addr.msf.second+ + vcd_entry.cdte_addr.msf.minute*60)*75; +} + +int vcd_seek_to_track(int fd,int track){ + vcd_entry.cdte_format = CDROM_MSF; + vcd_entry.cdte_track = track; + if (ioctl(fd, CDROMREADTOCENTRY, &vcd_entry)) { + perror("ioctl dif1"); + return -1; + } + return VCD_SECTOR_DATA*vcd_get_msf(); +} + +int vcd_get_track_end(int fd,int track){ + struct cdrom_tochdr tochdr; + if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) + { perror("read CDROM toc header: "); return -1; } + vcd_entry.cdte_format = CDROM_MSF; + vcd_entry.cdte_track = track<tochdr.cdth_trk1?(track+1):CDROM_LEADOUT; + if (ioctl(fd, CDROMREADTOCENTRY, &vcd_entry)) { + perror("ioctl dif2"); + return -1; + } + return VCD_SECTOR_DATA*vcd_get_msf(); +} + +void vcd_read_toc(int fd){ + struct cdrom_tochdr tochdr; + int i; + if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) + { perror("read CDROM toc header: "); return; } + for (i=tochdr.cdth_trk0 ; i<=tochdr.cdth_trk1 ; i++){ + struct cdrom_tocentry tocentry; + + tocentry.cdte_track = i; + tocentry.cdte_format = CDROM_MSF; + + if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)==-1) + { perror("read CDROM toc entry: "); return; } + + mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n", + (int)tocentry.cdte_track, + (int)tocentry.cdte_adr, + (int)tocentry.cdte_ctrl, + (int)tocentry.cdte_format, + (int)tocentry.cdte_addr.msf.minute, + (int)tocentry.cdte_addr.msf.second, + (int)tocentry.cdte_addr.msf.frame, + (int)tocentry.cdte_datamode + ); + } +} + + +static char vcd_buf[VCD_SECTOR_SIZE]; + +static int vcd_read(int fd,char *mem){ +#if defined(linux) || defined(__bsdi__) + memcpy(vcd_buf,&vcd_entry.cdte_addr.msf,sizeof(struct cdrom_msf)); + if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; // EOF? + memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); +#elif defined(sun) + { + int offset; + if (sun_vcd_read(fd, &offset) <= 0) return 0; + memcpy(mem,&vcd_buf[offset],VCD_SECTOR_DATA); + } +#endif + + vcd_entry.cdte_addr.msf.frame++; + if (vcd_entry.cdte_addr.msf.frame==75){ + vcd_entry.cdte_addr.msf.frame=0; + vcd_entry.cdte_addr.msf.second++; + if (vcd_entry.cdte_addr.msf.second==60){ + vcd_entry.cdte_addr.msf.second=0; + vcd_entry.cdte_addr.msf.minute++; + } + } + + return VCD_SECTOR_DATA; +} + + +#ifdef sun +#include <sys/scsi/generic/commands.h> +#include <sys/scsi/impl/uscsi.h> + +#define SUN_XAREAD 1 /*fails on atapi drives*/ +#define SUN_MODE2READ 2 /*fails on atapi drives*/ +#define SUN_SCSIREAD 3 +#define SUN_VCDREAD SUN_SCSIREAD + +static int sun_vcd_read(int fd, int *offset) +{ +#if SUN_VCDREAD == SUN_XAREAD + struct cdrom_cdxa cdxa; + cdxa.cdxa_addr = vcd_get_msf(); + cdxa.cdxa_length = 1; + cdxa.cdxa_data = vcd_buf; + cdxa.cdxa_format = CDROM_XA_SECTOR_DATA; + + if(ioctl(fd,CDROMCDXA,&cdxa)==-1) { + perror("CDROMCDXA"); + return 0; + } + *offset = 0; +#elif SUN_VCDREAD == SUN_MODE2READ + struct cdrom_read cdread; + cdread.cdread_lba = 4*vcd_get_msf(); + cdread.cdread_bufaddr = vcd_buf; + cdread.cdread_buflen = 2336; + + if(ioctl(fd,CDROMREADMODE2,&cdread)==-1) { + perror("CDROMREADMODE2"); + return 0; + } + *offset = 8; +#elif SUN_VCDREAD == SUN_SCSIREAD + struct uscsi_cmd sc; + union scsi_cdb cdb; + int lba = vcd_get_msf(); + int blocks = 1; + int sector_type; + int sync, header_code, user_data, edc_ecc, error_field; + int sub_channel; + + /* sector_type = 3; *//* mode2 */ + sector_type = 5; /* mode2/form2 */ + sync = 0; + header_code = 0; + user_data = 1; + edc_ecc = 0; + error_field = 0; + sub_channel = 0; + + memset(&cdb, 0, sizeof(cdb)); + memset(&sc, 0, sizeof(sc)); + cdb.scc_cmd = 0xBE; + cdb.cdb_opaque[1] = (sector_type) << 2; + cdb.cdb_opaque[2] = (lba >> 24) & 0xff; + cdb.cdb_opaque[3] = (lba >> 16) & 0xff; + cdb.cdb_opaque[4] = (lba >> 8) & 0xff; + cdb.cdb_opaque[5] = lba & 0xff; + cdb.cdb_opaque[6] = (blocks >> 16) & 0xff; + cdb.cdb_opaque[7] = (blocks >> 8) & 0xff; + cdb.cdb_opaque[8] = blocks & 0xff; + cdb.cdb_opaque[9] = (sync << 7) | + (header_code << 5) | + (user_data << 4) | + (edc_ecc << 3) | + (error_field << 1); + cdb.cdb_opaque[10] = sub_channel; + + sc.uscsi_cdb = (caddr_t)&cdb; + sc.uscsi_cdblen = 12; + sc.uscsi_bufaddr = vcd_buf; + sc.uscsi_buflen = 2336; + sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ; + sc.uscsi_timeout = 20; + if (ioctl(fd, USCSICMD, &sc)) { + perror("USCSICMD: READ CD"); + return -1; + } + if (sc.uscsi_status) { + fprintf(stderr, "scsi command failed with status %d\n", sc.uscsi_status); + return -1; + } + *offset = 0; + return 1; +#else +#error SUN_VCDREAD +#endif +} +#endif /*sun*/ + + +//================== VCD CACHE ======================= +#ifdef VCD_CACHE + +static int vcd_cache_size=0; +static char *vcd_cache_data=NULL; +static int *vcd_cache_sectors=NULL; +static int vcd_cache_index=0; // index to first free (or oldest) cache sector +static int vcd_cache_current=-1; + +void vcd_cache_init(int s){ + vcd_cache_size=s; + vcd_cache_sectors=malloc(s*sizeof(int)); + vcd_cache_data=malloc(s*VCD_SECTOR_SIZE); + memset(vcd_cache_sectors,255,s*sizeof(int)); +} + +static inline void vcd_cache_seek(int sect){ + vcd_cache_current=sect; +} + +int vcd_cache_read(int fd,char* mem){ + int i; + char* vcd_buf; + + for(i=0;i<vcd_cache_size;i++) + if(vcd_cache_sectors[i]==vcd_cache_current){ + // found in the cache! :) + vcd_buf=&vcd_cache_data[i*VCD_SECTOR_SIZE]; + ++vcd_cache_current; + memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); + return VCD_SECTOR_DATA; + } + // NEW cache entry: + vcd_buf=&vcd_cache_data[vcd_cache_index*VCD_SECTOR_SIZE]; + vcd_cache_sectors[vcd_cache_index]=vcd_cache_current; + ++vcd_cache_index;if(vcd_cache_index>=vcd_cache_size)vcd_cache_index=0; + // read data! + vcd_set_msf(vcd_cache_current); +#if defined(linux) || defined(__bsdi__) + memcpy(vcd_buf,&vcd_entry.cdte_addr.msf,sizeof(struct cdrom_msf)); + if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; // EOF? + memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); +#elif defined(sun) + { + int offset; + if (sun_vcd_read(fd, &offset) <= 0) return 0; + memcpy(mem,&vcd_buf[offset],VCD_SECTOR_DATA); + } +#endif + ++vcd_cache_current; + return VCD_SECTOR_DATA; +} +#endif + +#else /* linux || sun */ + +int vcd_seek_to_track(int fd,int track) +{ + return -1; +} + +int vcd_get_track_end(int fd,int track) +{ + return -1; +} + +void vcd_read_toc(int fd) +{ +} + +static char vcd_buf[VCD_SECTOR_SIZE]; + +static int vcd_read(int fd,char *mem) +{ + return -1; +} + +#endif /* !linux && !sun */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/vcd_read_fbsd.h Sat Oct 20 18:49:08 2001 +0000 @@ -0,0 +1,143 @@ +#include <sys/cdio.h> +#include <sys/cdrio.h> + +//=================== VideoCD ========================== +#define CDROM_LEADOUT 0xAA + +typedef struct { + uint8_t sync [12]; + uint8_t header [4]; + uint8_t subheader [8]; + uint8_t data [2324]; + uint8_t spare [4]; +} cdsector_t; + +static cdsector_t vcd_buf; +static struct ioc_read_toc_single_entry vcd_entry; + +static inline void vcd_set_msf(unsigned int sect){ + vcd_entry.entry.addr.msf.frame=sect%75; + sect=sect/75; + vcd_entry.entry.addr.msf.second=sect%60; + sect=sect/60; + vcd_entry.entry.addr.msf.minute=sect; +} + +static inline unsigned int vcd_get_msf(){ + return vcd_entry.entry.addr.msf.frame + + (vcd_entry.entry.addr.msf.second+ + vcd_entry.entry.addr.msf.minute*60)*75; +} + +int vcd_seek_to_track(int fd,int track){ + vcd_entry.address_format = CD_MSF_FORMAT; + vcd_entry.track = track; + if (ioctl(fd, CDIOREADTOCENTRY, &vcd_entry)) { + perror("ioctl dif1"); + return -1; + } + return VCD_SECTOR_DATA*vcd_get_msf(); +} + +int vcd_get_track_end(int fd,int track){ + struct ioc_toc_header tochdr; + if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) + { perror("read CDROM toc header: "); return -1; } + vcd_entry.address_format = CD_MSF_FORMAT; + vcd_entry.track = track<tochdr.ending_track?(track+1):CDROM_LEADOUT; + if (ioctl(fd, CDIOREADTOCENTRY, &vcd_entry)) { + perror("ioctl dif2"); + return -1; + } + return VCD_SECTOR_DATA*vcd_get_msf(); +} + +void vcd_read_toc(int fd){ + struct ioc_toc_header tochdr; + int i; + if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) + { perror("read CDROM toc header: "); return; } + for (i=tochdr.starting_track ; i<=tochdr.ending_track ; i++){ + struct ioc_read_toc_single_entry tocentry; + + tocentry.track = i; + tocentry.address_format = CD_MSF_FORMAT; + + if (ioctl(fd,CDIOREADTOCENTRY,&tocentry)==-1) + { perror("read CDROM toc entry: "); return; } + + printf("track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n", + (int)tocentry.track, + (int)tocentry.entry.addr_type, + (int)tocentry.entry.control, + (int)tocentry.address_format, + (int)tocentry.entry.addr.msf.minute, + (int)tocentry.entry.addr.msf.second, + (int)tocentry.entry.addr.msf.frame + ); + } +} + +static int vcd_read(int fd,char *mem){ + + if (pread(fd,&vcd_buf,VCD_SECTOR_SIZE,vcd_get_msf()*VCD_SECTOR_SIZE) + != VCD_SECTOR_SIZE) return 0; // EOF? + + vcd_entry.entry.addr.msf.frame++; + if (vcd_entry.entry.addr.msf.frame==75){ + vcd_entry.entry.addr.msf.frame=0; + vcd_entry.entry.addr.msf.second++; + if (vcd_entry.entry.addr.msf.second==60){ + vcd_entry.entry.addr.msf.second=0; + vcd_entry.entry.addr.msf.minute++; + } + } + memcpy(mem,vcd_buf.data,VCD_SECTOR_DATA); + return VCD_SECTOR_DATA; +} + +//================== VCD CACHE ======================= +#ifdef VCD_CACHE + +static int vcd_cache_size=0; +static char *vcd_cache_data=NULL; +static int *vcd_cache_sectors=NULL; +static int vcd_cache_index=0; // index to first free (or oldest) cache sector +static int vcd_cache_current=-1; + +void vcd_cache_init(int s){ + vcd_cache_size=s; + vcd_cache_sectors=malloc(s*sizeof(int)); + vcd_cache_data=malloc(s*VCD_SECTOR_SIZE); + memset(vcd_cache_sectors,255,s*sizeof(int)); +} + +static inline void vcd_cache_seek(int sect){ + vcd_cache_current=sect; +} + +int vcd_cache_read(int fd,char* mem){ +int i; +char* vcd_buf; + for(i=0;i<vcd_cache_size;i++) + if(vcd_cache_sectors[i]==vcd_cache_current){ + // found in the cache! :) + vcd_buf=&vcd_cache_data[i*VCD_SECTOR_SIZE]; + ++vcd_cache_current; + memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); + return VCD_SECTOR_DATA; + } + // NEW cache entry: + vcd_buf=&vcd_cache_data[vcd_cache_index*VCD_SECTOR_SIZE]; + vcd_cache_sectors[vcd_cache_index]=vcd_cache_current; + ++vcd_cache_index;if(vcd_cache_index>=vcd_cache_size)vcd_cache_index=0; + // read data! + vcd_set_msf(vcd_cache_current); + memcpy(vcd_buf,&vcd_entry.entry.addr.msf,sizeof(struct cdrom_msf)); +/* if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; */ // EOF? + ++vcd_cache_current; + memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); + return VCD_SECTOR_DATA; +} + +#endif
--- a/network.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,592 +0,0 @@ -/* - * Network layer for MPlayer - * by Bertrand BAUDET <bertrand_baudet@yahoo.com> - * (C) 2001, MPlayer team. - */ - -//#define DUMP2FILE - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <fcntl.h> -#include <netdb.h> -#include <netinet/in.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> - -#include <pthread.h> - -#include <errno.h> -#include <ctype.h> - -#include "stream.h" -#include "demuxer.h" - -#include "network.h" -#include "http.h" -#include "url.h" -#include "asf.h" - -streaming_ctrl_t *streaming_ctrl; - -static ASF_StreamType_e streaming_type = ASF_Unknown_e; - -Net_Fifo * -net_fifo_new() { - Net_Fifo *net_fifo; - net_fifo = (Net_Fifo*)malloc(sizeof(Net_Fifo)); - if( net_fifo==NULL ) { - printf("Memory allocation failed\n"); - return NULL; - } - memset( net_fifo, 0, sizeof(Net_Fifo) ); - return net_fifo; -} - -void -net_fifo_free( Net_Fifo *net_fifo ) { - if( net_fifo->buffer!=NULL ) free( net_fifo->buffer ); - free( net_fifo ); -} - -int -net_fifo_push(Net_Fifo *net_fifo, char *buffer, int length ) { - char *ptr; - if( net_fifo==NULL || buffer==NULL || length<0 ) return -1; - - ptr = (char*)malloc(length+net_fifo->length); - if( ptr==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - if( net_fifo->buffer!=NULL ) { - memcpy( ptr, net_fifo->buffer, net_fifo->length ); - free( net_fifo->buffer ); - } - memcpy( ptr+net_fifo->length, buffer, length ); - net_fifo->buffer = ptr; - net_fifo->length += length; - return net_fifo->length; -} - -int -net_fifo_pop(Net_Fifo *net_fifo, char *buffer, int length ) { - char *ptr; - int len; - if( net_fifo==NULL || buffer==NULL || length<0 ) return -1; - if( net_fifo->buffer==NULL || net_fifo->length==0 ) return -1; - - len = MIN(net_fifo->length, length); - - ptr = (char*)malloc(net_fifo->length-len); - if( ptr==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - memcpy( buffer, net_fifo->buffer, len ); - if( net_fifo->length-len!=0 ) { - memcpy( ptr, net_fifo->buffer+len, net_fifo->length-len ); - free( net_fifo->buffer ); - net_fifo->buffer = ptr; - net_fifo->length -= len; - } else { - free( net_fifo->buffer ); - net_fifo->buffer = NULL; - net_fifo->length = 0; - } - return len; -} - -streaming_ctrl_t * -streaming_ctrl_new( ) { - streaming_ctrl_t *streaming_ctrl; - streaming_ctrl = (streaming_ctrl_t*)malloc(sizeof(streaming_ctrl_t)); - if( streaming_ctrl==NULL ) { - printf("Failed to allocate memory\n"); - return NULL; - } - memset( streaming_ctrl, 0, sizeof(streaming_ctrl_t) ); - streaming_ctrl->buffer = net_fifo_new(); - return streaming_ctrl; -} - -void -streaming_ctrl_free( streaming_ctrl_t *streaming_ctrl ) { - if( streaming_ctrl==NULL ) return; - if( streaming_ctrl->buffer!=NULL ) net_fifo_free( streaming_ctrl->buffer ); - free( streaming_ctrl ); -} - -int -readFromServer(int fd, char *buffer, int length) { - int ret; - int done=0; - fd_set set; - struct timeval tv; - if( buffer==NULL || length<0 ) return -1; - - -// fcntl( fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK ); - return read( fd, buffer, length ); - - do { - tv.tv_sec = 0; - tv.tv_usec = 10000; // 10 milli-seconds timeout - FD_ZERO( &set ); - FD_SET( fd, &set ); - ret = select( fd+1, &set, NULL, NULL, &tv ); - if( ret<0 ) { - perror("select"); - } else if( ret==0 ) { - printf("timeout\n"); - } - if( FD_ISSET(fd, &set) ) { - ret = read( fd, buffer, length ); - if( ret<0 ) { - if( errno!=EINPROGRESS ) { - } - } else { - done = 1; - } - } else { - return -1; - } - } while( !done ); - - return ret; -} - -// Connect to a server using a TCP connection -int -connect2Server(char *host, int port) { - int socket_server_fd; - int err, err_len; - fd_set set; - struct timeval tv; - struct sockaddr_in server_address; - - printf("Connecting to server %s:%d ...\n", host, port ); - - socket_server_fd = socket(AF_INET, SOCK_STREAM, 0); -// fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); - if( socket_server_fd==-1 ) { - perror("Failed to create socket"); - return -1; - } - - if( isalpha(host[0]) ) { - struct hostent *hp =(struct hostent*)gethostbyname( host ); - if( hp==NULL ) { - printf("Counldn't resolve name: %s\n", host); - return -1; - } - memcpy( (void*)&server_address.sin_addr.s_addr, (void*)hp->h_addr, hp->h_length ); - } else { - inet_pton(AF_INET, host, &server_address.sin_addr); - } - server_address.sin_family=AF_INET; - server_address.sin_port=htons(port); - - if( connect( socket_server_fd, (struct sockaddr*)&server_address, sizeof(server_address) )==-1 ) { - if( errno!=EINPROGRESS ) { - perror("Failed to connect to server"); - close(socket_server_fd); - return -1; - } - } - - tv.tv_sec = 0; - tv.tv_usec = 10000; // 10 milli-seconds timeout - FD_ZERO( &set ); - FD_SET( socket_server_fd, &set ); - if( select(socket_server_fd+1, NULL, &set, NULL, &tv)>0 ) { - err_len = sizeof( err ); - getsockopt( socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len ); - if( err ) { - printf("Couldn't connect to host %s\n", host ); - printf("Socket error: %d\n", err ); - close(socket_server_fd); - return -1; - } - } - return socket_server_fd; -} - -int -http_send_request( URL_t *url ) { - HTTP_header_t *http_hdr; - int fd; - http_hdr = http_new_header(); - http_set_uri( http_hdr, url->file ); - http_set_field( http_hdr, "User-Agent: MPlayer"); - http_set_field( http_hdr, "Connection: closed"); - if( http_build_request( http_hdr )==NULL ) { - return -1; - } - - fd = connect2Server( url->hostname, url->port ); - if( fd<0 ) { - return -1; - } - write( fd, http_hdr->buffer, http_hdr->buffer_size ); - http_free( http_hdr ); - - return fd; -} - -HTTP_header_t * -http_read_response( int fd ) { - HTTP_header_t *http_hdr; - char response[BUFFER_SIZE]; - int i; - - http_hdr = http_new_header(); - if( http_hdr==NULL ) { - return NULL; - } - - do { - i = readFromServer( fd, response, BUFFER_SIZE ); - if( i<0 ) { - printf("Read failed\n"); - } - http_response_append( http_hdr, response, i ); - } while( !http_is_header_entired( http_hdr ) ); - http_response_parse( http_hdr ); - return http_hdr; -} - -// By using the protocol, the extension of the file or the content-type -// we might be able to guess the streaming type. -int -autodetectProtocol(URL_t *url, int *fd_out) { - HTTP_header_t *http_hdr; - int fd=-1; - int i; - int redirect; - char *extension; - char *content_type; - char *next_url; - char response[1024]; - - do { - *fd_out=-1; - next_url = NULL; - extension = NULL; - content_type = NULL; - redirect = 0; - - if( url==NULL ) return DEMUXER_TYPE_UNKNOWN; - - // Get the extension of the file if present - if( url->file!=NULL ) { - for( i=strlen(url->file) ; i>0 ; i-- ) { - if( url->file[i]=='.' ) { - extension=(url->file)+i+1; - break; - } - } - } -// extension=NULL; - if( extension!=NULL ) { - printf("Extension: %s\n", extension ); - if( !strcasecmp(extension, "asf") || - !strcasecmp(extension, "wmv") || - !strcasecmp(extension, "asx") ) { - if( url->port==0 ) url->port = 80; - return DEMUXER_TYPE_ASF; - } - if( !strcasecmp(extension, "mpg") || - !strcasecmp(extension, "mpeg") ) { - if( url->port==0 ) url->port = 80; - return DEMUXER_TYPE_MPEG_PS; - } - if( !strcasecmp(extension, "avi") ) { - if( url->port==0 ) url->port = 80; - return DEMUXER_TYPE_AVI; - } - } - - // Checking for RTSP - if( !strcasecmp(url->protocol, "rtsp") ) { - printf("RTSP protocol not yet implemented!\n"); - return DEMUXER_TYPE_UNKNOWN; - } - - // Checking for ASF - if( !strcasecmp(url->protocol, "mms") ) { - if( url->port==0 ) url->port = 80; - return DEMUXER_TYPE_ASF; - } - - // HTTP based protocol - if( !strcasecmp(url->protocol, "http") ) { - if( url->port==0 ) url->port = 80; - - fd = http_send_request( url ); - if( fd<0 ) { - *fd_out=-1; - return DEMUXER_TYPE_UNKNOWN; - } - - http_hdr = http_read_response( fd ); - if( http_hdr==NULL ) { - close( fd ); - *fd_out=-1; - return DEMUXER_TYPE_UNKNOWN; - } - - *fd_out=fd; - //http_debug_hdr( http_hdr ); - - // Check if the response is an ICY status_code reason_phrase - if( !strcasecmp(http_hdr->protocol, "ICY") ) { - // Ok, we have detected an mp3 streaming - return DEMUXER_TYPE_MPEG_PS; - } - - switch( http_hdr->status_code ) { - case 200: // OK - // Look if we can use the Content-Type - content_type = http_get_field( http_hdr, "Content-Type" ); - if( content_type!=NULL ) { - printf("Content-Type: [%s]\n", content_type ); - printf("Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); - // Check for ASF - if( asf_http_streaming_type(content_type, NULL)!=ASF_Unknown_e ) { - return DEMUXER_TYPE_ASF; - } - // Check for MP3 streaming - // Some MP3 streaming server answer with audio/mpeg - if( !strcasecmp(content_type, "audio/mpeg") ) { - return DEMUXER_TYPE_MPEG_PS; - } - // Check for MPEG streaming - if( !strcasecmp(content_type, "video/mpeg") ) { - return DEMUXER_TYPE_MPEG_PS; - } - // AVI ??? => video/x-msvideo - if( !strcasecmp(content_type, "video/x-msvideo") ) { - return DEMUXER_TYPE_AVI; - } - } - break; - // Redirect - case 301: // Permanently - case 302: // Temporarily - // TODO: RFC 2616, recommand to detect infinite redirection loops - next_url = http_get_field( http_hdr, "Location" ); - if( next_url!=NULL ) { - close( fd ); - url_free( url ); - url = url_new( next_url ); - redirect = 1; - } - break; - default: - printf("Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); - close( fd ); - *fd_out=-1; - return DEMUXER_TYPE_UNKNOWN; - } - } - } while( redirect ); - - return DEMUXER_TYPE_UNKNOWN; -} - -int -nop_streaming_read( streaming_ctrl_t *streaming_ctrl ) { - char *buffer; - int len; - if( streaming_ctrl==NULL ) return -1; - len = streaming_ctrl->buffer->length; - if( len==0 ) return 0; - - buffer = (char*)malloc( len ); - if( buffer==NULL ) { - printf("Memory allocation failed\n"); - return -1; - } - net_fifo_pop( streaming_ctrl->buffer, buffer, len ); - write( streaming_ctrl->fd_pipe_in, buffer, len ); - free( buffer ); - return len; -} - -int -nop_streaming_start( streaming_ctrl_t *streaming_ctrl ) { - HTTP_header_t *http_hdr; - int fd; - if( streaming_ctrl==NULL ) return -1; - - fd = streaming_ctrl->fd_net; - if( fd<0 ) { - fd = http_send_request( *(streaming_ctrl->url) ); - if( fd<0 ) return -1; - http_hdr = http_read_response( fd ); - if( http_hdr==NULL ) return -1; - - switch( http_hdr->status_code ) { - case 200: // OK - printf("Content-Type: [%s]\n", http_get_field(http_hdr, "Content-Type") ); - printf("Content-Length: [%s]\n", http_get_field(http_hdr, "Content-Length") ); - if( http_hdr->body_size>0 ) { - write( streaming_ctrl->fd_pipe_in, http_hdr->body, http_hdr->body_size ); - } - break; - default: - printf("Server return %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); - close( fd ); - fd = -1; - } - streaming_ctrl->fd_net = fd; - } - - http_free( http_hdr ); - - streaming_ctrl->streaming_read = nop_streaming_read; - streaming_ctrl->prebuffer_size = 180000; -// streaming_ctrl->prebuffer_size = 0; - streaming_ctrl->buffering = 1; -// streaming_ctrl->buffering = 0; - streaming_ctrl->status = streaming_playing_e; - return fd; -} - -void -network_streaming(void *arg) { - char buffer[BUFFER_SIZE]; - fd_set fd_net_in; - int ret; - - arg = arg; - - do { - FD_ZERO( &fd_net_in ); - FD_SET( streaming_ctrl->fd_net, &fd_net_in ); - - ret = select( streaming_ctrl->fd_net+1, &fd_net_in, NULL, NULL, NULL ); - if( ret<0 ) { - perror("select"); - return; //exit(1); // FIXME! - } - if( FD_ISSET( streaming_ctrl->fd_net, &fd_net_in ) ) { - ret = readFromServer( streaming_ctrl->fd_net, buffer, BUFFER_SIZE ); - if( ret<=0 ) { - streaming_ctrl->status=streaming_stopped_e; - } else { -//printf(" push: 0x%02X\n", *((unsigned int*)buffer) ); - net_fifo_push( streaming_ctrl->buffer, buffer, ret ); - if( !streaming_ctrl->buffering ) { - do { - ret = streaming_ctrl->streaming_read( streaming_ctrl ); - if( ret<0 && streaming_ctrl->buffer->length<streaming_ctrl->prebuffer_size ) { - // Need buffering - streaming_ctrl->buffering = 1; - } - } while( streaming_ctrl->buffer->length>streaming_ctrl->prebuffer_size ); - } else { - if( streaming_ctrl->buffer->length>streaming_ctrl->prebuffer_size ) { - streaming_ctrl->buffering = 0; - printf("\n"); - } else { - printf(" Buffering: %d \%\r", (int)((float)(((float)streaming_ctrl->buffer->length)/((float)streaming_ctrl->prebuffer_size))*100) ); - fflush(stdout); - } - } - } - } else { - printf("Network fd not set\n"); - } - } while( streaming_ctrl->status==streaming_playing_e ); - - // Flush the buffer - while( streaming_ctrl->buffer->length>0 ) { - ret = streaming_ctrl->streaming_read( streaming_ctrl ); - if( ret<0 ) break; - } - -printf("Network thread done\n"); - - // Close to the pipe to stop mplayer. - close( streaming_ctrl->fd_pipe_in ); - -} - -int -streaming_start(URL_t **url, int fd, int streaming_type) { - int fd_pipe[2]; - // Open the pipe - if( pipe(fd_pipe)<0 ) { - printf("Pipe creation failed\n"); - return -1; - } - - streaming_ctrl = streaming_ctrl_new( ); - if( streaming_ctrl==NULL ) { - return -1; - } - streaming_ctrl->url = url; - streaming_ctrl->fd_pipe_in = fd_pipe[1]; - streaming_ctrl->fd_net = fd; - -#ifdef DUMP2FILE -{ - int fd_file; - fd_file = open("dump.stream", O_WRONLY | O_CREAT ); - if( fd_file<0 ) { - perror("open"); - } - streaming_ctrl->fd_pipe_in = fd_file; -} -#endif - - switch( streaming_type ) { - case DEMUXER_TYPE_ASF: - // Send the appropriate HTTP request - fd = asf_http_streaming_start( streaming_ctrl ); - break; - case DEMUXER_TYPE_AVI: - case DEMUXER_TYPE_MPEG_ES: - case DEMUXER_TYPE_MPEG_PS: - fd = nop_streaming_start( streaming_ctrl ); - break; - case DEMUXER_TYPE_UNKNOWN: - default: - printf("Unable to detect the streaming type\n"); - close( fd ); - free( streaming_ctrl ); - return -1; - } - - if( fd<0 ) { - free( streaming_ctrl ); - return -1; - } - - // Start the network thread - if( pthread_create( &(streaming_ctrl->thread_id), NULL , (void*)network_streaming, (void*)NULL)<0 ) { - printf("Unable to start the network thread.\n"); - close( fd ); - free( streaming_ctrl ); - return -1; - } -printf("Network thread created with id: %d\n", streaming_ctrl->thread_id ); - -// streaming_ctrl->status = streaming_stopped_e; - -// return fd; - return fd_pipe[0]; -} - -int -streaming_stop( ) { - streaming_ctrl->status = streaming_stopped_e; - return 0; -}
--- a/network.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Network layer for MPlayer - * by Bertrand BAUDET <bertrand_baudet@yahoo.com> - * (C) 2001, MPlayer team. - */ - -#ifndef __NETWORK_H -#define __NETWORK_H - -#include <pthread.h> - -#include "stream.h" - -#include "url.h" - -#define BUFFER_SIZE 2048 - -typedef enum { - streaming_stopped_e, - streaming_playing_e -} streaming_status; - -typedef struct { - char *buffer; - int length; -} Net_Fifo; - -typedef struct streaming_control { - URL_t **url; - int fd_net; - int fd_pipe_in; - streaming_status status; - pthread_t thread_id; - Net_Fifo *buffer; - int buffering; // boolean - int prebuffer_size; - int (*streaming_read)( struct streaming_control *stream_ctrl ); -} streaming_ctrl_t; - -Net_Fifo* net_fifo_new( ); -void net_fifo_free(Net_Fifo *net_fifo ); -int net_fifo_pop(Net_Fifo *net_fifo, char *buffer, int length ); -int net_fifo_push(Net_Fifo *net_fifo, char *buffer, int length ); - -int connect2Server(char *host, int port); -int readFromServer(int fd, char *buffer, int length ); -int autodetectProtocol( URL_t *url, int *fd_out ); - -#endif
--- a/open.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,437 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#ifdef __FreeBSD__ -#include <sys/cdrio.h> -#endif - -#include "stream.h" -#include "demuxer.h" - -#ifdef STREAMING -#include "url.h" -#include "network.h" -static URL_t* url; -#endif - -int dvd_title=0; -int dvd_chapter=1; -int dvd_angle=1; - -#ifdef USE_DVDREAD - -#include <dvdread/dvd_reader.h> -#include <dvdread/ifo_types.h> -#include <dvdread/ifo_read.h> -#include <dvdread/nav_read.h> - -#define DVDREAD_VERSION(maj,min,micro) ((maj)*10000 + (min)*100 + (micro)) - -/* - * Try to autodetect the libdvd-0.9.0 library - * (0.9.0 removed the <dvdread/dvd_udf.h> header, and moved the two defines - * DVD_VIDEO_LB_LEN and MAX_UDF_FILE_NAME_LEN from it to - * <dvdread/dvd_reader.h>) - */ -#if defined(DVD_VIDEO_LB_LEN) && defined(MAX_UDF_FILE_NAME_LEN) -#define LIBDVDREAD_VERSION DVDREAD_VERSION(0,9,0) -#else -#define LIBDVDREAD_VERSION DVDREAD_VERSION(0,8,0) -#endif - - -typedef struct { - dvd_reader_t *dvd; - dvd_file_t *title; - ifo_handle_t *vmg_file; - tt_srpt_t *tt_srpt; - ifo_handle_t *vts_file; - vts_ptt_srpt_t *vts_ptt_srpt; - pgc_t *cur_pgc; - // - int cur_cell; - int cur_pack; - int cell_last_pack; - // Navi: - int packs_left; - dsi_t dsi_pack; - int angle_seek; -} dvd_priv_t; - -#endif - -extern int vcd_get_track_end(int fd,int track); - -// Open a new stream (stdin/file/vcd/url) - -stream_t* open_stream(char* filename,int vcd_track,int* file_format){ -stream_t* stream=NULL; -int f=-1; -off_t len; -#ifdef VCD_CACHE -int vcd_cache_size=128; -#endif -#ifdef __FreeBSD__ -int bsize = VCD_SECTOR_SIZE; -#endif - -//============ Open VideoCD track ============== -if(vcd_track){ - int ret,ret2; - if(!filename) filename=DEFAULT_CDROM_DEVICE; - f=open(filename,O_RDONLY); - if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CdDevNotfound,filename);return NULL; } - vcd_read_toc(f); - ret2=vcd_get_track_end(f,vcd_track); - if(ret2<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");return NULL;} - ret=vcd_seek_to_track(f,vcd_track); - if(ret<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");return NULL;} -// seek_to_byte+=ret; - mp_msg(MSGT_OPEN,MSGL_V,"VCD start byte position: 0x%X end: 0x%X\n",ret,ret2); -#ifdef VCD_CACHE - vcd_cache_init(vcd_cache_size); -#endif -#ifdef __FreeBSD__ - if (ioctl (f, CDRIOCSETBLOCKSIZE, &bsize) == -1) { - perror ( "Error in CDRIOCSETBLOCKSIZE"); - } -#endif - stream=new_stream(f,STREAMTYPE_VCD); - stream->start_pos=ret; - stream->end_pos=ret2; - return stream; -} - -//============ Open DVD title ============== -#ifdef USE_DVDREAD -if(dvd_title){ -// int ret,ret2; - dvd_priv_t *d; - int ttn,pgc_id,pgn; - dvd_reader_t *dvd; - dvd_file_t *title; - ifo_handle_t *vmg_file; - tt_srpt_t *tt_srpt; - ifo_handle_t *vts_file; - /** - * Open the disc. - */ - if(!filename) filename=DEFAULT_DVD_DEVICE; - dvd = DVDOpen(filename); - if( !dvd ) { - mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename); - return NULL; - } - - mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_DVDwait); - - /** - * Load the video manager to find out the information about the titles on - * this disc. - */ - vmg_file = ifoOpen( dvd, 0 ); - if( !vmg_file ) { - mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open VMG info!\n"); - DVDClose( dvd ); - return NULL; - } - tt_srpt = vmg_file->tt_srpt; - /** - * Make sure our title number is valid. - */ - mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumTitles, - tt_srpt->nr_of_srpts ); - if( dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts ) { - mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidTitle, dvd_title); - ifoClose( vmg_file ); - DVDClose( dvd ); - return NULL; - } - --dvd_title; // remap 1.. -> 0.. - /** - * Make sure the chapter number is valid for this title. - */ - mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumChapters, - tt_srpt->title[dvd_title].nr_of_ptts ); - if( dvd_chapter<1 || dvd_chapter>tt_srpt->title[dvd_title].nr_of_ptts ) { - mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidChapter, dvd_chapter); - ifoClose( vmg_file ); - DVDClose( dvd ); - return NULL; - } - --dvd_chapter; // remap 1.. -> 0.. - /** - * Make sure the angle number is valid for this title. - */ - mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDnumAngles, - tt_srpt->title[dvd_title].nr_of_angles ); - if( dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles ) { - mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidAngle, dvd_angle); - ifoClose( vmg_file ); - DVDClose( dvd ); - return NULL; - } - --dvd_angle; // remap 1.. -> 0.. - /** - * Load the VTS information for the title set our title is in. - */ - vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr ); - if( !vts_file ) { - mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoIFO, - tt_srpt->title[dvd_title].title_set_nr ); - ifoClose( vmg_file ); - DVDClose( dvd ); - return NULL; - } - /** - * We've got enough info, time to open the title set data. - */ - title = DVDOpenFile( dvd, tt_srpt->title[dvd_title].title_set_nr, - DVD_READ_TITLE_VOBS ); - if( !title ) { - mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVOBs, - tt_srpt->title[dvd_title].title_set_nr ); - ifoClose( vts_file ); - ifoClose( vmg_file ); - DVDClose( dvd ); - return NULL; - } - - mp_msg(MSGT_OPEN,MSGL_INFO, MSGTR_DVDopenOk); - // store data - d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t)); - d->dvd=dvd; - d->title=title; - d->vmg_file=vmg_file; - d->tt_srpt=tt_srpt; - d->vts_file=vts_file; - - /** - * Determine which program chain we want to watch. This is based on the - * chapter number. - */ - ttn = tt_srpt->title[ dvd_title ].vts_ttn; // local - pgc_id = vts_file->vts_ptt_srpt->title[ttn-1].ptt[dvd_chapter].pgcn; // local - pgn = vts_file->vts_ptt_srpt->title[ttn-1].ptt[dvd_chapter].pgn; // local - d->cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc; - d->cur_cell = d->cur_pgc->program_map[pgn-1] - 1; // start playback here - d->packs_left=-1; // for Navi stuff - d->angle_seek=0; - - if( d->cur_pgc->cell_playback[d->cur_cell].block_type - == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle; - d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; - d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; - mp_msg(MSGT_DVD,MSGL_V, "DVD start cell: %d pack: 0x%X-0x%X \n",d->cur_cell,d->cur_pack,d->cell_last_pack); - - // ... (unimplemented) -// return NULL; - stream=new_stream(-1,STREAMTYPE_DVD); - stream->start_pos=(off_t)d->cur_pack*2048; - //stream->end_pos=0; - stream->priv=(void*)d; - return stream; -} -#endif - -//============ Open STDIN ============ - if(!strcmp(filename,"-")){ - // read from stdin - mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ReadSTDIN); - f=0; // 0=stdin - stream=new_stream(f,STREAMTYPE_STREAM); - return stream; - } - -#ifdef STREAMING - url = url_new(filename); - if(url) { - (*file_format)=autodetectProtocol( url, &f ); - if( (*file_format)==DEMUXER_TYPE_UNKNOWN ) { - mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, filename); - url_free(url); - return NULL; - } - f=streaming_start( &url, f, *file_format ); - if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_UnableOpenURL, url->url); return NULL; } - mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ConnToServer, url->hostname ); - stream=new_stream(f,STREAMTYPE_STREAM); - return NULL; - } -#endif - -//============ Open plain FILE ============ - f=open(filename,O_RDONLY); - if(f<0){ mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename);return NULL; } - len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET); - if (len == -1) - perror("Error: lseek failed to obtain video file size"); - else - if(verbose) -#ifdef _LARGEFILE_SOURCE - mp_msg(MSGT_OPEN,MSGL_V,"File size is %lld bytes\n", (long long)len); -#else - mp_msg(MSGT_OPEN,MSGL_V,"File size is %u bytes\n", (unsigned int)len); -#endif - stream=new_stream(f,STREAMTYPE_FILE); - stream->end_pos=len; - return stream; - -} - - -#ifdef USE_DVDREAD - -static int dvd_next_cell(dvd_priv_t *d){ - int next_cell=d->cur_cell; - - mp_msg(MSGT_DVD,MSGL_V, "dvd_next_cell: next1=0x%X \n",next_cell); - - if( d->cur_pgc->cell_playback[ next_cell ].block_type - == BLOCK_TYPE_ANGLE_BLOCK ) { - while(next_cell<d->cur_pgc->nr_of_cells){ - if( d->cur_pgc->cell_playback[next_cell].block_mode - == BLOCK_MODE_LAST_CELL ) break; - ++next_cell; - } - } - mp_msg(MSGT_DVD,MSGL_V, "dvd_next_cell: next2=0x%X \n",next_cell); - - ++next_cell; - if(next_cell>=d->cur_pgc->nr_of_cells) return -1; // EOF - if( d->cur_pgc->cell_playback[next_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK ){ - next_cell+=dvd_angle; - if(next_cell>=d->cur_pgc->nr_of_cells) return -1; // EOF - } - mp_msg(MSGT_DVD,MSGL_V, "dvd_next_cell: next3=0x%X \n",next_cell); - return next_cell; -} - -int dvd_read_sector(dvd_priv_t *d,unsigned char* data){ - int len; - - if(d->packs_left==0){ - /** - * If we're not at the end of this cell, we can determine the next - * VOBU to display using the VOBU_SRI information section of the - * DSI. Using this value correctly follows the current angle, - * avoiding the doubled scenes in The Matrix, and makes our life - * really happy. - * - * Otherwise, we set our next address past the end of this cell to - * force the code above to go to the next cell in the program. - */ - if( d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL ) { - d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn + - ( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff ); - mp_msg(MSGT_DVD,MSGL_DBG2, "Navi new pos=0x%X \n",d->cur_pack); - } else { - // end of cell! find next cell! - mp_msg(MSGT_DVD,MSGL_V, "--- END OF CELL !!! ---\n"); - d->cur_pack=d->cell_last_pack+1; - } - } - -read_next: - - if(d->cur_pack>d->cell_last_pack){ - // end of cell! - int next=dvd_next_cell(d); - if(next>=0){ - d->cur_cell=next; - -// if( d->cur_pgc->cell_playback[d->cur_cell].block_type -// == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle; - d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; - d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; - mp_msg(MSGT_DVD,MSGL_V, "DVD next cell: %d pack: 0x%X-0x%X \n",d->cur_cell,d->cur_pack,d->cell_last_pack); - - } else return -1; // EOF - } - - len = DVDReadBlocks( d->title, d->cur_pack, 1, data ); - if(!len) return -1; //error - - if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF && - data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF){ - // found a Navi packet!!! -#if LIBDVDREAD_VERSION >= DVDREAD_VERSION(0,9,0) - navRead_DSI( &d->dsi_pack, &(data[ DSI_START_BYTE ]) ); -#else - navRead_DSI( &d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t) ); -#endif - if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ){ - mp_msg(MSGT_DVD,MSGL_V, "Invalid NAVI packet! lba=0x%X navi=0x%X \n", - d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn); - } else { - // process! - d->packs_left = d->dsi_pack.dsi_gi.vobu_ea; - mp_msg(MSGT_DVD,MSGL_DBG2, "Found NAVI packet! lba=0x%X len=%d \n",d->cur_pack,d->packs_left); - if(d->angle_seek){ - int skip=d->dsi_pack.sml_agli.data[dvd_angle].address; - if(skip) d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+skip; - d->angle_seek=0; - mp_msg(MSGT_DVD,MSGL_V, "Angle-seek synced! skip=%d new_lba=0x%X \n",skip,d->cur_pack); - } - } - ++d->cur_pack; - goto read_next; - } - - ++d->cur_pack; - if(d->packs_left>=0) --d->packs_left; - - if(d->angle_seek) goto read_next; // searching for Navi packet - - return d->cur_pack-1; -} - -void dvd_seek(dvd_priv_t *d,int pos){ - d->packs_left=-1; - d->cur_pack=pos; - -// check if we stay in current cell (speedup things, and avoid angle skip) -if(d->cur_pack>d->cell_last_pack || - d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector){ - - // ok, cell change, find the right cell! - d->cur_cell=0; - if( d->cur_pgc->cell_playback[d->cur_cell].block_type - == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle; - - while(1){ - int next; - d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; - if(d->cur_pack<d->cur_pgc->cell_playback[ d->cur_cell ].first_sector){ - d->cur_pack=d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; - break; - } - if(d->cur_pack<=d->cell_last_pack) break; // ok, we find it! :) - next=dvd_next_cell(d); - if(next<0){ -// d->cur_pack=d->cell_last_pack+1; - break; // we're after the last cell - } - d->cur_cell=next; - } - -} - -mp_msg(MSGT_DVD,MSGL_V, "DVD Seek! lba=0x%X cell=%d packs: 0x%X-0x%X \n", - d->cur_pack,d->cur_cell,d->cur_pgc->cell_playback[ d->cur_cell ].first_sector,d->cell_last_pack); - -// if we're in interleaved multi-angle cell, find the right angle chain! -// (read Navi block, and use the seamless angle jump table) -d->angle_seek=1; - -} - -#endif
--- a/parse_es.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -//=================== MPEG-ES VIDEO PARSER ========================= - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -extern int verbose; // defined in mplayer.c - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#include "stream.h" -#include "demuxer.h" - -#include "parse_es.h" - -//static unsigned char videobuffer[MAX_VIDEO_PACKET_SIZE]; -unsigned char* videobuffer=NULL; -int videobuf_len=0; -unsigned char videobuf_code[4]; -int videobuf_code_len=0; - -// sync video stream, and returns next packet code -int sync_video_packet(demux_stream_t *ds){ - int skipped=0; - // we need enough bytes in the buffer: - while(videobuf_code_len<4){ -#if 0 - int c; - c=demux_getc(ds);if(c<0){ return 0;} // EOF - videobuf_code[videobuf_code_len++]=c; -#else - videobuf_code[videobuf_code_len++]=demux_getc(ds); -#endif - } - // sync packet: - while(1){ - int c; - if(videobuf_code[0]==0 && - videobuf_code[1]==0 && - videobuf_code[2]==1) break; // synced - // shift buffer, drop first byte - ++skipped; - videobuf_code[0]=videobuf_code[1]; - videobuf_code[1]=videobuf_code[2]; - videobuf_code[2]=videobuf_code[3]; - c=demux_getc(ds);if(c<0){ return 0;} // EOF - videobuf_code[3]=c; - } - if(skipped) mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: %d bytes skipped (next: 0x1%02X)\n",skipped,videobuf_code[3]); - return 0x100|videobuf_code[3]; -} - -// return: packet length -int read_video_packet(demux_stream_t *ds){ -int packet_start; - - // SYNC STREAM -// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF) - - // COPY STARTCODE: - packet_start=videobuf_len; - videobuffer[videobuf_len+0]=videobuf_code[0]; - videobuffer[videobuf_len+1]=videobuf_code[1]; - videobuffer[videobuf_len+2]=videobuf_code[2]; - videobuffer[videobuf_len+3]=videobuf_code[3]; - videobuf_len+=4; - - // READ PACKET: - { unsigned int head=-1; - while(videobuf_len<VIDEOBUFFER_SIZE){ - int c=demux_getc(ds); - if(c<0) break; // EOF - videobuffer[videobuf_len++]=c; -#if 1 - head<<=8; - if(head==0x100) break; // synced - head|=c; -#else - if(videobuffer[videobuf_len-4]==0 && - videobuffer[videobuf_len-3]==0 && - videobuffer[videobuf_len-2]==1) break; // synced -#endif - } - } - - if(ds->eof){ - videobuf_code_len=0; // EOF, no next code - return videobuf_len-packet_start; - } - - videobuf_len-=4; - - mp_dbg(MSGT_PARSEES,MSGL_DBG2,"videobuf: packet 0x1%02X len=%d (total=%d)\n",videobuffer[packet_start+3],videobuf_len-packet_start,videobuf_len); - - // Save next packet code: - videobuf_code[0]=videobuffer[videobuf_len]; - videobuf_code[1]=videobuffer[videobuf_len+1]; - videobuf_code[2]=videobuffer[videobuf_len+2]; - videobuf_code[3]=videobuffer[videobuf_len+3]; - videobuf_code_len=4; - - return videobuf_len-packet_start; -} - -// return: next packet code -int skip_video_packet(demux_stream_t *ds){ - - // SYNC STREAM -// if(!sync_video_packet(ds)) return 0; // cannot sync (EOF) - - videobuf_code_len=0; // force resync - - // SYNC AGAIN: - return sync_video_packet(ds); -}
--- a/parse_es.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ - -#define MAX_VIDEO_PACKET_SIZE (224*1024+4) -#define VIDEOBUFFER_SIZE 0x100000 - -extern unsigned char* videobuffer; -extern int videobuf_len; -extern unsigned char videobuf_code[4]; -extern int videobuf_code_len; - -// sync video stream, and returns next packet code -int sync_video_packet(demux_stream_t *ds); - -// return: packet length -int read_video_packet(demux_stream_t *ds); - -// return: next packet code -int skip_video_packet(demux_stream_t *ds); -
--- a/stheader.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -// Stream headers: - -/* -typedef struct { - int driver; - // codec descriptor from codec.conf -} codecinfo_t; -*/ - -#ifdef HAVE_OGGVORBIS -#include <math.h> -#include <vorbis/codec.h> -typedef struct { - ogg_sync_state oy; /* sync and verify incoming physical bitstream */ - ogg_stream_state os; /* take physical pages, weld into a logical - stream of packets */ - ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ - ogg_packet op; /* one raw packet of data for decode */ - - vorbis_info vi; /* struct that stores all the static vorbis bitstream - settings */ - vorbis_comment vc; /* struct that stores all the bitstream user comments */ - vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ - vorbis_block vb; /* local working space for packet->PCM decode */ -} ov_struct_t; -#endif - -typedef struct { - demux_stream_t *ds; - unsigned int format; - codecs_t *codec; - int inited; - // output format: - float timer; // value of old a_frame - int samplerate; - int samplesize; - int channels; - int o_bps; // == samplerate*samplesize*channels (uncompr. bytes/sec) - int i_bps; // == bitrate (compressed bytes/sec) - // in buffers: - char* a_in_buffer; - int a_in_buffer_len; - int a_in_buffer_size; - // out buffers: - char* a_buffer; - int a_buffer_len; - int a_buffer_size; - int sample_format; - // win32 codec stuff: - AVIStreamHeader audio; - WAVEFORMATEX *wf; -// char wf_ext[64]; // in format - WAVEFORMATEX o_wf; // out format - HACMSTREAM srcstream; // handle - int audio_in_minsize; - int audio_out_minsize; - // other codecs: -// ac3_frame_t *ac3_frame; - void* ac3_frame; - int pcm_bswap; -#ifdef HAVE_OGGVORBIS - ov_struct_t *ov; // should be assigned on init -#endif -} sh_audio_t; - -typedef struct { - demux_stream_t *ds; - unsigned int format; - codecs_t *codec; - int inited; - // output format: - float timer; // value of old v_frame - float fps; - float frametime; // 1/fps - int i_bps; // == bitrate (compressed bytes/sec) - int disp_w,disp_h; // display size (filled by fileformat parser) -// int coded_w,coded_h; // coded size (filled by video codec) - float aspect; - unsigned int outfmtidx; -// unsigned int bitrate; - // buffers: - float num_frames; // number of frames played - int num_frames_decoded; // number of frames decoded - char *our_out_buffer; - // win32 codec stuff: - AVIStreamHeader video; - BITMAPINFOHEADER *bih; // in format - BITMAPINFOHEADER o_bih; // out format - HIC hic; // handle -} sh_video_t; - -sh_audio_t* new_sh_audio(demuxer_t *demuxer,int id); -sh_video_t* new_sh_video(demuxer_t *demuxer,int id); -
--- a/stream.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <fcntl.h> - -#include "config.h" -#include "mp_msg.h" -#include "help_mp.h" - -#include "stream.h" - -extern int verbose; // defined in mplayer.c - -#ifdef __FreeBSD__ -#include "vcd_read_fbsd.c" -#else -#include "vcd_read.c" -#endif - -#ifdef USE_DVDREAD -int dvd_read_sector(void* d,void* p2); -void dvd_seek(void* d,off_t pos); -#endif - -//=================== STREAMER ========================= - -int stream_fill_buffer(stream_t *s){ - int len; - if(s->eof){ s->buf_pos=s->buf_len=0; return 0; } - switch(s->type){ - case STREAMTYPE_FILE: - case STREAMTYPE_STREAM: - len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break; - case STREAMTYPE_VCD: -#ifdef VCD_CACHE - len=vcd_cache_read(s->fd,s->buffer);break; -#else - len=vcd_read(s->fd,s->buffer);break; -#endif -#ifdef USE_DVDREAD - case STREAMTYPE_DVD: { - off_t pos=dvd_read_sector(s->priv,s->buffer); - if(pos>=0){ - len=2048; // full sector - s->pos=2048*pos-len; - } else len=-1; // error - break; - } -#endif - default: len=0; - } - if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; } - s->buf_pos=0; - s->buf_len=len; - s->pos+=len; -// printf("[%d]",len);fflush(stdout); - return len; -} - -int stream_seek_long(stream_t *s,off_t pos){ -off_t newpos; - -// if(verbose>=3) printf("seek_long to 0x%X\n",(unsigned int)pos); - - s->buf_pos=s->buf_len=0; - - switch(s->type){ - case STREAMTYPE_FILE: - case STREAMTYPE_STREAM: -#ifdef _LARGEFILE_SOURCE - newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break; -#else - newpos=pos&(~(STREAM_BUFFER_SIZE-1));break; -#endif - case STREAMTYPE_VCD: - newpos=(pos/VCD_SECTOR_DATA)*VCD_SECTOR_DATA;break; - case STREAMTYPE_DVD: - newpos=pos/2048; newpos*=2048; break; - } - -if(verbose>=3){ -#ifdef _LARGEFILE_SOURCE - printf("s->pos=%llX newpos=%llX new_bufpos=%llX buflen=%X \n", - (long long)s->pos,(long long)newpos,(long long)pos,s->buf_len); -#else - printf("s->pos=%X newpos=%X new_bufpos=%X buflen=%X \n", - (unsigned int)s->pos,newpos,pos,s->buf_len); -#endif -} - - pos-=newpos; - -if(newpos==0 || newpos!=s->pos){ - switch(s->type){ - case STREAMTYPE_FILE: - s->pos=newpos; // real seek - if(lseek(s->fd,s->pos,SEEK_SET)<0) s->eof=1; - break; - case STREAMTYPE_VCD: - s->pos=newpos; // real seek -#ifdef VCD_CACHE - vcd_cache_seek(s->pos/VCD_SECTOR_DATA); -#else - vcd_set_msf(s->pos/VCD_SECTOR_DATA); -#endif - break; -#ifdef USE_DVDREAD - case STREAMTYPE_DVD: - s->pos=newpos; // real seek - dvd_seek(s->priv,s->pos/2048); - break; -#endif - case STREAMTYPE_STREAM: - //s->pos=newpos; // real seek - if(newpos<s->pos){ - mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n"); - return 1; - } - while(s->pos<newpos){ - if(stream_fill_buffer(s)<=0) break; // EOF - } - break; - } -// putchar('.');fflush(stdout); -//} else { -// putchar('%');fflush(stdout); -} - - stream_fill_buffer(s); - if(pos>=0 && pos<=s->buf_len){ - s->buf_pos=pos; // byte position in sector - return 1; - } - -// if(pos==s->buf_len) printf("XXX Seek to last byte of file -> EOF\n"); - -#ifdef _LARGEFILE_SOURCE - mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%llX !\n",(long long)(pos+newpos)); -#else - mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%X !\n",(pos+newpos)); -#endif - return 0; -} - - -void stream_reset(stream_t *s){ - if(s->eof){ - s->pos=0; //ftell(f); -// s->buf_pos=s->buf_len=0; - s->eof=0; - } - //stream_seek(s,0); -} - -stream_t* new_memory_stream(unsigned char* data,int len){ - stream_t *s=malloc(sizeof(stream_t)+len); - s->fd=-1; - s->type=STREAMTYPE_MEMORY; - s->buf_pos=0; s->buf_len=len; - s->start_pos=0; s->end_pos=len; - stream_reset(s); - s->pos=len; - memcpy(s->buffer,data,len); - return s; -} - -stream_t* new_stream(int fd,int type){ - stream_t *s=malloc(sizeof(stream_t)); - s->fd=fd; - s->type=type; - s->buf_pos=s->buf_len=0; - s->start_pos=s->end_pos=0; - s->priv=NULL; - stream_reset(s); - return s; -} - -void free_stream(stream_t *s){ - if(s->priv) free(s->priv); - free(s); -} - -
--- a/stream.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -#ifndef __STREAM_H -#define __STREAM_H - -#define STREAM_BUFFER_SIZE 2048 - -#define STREAMTYPE_FILE 0 -#define STREAMTYPE_VCD 1 -#define STREAMTYPE_STREAM 2 // same as FILE but no seeking (for stdin) -#define STREAMTYPE_DVD 3 -#define STREAMTYPE_MEMORY 4 - -#define VCD_SECTOR_SIZE 2352 -#define VCD_SECTOR_OFFS 24 -#define VCD_SECTOR_DATA 2324 - -int vcd_seek_to_track(int fd,int track); -void vcd_read_toc(int fd); - -#ifdef VCD_CACHE -void vcd_cache_init(int s); -#endif - -typedef struct { - int fd; - off_t pos; - int eof; - int type; // 0=file 1=VCD - unsigned int buf_pos,buf_len; - off_t start_pos,end_pos; - void* priv; // used for DVD - unsigned char buffer[STREAM_BUFFER_SIZE>VCD_SECTOR_SIZE?STREAM_BUFFER_SIZE:VCD_SECTOR_SIZE]; -} stream_t; - -int stream_fill_buffer(stream_t *s); - -int stream_seek_long(stream_t *s,off_t pos); - -inline static int stream_read_char(stream_t *s){ - return (s->buf_pos<s->buf_len)?s->buffer[s->buf_pos++]: - (stream_fill_buffer(s)?s->buffer[s->buf_pos++]:-256); -// if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++]; -// stream_fill_buffer(s); -// if(s->buf_pos<s->buf_len) return s->buffer[s->buf_pos++]; -// return 0; // EOF -} - -inline static unsigned int stream_read_word(stream_t *s){ - int x,y; - x=stream_read_char(s); - y=stream_read_char(s); - return (x<<8)|y; -} - -inline static unsigned int stream_read_dword(stream_t *s){ - unsigned int y; - y=stream_read_char(s); - y=(y<<8)|stream_read_char(s); - y=(y<<8)|stream_read_char(s); - y=(y<<8)|stream_read_char(s); - return y; -} - -inline static unsigned int stream_read_word_le(stream_t *s){ - int x,y; - x=stream_read_char(s); - y=stream_read_char(s); - return (y<<8)|x; -} - -inline static unsigned int stream_read_dword_le(stream_t *s){ - unsigned int y; - y=stream_read_char(s); - y|=stream_read_char(s)<<8; - y|=stream_read_char(s)<<16; - y|=stream_read_char(s)<<24; - return y; -} - -inline static void stream_read(stream_t *s,char* mem,int len){ - while(len>0){ - int x; - x=s->buf_len-s->buf_pos; - if(x==0){ - if(!stream_fill_buffer(s)) return; // EOF - x=s->buf_len-s->buf_pos; - } - if(s->buf_pos>s->buf_len) printf("stream_read: WARNING! s->buf_pos>s->buf_len\n"); - if(x>len) x=len; - memcpy(mem,&s->buffer[s->buf_pos],x); - s->buf_pos+=x; mem+=x; len-=x; - } -} - -inline static int stream_eof(stream_t *s){ - return s->eof; -} - -inline static off_t stream_tell(stream_t *s){ - return s->pos+s->buf_pos-s->buf_len; -} - -inline static int stream_seek(stream_t *s,off_t pos){ - -// if(verbose>=3) printf("seek to 0x%qX\n",(long long)pos); - - if(pos<s->pos){ - off_t x=pos-(s->pos-s->buf_len); - if(x>=0){ - s->buf_pos=x; -// putchar('*');fflush(stdout); - return 1; - } - } - - return stream_seek_long(s,pos); -} - -inline static int stream_skip(stream_t *s,int len){ - if(len<0 || (len>2*STREAM_BUFFER_SIZE && s->type!=STREAMTYPE_STREAM)){ - // negative or big skip! - return stream_seek(s,stream_tell(s)+len); - } - while(len>0){ - int x=s->buf_len-s->buf_pos; - if(x==0){ - if(!stream_fill_buffer(s)) return 0; // EOF - x=s->buf_len-s->buf_pos; - } - if(x>len) x=len; - //memcpy(mem,&s->buf[s->buf_pos],x); - s->buf_pos+=x; len-=x; - } - return 1; -} - -void stream_reset(stream_t *s); -stream_t* new_stream(int fd,int type); -void free_stream(stream_t *s); -stream_t* new_memory_stream(unsigned char* data,int len); - -#endif // __STREAM_H
--- a/url.c Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * URL Helper - * by Bertrand Baudet <bertrand_baudet@yahoo.com> - * (C) 2001, MPlayer team. - * - * TODO: - * Extract the username/password if present - */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include "url.h" - -URL_t* -url_new(char* url) { - int pos1, pos2; - URL_t* Curl; - char *ptr1, *ptr2; - - // Create the URL container - Curl = (URL_t*)malloc(sizeof(URL_t)); - if( Curl==NULL ) { - printf("Memory allocation failed!\n"); - return NULL; - } - // Initialisation of the URL container members - memset( Curl, 0, sizeof(URL_t) ); - - // Copy the url in the URL container - Curl->url = (char*)malloc(strlen(url)+1); - if( Curl->url==NULL ) { - printf("Memory allocation failed!\n"); - return NULL; - } - strcpy(Curl->url, url); - - // extract the protocol - ptr1 = strstr(url, "://"); - if( ptr1==NULL ) { - printf("Not an URL!\n"); - return NULL; - } - pos1 = ptr1-url; - Curl->protocol = (char*)malloc(pos1+1); - strncpy(Curl->protocol, url, pos1); - Curl->protocol[pos1] = '\0'; - - // look if the port is given - ptr2 = strstr(ptr1+3, ":"); - if( ptr2==NULL ) { - // No port is given - // Look if a path is given - ptr2 = strstr(ptr1+3, "/"); - if( ptr2==NULL ) { - // No path/filename - // So we have an URL like http://www.hostname.com - pos2 = strlen(url); - } else { - // We have an URL like http://www.hostname.com/file.txt - pos2 = ptr2-url; - } - } else { - // We have an URL beginning like http://www.hostname.com:1212 - // Get the port number - Curl->port = atoi(ptr2+1); - pos2 = ptr2-url; - } - // copy the hostname in the URL container - Curl->hostname = (char*)malloc(pos2-pos1-3+1); - if( Curl->hostname==NULL ) { - printf("Memory allocation failed!\n"); - return NULL; - } - strncpy(Curl->hostname, ptr1+3, pos2-pos1-3); - Curl->hostname[pos2-pos1-3] = '\0'; - - // Look if a path is given - ptr2 = strstr(ptr1+3, "/"); - if( ptr2!=NULL ) { - // A path/filename is given - // check if it's not a trailing '/' - if( strlen(ptr2)>1 ) { - // copy the path/filename in the URL container - Curl->file = (char*)malloc(strlen(ptr2)+1); - if( Curl->file==NULL ) { - printf("Memory allocation failed!\n"); - return NULL; - } - strcpy(Curl->file, ptr2); - } - } - // Check if a filenme was given or set, else set it with '/' - if( Curl->file==NULL ) { - Curl->file = (char*)malloc(2); - if( Curl->file==NULL ) { - printf("Memory allocation failed!\n"); - return NULL; - } - strcpy(Curl->file, "/"); - } - - return Curl; -} - -void -url_free(URL_t* url) { - if(!url) return; - if(url->url) free(url->url); - if(url->protocol) free(url->protocol); - if(url->hostname) free(url->hostname); - if(url->file) free(url->file); - if(url->username) free(url->username); - if(url->password) free(url->password); - free(url); -}
--- a/url.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/* - * URL Helper - * by Bertrand Baudet <bertrand_baudet@yahoo.com> - * (C) 2001, MPlayer team. - */ - -#ifndef __URL_H -#define __URL_H - -typedef struct { - char *url; - char *protocol; - char *hostname; - char *file; - unsigned int port; - char *username; - char *password; -} URL_t; - -URL_t* url_new(char* url); -void url_free(URL_t* url); - -#endif
--- a/vcd_read.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,280 +0,0 @@ -//=================== VideoCD ========================== -#if defined(linux) || defined(sun) || defined(__bsdi__) - -#if defined(linux) -#include <linux/cdrom.h> -#elif defined(sun) -#include <sys/cdio.h> -static int sun_vcd_read(int, int*); -#elif defined(__bsdi__) -#include <dvd.h> -#endif - - -static struct cdrom_tocentry vcd_entry; - -static inline void vcd_set_msf(unsigned int sect){ - vcd_entry.cdte_addr.msf.frame=sect%75; - sect=sect/75; - vcd_entry.cdte_addr.msf.second=sect%60; - sect=sect/60; - vcd_entry.cdte_addr.msf.minute=sect; -} - -static inline unsigned int vcd_get_msf(){ - return vcd_entry.cdte_addr.msf.frame + - (vcd_entry.cdte_addr.msf.second+ - vcd_entry.cdte_addr.msf.minute*60)*75; -} - -int vcd_seek_to_track(int fd,int track){ - vcd_entry.cdte_format = CDROM_MSF; - vcd_entry.cdte_track = track; - if (ioctl(fd, CDROMREADTOCENTRY, &vcd_entry)) { - perror("ioctl dif1"); - return -1; - } - return VCD_SECTOR_DATA*vcd_get_msf(); -} - -int vcd_get_track_end(int fd,int track){ - struct cdrom_tochdr tochdr; - if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) - { perror("read CDROM toc header: "); return -1; } - vcd_entry.cdte_format = CDROM_MSF; - vcd_entry.cdte_track = track<tochdr.cdth_trk1?(track+1):CDROM_LEADOUT; - if (ioctl(fd, CDROMREADTOCENTRY, &vcd_entry)) { - perror("ioctl dif2"); - return -1; - } - return VCD_SECTOR_DATA*vcd_get_msf(); -} - -void vcd_read_toc(int fd){ - struct cdrom_tochdr tochdr; - int i; - if (ioctl(fd,CDROMREADTOCHDR,&tochdr)==-1) - { perror("read CDROM toc header: "); return; } - for (i=tochdr.cdth_trk0 ; i<=tochdr.cdth_trk1 ; i++){ - struct cdrom_tocentry tocentry; - - tocentry.cdte_track = i; - tocentry.cdte_format = CDROM_MSF; - - if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)==-1) - { perror("read CDROM toc entry: "); return; } - - mp_msg(MSGT_OPEN,MSGL_INFO,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n", - (int)tocentry.cdte_track, - (int)tocentry.cdte_adr, - (int)tocentry.cdte_ctrl, - (int)tocentry.cdte_format, - (int)tocentry.cdte_addr.msf.minute, - (int)tocentry.cdte_addr.msf.second, - (int)tocentry.cdte_addr.msf.frame, - (int)tocentry.cdte_datamode - ); - } -} - - -static char vcd_buf[VCD_SECTOR_SIZE]; - -static int vcd_read(int fd,char *mem){ -#if defined(linux) || defined(__bsdi__) - memcpy(vcd_buf,&vcd_entry.cdte_addr.msf,sizeof(struct cdrom_msf)); - if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; // EOF? - memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); -#elif defined(sun) - { - int offset; - if (sun_vcd_read(fd, &offset) <= 0) return 0; - memcpy(mem,&vcd_buf[offset],VCD_SECTOR_DATA); - } -#endif - - vcd_entry.cdte_addr.msf.frame++; - if (vcd_entry.cdte_addr.msf.frame==75){ - vcd_entry.cdte_addr.msf.frame=0; - vcd_entry.cdte_addr.msf.second++; - if (vcd_entry.cdte_addr.msf.second==60){ - vcd_entry.cdte_addr.msf.second=0; - vcd_entry.cdte_addr.msf.minute++; - } - } - - return VCD_SECTOR_DATA; -} - - -#ifdef sun -#include <sys/scsi/generic/commands.h> -#include <sys/scsi/impl/uscsi.h> - -#define SUN_XAREAD 1 /*fails on atapi drives*/ -#define SUN_MODE2READ 2 /*fails on atapi drives*/ -#define SUN_SCSIREAD 3 -#define SUN_VCDREAD SUN_SCSIREAD - -static int sun_vcd_read(int fd, int *offset) -{ -#if SUN_VCDREAD == SUN_XAREAD - struct cdrom_cdxa cdxa; - cdxa.cdxa_addr = vcd_get_msf(); - cdxa.cdxa_length = 1; - cdxa.cdxa_data = vcd_buf; - cdxa.cdxa_format = CDROM_XA_SECTOR_DATA; - - if(ioctl(fd,CDROMCDXA,&cdxa)==-1) { - perror("CDROMCDXA"); - return 0; - } - *offset = 0; -#elif SUN_VCDREAD == SUN_MODE2READ - struct cdrom_read cdread; - cdread.cdread_lba = 4*vcd_get_msf(); - cdread.cdread_bufaddr = vcd_buf; - cdread.cdread_buflen = 2336; - - if(ioctl(fd,CDROMREADMODE2,&cdread)==-1) { - perror("CDROMREADMODE2"); - return 0; - } - *offset = 8; -#elif SUN_VCDREAD == SUN_SCSIREAD - struct uscsi_cmd sc; - union scsi_cdb cdb; - int lba = vcd_get_msf(); - int blocks = 1; - int sector_type; - int sync, header_code, user_data, edc_ecc, error_field; - int sub_channel; - - /* sector_type = 3; *//* mode2 */ - sector_type = 5; /* mode2/form2 */ - sync = 0; - header_code = 0; - user_data = 1; - edc_ecc = 0; - error_field = 0; - sub_channel = 0; - - memset(&cdb, 0, sizeof(cdb)); - memset(&sc, 0, sizeof(sc)); - cdb.scc_cmd = 0xBE; - cdb.cdb_opaque[1] = (sector_type) << 2; - cdb.cdb_opaque[2] = (lba >> 24) & 0xff; - cdb.cdb_opaque[3] = (lba >> 16) & 0xff; - cdb.cdb_opaque[4] = (lba >> 8) & 0xff; - cdb.cdb_opaque[5] = lba & 0xff; - cdb.cdb_opaque[6] = (blocks >> 16) & 0xff; - cdb.cdb_opaque[7] = (blocks >> 8) & 0xff; - cdb.cdb_opaque[8] = blocks & 0xff; - cdb.cdb_opaque[9] = (sync << 7) | - (header_code << 5) | - (user_data << 4) | - (edc_ecc << 3) | - (error_field << 1); - cdb.cdb_opaque[10] = sub_channel; - - sc.uscsi_cdb = (caddr_t)&cdb; - sc.uscsi_cdblen = 12; - sc.uscsi_bufaddr = vcd_buf; - sc.uscsi_buflen = 2336; - sc.uscsi_flags = USCSI_ISOLATE | USCSI_READ; - sc.uscsi_timeout = 20; - if (ioctl(fd, USCSICMD, &sc)) { - perror("USCSICMD: READ CD"); - return -1; - } - if (sc.uscsi_status) { - fprintf(stderr, "scsi command failed with status %d\n", sc.uscsi_status); - return -1; - } - *offset = 0; - return 1; -#else -#error SUN_VCDREAD -#endif -} -#endif /*sun*/ - - -//================== VCD CACHE ======================= -#ifdef VCD_CACHE - -static int vcd_cache_size=0; -static char *vcd_cache_data=NULL; -static int *vcd_cache_sectors=NULL; -static int vcd_cache_index=0; // index to first free (or oldest) cache sector -static int vcd_cache_current=-1; - -void vcd_cache_init(int s){ - vcd_cache_size=s; - vcd_cache_sectors=malloc(s*sizeof(int)); - vcd_cache_data=malloc(s*VCD_SECTOR_SIZE); - memset(vcd_cache_sectors,255,s*sizeof(int)); -} - -static inline void vcd_cache_seek(int sect){ - vcd_cache_current=sect; -} - -int vcd_cache_read(int fd,char* mem){ - int i; - char* vcd_buf; - - for(i=0;i<vcd_cache_size;i++) - if(vcd_cache_sectors[i]==vcd_cache_current){ - // found in the cache! :) - vcd_buf=&vcd_cache_data[i*VCD_SECTOR_SIZE]; - ++vcd_cache_current; - memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); - return VCD_SECTOR_DATA; - } - // NEW cache entry: - vcd_buf=&vcd_cache_data[vcd_cache_index*VCD_SECTOR_SIZE]; - vcd_cache_sectors[vcd_cache_index]=vcd_cache_current; - ++vcd_cache_index;if(vcd_cache_index>=vcd_cache_size)vcd_cache_index=0; - // read data! - vcd_set_msf(vcd_cache_current); -#if defined(linux) || defined(__bsdi__) - memcpy(vcd_buf,&vcd_entry.cdte_addr.msf,sizeof(struct cdrom_msf)); - if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; // EOF? - memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); -#elif defined(sun) - { - int offset; - if (sun_vcd_read(fd, &offset) <= 0) return 0; - memcpy(mem,&vcd_buf[offset],VCD_SECTOR_DATA); - } -#endif - ++vcd_cache_current; - return VCD_SECTOR_DATA; -} -#endif - -#else /* linux || sun */ - -int vcd_seek_to_track(int fd,int track) -{ - return -1; -} - -int vcd_get_track_end(int fd,int track) -{ - return -1; -} - -void vcd_read_toc(int fd) -{ -} - -static char vcd_buf[VCD_SECTOR_SIZE]; - -static int vcd_read(int fd,char *mem) -{ - return -1; -} - -#endif /* !linux && !sun */
--- a/vcd_read_fbsd.h Sat Oct 20 18:05:30 2001 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -#include <sys/cdio.h> -#include <sys/cdrio.h> - -//=================== VideoCD ========================== -#define CDROM_LEADOUT 0xAA - -typedef struct { - uint8_t sync [12]; - uint8_t header [4]; - uint8_t subheader [8]; - uint8_t data [2324]; - uint8_t spare [4]; -} cdsector_t; - -static cdsector_t vcd_buf; -static struct ioc_read_toc_single_entry vcd_entry; - -static inline void vcd_set_msf(unsigned int sect){ - vcd_entry.entry.addr.msf.frame=sect%75; - sect=sect/75; - vcd_entry.entry.addr.msf.second=sect%60; - sect=sect/60; - vcd_entry.entry.addr.msf.minute=sect; -} - -static inline unsigned int vcd_get_msf(){ - return vcd_entry.entry.addr.msf.frame + - (vcd_entry.entry.addr.msf.second+ - vcd_entry.entry.addr.msf.minute*60)*75; -} - -int vcd_seek_to_track(int fd,int track){ - vcd_entry.address_format = CD_MSF_FORMAT; - vcd_entry.track = track; - if (ioctl(fd, CDIOREADTOCENTRY, &vcd_entry)) { - perror("ioctl dif1"); - return -1; - } - return VCD_SECTOR_DATA*vcd_get_msf(); -} - -int vcd_get_track_end(int fd,int track){ - struct ioc_toc_header tochdr; - if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) - { perror("read CDROM toc header: "); return -1; } - vcd_entry.address_format = CD_MSF_FORMAT; - vcd_entry.track = track<tochdr.ending_track?(track+1):CDROM_LEADOUT; - if (ioctl(fd, CDIOREADTOCENTRY, &vcd_entry)) { - perror("ioctl dif2"); - return -1; - } - return VCD_SECTOR_DATA*vcd_get_msf(); -} - -void vcd_read_toc(int fd){ - struct ioc_toc_header tochdr; - int i; - if (ioctl(fd,CDIOREADTOCHEADER,&tochdr)==-1) - { perror("read CDROM toc header: "); return; } - for (i=tochdr.starting_track ; i<=tochdr.ending_track ; i++){ - struct ioc_read_toc_single_entry tocentry; - - tocentry.track = i; - tocentry.address_format = CD_MSF_FORMAT; - - if (ioctl(fd,CDIOREADTOCENTRY,&tocentry)==-1) - { perror("read CDROM toc entry: "); return; } - - printf("track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n", - (int)tocentry.track, - (int)tocentry.entry.addr_type, - (int)tocentry.entry.control, - (int)tocentry.address_format, - (int)tocentry.entry.addr.msf.minute, - (int)tocentry.entry.addr.msf.second, - (int)tocentry.entry.addr.msf.frame - ); - } -} - -static int vcd_read(int fd,char *mem){ - - if (pread(fd,&vcd_buf,VCD_SECTOR_SIZE,vcd_get_msf()*VCD_SECTOR_SIZE) - != VCD_SECTOR_SIZE) return 0; // EOF? - - vcd_entry.entry.addr.msf.frame++; - if (vcd_entry.entry.addr.msf.frame==75){ - vcd_entry.entry.addr.msf.frame=0; - vcd_entry.entry.addr.msf.second++; - if (vcd_entry.entry.addr.msf.second==60){ - vcd_entry.entry.addr.msf.second=0; - vcd_entry.entry.addr.msf.minute++; - } - } - memcpy(mem,vcd_buf.data,VCD_SECTOR_DATA); - return VCD_SECTOR_DATA; -} - -//================== VCD CACHE ======================= -#ifdef VCD_CACHE - -static int vcd_cache_size=0; -static char *vcd_cache_data=NULL; -static int *vcd_cache_sectors=NULL; -static int vcd_cache_index=0; // index to first free (or oldest) cache sector -static int vcd_cache_current=-1; - -void vcd_cache_init(int s){ - vcd_cache_size=s; - vcd_cache_sectors=malloc(s*sizeof(int)); - vcd_cache_data=malloc(s*VCD_SECTOR_SIZE); - memset(vcd_cache_sectors,255,s*sizeof(int)); -} - -static inline void vcd_cache_seek(int sect){ - vcd_cache_current=sect; -} - -int vcd_cache_read(int fd,char* mem){ -int i; -char* vcd_buf; - for(i=0;i<vcd_cache_size;i++) - if(vcd_cache_sectors[i]==vcd_cache_current){ - // found in the cache! :) - vcd_buf=&vcd_cache_data[i*VCD_SECTOR_SIZE]; - ++vcd_cache_current; - memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); - return VCD_SECTOR_DATA; - } - // NEW cache entry: - vcd_buf=&vcd_cache_data[vcd_cache_index*VCD_SECTOR_SIZE]; - vcd_cache_sectors[vcd_cache_index]=vcd_cache_current; - ++vcd_cache_index;if(vcd_cache_index>=vcd_cache_size)vcd_cache_index=0; - // read data! - vcd_set_msf(vcd_cache_current); - memcpy(vcd_buf,&vcd_entry.entry.addr.msf,sizeof(struct cdrom_msf)); -/* if(ioctl(fd,CDROMREADRAW,vcd_buf)==-1) return 0; */ // EOF? - ++vcd_cache_current; - memcpy(mem,&vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA); - return VCD_SECTOR_DATA; -} - -#endif