summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/mplayer.188
-rw-r--r--DOCS/xml/en/faq.xml10
-rw-r--r--Makefile2
-rwxr-xr-xconfigure2
-rw-r--r--etc/codecs.conf7
-rw-r--r--libmpcodecs/vd_qtvideo.c12
-rw-r--r--libmpcodecs/ve_qtvideo.c2
-rw-r--r--libmpcodecs/vf.c2
-rw-r--r--libmpcodecs/vf_fixpts.c137
-rw-r--r--libmpdemux/mp_taglists.c1
-rw-r--r--libvo/vo_fbdev.c38
-rw-r--r--loader/dshow/DS_Filter.c7
-rw-r--r--loader/dshow/allocator.c8
-rw-r--r--loader/dshow/graph.c163
-rw-r--r--loader/dshow/graph.h57
-rw-r--r--loader/dshow/guids.c4
-rw-r--r--loader/dshow/guids.h2
-rw-r--r--loader/dshow/interfaces.h28
-rw-r--r--loader/qtx/qtxsdk/components.h6
-rw-r--r--loader/win32.c196
-rw-r--r--mencoder.c129
-rw-r--r--mplayer.c2
-rw-r--r--stream/stream.h5
-rw-r--r--stream/stream_cddb.c4
-rw-r--r--stream/stream_file.c2
-rw-r--r--stream/stream_live555.c4
26 files changed, 828 insertions, 90 deletions
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=<fps>
+Specify a frame per second value.
+.IPs start=<pts>
+Specify an initial value for the PTS.
+.IPs autostart=<n>
+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=<n>
+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=<undef|show|crop>
+Include VUI overscan information in the stream (default: disabled).
+See doc/vui.txt in the x264 source code for more information.
+.
+.TP
+.B videoformat=<component|pal|ntsc|secam|mac|undef>
+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=<bt709|bt470m|bt470bg|smpte170m|smpte240m|film|undef>
+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=<bt709|bt470m|bt470bg|linear|log100|log316|smpte170m|smpte240m>
+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=<bt709|fcc|bt470bg|smpte170m|smpte240m|GBR|YCgCo>
+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?
</para></question>
<answer><para>
-<application>MPlayer</application> 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 <application>xine</application>,
-<application>VLC</application> or <application>Ogle</application>.
-If you want to see DVD navigation in <application>MPlayer</application> you
-will have to implement it yourself, but be aware that it is a major
-undertaking.
+<application>MPlayer</application> should support DVD menus nowadays.
+Your mileage may vary.
</para></answer>
</qandaentry>
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#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 <stdio.h>
@@ -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 <stdio.h>
+#include <stdlib.h>
+
+#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 : "<null>"));
@@ -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 @@ play_next_file:
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 <string.h>
#include <inttypes.h>
#include <sys/types.h>
+#include <fcntl.h>
+
+#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;