diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index beb16e4551..e542154378 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -7480,6 +7480,48 @@ Larger radius makes for smoother gradients, but also prevents the filter from modifying pixels near detailed regions (default: 16). .RE . +.TP +.B fixpts[=options] +Fixes the presentation timestamps (PTS) of the frames. +By default, the PTS passed to the next filter is dropped, but the following +options can change that: +.RSs +.IPs print +Print the incoming PTS. +.IPs fps= +Specify a frame per second value. +.IPs start= +Specify an initial value for the PTS. +.IPs autostart= +Uses the +.IR n th +incoming PTS as the initial PTS. +All previous pts are kept, so setting a huge value or \-1 keeps the PTS +intact. +.IPs autofps= +Uses the +.IR n th +incoming PTS after the end of autostart to determine the framerate. +.RE +.sp 1 +.RS +.I EXAMPLE: +.RE +.PD 0 +.RSs +.IPs "\-vf fixpts=fps=24000/1001,ass,fixpts" +Generates a new sequence of PTS, uses it for ASS subtitles, then drops it. +Generating a new sequence is useful when the timestamps are reset during the +program; this is frequent on DVDs. +Dropping it may be necessary to avoid confusing encoders. +.RE +.PD 1 +.sp 1 +.RS +.I NOTE: +Using this filter together with any sort of seeking (including -ss and EDLs) +may make demons fly out of your nose. +.RE . . .SH "GENERAL ENCODING OPTIONS (MENCODER ONLY)" @@ -10668,6 +10710,52 @@ SVC encodes. .TP .B (no)aud Write access unit delimeters to the stream (default: disabled). +Enable this only if your target container format requires access unit +delimiters. +. +.TP +.B overscan= +Include VUI overscan information in the stream (default: disabled). +See doc/vui.txt in the x264 source code for more information. +. +.TP +.B videoformat= +Include VUI video format information in the stream (default: disabled). +This is a purely informative setting for describing the original source. +See doc/vui.txt in the x264 source code for more information. +. +.TP +.B (no)fullrange +Include VUI full range information in the stream (default: disabled). +Use this option if your source video is not range limited. +See doc/vui.txt in the x264 source code for more information. +. +.TP +.B colorprim= +Include color primaries information (default: disabled). +This can be used for color correction. +See doc/vui.txt in the x264 source code for more information. +. +.TP +.B transfer= +Include VUI transfer characteristics information in the stream +(default: disabled). +This can be used for color correction. +See doc/vui.txt in the x264 source code for more information. +. +.TP +.B colormatrix= +Include VUI matrix coefficients in the stream (default: disabled). +This can be used for color correction. +See doc/vui.txt in the x264 source code for more information. +. +.TP +.B chromaloc=<0-5> +Include VUI chroma sample location information in the stream (default: +disabled). +Use this option to ensure alignment of the chroma and luma planes after +color space conversions. +See doc/vui.txt in the x264 source code for more information. . .TP .B log=<\-1\-3> diff --git a/DOCS/xml/en/faq.xml b/DOCS/xml/en/faq.xml index 9234ad7334..58450c3d83 100644 --- a/DOCS/xml/en/faq.xml +++ b/DOCS/xml/en/faq.xml @@ -789,14 +789,8 @@ while seeking through RealMedia streams? What about DVD navigation/menus? -MPlayer does not support DVD menus due to serious -architectural limitations that prevent proper handling of still images and -interactive content. If you want to have fancy menus, you will have to use -another player like xine, -VLC or Ogle. -If you want to see DVD navigation in MPlayer you -will have to implement it yourself, but be aware that it is a major -undertaking. +MPlayer should support DVD menus nowadays. +Your mileage may vary. diff --git a/Makefile b/Makefile index 6fcf358b0b..b2735bd913 100644 --- a/Makefile +++ b/Makefile @@ -313,6 +313,7 @@ SRCS_COMMON-$(WIN32DLL) += libmpcodecs/ad_acm.c \ loader/dshow/DS_VideoDecoder.c \ loader/dshow/allocator.c \ loader/dshow/cmediasample.c \ + loader/dshow/graph.c \ loader/dshow/guids.c \ loader/dshow/inputpin.c \ loader/dshow/mediatype.c \ @@ -425,6 +426,7 @@ SRCS_COMMON = asxparser.c \ libmpcodecs/vf_field.c \ libmpcodecs/vf_fil.c \ libmpcodecs/vf_filmdint.c \ + libmpcodecs/vf_fixpts.c \ libmpcodecs/vf_flip.c \ libmpcodecs/vf_format.c \ libmpcodecs/vf_framestep.c \ diff --git a/configure b/configure index bb5c2715a7..93804a8734 100755 --- a/configure +++ b/configure @@ -289,7 +289,7 @@ Codecs: --enable-jpeg enable JPEG input/output support [autodetect] --enable-libcdio enable libcdio support [autodetect] --enable-liblzo enable liblzo support [autodetect] - --disable-win32dll disable Win32 DLL support [enabled] + --disable-win32dll disable Win32 DLL support [autodetect] --disable-qtx disable QuickTime codecs support [enabled] --disable-xanim disable XAnim codecs support [enabled] --disable-real disable RealPlayer codecs support [enabled] diff --git a/etc/codecs.conf b/etc/codecs.conf index f78c2ea32c..d52e7c7a3d 100644 --- a/etc/codecs.conf +++ b/etc/codecs.conf @@ -3677,6 +3677,13 @@ audiocodec raatrcmac driver realaud dll "atrc.bundle/Contents/MacOS/atrc" +audiocodec ffadpcmadx + info "FFmpeg SEGA CRI adx codec" + status working + fourcc Sadx ; internal MPlayer FourCC + driver ffmpeg + dll adpcm_adx + audiocodec ffadpcmimaamv info "FFmpeg AMV IMA ADPCM audio" status working diff --git a/libmpcodecs/vd_qtvideo.c b/libmpcodecs/vd_qtvideo.c index 8e73c84753..aeead624e0 100644 --- a/libmpcodecs/vd_qtvideo.c +++ b/libmpcodecs/vd_qtvideo.c @@ -90,7 +90,7 @@ static OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw, GWorldFlags flags, void *baseAddr, long rowBytes); -static OSErr (*NewHandleClear)(Size byteCount); +static Handle (*NewHandleClear)(Size byteCount); #endif /* #ifndef CONFIG_QUICKTIME */ // to set/get/query special features/parameters @@ -103,7 +103,7 @@ static int codec_initialized=0; // init driver static int init(sh_video_t *sh){ #ifndef CONFIG_QUICKTIME - long result = 1; + OSErr result = 1; #endif ComponentResult cres; ComponentDescription desc; @@ -156,7 +156,7 @@ static int init(sh_video_t *sh){ result=InitializeQTML(6+16); // result=InitializeQTML(0); - mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"InitializeQTML returned %li\n",result); + mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"InitializeQTML returned %d\n",result); // result=EnterMovies(); // printf("EnterMovies->%d\n",result); #endif /* CONFIG_QUICKTIME */ @@ -305,7 +305,7 @@ static void uninit(sh_video_t *sh){ // decode a frame static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){ - long result = 1; + OSErr result = 1; int i; mp_image_t* mpi; ComponentResult cres; @@ -335,7 +335,7 @@ if(!codec_initialized){ 0, mpi->planes[0], mpi->stride[0]); - mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"NewGWorldFromPtr returned:%ld\n",65536-(result&0xffff)); + mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"NewGWorldFromPtr returned:%d\n",result); // if (65536-(result&0xFFFF) != 10000) // return NULL; @@ -406,7 +406,7 @@ if(!codec_initialized){ ++decpar.frameNumber; - if(cres&0xFFFF){ + if(cres) { mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"ImageCodecBandDecompress cres=0x%X (-0x%X) %d\n",cres,-cres,cres); return NULL; } diff --git a/libmpcodecs/ve_qtvideo.c b/libmpcodecs/ve_qtvideo.c index 92b76fb252..f3bba153e4 100644 --- a/libmpcodecs/ve_qtvideo.c +++ b/libmpcodecs/ve_qtvideo.c @@ -69,7 +69,7 @@ static OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw, GWorldFlags flags, void *baseAddr, long rowBytes); -static OSErr (*NewHandleClear)(Size byteCount); +static Handle (*NewHandleClear)(Size byteCount); static OSErr (*CompressSequenceBegin) ( ImageSequence *seqID, PixMapHandle src, diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index fa72ad25aa..cc0d01c55e 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -118,6 +118,7 @@ extern const vf_info_t vf_info_yadif; extern const vf_info_t vf_info_blackframe; extern const vf_info_t vf_info_geq; extern const vf_info_t vf_info_ow; +extern const vf_info_t vf_info_fixpts; // list of available filters: static const vf_info_t* const filter_list[]={ @@ -219,6 +220,7 @@ static const vf_info_t* const filter_list[]={ &vf_info_yadif, &vf_info_blackframe, &vf_info_ow, + &vf_info_fixpts, NULL }; diff --git a/libmpcodecs/vf_fixpts.c b/libmpcodecs/vf_fixpts.c new file mode 100644 index 0000000000..5ceb516c6b --- /dev/null +++ b/libmpcodecs/vf_fixpts.c @@ -0,0 +1,137 @@ +/* + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "img_format.h" +#include "mp_image.h" +#include "vf.h" + +struct vf_priv_s { + double current; + double step; + int autostart; + int autostep; + unsigned have_step:1; + unsigned print:1; +}; + +static int put_image(vf_instance_t *vf, mp_image_t *src, double pts) +{ + struct vf_priv_s *p = vf->priv; + + if (p->print) { + if (pts == MP_NOPTS_VALUE) + mp_msg(MSGT_VFILTER, MSGL_INFO, "PTS: undef\n"); + else + mp_msg(MSGT_VFILTER, MSGL_INFO, "PTS: %f\n", pts); + } + if (pts != MP_NOPTS_VALUE && p->autostart != 0) { + p->current = pts; + if (p->autostart > 0) + p->autostart--; + } else if (pts != MP_NOPTS_VALUE && p->autostep > 0) { + p->step = pts - p->current; + p->current = pts; + p->autostep--; + p->have_step = 1; + } else if (p->have_step) { + p->current += p->step; + pts = p->current; + } else { + pts = MP_NOPTS_VALUE; + } + return vf_next_put_image(vf, src, pts); +} + +static void uninit(vf_instance_t *vf) +{ + free(vf->priv); +} + +static int parse_args(struct vf_priv_s *p, const char *args) +{ + int pos; + double num, denom = 1; + int iarg; + + while (*args != 0) { + pos = 0; + if (sscanf(args, "print%n", &pos) == 0 && pos > 0) { + p->print = 1; + } else if (sscanf(args, "fps=%lf%n/%lf%n", &num, &pos, &denom, &pos) >= + 1 && pos > 0) { + p->step = denom / num; + p->have_step = 1; + } else if (sscanf(args, "start=%lf%n", &num, &pos) >= 1 && pos > 0) { + p->current = num; + } else if (sscanf(args, "autostart=%d%n", &iarg, &pos) == 1 && pos > 0) { + p->autostart = iarg; + } else if (sscanf(args, "autofps=%d%n", &iarg, &pos) == 1 && pos > 0) { + p->autostep = iarg; + } else { + mp_msg(MSGT_VFILTER, MSGL_FATAL, + "fixpts: unknown suboption: %s\n", args); + return 0; + } + args += pos; + if (*args == ':') + args++; + } + return 1; +} + +static int open(vf_instance_t *vf, char *args) +{ + struct vf_priv_s *p; + struct vf_priv_s ptmp = { + .current = 0, + .step = 0, + .autostart = 0, + .autostep = 0, + .have_step = 0, + .print = 0, + }; + + if (!parse_args(&ptmp, args == NULL ? "" : args)) + return 0; + + vf->put_image = put_image; + vf->uninit = uninit; + vf->priv = p = malloc(sizeof(struct vf_priv_s)); + *p = ptmp; + p->current = -p->step; + + return 1; +} + +vf_info_t vf_info_fixpts = { + "Fix presentation timestamps", + "fixpts", + "Nicolas George", + "", + &open, + NULL +}; diff --git a/libmpdemux/mp_taglists.c b/libmpdemux/mp_taglists.c index adfe1059b2..7fc68db5f9 100644 --- a/libmpdemux/mp_taglists.c +++ b/libmpdemux/mp_taglists.c @@ -27,6 +27,7 @@ static const struct mp_AVCodecTag mp_wav_tags[] = { { CODEC_ID_ADPCM_4XM, MKTAG('4', 'X', 'M', 'A')}, + { CODEC_ID_ADPCM_ADX, MKTAG('S', 'a', 'd', 'x')}, { CODEC_ID_ADPCM_EA, MKTAG('A', 'D', 'E', 'A')}, { CODEC_ID_ADPCM_EA_MAXIS_XA, MKTAG('A', 'D', 'X', 'A')}, { CODEC_ID_ADPCM_IMA_WS, MKTAG('A', 'I', 'W', 'S')}, diff --git a/libvo/vo_fbdev.c b/libvo/vo_fbdev.c index df3f21299c..4534b17d9f 100644 --- a/libvo/vo_fbdev.c +++ b/libvo/vo_fbdev.c @@ -572,6 +572,7 @@ static int fb_bpp_we_want; // 32: 32 24: 24 16: 16 15: 15 static int fb_line_len; static int fb_xres; static int fb_yres; +static int fb_page; static void (*draw_alpha_p)(int w, int h, unsigned char *src, unsigned char *srca, int stride, unsigned char *dst, int dstride); @@ -804,6 +805,12 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, set_bpp(&fb_vinfo, fb_bpp); fb_vinfo.xres_virtual = fb_vinfo.xres; fb_vinfo.yres_virtual = fb_vinfo.yres; + fb_page = 0; + if (vo_doublebuffering) { + fb_vinfo.yres_virtual <<= 1; + fb_vinfo.yoffset = 0; + fb_page = 1; // start writing into the page we don't display + } if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) { mp_msg(MSGT_VO, MSGL_V, "Can't set graphics mode: %s\n", strerror(errno)); @@ -903,6 +910,12 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, fb_line_len = fb_finfo.line_length; fb_size = fb_finfo.smem_len; + if (vo_doublebuffering && fb_size < 2 * fb_yres * fb_line_len) + { + mp_msg(MSGT_VO, MSGL_WARN, "framebuffer too small for double-buffering, disabling\n"); + vo_doublebuffering = 0; + fb_page = 0; + } #ifdef CONFIG_VIDIX if (vidix_name) { @@ -963,14 +976,19 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, center = frame_buffer + ( (out_width - in_width) / 2 ) * fb_pixel_size + ( (out_height - in_height) / 2 ) * fb_line_len + - x_offset * fb_pixel_size + y_offset * fb_line_len; + x_offset * fb_pixel_size + y_offset * fb_line_len + + fb_page * fb_yres * fb_line_len; mp_msg(MSGT_VO, MSGL_DBG2, "frame_buffer @ %p\n", frame_buffer); mp_msg(MSGT_VO, MSGL_DBG2, "center @ %p\n", center); mp_msg(MSGT_VO, MSGL_V, "pixel per line: %d\n", fb_line_len / fb_pixel_size); - if (fs || vm) - memset(frame_buffer, '\0', fb_line_len * fb_yres); + if (fs || vm) { + int clear_size = fb_line_len * fb_yres; + if (vo_doublebuffering) + clear_size <<= 1; + memset(frame_buffer, 0, clear_size); + } } vt_set_textarea(last_row, fb_yres); @@ -1027,6 +1045,20 @@ static void check_events(void) static void flip_page(void) { + int next_page = !fb_page; + int page_delta = next_page - fb_page; +#ifdef CONFIG_VIDIX + if (vidix_name) + return; +#endif + if (!vo_doublebuffering) + return; + + fb_vinfo.yoffset = fb_page * fb_yres; + ioctl(fb_dev_fd, FBIOPAN_DISPLAY, &fb_vinfo); + + center += page_delta * fb_yres * fb_line_len; + fb_page = next_page; } static void draw_osd(void) diff --git a/loader/dshow/DS_Filter.c b/loader/dshow/DS_Filter.c index e3102cf264..693d59c25f 100644 --- a/loader/dshow/DS_Filter.c +++ b/loader/dshow/DS_Filter.c @@ -5,6 +5,7 @@ #include "config.h" #include "DS_Filter.h" +#include "graph.h" #include "loader/drv.h" #include "loader/com.h" #include @@ -125,6 +126,7 @@ DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id, // char eb[250]; const char* em = NULL; MemAllocator* tempAll; + FilterGraph* graph; ALLOCATOR_PROPERTIES props,props1; DS_Filter* This = malloc(sizeof(DS_Filter)); if (!This) @@ -166,6 +168,7 @@ DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id, ULONG fetched; HRESULT result; unsigned int i; + static const uint16_t filter_name[] = { 'F', 'i', 'l', 't', 'e', 'r', 0 }; This->m_iHandle = LoadLibraryA(dllname); if (!This->m_iHandle) @@ -199,6 +202,10 @@ DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id, em = "object does not provide IBaseFilter interface"; break; } + + graph = FilterGraphCreate(); + result = This->m_pFilter->vt->JoinFilterGraph(This->m_pFilter, (IFilterGraph*)graph, filter_name); + // enumerate pins result = This->m_pFilter->vt->EnumPins(This->m_pFilter, &enum_pins); if (result || !enum_pins) diff --git a/loader/dshow/allocator.c b/loader/dshow/allocator.c index b75f1bebfb..a90bd9d3d2 100644 --- a/loader/dshow/allocator.c +++ b/loader/dshow/allocator.c @@ -116,7 +116,7 @@ static inline avm_list_t* avm_list_find(avm_list_t* head, void* member) static long MemAllocator_CreateAllocator(GUID* clsid, const GUID* iid, void** ppv) { - IMemAllocator* p; + IUnknown* p; int result; if (!ppv) return -1; @@ -124,9 +124,9 @@ static long MemAllocator_CreateAllocator(GUID* clsid, const GUID* iid, void** pp if (memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID))) return -1; - p = (IMemAllocator*) MemAllocatorCreate(); - result = p->vt->QueryInterface((IUnknown*)p, iid, ppv); - p->vt->Release((IUnknown*)p); + p = (IUnknown*) MemAllocatorCreate(); + result = p->vt->QueryInterface(p, iid, ppv); + p->vt->Release(p); return result; } diff --git a/loader/dshow/graph.c b/loader/dshow/graph.c new file mode 100644 index 0000000000..01bf6c7253 --- /dev/null +++ b/loader/dshow/graph.c @@ -0,0 +1,163 @@ +/* + * Implemention of FilterGraph. Based on allocator.c. + * Copyright 2010 Steinar H. Gunderson + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Modified for use with MPlayer, detailed changelog at + * http://svn.mplayerhq.hu/mplayer/trunk/ + */ + +#include +#include + +#include "config.h" +#include "loader/com.h" +#include "loader/dshow/graph.h" +#include "loader/wine/winerror.h" + +// How many FilterGraph objects exist. +// Used for knowing when to register and unregister the class in COM. +static int GraphKeeper = 0; + +static long FilterGraph_CreateGraph(GUID* clsid, const GUID* iid, void** ppv) +{ + IUnknown* p; + int result; + if (!ppv) + return -1; + *ppv = 0; + if (memcmp(clsid, &CLSID_FilterGraph, sizeof(*clsid))) + return -1; + + p = (IUnknown*) FilterGraphCreate(); + result = p->vt->QueryInterface(p, iid, ppv); + p->vt->Release(p); + + return result; +} + +static void FilterGraph_Destroy(FilterGraph* This) +{ + Debug printf("FilterGraph_Destroy(%p) called (%d, %d)\n", This, This->refcount, GraphKeeper); +#ifdef WIN32_LOADER + if (--GraphKeeper == 0) + UnregisterComClass(&CLSID_FilterGraph, FilterGraph_CreateGraph); +#endif + free(This->vt); + free(This); +} + +HRESULT STDCALL FilterGraph_AddFilter(FilterGraph* This, + IBaseFilter* pFilter, + unsigned short* pName) +{ + Debug printf("FilterGraph_AddFilter(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_RemoveFilter(FilterGraph* This, IBaseFilter* pFilter) +{ + Debug printf("FilterGraph_RemoveFilter(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_EnumFilters(FilterGraph* This, IEnumFilters** ppEnum) +{ + Debug printf("FilterGraph_EnumFilters(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_FindFilterByName(FilterGraph* This, + unsigned short* pName, + IBaseFilter** ppFilter) +{ + Debug printf("FilterGraph_FindFilterByName(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_ConnectDirect(FilterGraph* This, + IPin* ppinOut, + IPin* ppinIn, + const AM_MEDIA_TYPE* pmt) +{ + Debug printf("FilterGraph_ConnectDirect(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_Reconnect(FilterGraph* This, IPin* ppin) +{ + Debug printf("FilterGraph_Reconnect(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_Disconnect(FilterGraph* This, IPin* ppin) +{ + Debug printf("FilterGraph_Disconnect(%p) called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL FilterGraph_SetDefaultSyncSource(FilterGraph* This) +{ + Debug printf("FilterGraph_SetDefaultSyncSource(%p) called\n", This); + return E_NOTIMPL; +} + +IMPLEMENT_IUNKNOWN(FilterGraph) + +FilterGraph* FilterGraphCreate() +{ + FilterGraph* This = calloc(1, sizeof(*This)); + + if (!This) + return NULL; + + Debug printf("FilterGraphCreate() called -> %p\n", This); + + This->refcount = 1; + + This->vt = calloc(1, sizeof(*This->vt)); + + if (!This->vt) { + free(This); + return NULL; + } + + This->vt->QueryInterface = FilterGraph_QueryInterface; + This->vt->AddRef = FilterGraph_AddRef; + This->vt->Release = FilterGraph_Release; + + This->vt->AddFilter = FilterGraph_AddFilter; + This->vt->RemoveFilter = FilterGraph_RemoveFilter; + This->vt->EnumFilters = FilterGraph_EnumFilters; + This->vt->FindFilterByName = FilterGraph_FindFilterByName; + This->vt->ConnectDirect = FilterGraph_ConnectDirect; + This->vt->Reconnect = FilterGraph_Reconnect; + This->vt->Disconnect = FilterGraph_Disconnect; + This->vt->SetDefaultSyncSource = FilterGraph_SetDefaultSyncSource; + + This->interfaces[0] = IID_IUnknown; + This->interfaces[1] = IID_IFilterGraph; + +#ifdef WIN32_LOADER + if (GraphKeeper++ == 0) + RegisterComClass(&CLSID_FilterGraph, FilterGraph_CreateGraph); +#endif + + return This; +} + diff --git a/loader/dshow/graph.h b/loader/dshow/graph.h new file mode 100644 index 0000000000..7667f5a39e --- /dev/null +++ b/loader/dshow/graph.h @@ -0,0 +1,57 @@ +#ifndef MPLAYER_GRAPH_H +#define MPLAYER_GRAPH_H + +/* + * Copyright 2010 Steinar H. Gunderson + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "interfaces.h" +#include "cmediasample.h" + +typedef struct FilterGraph FilterGraph; + +struct FilterGraph { + IFilterGraph_vt* vt; + DECLARE_IUNKNOWN(); + GUID interfaces[2]; + + HRESULT STDCALL (*AddFilter)(FilterGraph* This, + /* [in] */ IBaseFilter* pFilter, + /* [string][in] */ unsigned short* pName); + HRESULT STDCALL (*RemoveFilter)(FilterGraph* This, + /* [in] */ IBaseFilter* pFilter); + HRESULT STDCALL (*EnumFilters)(FilterGraph* This, + /* [out] */ IEnumFilters** ppEnum); + HRESULT STDCALL (*FindFilterByName)(FilterGraph* This, + /* [string][in] */ unsigned short* pName, + /* [out] */ IBaseFilter** ppFilter); + HRESULT STDCALL (*ConnectDirect)(FilterGraph* This, + /* [in] */ IPin* ppinOut, + /* [in] */ IPin* ppinIn, + /* [in] */ const AM_MEDIA_TYPE* pmt); + HRESULT STDCALL (*Reconnect)(FilterGraph* This, + /* [in] */ IPin* ppin); + HRESULT STDCALL (*Disconnect)(FilterGraph* This, + /* [in] */ IPin* ppin); + HRESULT STDCALL (*SetDefaultSyncSource)(FilterGraph* This); +}; + +FilterGraph* FilterGraphCreate(void); + +#endif /* MPLAYER_GRAPH_H */ diff --git a/loader/dshow/guids.c b/loader/dshow/guids.c index 73cf7f5456..5d793bb14d 100644 --- a/loader/dshow/guids.c +++ b/loader/dshow/guids.c @@ -11,6 +11,8 @@ const GUID IID_IBaseFilter={0x56a86895, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; const GUID IID_IEnumPins={0x56a86892, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +const GUID IID_IFilterGraph={0x56a8689f, 0x0ad4, 0x11ce, + {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; const GUID IID_IEnumMediaTypes={0x89c31040, 0x846b, 0x11ce, {0x97, 0xd3, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; const GUID IID_IMemInputPin={0x56a8689d, 0x0ad4, 0x11ce, @@ -64,6 +66,8 @@ const GUID MEDIASUBTYPE_I420={0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; const GUID MEDIASUBTYPE_IF09={0x39304649, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +const GUID CLSID_FilterGraph={0xe436ebb3, 0x524f, 0x11ce, + {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; const GUID CLSID_MemoryAllocator={0x1e651cc0, 0xb199, 0x11d0, {0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45}}; const GUID IID_DivxHidden={0x598eba01, 0xb49a, 0x11d2, diff --git a/loader/dshow/guids.h b/loader/dshow/guids.h index 80686558b4..76a4970d27 100644 --- a/loader/dshow/guids.h +++ b/loader/dshow/guids.h @@ -46,6 +46,7 @@ typedef GUID IID; extern const GUID IID_IBaseFilter; extern const GUID IID_IEnumPins; extern const GUID IID_IEnumMediaTypes; +extern const GUID IID_IFilterGraph; extern const GUID IID_IMemInputPin; extern const GUID IID_IMemAllocator; extern const GUID IID_IMediaSample; @@ -54,6 +55,7 @@ extern const GUID IID_Iv50Hidden; extern const GUID CLSID_DivxDecompressorCF; extern const GUID IID_IDivxFilterInterface; extern const GUID CLSID_IV50_Decoder; +extern const GUID CLSID_FilterGraph; extern const GUID CLSID_MemoryAllocator; extern const GUID MEDIATYPE_Video; // avoid a clash with MinGW-W64 libuuid diff --git a/loader/dshow/interfaces.h b/loader/dshow/interfaces.h index 5c927a55be..af9544ada5 100644 --- a/loader/dshow/interfaces.h +++ b/loader/dshow/interfaces.h @@ -329,4 +329,32 @@ struct IDivxFilterInterface_vt HRESULT STDCALL ( *get_AspectRatio )(IDivxFilterInterface* This, int* x, IDivxFilterInterface* Thisit, int* y); }; +typedef struct IEnumFilters IEnumFilters; + +typedef struct IFilterGraph_vt +{ + INHERIT_IUNKNOWN(); + + HRESULT STDCALL ( *AddFilter )(IFilterGraph* This, + /* [in] */ IBaseFilter* pFilter, + /* [string][in] */ unsigned short* pName); + HRESULT STDCALL ( *RemoveFilter )(IFilterGraph* This, + /* [in] */ IBaseFilter* pFilter); + HRESULT STDCALL ( *EnumFilters )(IFilterGraph* This, + /* [out] */ IEnumFilters** ppEnum); + HRESULT STDCALL ( *FindFilterByName )(IFilterGraph* This, + /* [string][in] */ unsigned short* pName, + /* [out] */ IBaseFilter** ppFilter); + HRESULT STDCALL ( *ConnectDirect )(IFilterGraph* This, + /* [in] */ IPin* ppinOut, + /* [in] */ IPin* ppinIn, + /* [in] */ const AM_MEDIA_TYPE* pmt); + HRESULT STDCALL ( *Reconnect )(IFilterGraph* This, + /* [in] */ IPin* ppin); + HRESULT STDCALL ( *Disconnect )(IFilterGraph* This, + /* [in] */ IPin* ppin); + HRESULT STDCALL ( *SetDefaultSyncSource )(IFilterGraph* This); +} IFilterGraph_vt; +struct IFilterGraph { IFilterGraph_vt *vt; }; + #endif /*MPLAYER_INTERFACES_H */ diff --git a/loader/qtx/qtxsdk/components.h b/loader/qtx/qtxsdk/components.h index 08b883099c..2e42a0412f 100644 --- a/loader/qtx/qtxsdk/components.h +++ b/loader/qtx/qtxsdk/components.h @@ -12,7 +12,7 @@ typedef unsigned char Boolean; typedef unsigned char Str31[32]; typedef int32_t Fixed; -typedef int32_t OSErr; +typedef int16_t OSErr; typedef int OSType; typedef int32_t ComponentResult; @@ -641,10 +641,10 @@ static inline void dump_ImageDescription(void* xxx){ printf("=============== ImageDescription at %p ==================\n",xxx); printf("idSize=0x%X fourcc=0x%08X\n",id->idSize,id->cType); printf("ver=%d rev=%d vendor=0x%08X\n",id->version,id->revisionLevel,id->vendor); - printf("tempQ=%d spatQ=%d dim: %d x %d dpi: %d x %d depth: %d\n", + printf("tempQ=%d spatQ=%d dim: %d x %d dpi: %.2f x %.2f depth: %d\n", id->temporalQuality,id->spatialQuality, id->width, id->height, - id->hRes, id->vRes, + id->hRes / 65536.0, id->vRes / 65536.0, id->depth); printf("dataSize=%d frameCount=%d clutID=%d\n",id->dataSize, id->frameCount, id->clutID); printf("name='%.*s'\n",((char*)(&id->name))[0],((char*)(&id->name))+1); diff --git a/loader/win32.c b/loader/win32.c index 08985a28e1..d540e6dfe2 100644 --- a/loader/win32.c +++ b/loader/win32.c @@ -240,6 +240,7 @@ typedef struct th_list_t{ //static int heap_counter=0; static tls_t* g_tls=NULL; static th_list* list=NULL; +static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER; #if 0 static void test_heap(void) @@ -638,6 +639,7 @@ static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize, printf( "WARNING: CreateThread flags not supported\n"); if(dwThreadId) *dwThreadId=(long)pth; + pthread_mutex_lock(&list_lock); if(list==NULL) { list=my_mreq(sizeof(th_list), 1); @@ -651,11 +653,19 @@ static void* WINAPI expCreateThread(void* pSecAttr, long dwStackSize, list=list->next; } list->thread=pth; + pthread_mutex_unlock(&list_lock); dbgprintf("CreateThread(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x) => 0x%x\n", pSecAttr, dwStackSize, lpStartAddress, lpParameter, dwFlags, dwThreadId, pth); return pth; } +static DWORD WINAPI expResumeThread(HANDLE hThread) +{ + int ret = 1; + dbgprintf("ResumeThread(0x%x) => 0x%x\n", hThread, ret); + return ret; +} + struct mutex_list_t; struct mutex_list_t @@ -667,14 +677,18 @@ struct mutex_list_t char reset; char name[128]; int semaphore; + int lock_count; + pthread_t owner; struct mutex_list_t* next; struct mutex_list_t* prev; }; typedef struct mutex_list_t mutex_list; static mutex_list* mlist=NULL; +static pthread_mutex_t mlist_lock = PTHREAD_MUTEX_INITIALIZER; void destroy_event(void* event) { + pthread_mutex_lock(&mlist_lock); mutex_list* pp=mlist; // printf("garbage collector: destroy_event(%x)\n", event); while(pp) @@ -696,10 +710,12 @@ void destroy_event(void* event) } printf("0\n"); */ + pthread_mutex_unlock(&mlist_lock); return; } pp=pp->prev; } + pthread_mutex_unlock(&mlist_lock); } static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, @@ -707,6 +723,7 @@ static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, { pthread_mutex_t *pm; pthread_cond_t *pc; + void *ret; /* mutex_list* pp; pp=mlist; @@ -717,6 +734,7 @@ static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, } printf("0\n"); */ + pthread_mutex_lock(&mlist_lock); if(mlist!=NULL) { mutex_list* pp=mlist; @@ -727,6 +745,7 @@ static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, { dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, 0x%x='%s') => 0x%x\n", pSecAttr, bManualReset, bInitialState, name, name, pp->pm); + pthread_mutex_unlock(&mlist_lock); return pp->pm; } }while((pp=pp->prev) != NULL); @@ -768,7 +787,9 @@ static void* WINAPI expCreateEventA(void* pSecAttr, char bManualReset, else dbgprintf("CreateEventA(0x%x, 0x%x, 0x%x, NULL) => 0x%x\n", pSecAttr, bManualReset, bInitialState, mlist); - return mlist; + ret = mlist; + pthread_mutex_unlock(&mlist_lock); + return ret; } static void* WINAPI expSetEvent(void* event) @@ -800,8 +821,8 @@ static void* WINAPI expWaitForSingleObject(void* object, int duration) mutex_list *ml = (mutex_list *)object; // FIXME FIXME FIXME - this value is sometime unititialize !!! int ret = WAIT_FAILED; - mutex_list* pp=mlist; - th_list* tp=list; + mutex_list* pp; + th_list* tp; if(object == (void*)0xcfcf9898) { /** @@ -818,8 +839,11 @@ static void* WINAPI expWaitForSingleObject(void* object, int duration) dbgprintf("WaitForSingleObject(0x%x, duration %d) =>\n",object, duration); // See if this is a thread. + pthread_mutex_lock(&list_lock); + tp=list; while (tp && (tp->thread != object)) tp = tp->prev; + pthread_mutex_unlock(&list_lock); if (tp) { if (pthread_join(*(pthread_t*)object, NULL) == 0) { return (void*)WAIT_OBJECT_0; @@ -832,8 +856,11 @@ static void* WINAPI expWaitForSingleObject(void* object, int duration) // this object really exists in our list if (!ml) return (void*) ret; + pthread_mutex_lock(&mlist_lock); + pp=mlist; while (pp && (pp->pm != ml->pm)) pp = pp->prev; + pthread_mutex_unlock(&mlist_lock); if (!pp) { dbgprintf("WaitForSingleObject: NotFound\n"); return (void*)ret; @@ -872,7 +899,7 @@ static void* WINAPI expWaitForSingleObject(void* object, int duration) if (duration == 0) { if(ml->semaphore==0) ret = WAIT_FAILED; else { - ml->semaphore++; + ml->semaphore--; ret = WAIT_OBJECT_0; } } @@ -880,6 +907,25 @@ static void* WINAPI expWaitForSingleObject(void* object, int duration) if (ml->semaphore==0) pthread_cond_wait(ml->pc,ml->pm); ml->semaphore--; + ret = WAIT_OBJECT_0; + } + break; + case 2: /* Mutex */ + if (duration == 0) { + if(ml->lock_count > 0 && ml->owner != pthread_self()) ret = WAIT_FAILED; + else { + ml->lock_count++; + ml->owner = pthread_self(); + ret = WAIT_OBJECT_0; + } + } + if (duration == -1) { + if (ml->lock_count > 0 && ml->owner != pthread_self()) { + pthread_cond_wait(ml->pc,ml->pm); + } + ml->lock_count++; + ml->owner = pthread_self(); + ret = WAIT_OBJECT_0; } break; } @@ -917,31 +963,6 @@ static void WINAPI expExitThread(int retcode) dbgprintf("ExitThread(%d)\n", retcode); pthread_exit(&retcode); } - -static HANDLE WINAPI expCreateMutexA(void *pSecAttr, - char bInitialOwner, const char *name) -{ - HANDLE mlist = (HANDLE)expCreateEventA(pSecAttr, 0, 0, name); - - if (name) - dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n", - pSecAttr, bInitialOwner, name, mlist); - else - dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n", - pSecAttr, bInitialOwner, mlist); -#ifndef CONFIG_QTX_CODECS - /* 10l to QTX, if CreateMutex returns a real mutex, WaitForSingleObject - waits for ever, else it works ;) */ - return mlist; -#endif -} - -static int WINAPI expReleaseMutex(HANDLE hMutex) -{ - dbgprintf("ReleaseMutex(%x) => 1\n", hMutex); - /* FIXME:XXX !! not yet implemented */ - return 1; -} #endif static int pf_set = 0; @@ -1801,6 +1822,7 @@ static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count, { pthread_mutex_t *pm; pthread_cond_t *pc; + HANDLE ret; /* mutex_list* pp; printf("CreateSemaphoreA(%p = %s)\n", name, (name ? name : "")); @@ -1812,6 +1834,7 @@ static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count, } printf("0\n"); */ + pthread_mutex_lock(&mlist_lock); if(mlist!=NULL) { mutex_list* pp=mlist; @@ -1822,7 +1845,9 @@ static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count, { dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0x%x='%s') => 0x%x\n", v1, init_count, max_count, name, name, mlist); - return (HANDLE)mlist; + ret = (HANDLE)mlist; + pthread_mutex_unlock(&mlist_lock); + return ret; } }while((pp=pp->prev) != NULL); } @@ -1861,7 +1886,9 @@ static HANDLE WINAPI expCreateSemaphoreA(char* v1, long init_count, else dbgprintf("CreateSemaphoreA(0x%x, init_count %d, max_count %d, name 0) => 0x%x\n", v1, init_count, max_count, mlist); - return (HANDLE)mlist; + ret = (HANDLE)mlist; + pthread_mutex_unlock(&mlist_lock); + return ret; } static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_count) @@ -1882,6 +1909,105 @@ static long WINAPI expReleaseSemaphore(long hsem, long increment, long* prev_cou return 1; } +static HANDLE WINAPI expCreateMutexA(void *pSecAttr, + char bInitialOwner, const char *name) +{ + pthread_mutex_t *pm; + pthread_cond_t *pc; + HANDLE ret; + pthread_mutex_lock(&mlist_lock); + if(mlist!=NULL) + { + mutex_list* pp=mlist; + if(name!=NULL) + do + { + if((strcmp(pp->name, name)==0) && (pp->type==2)) + { + dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n", pSecAttr, bInitialOwner, name, mlist); + ret = (HANDLE)mlist; + pthread_mutex_unlock(&mlist_lock); + return ret; + } + }while((pp=pp->prev) != NULL); + } + pm=mreq_private(sizeof(pthread_mutex_t), 0, AREATYPE_MUTEX); + pthread_mutex_init(pm, NULL); + pc=mreq_private(sizeof(pthread_cond_t), 0, AREATYPE_COND); + pthread_cond_init(pc, NULL); + if(mlist==NULL) + { + mlist=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT); + mlist->next=mlist->prev=NULL; + } + else + { + mlist->next=mreq_private(sizeof(mutex_list), 00, AREATYPE_EVENT); + mlist->next->prev=mlist; + mlist->next->next=NULL; + mlist=mlist->next; + } + mlist->type=2; /* Type Mutex */ + mlist->pm=pm; + mlist->pc=pc; + mlist->state=0; + mlist->reset=0; + mlist->semaphore=0; + if (bInitialOwner) { + mlist->owner = pthread_self(); + mlist->lock_count = 1; + } else { + mlist->owner = (pthread_t)0; + mlist->lock_count = 0; + } + if(name!=NULL) + strncpy(mlist->name, name, 64); + else + mlist->name[0]=0; + if(pm==NULL) + dbgprintf("ERROR::: CreateMutexA failure\n"); + if(name) + dbgprintf("CreateMutexA(0x%x, %d, '%s') => 0x%x\n", + pSecAttr, bInitialOwner, name, mlist); + else + dbgprintf("CreateMutexA(0x%x, %d, NULL) => 0x%x\n", + pSecAttr, bInitialOwner, mlist); + ret = (HANDLE)mlist; + pthread_mutex_unlock(&mlist_lock); + return ret; +} + +static int WINAPI expReleaseMutex(HANDLE hMutex) +{ + mutex_list *ml = (mutex_list *)hMutex; + + pthread_mutex_lock(ml->pm); + if (--ml->lock_count == 0) pthread_cond_signal(ml->pc); + pthread_mutex_unlock(ml->pm); + return 1; +} + +static DWORD WINAPI expSignalObjectAndWait(HANDLE hObjectToSignal, + HANDLE hObjectToWaitOn, + DWORD dwMilliseconds, + WIN_BOOL bAlertable) { + mutex_list* mlist = (mutex_list*)hObjectToSignal; + + switch (mlist->type) { + case 0: // Event + expSetEvent(mlist); + break; + case 1: // Semaphore + expReleaseSemaphore(mlist, 1, NULL); + break; + case 2: // Mutex + expReleaseMutex(mlist); + break; + default: + dbgprintf("Signalling unknown object type %d!\n", hObjectToSignal); + } + return expWaitForSingleObject(hObjectToWaitOn, dwMilliseconds); +} static long WINAPI expRegOpenKeyExA(long key, const char* subkey, long reserved, long access, int* newkey) { @@ -5002,6 +5128,7 @@ struct exports exp_kernel32[]= FF(IsBadStringPtrA, -1) FF(DisableThreadLibraryCalls, -1) FF(CreateThread, -1) + FF(ResumeThread, -1) FF(CreateEventA, -1) FF(SetEvent, -1) FF(ResetEvent, -1) @@ -5009,8 +5136,6 @@ struct exports exp_kernel32[]= #ifdef CONFIG_QTX_CODECS FF(WaitForMultipleObjects, -1) FF(ExitThread, -1) - FF(CreateMutexA,-1) - FF(ReleaseMutex,-1) #endif FF(GetSystemInfo, -1) FF(GetVersion, 332) @@ -5055,6 +5180,9 @@ struct exports exp_kernel32[]= FF(GlobalFree, -1) FF(LoadResource, -1) FF(ReleaseSemaphore, -1) + FF(CreateMutexA, -1) + FF(ReleaseMutex, -1) + FF(SignalObjectAndWait, -1) FF(FindResourceA, -1) FF(LockResource, -1) FF(FreeResource, -1) @@ -5662,5 +5790,7 @@ void my_garbagecollection(void) dbgprintf("Total Unfree %d bytes cnt %d [%p,%d]\n",unfree, unfreecnt, last_alloc, alccnt); #endif g_tls = NULL; + pthread_mutex_lock(&list_lock); list = NULL; + pthread_mutex_unlock(&list_lock); } diff --git a/mencoder.c b/mencoder.c index 4b2bea30fa..7d92b2983c 100644 --- a/mencoder.c +++ b/mencoder.c @@ -375,6 +375,46 @@ static void exit_sighandler(int x){ static muxer_t* muxer=NULL; +void add_subtitles(char *filename, float fps, int silent) +{ + sub_data *subd; +#ifdef CONFIG_ASS + ASS_Track *asst = 0; +#endif + + if (!filename) return; + + subd = sub_read_file(filename, fps); +#ifdef CONFIG_ASS + if (opts.ass_enabled) +#ifdef CONFIG_ICONV + asst = ass_read_file(ass_library, filename, sub_cp); +#else + asst = ass_read_file(ass_library, filename, 0); +#endif + if (opts.ass_enabled && subd && !asst) + asst = ass_read_subdata(ass_library, subd, fps); + + if (!asst && !subd && !silent) +#else + if (!subd && !silent) +#endif + mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Cannot load subtitles: %s\n", + filename_recode(filename)); + +#ifdef CONFIG_ASS + if (!asst && !subd) return; + ass_track = asst; +#else + if (!subd) return; +#endif + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n", + filename_recode(filename)); + subdata = subd; +} + +void print_wave_header(WAVEFORMATEX *h, int verbose_level); + int main(int argc,char* argv[]){ stream_t* stream=NULL; @@ -535,6 +575,10 @@ if (frameno_filename) { m_entry_set_options(mconfig,&filelist[curfile]); filename = filelist[curfile].name; +#ifdef CONFIG_ASS + ass_library = ass_init(); +#endif + if(!filename){ mp_tmsg(MSGT_CPLAYER, MSGL_FATAL, "\nFilename missing.\n\n"); mencoder_exit(1,NULL); @@ -666,26 +710,6 @@ if(sh_audio && (out_audio_codec || seek_to_sec || !sh_audio->wf || opts.playback } } -// after reading video params we should load subtitles because -// we know fps so now we can adjust subtitles time to ~6 seconds AST -// check .sub -// current_module="read_subtitles_file"; - if(sub_name && sub_name[0]){ - subdata=sub_read_file(sub_name[0], sh_video->fps); - if(!subdata) mp_tmsg(MSGT_CPLAYER,MSGL_ERR,"Cannot load subtitles: %s\n",sub_name[0]); - } else - if(sub_auto && filename) { // auto load sub file ... - char **tmp = NULL; - int i = 0; - char *psub = get_path( "sub/" ); - tmp = sub_filenames((psub ? psub : ""), filename); - free(psub); - subdata=sub_read_file(tmp[0], sh_video->fps); - while (tmp[i]) - free(tmp[i++]); - free(tmp); - } - // set up video encoder: if (!curfile) { // curfile is non zero when a second file is opened @@ -865,12 +889,77 @@ default: { ve = sh_video->vfilter; } else sh_video->vfilter = ve; // append 'expand' filter, it fixes stride problems and renders osd: +#ifdef CONFIG_ASS + if (auto_expand && !opts.ass_enabled) { /* we do not want both */ +#else if (auto_expand) { +#endif char* vf_args[] = { "osd", "1", NULL }; sh_video->vfilter=vf_open_filter(&opts, sh_video->vfilter,"expand",vf_args); } + +#ifdef CONFIG_ASS + if(opts.ass_enabled) { + int i; + int insert = 1; + if (opts.vf_settings) + for (i = 0; opts.vf_settings[i].name; ++i) + if (strcmp(opts.vf_settings[i].name, "ass") == 0) { + insert = 0; + break; + } + if (insert) { + extern vf_info_t vf_info_ass; + vf_info_t* libass_vfs[] = {&vf_info_ass, NULL}; + char* vf_arg[] = {"auto", "1", NULL}; + vf_instance_t* vf_ass = vf_open_plugin(&opts,libass_vfs,sh_video->vfilter,"ass",vf_arg); + if (vf_ass) + sh_video->vfilter=(void*)vf_ass; + else + mp_msg(MSGT_CPLAYER,MSGL_ERR, "ASS: cannot add video filter\n"); + } + + if (ass_library) { + for (i = 0; i < demuxer->num_attachments; ++i) { + demux_attachment_t* att = demuxer->attachments + i; + if (use_embedded_fonts && + att->name && att->type && att->data && att->data_size && + (strcmp(att->type, "application/x-truetype-font") == 0 || + strcmp(att->type, "application/x-font") == 0)) + ass_add_font(ass_library, att->name, att->data, att->data_size); + } + } + } +#endif + sh_video->vfilter=append_filters(sh_video->vfilter, opts.vf_settings); +#ifdef CONFIG_ASS + if (opts.ass_enabled) + ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_INIT_EOSD, ass_library); +#endif + +// after reading video params we should load subtitles because +// we know fps so now we can adjust subtitles time to ~6 seconds AST +// check .sub + if(sub_name && sub_name[0]){ + for (i = 0; sub_name[i] != NULL; ++i) + add_subtitles (sub_name[i], sh_video->fps, 0); + } else + if(sub_auto && filename) { // auto load sub file ... + char **tmp = NULL; + int i = 0; + char *psub = get_path( "sub/" ); + tmp = sub_filenames((psub ? psub : ""), filename); + free(psub); + while (tmp[i]) + { + add_subtitles (tmp[i], sh_video->fps, 0); + free(tmp[i++]); + } + free(tmp); + } + mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); init_best_video_codec(sh_video,video_codec_list,video_fm_list); mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); diff --git a/mplayer.c b/mplayer.c index c6689c8249..957a9f46a0 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1239,7 +1239,7 @@ static void saddf(char *buf, unsigned *pos, int len, const char *format, ...) * \param time time value to convert/append */ static void sadd_hhmmssf(char *buf, unsigned *pos, int len, float time) { - long tenths = 10 * time; + int64_t tenths = 10 * time; int f1 = tenths % 10; int ss = (tenths / 10) % 60; int mm = (tenths / 600) % 60; diff --git a/stream/stream.h b/stream/stream.h index 7d6619f75b..523da2ce00 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -25,6 +25,11 @@ #include #include #include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif #define STREAMTYPE_DUMMY -1 // for placeholders, when the actual reading is handled in the demuxer #define STREAMTYPE_FILE 0 // read from seekable file diff --git a/stream/stream_cddb.c b/stream/stream_cddb.c index 811a1c1570..e6caa21a4c 100644 --- a/stream/stream_cddb.c +++ b/stream/stream_cddb.c @@ -76,10 +76,6 @@ #include "network.h" #include "libavutil/common.h" -#ifndef O_BINARY -#define O_BINARY 0 -#endif - #define DEFAULT_FREEDB_SERVER "freedb.freedb.org" #define DEFAULT_CACHE_DIR "/.cddb/" diff --git a/stream/stream_file.c b/stream/stream_file.c index a77d51d315..b78a851432 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -136,9 +136,7 @@ static int open_f(stream_t *stream,int mode, void* opts, int* file_format) { filename++; #endif -#if defined(__CYGWIN__)|| defined(__MINGW32__) || defined(__OS2__) m |= O_BINARY; -#endif if(!strcmp(filename,"-")){ if(mode == STREAM_READ) { diff --git a/stream/stream_live555.c b/stream/stream_live555.c index acf616acd4..cb198ef60c 100644 --- a/stream/stream_live555.c +++ b/stream/stream_live555.c @@ -79,11 +79,7 @@ static int open_live_sdp(stream_t *stream,int mode, void* opts, int* file_format if(strncmp("sdp://",filename,6) == 0) { filename += 6; -#if defined(__CYGWIN__) || defined(__MINGW32__) f = open(filename,O_RDONLY|O_BINARY); -#else - f = open(filename,O_RDONLY); -#endif if(f < 0) { mp_tmsg(MSGT_OPEN,MSGL_ERR,"File not found: '%s'\n",filename); return STREAM_ERROR;