Merge svn changes r31198 - r31256

The cache changes in r31198 were somewhat broken; merge them together
with later fixes in one commit to keep all the "main branch side"
commits working.
This commit is contained in:
Uoti Urpala 2010-05-30 16:41:23 +03:00
commit 57e0de3715
14 changed files with 194 additions and 393 deletions

View File

@ -17,6 +17,7 @@ MPlayer (1.0)
* JPEG 2000 support via OpenJPEG
* internal liba52 copy removed
* CineForm HD (CFHD) via binary DLL
* VP8 decoding through libvpx wrapper in FFmpeg
Demuxers:
* support for TrueHD in Blu-ray streams in libmpdemux
@ -24,7 +25,11 @@ MPlayer (1.0)
* fix length in ASF/WMV files
* support ISDB-Tb DVB streams
Filters:
* remove vf_yuy2, functionality is replaced by -vf format=yuv2
Drivers:
* -vo md5sum md5 calculation changed so output matches FFmpeg's -f framemd5
* Support for more formats in OpenGL video output drivers (different YUV
subsampling, 16 bit per component)
* Selectable YUV to RGB conversion standard for -vo gl
@ -56,6 +61,8 @@ MPlayer (1.0)
MEncoder:
* add -tsprog for demuxer lavf
rc3: "BikeshedCounter" March 27, 2009
Decoders:
* support for X8 frames (fixes "J-type picture is not supported" for WMV2)
@ -76,7 +83,7 @@ MPlayer (1.0)
* GeoVision Advanced MPEG-4 (GMP4, GM40) via binary DLL
* Xiricam JPEG from Veo PC Camera (XJPG) via binary DLL
* WorldConnect Wavelet Video (SMSV) via binary DLL
* VDOWave 3 advanced (VDO3,VDOM,VDOW) via binary DLL
* VDOWave 3 advanced (VDO3, VDOM, VDOW) via binary DLL
* VoxWare MetaVoice (format 0x0074) via binary DLL
* Ulead DV Audio (0x215,0x216) via binary DLL
* GoToMeeting codec (G2M2,G2M3) via binary DLL
@ -85,10 +92,10 @@ MPlayer (1.0)
* ZDSoft screen recorder (ZDSV) via binary DLL
* WebTrain Communication lossless screen recorder (WTVC) via binary DLL
* xfire video (XFR1) via binary DLL
* VFAPI rgb transcode (vifp) via binary DLL
* VFAPI RGB transcode (vifp) via binary DLL
* ETI CamCorder EYECON (NUB0,NUB1,NUB2) via binary DLL
* fox motion (FMVC) via binary DLL
* Trident video (TY2C,TY2N,TY0N) via binary DLL
* Trident video (TY2C, TY2N, TY0N) via binary DLL
* 10-bit video (v210) via Cinewave binary DLL
* Brooktree YUV 4:1:1 Raw (Y41P) via binary DLL
* many rare/obscure fourccs for known formats added
@ -119,8 +126,7 @@ MPlayer (1.0)
* change vf_screenshot dependency from libpng to lavc
* add af_scaletempo which maintains audio pitch when changing playback speed
* fix multi-channel reordering
* af_stats, filter to print information about the audio stream
* remove vf_yuy2, functionality is replaced by -vf format=yuv2
* af_stats filter to print information about the audio stream
Streaming:
* tv:// support for Windows
@ -238,10 +244,10 @@ MPlayer (1.0)
Ports:
* small crash with vo_macosx fixed
* AC3/DTS passthrough for ao_macosx
* fix frozen OSD on Mac OS X
* fix frozen OSD on OS X
* vo_gl now works with -wid and nVidia drivers on Windows (this is a hack)
* VIDIX on SuperH
* workarounds for AltiVec on Apple gcc 3.3 on Mac OS X dropped
* workarounds for AltiVec on Apple gcc 3.3 on OS X dropped
* vo_macosx can now be compiled in 64-bits mode
* allow multiple MPlayer instances with vo_macosx using buffer_name
* OpenGL support for unmodified MinGW64

View File

@ -1,309 +0,0 @@
New Policy Draft
Version 20070301
Intro:
------
This document is an attempt to write a new policy as the old is fairly
confusing and easy to misunderstand, its intention is not really to
change the rules but rather to write them down clearer ...
also for simplicity and to prevent flamewars, i would suggest that you
fork this document and propose that fork as alternative if you have a
significant disagreement with me on some part
Author:
-------
Michael Niedermayer
the authors of the old policy as I liberally copy and pasted from it
TODO:
add more explanations, justifications and examples
how to become/loose maintainer status
review patches.txt
security/exploit rules
------------------------
1. Definitions
--------------
* MPlayer developer, generally referred to simply as developer in this document
is any person who has a open (not cracked, not suspended) svn write account
* MPlayer leader, generally referred to simply as leader in this document, every
leader is also a developer
* CAN/MUST/SHOULD descriptions ...
* public developer mailing list (mplayer-dev-eng at mplayerhq in hungary)
C. Code and SVN Rules
-----------------------------
Renaming/moving/copying files or contents of files
Do not move, rename or copy files of which you are not the maintainer without
discussing it on the public developer mailinglist first!
Never copy or move a file by using 'svn delete' and 'svn add'. Always use
'svn move' or 'svn copy' instead in order to preserve history and minimize
the size of diffs.
To split a file, use 'svn copy' and remove the unneeded lines from each file.
Don't do a lot of cut'n'paste from one file to another without a very good
reason and discuss it on the mplayer-dev-eng mailing list first. It will make
those changes hard to trace.
Such actions are useless and treated as cosmetics in 99% of cases,
so try to avoid them.
Reverting broken commits
There are 2 ways to reverse a change, they differ significantly in what they
do to the svn repository
The recommit old method:
svn merge
svn ci <file>
This simply changes the file(s) back to their old version localy and then
the change is commited as if it is a new change
The svn copy method
svn rm <file>
svn ci <file>
svn cp -r<good revision> svn://svn.mplayerhq.hu/mplayer/trunk/[<path>/]<file> <file>
svn ci <file>
This simply removes the file and then copies the last good version with
its history over it, this method can only be used to revert the n last
commits but not to revert a bad commit in the middle of its history
Neither method will change the history, checking out an old version will
always return exactly that revision with all its bugs and features. The
difference is that with the svn copy method the broken commit will not be
part of the directly visible history of the revisions after the reversal
So if the change was completely broken like reindenting a file against the
maintainers decision, or a change which mixed functional and cosmetic
changes then it is better if it is not part of the visible history as it
would make it hard to read, review and would also break svn annotate
For the example of a change which mixed functional and cosmetic parts they
should of course be committed again after the reversal but separately, so one
change with the functional stuff and one with the cosmetics
OTOH if the change which you want to reverse was simply buggy but not
totally broken then it should be reversed with svn merge as otherwise
the fact that the change was bad would be hidden
One method to decide which reversal method is best is to ask yourself
if there is any value in seeing the whole bad change and its removal
in SVN vs just seeing a comment that says what has been reversed while
the actual change does not clutter the immediately visible history and
svn annotate.
If you are even just slightly uncertain how to revert something then ask on
the mplayer-dev-eng mailing list.
Broken code
You must not commit code which breaks MPlayer! (Meaning unfinished but
enabled code which breaks compilation or compiles but does not work.)
You can commit unfinished stuff (for testing etc), but it must be disabled
(#ifdef etc) by default so it does not interfere with other developers'
work.
Testing code
You don't have to over-test things. If it works for you, and you think it
should work for others, too, then commit. If your code has problems
(portability, exploits compiler bugs, unusual environment etc) they will be
reported and eventually fixed.
Splitting changes
Do not commit unrelated changes together, split them into self-contained
pieces. Also dont forget that if part B depends on part A but A doesnt
depend on B, then A can and should be commited first and seperately from B.
Keeping changes well split into self contained parts makes reviewing and
understanding them on svn log at the time of commit and later when
debugging a bug much easier.
Also if you have doubt about spliting or not spliting, dont hesitate to
ask/disscuss it on the developer mailing list.
4. Do not change behavior of the program (renaming options etc) or
remove functionality from the code without approval in a discussion on
the mplayer-dev-eng mailing list.
5. Do not commit changes to the build system (Makefiles, configure script)
which change behaviour, defaults etc, without asking first. The same
applies to compiler warning fixes, trivial looking fixes and to code
maintained by other developers. We usually have a reason for doing things
the way we do. Send your changes as patches to the mplayer-dev-eng mailing
list, and if the code maintainers say OK, you may commit. This does not
apply to files you wrote and/or maintain.
Cosmetics
We refuse source indentation and other cosmetic changes if they are mixed
with functional changes, such commits will be reverted. Every
developer has his own indentation style, you should not change it. Of course
if you (re)write something, you can use your own style... (Many projects
force a given indentation style - we don't.) If you really need to make
indentation changes (try to avoid this), separate them strictly from real
changes.
NOTE: If you had to put if()@{ .. @} over a large (> 5 lines) chunk of code,
then either do NOT change the indentation of the inner part within (don't
move it to the right)! or do so in a separate commit
Commit log message
Always fill out the commit log message. Describe in a few lines what you
changed and why. You can refer to mailing list postings if you fix a
particular bug. Comments such as "fixed!" or "Changed it." are unacceptable.
Applying patches
If you apply a patch by someone else, include the name and email address in
the log message. Since the mplayer-cvslog mailing list is publicly
archived you should add some spam protection to the email address. Send an
answer to mplayer-dev-eng (or wherever you got the patch from) saying that
you applied the patch. If the patch contains a documentation change, commit
that as well; do not leave it to the documentation maintainers.
messing with other developers code
Do NOT commit to code actively maintained by others without permission. Send
a patch to mplayer-dev-eng instead.
Subscribe to svnlog
Subscribe to the mplayer-cvslog mailing list. The diffs of all commits
are sent there and reviewed by all the other developers. Bugs and possible
improvements or general questions regarding commits are discussed there. We
expect you to react if problems with your code are uncovered.
Documentation
Update the documentation if you change behavior or add features. If you are
unsure how best to do this, send a patch to mplayer-docs, the documentation
maintainers will review and commit your stuff.
Controversial changes
Always send a patch to the mplayer-dev-eng mailing list before committing
if you suspect that the change is going to be controversial. Based on past
experience, these changes are likely to be controversial:
- feature removal, even if obsolete
- changes to "special" output messages (like the "Core dumped ;)" message)
- verbosity changes from default (info) level
- changes to "historical" parts of docs and webpages
- use of internal or external libraries
- changes to the internal architecture
- non trivial changes to very fundamental parts of mplayer
Public discussions
Try to keep important discussions and requests (also) on the
mplayer-dev-eng mailing list, so that all developers can benefit from them.
IRC is good for quick discussions, but nobody is there 24/7.
also subscribe to the public developer mailing list
Compiler Warning fixes
Do not change code to hide warnings without ensuring that the underlaying
logic is correct and thus the warning was inappropriate
Patches
read and follow patches.txt when sending patches for mplayer
Insults
Do not insult other people in relation to mplayer on any public mailing
list, that is calling code from someone else a pile of broken shit is
perfectly fine but calling the developer herself a retarded f*cking moron
is not acceptable
Forking
People disagreeing with the developers or leaders may fork the project,
the leaders MUST in that case provide a svn dump with all history if
the person forking wants one
Communicating passwords
Developers who have provided a public gpg key shall only receive
passwords or other sensitive information related to mplayer encrypted
with their gpg key or in another secure way
V. Votes
--------
Its inevitable that some things will be decided by voting, votes in the past
have due to total lack of rules been problematic for example as many people
rather wrote long texts and voted based on some condition instead of saying
a clear yes or no, still its important that people can vote based on a
condition
The result of a vote is binding for all developers and leaders, though of
course they can leave the project and thus cease to be a developer or leader
any time
Vs. Starting a vote
Any single developer can start a vote, to do so she has to send a mail to the
public developer mailing list of the project with a subject containing [VOTE]
and a clear and concise description, a longer descrition can be in the body
of the mail
Vp. Proposing an option (point on the ballot, better term?)
Any single developer can propose an option up to 7 days after a vote has
been started, to do so she has to reply to the original vote mail on the
public developer mailing list and clearly, concise and unmistakably describe
the option and place [VOTE-OPTION] instead of [VOTE] in the subject
in addition to proposed options, there always exists the default option
of doing nothing
options can be conditional on anything which at the end of the vote can
be clearly and unmistakably be answered with true or false
Vv. Voting
Any developer can cast a vote up to 10 days days after a vote has been
started, to do so she has to reply to the original vote mail on the
public developer mailing list and rate options each with an integer
unrated options shall be counted equal to the default option
Any leader can cast a veto against any option except the default up to 10 days
days after a vote has been started, to do so she has to reply to the original
vote mail on the public developer mailing list and replace
[VOTE] by [VOTE-VETO]
Developers and leaders who use gpg/pgp MUST sign their votes and vetoes
Vc. Counting votes
The person starting the vote has to count the votes and vetoes and publish
the result on the public developer mailing list as reply to the original vote
with [VOTE-RESULTS] instead of [VOTE] in the subject
Vcv. Counting vetoes
if the majority of leaders that is yes >= no && yes>0 cast a veto against an
option then it has a required supermajority of 2:1 otherwise it has a
required supermajority of 0:1 and in either case no quorum requirement
Vcc. the votes shall be counted by using the Condorcet/Clone Proof SSD
Voting Method described in http://www.debian.org/devel/constitution A.6
Reasoning behind avoiding of a quorum and majority requirement except in
the case of vetoes
short awnser its stupid and has catastrophical failure modes
example of one such failure mode, lets assume a 1:1 majority requirement
as debian uses by default, there are 101 developers who vote, there are
3 options A,B and D the default (doing nothing / further discussions)
50 developers prefer A over B and B over discussions (A>B>D)
50 developers prefer discussions over A and A over B (D>A>B)
1 developer prefers B over discussions and discussions over A (B>D>A)
in this case A is approved by 50 of 101 developers and is droped due to
the lack of majority, B is approved by 51 of 101 developers and is not
furthermore B wins even though 100 of 101 developers prefer A over B
S. Changes to developer and Leader status
----------------------------------------
The majority of leaders, that is yes>no can give and take away
developer and leader status to people
furthermore any developer or leader can step back and thus loose
his leader and or developer status
People disagreeing with the leaders are free to fork the project
new developers should be asked for real name, public gpg key, phone
number and email addresses, none of this is mandatory though, it is asked
so as to be able to contact the developer if the need arises and one
contact method fails
O. Violations
-------------
Any leader can after at least one leader has warned another developer
due to breaking policy, suspend his account if he repeats the violation
Ow. A policy violation warning MUST be CCed to the developer who violated
the policy
We think our rules are not too hard. If you have comments, contact us.

11
configure vendored
View File

@ -462,7 +462,6 @@ Use these options if autodetection fails:
--with-xvmclib=NAME adapter-specific library name (e.g. XvMCNVIDIA)
--with-freetype-config=PATH path to freetype-config
--with-fribidi-config=PATH path to fribidi-config
--with-glib-config=PATH path to glib*-config
--with-gtk-config=PATH path to gtk*-config
--with-sdl-config=PATH path to sdl*-config
@ -681,7 +680,6 @@ _macosx_bundle=auto
_sortsub=yes
_freetypeconfig='freetype-config'
_fribidi=auto
_fribidiconfig='fribidi-config'
_enca=auto
_inet6=auto
_gethostbyname2=auto
@ -743,9 +741,6 @@ for ac_option do
--with-freetype-config=*)
_freetypeconfig=$(echo $ac_option | cut -d '=' -f 2)
;;
--with-fribidi-config=*)
_fribidiconfig=$(echo $ac_option | cut -d '=' -f 2)
;;
--with-gtk-config=*)
_gtkconfig=$(echo $ac_option | cut -d '=' -f 2)
;;
@ -6171,10 +6166,10 @@ EOF
_inc_tmp=""
_ld_tmp="-lfribidi"
cc_check $_inc_tmp $_ld_tmp && _fribidi=yes
if $_fribidiconfig --version > /dev/null 2>&1 &&
if $_pkg_config --exists fribidi > /dev/null 2>&1 &&
test "$_fribidi" = no ; then
_inc_tmp="$($_fribidiconfig --cflags)"
_ld_tmp="$($_fribidiconfig --libs)"
_inc_tmp="$($_pkg_config --cflags)"
_ld_tmp="$($_pkg_config --libs)"
cc_check $_inc_tmp $_ld_tmp && _fribidi=yes
fi
fi

View File

@ -1003,6 +1003,7 @@ videocodec ffodivx
fourcc M4T3,DMK2,DIGI,INMC
fourcc EPHV,SN40
fourcc uldx,ULDX,VSPX
fourcc SIPP ; Samsung SHR-6040
driver ffmpeg
dll mpeg4 ;opendivx
out YV12,I420,IYUV
@ -1035,6 +1036,7 @@ videocodec ffodivxvdpau
fourcc M4T3,DMK2,DIGI,INMC
fourcc EPHV,SN40
fourcc uldx,ULDX,VSPX
fourcc SIPP ; Samsung SHR-6040
driver ffmpeg
dll mpeg4_vdpau
out VDPAU_MPEG4
@ -1088,6 +1090,7 @@ videocodec xvid
fourcc EPHV,SN40
fourcc uldx,ULDX,VSPX
format 0x10000004 ; mpeg 4 es
fourcc SIPP ; Samsung SHR-6040
driver xvid
out YV12
out I420
@ -2171,6 +2174,14 @@ videocodec vp7
out YUY2
out BGR32,BGR24
videocodec fflibvpx
info "FFmpeg wrapper for libvpx/VP8"
status working
fourcc VP80
driver ffmpeg
dll "libvpx"
out YV12
videocodec mwv1
info "Motion Wavelets"
status working

View File

@ -1169,6 +1169,9 @@ static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
}
/**
* \param time time to wait at most for an event in milliseconds
*/
static mp_cmd_t *read_events(struct input_ctx *ictx, int time)
{
int i;
@ -1837,6 +1840,9 @@ static int print_cmd_list(m_option_t* cfg)
exit(0);
}
/**
* \param time time to wait for an interruption in milliseconds
*/
int mp_input_check_interrupt(struct input_ctx *ictx, int time)
{
mp_cmd_t* cmd;

View File

@ -98,7 +98,7 @@ static int init(sh_video_t *sh){
op.packet = extradata + 2;
op.b_o_s = 1;
if (extradata_size < op.bytes + 2) {
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Theora header too small\n");
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Theora header too small\n");
goto err_out;
}
extradata += op.bytes + 2;
@ -110,7 +110,7 @@ static int init(sh_video_t *sh){
if ( (errorCode = theora_decode_header (&context->inf, &context->cc, &op)) )
{
mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Broken Theora header; errorCode=%i!\n", errorCode);
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Broken Theora header; errorCode=%i!\n", errorCode);
goto err_out;
}
}
@ -167,6 +167,10 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
yuv_buffer yuv;
mp_image_t* mpi;
// no delayed frames
if (!data || !len)
return NULL;
memset (&op, 0, sizeof (op));
op.bytes = len;
op.packet = data;
@ -183,7 +187,7 @@ static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags)
errorCode = theora_decode_YUVout (&context->st, &yuv);
if (errorCode)
{
mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora decode YUVout failed: %i \n",
mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Theora decode YUVout failed: %i \n",
errorCode);
return NULL;
}

View File

@ -213,6 +213,7 @@ static const char * const preferred_list[] = {
"mpc",
"mpc8",
"mxf",
"ogg",
"swf",
"vqf",
"w64",

View File

@ -284,6 +284,7 @@ void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, i
}
#ifdef FAST_OSD_TABLE
static unsigned short fast_osd_12bpp_table[256];
static unsigned short fast_osd_15bpp_table[256];
static unsigned short fast_osd_16bpp_table[256];
#endif
@ -292,6 +293,7 @@ void vo_draw_alpha_init(void){
#ifdef FAST_OSD_TABLE
int i;
for(i=0;i<256;i++){
fast_osd_12bpp_table[i]=((i>>4)<< 8)|((i>>4)<<4)|(i>>4);
fast_osd_15bpp_table[i]=((i>>3)<<10)|((i>>3)<<5)|(i>>3);
fast_osd_16bpp_table[i]=((i>>3)<<11)|((i>>2)<<5)|(i>>3);
}

View File

@ -503,12 +503,19 @@ static void autodetectGlExtensions(void) {
ati_broken_pbo = ver && ver < 8395;
}
if (ati_hack == -1) ati_hack = ati_broken_pbo;
if (force_pbo == -1 && extensions && strstr(extensions, "_pixel_buffer_object"))
force_pbo = is_ati;
if (use_rectangle == -1 && extensions && strstr(extensions, "_texture_non_power_of_two"))
if (force_pbo == -1) {
force_pbo = 0;
if (extensions && strstr(extensions, "_pixel_buffer_object"))
force_pbo = is_ati;
}
if (use_rectangle == -1) {
use_rectangle = 0;
if (use_rectangle == -1 && extensions && strstr(extensions, "_texture_rectangle"))
use_rectangle = renderer && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
if (extensions) {
// if (strstr(extensions, "_texture_non_power_of_two"))
if (strstr(extensions, "_texture_rectangle"))
use_rectangle = renderer && strstr(renderer, "Mesa DRI R200") ? 1 : 0;
}
}
if (use_osd == -1)
use_osd = mpglBindTexture != NULL;
if (use_yuv == -1)

View File

@ -218,6 +218,8 @@ static uint32_t draw_image(mp_image_t *mpi)
h = h / 2;
for (i=0; i<h; i++) {
av_md5_update(md5_context, planeU + i * strideU, w);
}
for (i=0; i<h; i++) {
av_md5_update(md5_context, planeV + i * strideV, w);
}
av_md5_final(md5_context, md5sum);

View File

@ -2468,7 +2468,7 @@ static double update_video(struct MPContext *mpctx)
if (in_size < 0) {
// try to extract last frames in case of decoder lag
in_size = 0;
pts = 1e300;
pts = MP_NOPTS_VALUE;
hit_eof = true;
}
if (in_size > max_framesize)

View File

@ -19,10 +19,14 @@
#include "config.h"
// Initial draft of my new cache system...
// Note it runs in 2 processes (using fork()), but doesn't requires locking!!
// Note it runs in 2 processes (using fork()), but doesn't require locking!!
// TODO: seeking, data consistency checking
#define READ_USLEEP_TIME 10000
#define READ_SLEEP_TIME 10
// These defines are used to reduce the cost of many successive
// seeks (e.g. when a file has no index) by spinning quickly at first.
#define INITIAL_FILL_USLEEP_TIME 1000
#define INITIAL_FILL_USLEEP_COUNT 10
#define FILL_USLEEP_TIME 50000
#define PREFILL_SLEEP_TIME 200
#define CONTROL_SLEEP_TIME 0
@ -49,6 +53,10 @@ static void ThreadProc( void *s );
static void *ThreadProc(void *s);
#else
#include <sys/wait.h>
#define FORKED_CACHE 1
#endif
#ifndef FORKED_CACHE
#define FORKED_CACHE 0
#endif
#include "mp_msg.h"
@ -58,12 +66,12 @@ static void *ThreadProc(void *s);
typedef struct {
// constats:
unsigned char *buffer; // base pointer of the alllocated buffer memory
int buffer_size; // size of the alllocated buffer memory
unsigned char *buffer; // base pointer of the allocated buffer memory
int buffer_size; // size of the allocated buffer memory
int sector_size; // size of a single sector (2048/2324)
int back_size; // we should keep back_size amount of old bytes for backward seek
int fill_limit; // we should fill buffer only if space>=fill_limit
int seek_limit; // keep filling cache if distanse is less that seek limit
int seek_limit; // keep filling cache if distance is less that seek limit
// filler's pointers:
int eof;
off_t min_filepos; // buffer contain only a part of the file, from min-max pos
@ -88,6 +96,14 @@ static int min_fill=0;
int cache_fill_status=0;
static void cache_wakeup(stream_t *s)
{
#if FORKED_CACHE
// signal process to wake up immediately
kill(s->cache_pid, SIGUSR1);
#endif
}
static void cache_stats(cache_vars_t *s)
{
int newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
@ -98,6 +114,8 @@ static void cache_stats(cache_vars_t *s)
static int cache_read(cache_vars_t *s, unsigned char *buf, int size)
{
int total=0;
int sleep_count = 0;
int last_max = s->max_filepos;
while(size>0){
int pos,newb,len;
@ -106,10 +124,21 @@ static int cache_read(cache_vars_t *s, unsigned char *buf, int size)
if(s->read_filepos>=s->max_filepos || s->read_filepos<s->min_filepos){
// eof?
if(s->eof) break;
if (s->max_filepos == last_max) {
if (sleep_count++ == 10)
mp_msg(MSGT_CACHE, MSGL_WARN, "Cache not filling!\n");
} else {
last_max = s->max_filepos;
sleep_count = 0;
}
// waiting for buffer fill...
usec_sleep(READ_USLEEP_TIME); // 10ms
if (stream_check_interrupt(READ_SLEEP_TIME)) {
s->eof = 1;
break;
}
continue; // try again...
}
sleep_count = 0;
newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
if(newb<min_fill) min_fill=newb; // statistics...
@ -207,7 +236,7 @@ static int cache_fill(cache_vars_t *s)
//memcpy(&s->buffer[pos],s->stream->buffer,len); // avoid this extra copy!
// ....
len=stream_read(s->stream,&s->buffer[pos],space);
if(!len) s->eof=1;
s->eof= !len;
s->max_filepos+=len;
if(pos+len>=s->buffer_size){
@ -261,13 +290,25 @@ static int cache_execute_control(cache_vars_t *s) {
return 1;
}
static void *shared_alloc(int size) {
#if FORKED_CACHE
return shmem_alloc(size);
#else
return malloc(size);
#endif
}
static void shared_free(void *ptr, int size) {
#if FORKED_CACHE
shmem_free(ptr, size);
#else
free(ptr);
#endif
}
static cache_vars_t* cache_init(int size,int sector){
int num;
#if !defined(__MINGW32__) && !defined(PTHREAD_CACHE) && !defined(__OS2__)
cache_vars_t* s=shmem_alloc(sizeof(cache_vars_t));
#else
cache_vars_t* s=malloc(sizeof(cache_vars_t));
#endif
cache_vars_t* s=shared_alloc(sizeof(cache_vars_t));
if(s==NULL) return NULL;
memset(s,0,sizeof(cache_vars_t));
@ -277,18 +318,10 @@ static cache_vars_t* cache_init(int size,int sector){
}//32kb min_size
s->buffer_size=num*sector;
s->sector_size=sector;
#if !defined(__MINGW32__) && !defined(PTHREAD_CACHE) && !defined(__OS2__)
s->buffer=shmem_alloc(s->buffer_size);
#else
s->buffer=malloc(s->buffer_size);
#endif
s->buffer=shared_alloc(s->buffer_size);
if(s->buffer == NULL){
#if !defined(__MINGW32__) && !defined(PTHREAD_CACHE) && !defined(__OS2__)
shmem_free(s,sizeof(cache_vars_t));
#else
free(s);
#endif
shared_free(s, sizeof(cache_vars_t));
return NULL;
}
@ -300,7 +333,7 @@ static cache_vars_t* cache_init(int size,int sector){
void cache_uninit(stream_t *s) {
cache_vars_t* c = s->cache_data;
if(s->cache_pid) {
#if defined(__MINGW32__) || defined(PTHREAD_CACHE) || defined(__OS2__)
#if !FORKED_CACHE
cache_do_control(s, -2, NULL);
#else
kill(s->cache_pid,SIGKILL);
@ -309,16 +342,10 @@ void cache_uninit(stream_t *s) {
s->cache_pid = 0;
}
if(!c) return;
#if defined(__MINGW32__) || defined(PTHREAD_CACHE) || defined(__OS2__)
free(c->buffer);
shared_free(c->buffer, c->buffer_size);
c->buffer = NULL;
c->stream = NULL;
free(s->cache_data);
#else
shmem_free(c->buffer,c->buffer_size);
c->buffer = NULL;
shmem_free(s->cache_data,sizeof(cache_vars_t));
#endif
shared_free(s->cache_data, sizeof(cache_vars_t));
s->cache_data = NULL;
}
@ -327,6 +354,39 @@ static void exit_sighandler(int x){
exit(0);
}
static void dummy_sighandler(int x) {
}
/**
* Main loop of the cache process or thread.
*/
static void cache_mainloop(cache_vars_t *s) {
int sleep_count = 0;
#if FORKED_CACHE
signal(SIGUSR1, SIG_IGN);
#endif
do {
if (!cache_fill(s)) {
#if FORKED_CACHE
// Let signal wake us up, we cannot leave this
// enabled since we do not handle EINTR in most places.
// This might need extra code to work on BSD.
signal(SIGUSR1, dummy_sighandler);
#endif
if (sleep_count < INITIAL_FILL_USLEEP_COUNT) {
sleep_count++;
usec_sleep(INITIAL_FILL_USLEEP_TIME);
} else
usec_sleep(FILL_USLEEP_TIME); // idle
#if FORKED_CACHE
signal(SIGUSR1, SIG_IGN);
#endif
} else
sleep_count = 0;
// cache_stats(s->cache_data);
} while (cache_execute_control(s));
}
/**
* \return 1 on success, 0 if the function was interrupted and -1 on error
*/
@ -348,15 +408,19 @@ int stream_enable_cache(stream_t *stream,int size,int min,int seek_limit){
//make sure that we won't wait from cache_fill
//more data than it is alowed to fill
//more data than it is allowed to fill
if (s->seek_limit > s->buffer_size - s->fill_limit ){
s->seek_limit = s->buffer_size - s->fill_limit;
}
if (min > s->buffer_size - s->fill_limit) {
min = s->buffer_size - s->fill_limit;
}
// to make sure we wait for the cache process/thread to be active
// before continuing
if (min <= 0)
min = 1;
#if !defined(__MINGW32__) && !defined(PTHREAD_CACHE) && !defined(__OS2__)
#if FORKED_CACHE
if((stream->cache_pid=fork())){
if ((pid_t)stream->cache_pid == -1)
stream->cache_pid = 0;
@ -404,36 +468,30 @@ err_out:
return res;
}
#if defined(__MINGW32__) || defined(PTHREAD_CACHE) || defined(__OS2__)
}
#ifdef PTHREAD_CACHE
static void *ThreadProc( void *s ){
#else
static void ThreadProc( void *s ){
#endif
#endif
// cache thread mainloop:
#if FORKED_CACHE
signal(SIGTERM,exit_sighandler); // kill
do {
if(!cache_fill(s)){
usec_sleep(FILL_USLEEP_TIME); // idle
}
// cache_stats(s->cache_data);
} while (cache_execute_control(s));
#if defined(__MINGW32__) || defined(__OS2__)
_endthread();
#elif defined(PTHREAD_CACHE)
return NULL;
#else
cache_mainloop(s);
// make sure forked code never leaves this function
exit(0);
#endif
}
#if !FORKED_CACHE
#if defined(__MINGW32__) || defined(__OS2__)
static void ThreadProc( void *s ){
cache_mainloop(s);
_endthread();
}
#else
static void *ThreadProc( void *s ){
cache_mainloop(s);
return NULL;
}
#endif
#endif
int cache_stream_fill_buffer(stream_t *s){
int len;
if(s->eof){ s->buf_pos=s->buf_len=0; return 0; }
if(!s->cache_pid) return stream_fill_buffer(s);
// cache_stats(s->cache_data);
@ -444,6 +502,7 @@ int cache_stream_fill_buffer(stream_t *s){
//printf("cache_stream_fill_buffer->read -> %d\n",len);
if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; }
s->eof=0;
s->buf_pos=0;
s->buf_len=len;
s->pos+=len;
@ -465,6 +524,7 @@ int cache_stream_seek_long(stream_t *stream,off_t pos){
newpos=pos/s->sector_size; newpos*=s->sector_size; // align
stream->pos=s->read_filepos=newpos;
s->eof=0; // !!!!!!!
cache_wakeup(stream);
cache_stream_fill_buffer(stream);
@ -482,6 +542,7 @@ int cache_stream_seek_long(stream_t *stream,off_t pos){
}
int cache_do_control(stream_t *stream, int cmd, void *arg) {
int sleep_count = 0;
cache_vars_t* s = stream->cache_data;
switch (cmd) {
case STREAM_CTRL_SEEK_TO_TIME:
@ -509,8 +570,15 @@ int cache_do_control(stream_t *stream, int cmd, void *arg) {
default:
return STREAM_UNSUPPORTED;
}
while (s->control != -1)
usec_sleep(CONTROL_SLEEP_TIME);
cache_wakeup(stream);
while (s->control != -1) {
if (sleep_count++ == 1000)
mp_msg(MSGT_CACHE, MSGL_WARN, "Cache not responding!\n");
if (stream_check_interrupt(CONTROL_SLEEP_TIME)) {
s->eof = 1;
return STREAM_UNSUPPORTED;
}
}
switch (cmd) {
case STREAM_CTRL_GET_TIME_LENGTH:
case STREAM_CTRL_GET_CURRENT_TIME:

View File

@ -37,6 +37,7 @@
#include "mp_msg.h"
#include "osdep/shmem.h"
#include "osdep/timer.h"
#include "network.h"
#include "stream.h"
#include "libmpdemux/demuxer.h"
@ -260,7 +261,7 @@ stream_t *open_output_stream(const char *filename, struct MPOpts *options)
int stream_fill_buffer(stream_t *s){
int len;
if (/*s->fd == NULL ||*/ s->eof) { return 0; }
// we will retry even if we already reached EOF previously.
switch(s->type){
case STREAMTYPE_STREAM:
#ifdef CONFIG_NETWORK
@ -282,6 +283,9 @@ int stream_fill_buffer(stream_t *s){
len= s->fill_buffer ? s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE) : 0;
}
if(len<=0){ s->eof=1; return 0; }
// When reading succeeded we are obviously not at eof.
// This e.g. avoids issues with eof getting stuck when lavf seeks in MPEG-TS
s->eof=0;
s->buf_pos=0;
s->buf_len=len;
s->pos+=len;
@ -487,7 +491,10 @@ void stream_set_interrupt_callback(int (*cb)(struct input_ctx *, int),
}
int stream_check_interrupt(int time) {
if(!stream_check_interrupt_cb) return 0;
if(!stream_check_interrupt_cb) {
usec_sleep(time * 1000);
return 0;
}
return stream_check_interrupt_cb(stream_check_interrupt_ctx, time);
}

View File

@ -336,7 +336,8 @@ stream_t *open_output_stream(const char *filename, struct MPOpts *options);
struct input_ctx;
void stream_set_interrupt_callback(int (*cb)(struct input_ctx*, int),
struct input_ctx *ctx);
/// Call the interrupt checking callback if there is one.
/// Call the interrupt checking callback if there is one and
/// wait for time milliseconds
int stream_check_interrupt(int time);
extern int dvd_title;