Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2758bc462d | ||
|
|
2687b43dd0 | ||
|
|
bb40daf367 | ||
|
|
cc1f926441 | ||
|
|
67f653324a | ||
|
|
6e2c29b786 | ||
|
|
e565217f22 | ||
|
|
144c67efaf | ||
|
|
96d7e80ddf | ||
|
|
dde72c5c54 | ||
|
|
577d03da0c | ||
|
|
fc510f0da8 | ||
|
|
8d5775a8d2 | ||
|
|
cf8ff2fd87 | ||
|
|
852c924a60 | ||
|
|
1685d198b9 | ||
|
|
1e2d28f567 | ||
|
|
89973ebca1 | ||
|
|
3f4e528f73 | ||
|
|
6f7c9f516e | ||
|
|
33e0074603 | ||
|
|
b6ed94fa7c | ||
|
|
a419703549 | ||
|
|
5171da86e3 | ||
|
|
7bd670949c | ||
|
|
421b2be348 | ||
|
|
b659476ed9 | ||
|
|
689c3f47a8 | ||
|
|
677d4615ba | ||
|
|
5f788a7812 | ||
|
|
dba25e13c0 | ||
|
|
623b97e45a | ||
|
|
7a645ba62f | ||
|
|
63afe3eb98 | ||
|
|
72c70eb05b | ||
|
|
df0ec55499 | ||
|
|
542bcdfc9d | ||
|
|
218667b5a2 | ||
|
|
13a0e34aec | ||
|
|
76b7a1a713 | ||
|
|
6d6eee2e70 | ||
|
|
89f20cd2f3 | ||
|
|
cce2b675ac | ||
|
|
c1ed4dc242 | ||
|
|
712657a894 | ||
|
|
496956de3d | ||
|
|
483e703793 | ||
|
|
717cdeb95d | ||
|
|
315f3a9218 | ||
|
|
d857722618 | ||
|
|
6d9d597b10 | ||
|
|
c4d905b567 | ||
|
|
e4c69376fc | ||
|
|
842689bbf6 | ||
|
|
5ab2aa84e0 | ||
|
|
229d398ba9 | ||
|
|
5f1b155307 | ||
|
|
241cbe5065 |
No files matched your search
@@ -0,0 +1,139 @@
|
||||
Coding style
|
||||
============
|
||||
|
||||
mpv uses C99 with K&R formatting, with some exceptions.
|
||||
|
||||
General formatting
|
||||
------------------
|
||||
|
||||
- Use the K&R indent style.
|
||||
- Use 4 spaces of indentation, never use tabs (except in Makefiles).
|
||||
- Add a single space between keywords and binary operators. There are some other
|
||||
cases where spaces should be added. Example:
|
||||
|
||||
```C
|
||||
if ((a * b) > c) {
|
||||
// code
|
||||
some_function(a, b, c);
|
||||
}
|
||||
```
|
||||
- Break lines on 80 columns. There is a hard limit of 85 columns. You may ignore
|
||||
this limit if there's a strong case that not breaking the line will increase
|
||||
readability. Going over 85 columns might provoke endless discussions about
|
||||
whether such a limit is needed or not, so avoid it.
|
||||
- If the body of an if/for/while statement has more than 1 physical lines, then
|
||||
always add braces, even if they're technically redundant.
|
||||
|
||||
Bad:
|
||||
|
||||
```C
|
||||
if (a)
|
||||
// do something if b
|
||||
if (b)
|
||||
do_something();
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```C
|
||||
if (a) {
|
||||
// do something if b
|
||||
if (b)
|
||||
do_something();
|
||||
}
|
||||
```
|
||||
- If the body of an if statement uses braces, the else branch should also
|
||||
use braces (and reverse).
|
||||
|
||||
Example:
|
||||
|
||||
```C
|
||||
if (a) {
|
||||
// do something
|
||||
something();
|
||||
something_else();
|
||||
} else {
|
||||
one_line();
|
||||
}
|
||||
```
|
||||
- If an if condition spans multiple physical lines, then put the opening brace
|
||||
for the if body on the next physical line. (Also, preferably always add a
|
||||
brace, even if technically none is needed.)
|
||||
|
||||
Example:
|
||||
|
||||
```C
|
||||
if (very_long_condition_a &&
|
||||
very_long_condition_b)
|
||||
{
|
||||
code();
|
||||
}
|
||||
```
|
||||
- Remove any trailing whitespace.
|
||||
- If the file you're editing uses formatting different from from what is
|
||||
described here, it's probably an old file from times when nobody followed a
|
||||
consistent style. You're free to use the existing style, or the new style, or
|
||||
to send a patch to reformat the file to the new style before making functional
|
||||
changes.
|
||||
|
||||
General coding
|
||||
--------------
|
||||
|
||||
- Use C99. Also freely make use of C99 features if it's appropriate, such as
|
||||
stdbool.h.
|
||||
- Don't use GNU-only features. In some cases they may be warranted, if they
|
||||
are optional (such as attributes enabling printf-like format string checks).
|
||||
But in general, standard C99 should be used.
|
||||
- The same applies to libc functions. We have to be Windows-compatible too. Use
|
||||
functions guaranteed by C99 or POSIX only, unless your use is guarded by a
|
||||
configure check.
|
||||
- Prefer fusing declaration and initialization, rather than putting declarations
|
||||
on the top of a block. Obvious data flow is more important than avoiding
|
||||
mixing declarations and statements, which is just a C90 artifact.
|
||||
- tech-overview.txt might help to get an overview how mpv is structured.
|
||||
- If you add features that require intrusive changes, discuss them on the dev
|
||||
channel first. There might be a better way to add a feature and it can avoid
|
||||
wasted work.
|
||||
|
||||
Sending patches
|
||||
---------------
|
||||
|
||||
- Make a github pull request, or send a link to a plaintext patch created with
|
||||
``git format-patch``. diffs posted as pastebins (especially if the http link
|
||||
returns HTML) just cause extra work for everyone, because they lack commit
|
||||
message and authorship information.
|
||||
- Write informative commit messages. Use present tense to describe the
|
||||
situation with the patch applied, and past tense for the situation before
|
||||
the change.
|
||||
- The subject line (the first line in a commit message) should contain a
|
||||
prefix identifying the sub system, followed by a short description what
|
||||
impact this commit has. This subject line shouldn't be longer than 72
|
||||
characters, because it messes up the output of many git tools otherwise.
|
||||
|
||||
For example, you fixed a crash in af_volume.c:
|
||||
|
||||
Bad: ``fixed the bug (wtf?)``
|
||||
Good: ``af_volume: fix crash due to null pointer access``
|
||||
|
||||
Having a prefix gives context, and is especially useful when trying to find
|
||||
a specific change by looking at the history, or when running ``git blame``.
|
||||
- The body of the commit message (everything else after the subject line) should
|
||||
be as informative as possible and contain everything that isn't obvious. Don't
|
||||
hesitate to dump as much information as you can - it doesn't cost you
|
||||
anything. Put some effort into it. If someone finds a bug months or years
|
||||
later, and finds that it's caused by your commit (even though your commit was
|
||||
supposed to fix another bug), it would be bad if there wasn't enough
|
||||
information to test the original bug. The old bug might be reintroduced while
|
||||
fixing the new bug.
|
||||
|
||||
The commit message should be wrapped on 72 characters per line, because git
|
||||
tools usually do not break text automatically. On the other hand, you do not
|
||||
need to break text that would be unnatural to break (like data for test cases,
|
||||
or long URLs).
|
||||
|
||||
Important: put an empty line between the subject line and the commit message.
|
||||
If this is missing, it will break display in common git tools.
|
||||
- Try to separate cosmetic and functional changes. It's ok to make a few
|
||||
additional cosmetic changes in the same file you're working on, but don't do
|
||||
something like reformatting a whole file and hiding an actual functional
|
||||
change in the same commit.
|
||||
@@ -9,6 +9,8 @@ Using mingw-w64-cmake to setup a MinGW-w64 environment is recommended (this will
|
||||
also build mpv and its dependencies): https://github.com/lachs0r/mingw-w64-cmake
|
||||
|
||||
Alternatively, use MXE: http://mxe.cc
|
||||
With MXE, you have to modify the file settings.mk to target MinGW-w64 (even if
|
||||
you compile to 32 bit).
|
||||
|
||||
Warning: the original MinGW (http://www.mingw.org) is unsupported.
|
||||
|
||||
|
||||
+4
-4
@@ -266,7 +266,7 @@ Available filters are:
|
||||
Filter for internal use only. Converts between signed/unsigned formats
|
||||
and formats with different endian.
|
||||
|
||||
``volume[=volumedb[:softclip[:s16]]]``
|
||||
``volume[=<volumedb>[:...]]``
|
||||
Implements software volume control. Use this filter with caution since it
|
||||
can reduce the signal to noise ratio of the sound. In most cases it is
|
||||
best to use the *Master* volume control of your sound card or the volume
|
||||
@@ -279,14 +279,14 @@ Available filters are:
|
||||
Sets the desired gain in dB for all channels in the stream from -200dB
|
||||
to +60dB, where -200dB mutes the sound completely and +60dB equals a
|
||||
gain of 1000 (default: 0).
|
||||
``<softclip>``
|
||||
``softclip``
|
||||
Turns soft clipping on. Soft-clipping can make the
|
||||
sound more smooth if very high volume levels are used. Enable this
|
||||
option if the dynamic range of the loudspeakers is very low.
|
||||
|
||||
*WARNING*: This feature creates distortion and should be considered a
|
||||
last resort.
|
||||
``<s16>``
|
||||
``s16``
|
||||
Force S16 sample format if set. Lower quality, but might be faster
|
||||
in some situations.
|
||||
|
||||
@@ -296,7 +296,7 @@ Available filters are:
|
||||
Would amplify the sound by 10.1dB and hard-clip if the sound level
|
||||
is too high.
|
||||
|
||||
``pan=n[:<matrix>]``
|
||||
``pan=n:[<matrix>]``
|
||||
Mixes channels arbitrarily. Basically a combination of the volume and the
|
||||
channels filter that can be used to down-mix many channels to only a few,
|
||||
e.g. stereo to mono, or vary the "width" of the center speaker in a
|
||||
|
||||
@@ -52,11 +52,6 @@ You can bind multiple commands to one key. For example:
|
||||
|
||||
| a show_text "command 1" ; show_text "command 2"
|
||||
|
||||
Note that some magic is disabled for keys: seek commands inside lists are not
|
||||
coalesced (seeking will appear slower), and no check is done for abort commands
|
||||
(so these commands can't be used to abort playback if the network cache is
|
||||
stuck).
|
||||
|
||||
List of Input Commands
|
||||
----------------------
|
||||
|
||||
|
||||
@@ -796,7 +796,7 @@ OPTIONS
|
||||
|
||||
``--field-dominance=<auto|top|bottom>``
|
||||
Set first field for interlaced content. Useful for deinterlacers that
|
||||
double the framerate: ``--vf=yadif=1`` and ``--vo=vdpau:deint``.
|
||||
double the framerate: ``--vf=yadif=field`` and ``--vo=vdpau:deint``.
|
||||
|
||||
:auto: (default) If the decoder does not export the appropriate
|
||||
information, it falls back on ``top`` (top field first).
|
||||
@@ -1152,7 +1152,9 @@ OPTIONS
|
||||
You can get the list of allowed codecs with ``mpv --vd=help``. Remove the
|
||||
prefix, e.g. instead of ``lavc:h264`` use ``h264``.
|
||||
|
||||
By default this is set to ``h264,vc1,wmv3``.
|
||||
By default this is set to ``h264,vc1,wmv3``. Note that the hardware
|
||||
acceleration special codecs like ``h264_vdpau`` are not relevant anymore,
|
||||
and in fact have been removed from Libav in this form.
|
||||
|
||||
This is usually only needed with broken GPUs, where a codec is reported
|
||||
as supported, but decoding causes more problems than it solves.
|
||||
@@ -1780,7 +1782,7 @@ OPTIONS
|
||||
libquvi 0.9.x:
|
||||
|
||||
The following explanations are relevant:
|
||||
`<http://quvi.sourceforge.net/doc/0.9/glossary_termino.html#m_stream_id>`_
|
||||
`<http://quvi.sourceforge.net/r/api/0.9/glossary_termino.html#m_stream_id>`_
|
||||
|
||||
The ``quvi-format`` property can be used at runtime to cycle through the
|
||||
list of formats. Unfortunately, this is slow. On libquvi 0.4.x, this
|
||||
|
||||
@@ -45,13 +45,22 @@ Essential dependencies (incomplete list):
|
||||
- gcc or clang
|
||||
- X development headers (xlib, X extensions, libvdpau, libGL, libXv, ...)
|
||||
- Audio output development headers (libasound, pulseaudio)
|
||||
- fribidi, freetype, fontconfig development headers (for libass)
|
||||
- libass
|
||||
- FFmpeg libraries (libavutil libavcodec libavformat libswscale libpostproc)
|
||||
- libjpeg
|
||||
- FFmpeg libraries (libavutil libavcodec libavformat libswscale libavresample)
|
||||
- libjpeg (for screenshots)
|
||||
- libquvi if you want to play Youtube videos directly
|
||||
|
||||
Libass dependencies:
|
||||
|
||||
- gcc or clang, yasm on x86 and x86_64
|
||||
- fribidi, freetype, fontconfig development headers (for libass)
|
||||
|
||||
FFmpeg dependencies:
|
||||
|
||||
- gcc or clang, yasm on x86 and x86_64
|
||||
- OpenSSL (has to be explicitly enabled when compiling ffmpeg)
|
||||
- libx264/libmp3lame/libfdk-aac if you want to use encoding (has to be
|
||||
explicitly enabled when compiling ffmpeg)
|
||||
- Libav also works, but some features will not work. (See section below.)
|
||||
|
||||
Most of the above libraries are available in suitable versions on normal
|
||||
Linux distributions. However FFmpeg is an exception (distro versions may be
|
||||
|
||||
@@ -132,7 +132,8 @@ sub _bin2int($) {
|
||||
# creates a floating-point number with the given mantissa and exponent
|
||||
sub _ldexp {
|
||||
my ($mantissa, $exponent) = @_;
|
||||
return $mantissa * Math::BigRat->new(2)**$exponent;
|
||||
my $r = new Math::BigRat($mantissa);
|
||||
return $r * Math::BigRat->new(2)**$exponent;
|
||||
}
|
||||
|
||||
# NOTE: the read_* functions are hard to read because they're ports
|
||||
@@ -252,25 +253,27 @@ bytes from the internal filehandle.
|
||||
Only lengths C<4> and C<8> are supported (C C<float> and C<double>).
|
||||
|
||||
=cut
|
||||
sub read_float {
|
||||
my ($self, $length) = @_;
|
||||
my $i = $self->read_uint($length);
|
||||
my $f;
|
||||
{
|
||||
my $b1 = new Math::BigInt 1;
|
||||
|
||||
use bigrat try => BIGINT_TRY;
|
||||
sub read_float {
|
||||
my ($self, $length) = @_;
|
||||
my $i = new Math::BigInt $self->read_uint($length)->bstr;
|
||||
my $f;
|
||||
|
||||
# These evil expressions reinterpret an unsigned int as IEEE binary floats
|
||||
if ($length == 4) {
|
||||
$f = _ldexp(($i & (1<<23 - 1)) + (1<<23), ($i>>23 & (1<<8 - 1)) - 150);
|
||||
$f = -$f if $i & (1<<31);
|
||||
} elsif ($length == 8) {
|
||||
$f = _ldexp(($i & (1<<52 - 1)) + (1<<52), ($i>>52 & (1<<12 - 1)) - 1075);
|
||||
$f = -$f if $i & (1<<63);
|
||||
} else {
|
||||
croak "Matroska Syntax error: unsupported IEEE float byte size $length";
|
||||
# These evil expressions reinterpret an unsigned int as IEEE binary floats
|
||||
if ($length == 4) {
|
||||
$f = _ldexp(($i & ((1<<23) - 1)) + (1<<23), ($i>>23 & ((1<<8) - 1)) - 150);
|
||||
$f = -$f if $i & ($b1<<31);
|
||||
} elsif ($length == 8) {
|
||||
$f = _ldexp(($i & (($b1<<52) - 1)) + ($b1<<52), ($i>>52 & ((1<<12) - 1)) - 1075);
|
||||
$f = -$f if $i & ($b1<<63);
|
||||
} else {
|
||||
croak "Matroska Syntax error: unsupported IEEE float byte size $length";
|
||||
}
|
||||
|
||||
return $f;
|
||||
}
|
||||
|
||||
return $f;
|
||||
}
|
||||
|
||||
=method read_ebml_id($length)
|
||||
|
||||
+1
-1
@@ -485,5 +485,5 @@ void mp_chmap_print_help(struct mp_log *log)
|
||||
std_layout_names[n][0], std_layout_names[n][1]);
|
||||
}
|
||||
for (int n = 0; n < MP_NUM_CHANNELS; n++)
|
||||
mp_info(log, " unknown%d\n", n);
|
||||
mp_info(log, " unknown%d\n", n + 1);
|
||||
}
|
||||
+4
-10
@@ -172,11 +172,8 @@ static void set_from_wf(AVCodecContext *avctx, MP_WAVEFORMATEX *wf)
|
||||
avctx->block_align = wf->nBlockAlign;
|
||||
avctx->bits_per_coded_sample = wf->wBitsPerSample;
|
||||
|
||||
if (wf->cbSize > 0) {
|
||||
avctx->extradata = av_mallocz(wf->cbSize + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
avctx->extradata_size = wf->cbSize;
|
||||
memcpy(avctx->extradata, wf + 1, avctx->extradata_size);
|
||||
}
|
||||
if (wf->cbSize > 0)
|
||||
mp_lavc_set_extradata(avctx, wf + 1, wf->cbSize);
|
||||
}
|
||||
|
||||
static int init(struct dec_audio *da, const char *decoder)
|
||||
@@ -244,11 +241,8 @@ static int init(struct dec_audio *da, const char *decoder)
|
||||
// demux_mkv, demux_mpg
|
||||
if (sh_audio->codecdata_len && sh_audio->codecdata &&
|
||||
!lavc_context->extradata) {
|
||||
lavc_context->extradata = av_malloc(sh_audio->codecdata_len +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
lavc_context->extradata_size = sh_audio->codecdata_len;
|
||||
memcpy(lavc_context->extradata, (char *)sh_audio->codecdata,
|
||||
lavc_context->extradata_size);
|
||||
mp_lavc_set_extradata(lavc_context, sh_audio->codecdata,
|
||||
sh_audio->codecdata_len);
|
||||
}
|
||||
|
||||
if (sh->lav_headers)
|
||||
|
||||
+10
-6
@@ -100,7 +100,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
|
||||
float f_multi;
|
||||
|
||||
if (AF_FORMAT_IS_IEC61937(ao->format))
|
||||
return CONTROL_TRUE;
|
||||
return CONTROL_FALSE;
|
||||
|
||||
//allocate simple id
|
||||
snd_mixer_selem_id_alloca(&sid);
|
||||
@@ -561,9 +561,11 @@ static void audio_pause(struct ao *ao)
|
||||
int err;
|
||||
|
||||
if (p->can_pause) {
|
||||
p->delay_before_pause = get_delay(ao);
|
||||
err = snd_pcm_pause(p->alsa, 1);
|
||||
CHECK_ALSA_ERROR("pcm pause error");
|
||||
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_RUNNING) {
|
||||
p->delay_before_pause = get_delay(ao);
|
||||
err = snd_pcm_pause(p->alsa, 1);
|
||||
CHECK_ALSA_ERROR("pcm pause error");
|
||||
}
|
||||
} else {
|
||||
MP_VERBOSE(ao, "pause not supported by hardware\n");
|
||||
if (snd_pcm_delay(p->alsa, &p->prepause_frames) < 0
|
||||
@@ -591,8 +593,10 @@ static void audio_resume(struct ao *ao)
|
||||
}
|
||||
|
||||
if (p->can_pause) {
|
||||
err = snd_pcm_pause(p->alsa, 0);
|
||||
CHECK_ALSA_ERROR("pcm resume error");
|
||||
if (snd_pcm_state(p->alsa) == SND_PCM_STATE_PAUSED) {
|
||||
err = snd_pcm_pause(p->alsa, 0);
|
||||
CHECK_ALSA_ERROR("pcm resume error");
|
||||
}
|
||||
} else {
|
||||
MP_VERBOSE(ao, "resume not supported by hardware\n");
|
||||
err = snd_pcm_prepare(p->alsa);
|
||||
|
||||
+19
-3
@@ -60,10 +60,12 @@ struct priv {
|
||||
int connect;
|
||||
int autostart;
|
||||
int stdlayout;
|
||||
int last_chunk;
|
||||
volatile int paused;
|
||||
volatile int underrun;
|
||||
volatile float callback_interval;
|
||||
volatile float callback_time;
|
||||
volatile float last_ok_time; // last time real audio was played
|
||||
|
||||
int num_ports;
|
||||
struct port_ring ports[MP_NUM_CHANNELS];
|
||||
@@ -128,11 +130,15 @@ process(jack_nframes_t nframes, void *arg)
|
||||
underrun = 1;
|
||||
}
|
||||
|
||||
float now = mp_time_us() / 1000000.0;
|
||||
|
||||
if (underrun)
|
||||
p->underrun = 1;
|
||||
|
||||
if (!p->underrun)
|
||||
p->last_ok_time = now;
|
||||
|
||||
if (p->estimate) {
|
||||
float now = mp_time_us() / 1000000.0;
|
||||
float diff = p->callback_time + p->callback_interval - now;
|
||||
if ((diff > -0.002) && (diff < 0.002))
|
||||
p->callback_time += p->callback_interval;
|
||||
@@ -289,14 +295,23 @@ static float get_delay(struct ao *ao)
|
||||
struct priv *p = ao->priv;
|
||||
int buffered = mp_ring_buffered(p->ports[0].ring); // could be less
|
||||
float in_jack = p->jack_latency;
|
||||
float now = mp_time_us() / 1000000.0;
|
||||
|
||||
if (p->estimate && p->callback_interval > 0) {
|
||||
float elapsed = mp_time_us() / 1000000.0 - p->callback_time;
|
||||
in_jack += p->callback_interval - elapsed;
|
||||
if (in_jack < 0)
|
||||
in_jack = 0;
|
||||
}
|
||||
|
||||
if (p->underrun && !buffered && p->last_chunk) {
|
||||
// Report correct buffer drainage, when our buffer is empty, but jack
|
||||
// and/or the audio device still have some audio to play.
|
||||
// Assumes audio clock goes at about the same speed as the system time.
|
||||
in_jack += p->last_ok_time - now;
|
||||
}
|
||||
|
||||
if (in_jack < 0)
|
||||
in_jack = 0;
|
||||
|
||||
return (float)buffered / (float)ao->bps + in_jack;
|
||||
}
|
||||
|
||||
@@ -369,6 +384,7 @@ static int play(struct ao *ao, void **data, int samples, int flags)
|
||||
}
|
||||
|
||||
p->underrun = 0;
|
||||
p->last_chunk = flags & AOPLAY_FINAL_CHUNK;
|
||||
return ret / ao->sstride;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,8 +111,8 @@ static int init(struct ao *ao)
|
||||
return -1;
|
||||
}
|
||||
|
||||
rsd_set_param(priv->rd, RSD_SAMPLERATE, &ao->samplerate);
|
||||
rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels.num);
|
||||
rsd_set_param(priv->rd, RSD_SAMPLERATE, (int[]) { ao->samplerate });
|
||||
rsd_set_param(priv->rd, RSD_CHANNELS, (int[]) { ao->channels.num });
|
||||
|
||||
ao->format = af_fmt_from_planar(ao->format);
|
||||
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@
|
||||
from __future__ import print_function
|
||||
import os, sys, stat, hashlib, subprocess
|
||||
|
||||
WAFRELEASE = "waf-1.7.13"
|
||||
WAFRELEASE = "waf-1.7.15"
|
||||
WAFURL = "https://waf.googlecode.com/files/" + WAFRELEASE
|
||||
SHA256HASH = "03cc750049350ee01cdbc584b70924e333fcc17ba4a2d04648dab1535538a873"
|
||||
SHA256HASH = "e5ae7028f9b2d8ce1acb9fe1092e8010a90ba764d3ac065ea4e846743290b1d6"
|
||||
|
||||
if os.path.exists("waf"):
|
||||
wafver = subprocess.check_output(['./waf', '--version']).decode()
|
||||
|
||||
+14
-10
@@ -29,6 +29,19 @@
|
||||
|
||||
#include "osdep/numcores.h"
|
||||
|
||||
int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size)
|
||||
{
|
||||
if (size) {
|
||||
av_free(avctx->extradata);
|
||||
avctx->extradata_size = 0;
|
||||
avctx->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!avctx->extradata)
|
||||
return -1;
|
||||
avctx->extradata_size = size;
|
||||
memcpy(avctx->extradata, ptr, size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy the codec-related fields from st into avctx. This does not set the
|
||||
// codec itself, only codec related header data provided by libavformat.
|
||||
@@ -38,16 +51,7 @@
|
||||
// This is strictly for decoding only.
|
||||
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st)
|
||||
{
|
||||
if (st->extradata_size) {
|
||||
av_free(avctx->extradata);
|
||||
avctx->extradata_size = 0;
|
||||
avctx->extradata =
|
||||
av_mallocz(st->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (avctx->extradata) {
|
||||
avctx->extradata_size = st->extradata_size;
|
||||
memcpy(avctx->extradata, st->extradata, st->extradata_size);
|
||||
}
|
||||
}
|
||||
mp_lavc_set_extradata(avctx, st->extradata, st->extradata_size);
|
||||
avctx->codec_tag = st->codec_tag;
|
||||
avctx->stream_codec_tag = st->stream_codec_tag;
|
||||
avctx->bit_rate = st->bit_rate;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
struct mp_decoder_list;
|
||||
struct demux_packet;
|
||||
|
||||
int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size);
|
||||
void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st);
|
||||
void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb);
|
||||
int64_t mp_pts_to_av(double mp_pts, AVRational *tb);
|
||||
|
||||
@@ -458,6 +458,8 @@ static void handle_stream(demuxer_t *demuxer, int i)
|
||||
memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size);
|
||||
sh_sub->extradata_len = codec->extradata_size;
|
||||
}
|
||||
sh_sub->w = codec->width;
|
||||
sh_sub->h = codec->height;
|
||||
|
||||
// Hack for MicroDVD: if time_base matches the ffmpeg microdvd reader's
|
||||
// default FPS (23.976), assume the MicroDVD file did not declare a
|
||||
|
||||
@@ -87,6 +87,7 @@ typedef struct sh_video {
|
||||
typedef struct sh_sub {
|
||||
unsigned char *extradata; // extra header data passed from demuxer
|
||||
int extradata_len;
|
||||
int w, h; // mp4 vobsubs
|
||||
int frame_based; // timestamps are frame-based
|
||||
bool is_utf8; // if false, subtitle packet charset is unknown
|
||||
struct ass_track *track; // loaded by libass
|
||||
|
||||
@@ -83,6 +83,10 @@
|
||||
# Play Finnish audio if available, fall back to English otherwise.
|
||||
#alang = fi,en
|
||||
|
||||
# Change subtitle encoding. For Arabic subtitles use 'cp1256'.
|
||||
# If the file seems to be valid UTF-8, prefer UTF-8.
|
||||
#subcp = utf8:cp1256
|
||||
|
||||
# Enable hardware decoding if available. Often, this requires using an certain
|
||||
# video output, otherwise no hardware decoding will be used.
|
||||
#hwdec = auto
|
||||
|
||||
+15
-1
@@ -253,7 +253,7 @@ bool mp_replace_legacy_cmd(void *t, bstr *s)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mp_input_is_abort_cmd(int cmd_id)
|
||||
static bool is_abort_cmd(int cmd_id)
|
||||
{
|
||||
switch (cmd_id) {
|
||||
case MP_CMD_QUIT:
|
||||
@@ -264,6 +264,20 @@ bool mp_input_is_abort_cmd(int cmd_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mp_input_is_abort_cmd(struct mp_cmd *cmd)
|
||||
{
|
||||
if (is_abort_cmd(cmd->id))
|
||||
return true;
|
||||
if (cmd->id == MP_CMD_COMMAND_LIST) {
|
||||
for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
|
||||
{
|
||||
if (mp_input_is_abort_cmd(cmd))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void mp_print_cmd_list(struct mp_log *out)
|
||||
{
|
||||
for (int i = 0; mp_cmds[i].name; i++) {
|
||||
|
||||
+2
-1
@@ -107,7 +107,8 @@ enum mp_command_type {
|
||||
};
|
||||
|
||||
// Executing this command will abort playback (play something else, or quit).
|
||||
bool mp_input_is_abort_cmd(int cmd_id);
|
||||
struct mp_cmd;
|
||||
bool mp_input_is_abort_cmd(struct mp_cmd *cmd);
|
||||
|
||||
struct bstr;
|
||||
bool mp_replace_legacy_cmd(void *talloc_ctx, struct bstr *s);
|
||||
|
||||
+4
-4
@@ -237,7 +237,7 @@ static bool queue_has_abort_cmds(struct cmd_queue *queue)
|
||||
{
|
||||
bool ret = false;
|
||||
for (struct mp_cmd *cmd = queue->first; cmd; cmd = cmd->queue_next)
|
||||
if (mp_input_is_abort_cmd(cmd->id)) {
|
||||
if (mp_input_is_abort_cmd(cmd)) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
@@ -544,9 +544,9 @@ static void release_down_cmd(struct input_ctx *ictx, bool drop_current)
|
||||
|
||||
static int find_key_down(struct input_ctx *ictx, int code)
|
||||
{
|
||||
code &= ~(MP_KEY_STATE_UP | MP_KEY_STATE_DOWN);
|
||||
code &= ~(MP_KEY_STATE_UP | MP_KEY_STATE_DOWN | MP_KEY_MODIFIER_MASK);
|
||||
for (int j = 0; j < ictx->num_key_down; j++) {
|
||||
if (ictx->key_down[j] == code)
|
||||
if ((ictx->key_down[j] & ~MP_KEY_MODIFIER_MASK) == code)
|
||||
return j;
|
||||
}
|
||||
return -1;
|
||||
@@ -580,7 +580,7 @@ static bool should_drop_cmd(struct input_ctx *ictx, struct mp_cmd *cmd)
|
||||
{
|
||||
struct cmd_queue *queue = &ictx->cmd_queue;
|
||||
return (queue_count_cmds(queue) >= ictx->key_fifo_size &&
|
||||
(!mp_input_is_abort_cmd(cmd->id) || queue_has_abort_cmds(queue)));
|
||||
(!mp_input_is_abort_cmd(cmd) || queue_has_abort_cmds(queue)));
|
||||
}
|
||||
|
||||
static void interpret_key(struct input_ctx *ictx, int code, double scale)
|
||||
|
||||
+1
-2
@@ -27,8 +27,7 @@ SOURCES_AUDIO_INPUT-$(ALSA) += stream/ai_alsa1x.c
|
||||
SOURCES_AUDIO_INPUT-$(OSS) += stream/ai_oss.c
|
||||
SOURCES_AUDIO_INPUT-$(SNDIO) += stream/ai_sndio.c
|
||||
SOURCES-$(AUDIO_INPUT) += $(SOURCES_AUDIO_INPUT-yes)
|
||||
SOURCES-$(CDDA) += stream/stream_cdda.c \
|
||||
stream/cdinfo.c
|
||||
SOURCES-$(CDDA) += stream/stream_cdda.c
|
||||
SOURCES-$(DVBIN) += stream/dvb_tune.c \
|
||||
stream/stream_dvb.c
|
||||
SOURCES-$(DVDREAD) += stream/stream_dvd.c \
|
||||
|
||||
@@ -330,7 +330,8 @@ int cocoa_main(mpv_main_fn mpv_main, int argc, char *argv[])
|
||||
pthread_create(&playback_thread_id, NULL, playback_thread, &ctx);
|
||||
|
||||
[mpv_shared_app().input_ready lock];
|
||||
[mpv_shared_app().input_ready wait];
|
||||
while (!mpv_shared_app().inputContext)
|
||||
[mpv_shared_app().input_ready wait];
|
||||
[mpv_shared_app().input_ready unlock];
|
||||
|
||||
cocoa_run_runloop();
|
||||
@@ -388,13 +389,10 @@ void cocoa_stop_runloop(void)
|
||||
|
||||
void cocoa_set_input_context(struct input_ctx *input_context)
|
||||
{
|
||||
if (input_context) {
|
||||
[mpv_shared_app().input_ready lock];
|
||||
[mpv_shared_app().input_ready signal];
|
||||
[mpv_shared_app().input_ready unlock];
|
||||
}
|
||||
|
||||
[mpv_shared_app().input_ready lock];
|
||||
mpv_shared_app().inputContext = input_context;
|
||||
[mpv_shared_app().input_ready signal];
|
||||
[mpv_shared_app().input_ready unlock];
|
||||
}
|
||||
|
||||
void cocoa_post_fake_event(void)
|
||||
|
||||
+5
-1
@@ -59,7 +59,11 @@ char *mp_get_win_config_path(const char *filename)
|
||||
res = mp_path_join(NULL, bstr0(temp), bstr0(filename));
|
||||
if (!mp_path_exists(res) || mp_path_isdir(res)) {
|
||||
talloc_free(res);
|
||||
res = NULL;
|
||||
res = mp_path_join(NULL, bstr0(dir), bstr0(filename));
|
||||
if (!mp_path_exists(res) || mp_path_isdir(res)) {
|
||||
talloc_free(res);
|
||||
res = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -750,11 +750,9 @@ static int mp_property_chapter_metadata(m_option_t *prop, int action, void *arg,
|
||||
{
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
int chapter = get_current_chapter(mpctx);
|
||||
if (!demuxer || chapter < 0)
|
||||
if (!demuxer || chapter < 0 || chapter >= demuxer->num_chapters)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
assert(chapter < demuxer->num_chapters);
|
||||
|
||||
return tag_property(prop, action, arg, demuxer->chapters[chapter].metadata);
|
||||
}
|
||||
|
||||
@@ -2941,7 +2939,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
||||
}
|
||||
#endif /* HAVE_PVR */
|
||||
#if HAVE_DVBIN
|
||||
if (mpctx->stream->type == STREAMTYPE_DVB) {
|
||||
if (mpctx->stream && mpctx->stream->type == STREAMTYPE_DVB) {
|
||||
int dir;
|
||||
int v = cmd->args[0].v.i;
|
||||
|
||||
@@ -2979,7 +2977,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
||||
|
||||
#if HAVE_DVBIN
|
||||
case MP_CMD_DVB_SET_CHANNEL:
|
||||
if (mpctx->stream->type == STREAMTYPE_DVB) {
|
||||
if (mpctx->stream && mpctx->stream->type == STREAMTYPE_DVB) {
|
||||
mpctx->last_dvb_step = 1;
|
||||
|
||||
if (dvb_set_channel(mpctx->stream, cmd->args[1].v.i,
|
||||
|
||||
+6
-1
@@ -140,7 +140,10 @@ void mp_handle_nav(struct MPContext *mpctx)
|
||||
case MP_NAV_EVENT_RESET_ALL: {
|
||||
mpctx->stop_play = PT_RELOAD_DEMUXER;
|
||||
MP_VERBOSE(nav, "reload\n");
|
||||
break;
|
||||
// return immediately.
|
||||
// other events should be handled after reloaded.
|
||||
talloc_free(ev);
|
||||
return;
|
||||
}
|
||||
case MP_NAV_EVENT_RESET: {
|
||||
nav->nav_still_frame = 0;
|
||||
@@ -237,6 +240,8 @@ void mp_nav_get_highlight(struct osd_state *osd, struct mp_osd_res res,
|
||||
talloc_free(sub->bitmap);
|
||||
sub->bitmap = talloc_array(sub, uint32_t, sizes[0] * sizes[1]);
|
||||
memset(sub->bitmap, 0x80, talloc_get_size(sub->bitmap));
|
||||
nav->subsize[0] = sizes[0];
|
||||
nav->subsize[1] = sizes[1];
|
||||
}
|
||||
|
||||
sub->x = nav->highlight[0];
|
||||
|
||||
+6
-7
@@ -1014,7 +1014,7 @@ static bool demux_was_interrupted(struct MPContext *mpctx)
|
||||
mp_cmd_t *cmd = mp_input_get_cmd(mpctx->input, 0, 0);
|
||||
if (!cmd)
|
||||
break;
|
||||
if (mp_input_is_abort_cmd(cmd->id))
|
||||
if (mp_input_is_abort_cmd(cmd))
|
||||
run_command(mpctx, cmd);
|
||||
mp_cmd_free(cmd);
|
||||
}
|
||||
@@ -1307,14 +1307,13 @@ goto_reopen_demuxer: ;
|
||||
|
||||
// If there's a timeline force an absolute seek to initialize state
|
||||
double startpos = rel_time_to_abs(mpctx, opts->play_start, -1);
|
||||
if (startpos != -1 || mpctx->timeline) {
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, startpos, 0);
|
||||
execute_queued_seek(mpctx);
|
||||
}
|
||||
if (startpos == -1 && mpctx->resolve_result &&
|
||||
mpctx->resolve_result->start_time > 0)
|
||||
{
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->resolve_result->start_time, 0);
|
||||
startpos = mpctx->resolve_result->start_time;
|
||||
if (startpos == -1 && mpctx->timeline)
|
||||
startpos = 0;
|
||||
if (startpos != -1) {
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, startpos, 0);
|
||||
execute_queued_seek(mpctx);
|
||||
}
|
||||
if (opts->chapterrange[0] > 0) {
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv 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.
|
||||
*
|
||||
* mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
+8
-12
@@ -64,6 +64,14 @@
|
||||
#include "command.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
|
||||
#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE (0x0001)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_X11
|
||||
#include "video/out/x11_common.h"
|
||||
#endif
|
||||
@@ -76,18 +84,6 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
|
||||
#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE (0x0001)
|
||||
#endif
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_PERMANENT
|
||||
#define BASE_SEARCH_PATH_PERMANENT (0x8000)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char mp_help_text[] =
|
||||
"Usage: mpv [options] [url|path/]filename\n"
|
||||
"\n"
|
||||
|
||||
@@ -106,6 +106,10 @@ double get_start_time(struct MPContext *mpctx)
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return 0;
|
||||
// We reload the demuxer on menu transitions; don't make it use the first
|
||||
// timestamp it finds as start PTS.
|
||||
if (mpctx->nav_state)
|
||||
return 0;
|
||||
return demuxer_get_start_time(demuxer);
|
||||
}
|
||||
|
||||
|
||||
+16
-11
@@ -66,7 +66,7 @@ static const char av_desync_help_text[] =
|
||||
" Experiment with different values for --autosync, 30 is a good start.\n"
|
||||
" If you have PulseAudio, try --ao=alsa .\n"
|
||||
"- Slow video output.\n"
|
||||
" Try a different -vo driver (-vo help for a list) or try -framedrop!\n"
|
||||
" Try a different --vo driver (--vo=help for a list) or try --framedrop!\n"
|
||||
"- Playing a video file with --vo=opengl with higher FPS than the monitor.\n"
|
||||
" This is due to vsync limiting the framerate.\n"
|
||||
"- Playing from a slow network source.\n"
|
||||
@@ -168,14 +168,14 @@ void add_step_frame(struct MPContext *mpctx, int dir)
|
||||
}
|
||||
}
|
||||
|
||||
static void seek_reset(struct MPContext *mpctx, bool reset_ao)
|
||||
static void seek_reset(struct MPContext *mpctx, bool reset_ao, bool reset_ac)
|
||||
{
|
||||
if (mpctx->d_video) {
|
||||
video_reset_decoding(mpctx->d_video);
|
||||
vo_seek_reset(mpctx->video_out);
|
||||
}
|
||||
|
||||
if (mpctx->d_audio) {
|
||||
if (mpctx->d_audio && reset_ac) {
|
||||
audio_reset_decoding(mpctx->d_audio);
|
||||
if (reset_ao)
|
||||
clear_audio_output_buffers(mpctx);
|
||||
@@ -204,9 +204,6 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao)
|
||||
}
|
||||
|
||||
// return -1 if seek failed (non-seekable stream?), 0 otherwise
|
||||
// timeline_fallthrough: true if used to explicitly switch timeline - in this
|
||||
// case, don't drop buffered AO audio data, so that
|
||||
// timeline segment transition is seemless
|
||||
static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
bool timeline_fallthrough)
|
||||
{
|
||||
@@ -253,6 +250,9 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
seek.amount += get_current_time(mpctx);
|
||||
}
|
||||
|
||||
/* At least the liba52 decoder wants to read from the input stream
|
||||
* during initialization, so reinit must be done after the demux_seek()
|
||||
* call that clears possible stream EOF. */
|
||||
bool need_reset = false;
|
||||
double demuxer_amount = seek.amount;
|
||||
if (mpctx->timeline) {
|
||||
@@ -271,7 +271,6 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
}
|
||||
if (need_reset) {
|
||||
reinit_video_chain(mpctx);
|
||||
reinit_audio_chain(mpctx);
|
||||
reinit_subs(mpctx, 0);
|
||||
reinit_subs(mpctx, 1);
|
||||
}
|
||||
@@ -296,8 +295,10 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
demuxer_amount -= hr_seek_offset;
|
||||
int seekresult = demux_seek(mpctx->demuxer, demuxer_amount, demuxer_style);
|
||||
if (seekresult == 0) {
|
||||
if (need_reset)
|
||||
seek_reset(mpctx, !timeline_fallthrough);
|
||||
if (need_reset) {
|
||||
reinit_audio_chain(mpctx);
|
||||
seek_reset(mpctx, !timeline_fallthrough, false);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -315,7 +316,11 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek,
|
||||
}
|
||||
}
|
||||
|
||||
seek_reset(mpctx, !timeline_fallthrough);
|
||||
if (need_reset)
|
||||
reinit_audio_chain(mpctx);
|
||||
/* If we just reinitialized audio it doesn't need to be reset,
|
||||
* and resetting could lose audio some decoders produce during init. */
|
||||
seek_reset(mpctx, !timeline_fallthrough, !need_reset);
|
||||
|
||||
if (timeline_fallthrough) {
|
||||
// Important if video reinit happens.
|
||||
@@ -571,7 +576,7 @@ bool mp_seek_chapter(struct MPContext *mpctx, int chapter)
|
||||
if (res >= 0) {
|
||||
if (pts == -1) {
|
||||
// for DVD/BD - seek happened via stream layer
|
||||
seek_reset(mpctx, true);
|
||||
seek_reset(mpctx, true, true);
|
||||
mpctx->seek = (struct seek_params){0};
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ static void copy_chapters(struct chapter **chapters, int *num_chapters,
|
||||
double time = demuxer_chapter_time(src, n);
|
||||
if (time >= start && time <= start + len) {
|
||||
struct chapter ch = {
|
||||
.start = dest_offset + time,
|
||||
.start = dest_offset + time - start,
|
||||
.name = talloc_steal(*chapters, demuxer_chapter_name(src, n)),
|
||||
};
|
||||
MP_TARRAY_APPEND(NULL, *chapters, *num_chapters, ch);
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_CDD_H
|
||||
#define MPLAYER_CDD_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct mp_log;
|
||||
|
||||
typedef struct cd_track {
|
||||
char *name;
|
||||
unsigned int track_nb;
|
||||
unsigned int min;
|
||||
unsigned int sec;
|
||||
unsigned int msec;
|
||||
unsigned long frame_begin;
|
||||
unsigned long frame_length;
|
||||
struct cd_track *prev;
|
||||
struct cd_track *next;
|
||||
} cd_track_t;
|
||||
|
||||
typedef struct {
|
||||
char *artist;
|
||||
char *album;
|
||||
char *genre;
|
||||
unsigned int nb_tracks;
|
||||
unsigned int min;
|
||||
unsigned int sec;
|
||||
unsigned msec;
|
||||
cd_track_t *first;
|
||||
cd_track_t *last;
|
||||
cd_track_t *current;
|
||||
} cd_info_t;
|
||||
|
||||
cd_info_t* cd_info_new(void);
|
||||
void cd_info_free(cd_info_t *cd_info);
|
||||
cd_track_t* cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length);
|
||||
cd_track_t* cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb);
|
||||
|
||||
void cd_info_debug(cd_info_t *cd_info, struct mp_log *log);
|
||||
|
||||
#endif /* MPLAYER_CDD_H */
|
||||
-154
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* CD Info
|
||||
*
|
||||
* Copyright (C) 2002 Bertrand Baudet <bertrand_baudet@yahoo.com>
|
||||
*
|
||||
* 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 "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common/msg.h"
|
||||
#include "cdd.h"
|
||||
|
||||
/*******************************************************************************************************************
|
||||
*
|
||||
* xmcd parser, cd info list
|
||||
*
|
||||
*******************************************************************************************************************/
|
||||
|
||||
cd_info_t*
|
||||
cd_info_new(void) {
|
||||
cd_info_t *cd_info = NULL;
|
||||
|
||||
cd_info = malloc(sizeof(cd_info_t));
|
||||
if( cd_info==NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(cd_info, 0, sizeof(cd_info_t));
|
||||
|
||||
return cd_info;
|
||||
}
|
||||
|
||||
void
|
||||
cd_info_free(cd_info_t *cd_info) {
|
||||
cd_track_t *cd_track, *cd_track_next;
|
||||
if( cd_info==NULL ) return;
|
||||
free(cd_info->artist);
|
||||
free(cd_info->album);
|
||||
free(cd_info->genre);
|
||||
|
||||
cd_track_next = cd_info->first;
|
||||
while( cd_track_next!=NULL ) {
|
||||
cd_track = cd_track_next;
|
||||
cd_track_next = cd_track->next;
|
||||
free(cd_track->name);
|
||||
free(cd_track);
|
||||
}
|
||||
}
|
||||
|
||||
cd_track_t*
|
||||
cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length) {
|
||||
cd_track_t *cd_track;
|
||||
|
||||
if( cd_info==NULL || track_name==NULL ) return NULL;
|
||||
|
||||
cd_track = malloc(sizeof(cd_track_t));
|
||||
if( cd_track==NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
memset(cd_track, 0, sizeof(cd_track_t));
|
||||
|
||||
cd_track->name = malloc(strlen(track_name)+1);
|
||||
if( cd_track->name==NULL ) {
|
||||
free(cd_track);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(cd_track->name, track_name);
|
||||
cd_track->track_nb = track_nb;
|
||||
cd_track->min = min;
|
||||
cd_track->sec = sec;
|
||||
cd_track->msec = msec;
|
||||
cd_track->frame_begin = frame_begin;
|
||||
cd_track->frame_length = frame_length;
|
||||
|
||||
if( cd_info->first==NULL ) {
|
||||
cd_info->first = cd_track;
|
||||
}
|
||||
if( cd_info->last!=NULL ) {
|
||||
cd_info->last->next = cd_track;
|
||||
}
|
||||
|
||||
cd_track->prev = cd_info->last;
|
||||
|
||||
cd_info->last = cd_track;
|
||||
cd_info->current = cd_track;
|
||||
|
||||
cd_info->nb_tracks++;
|
||||
|
||||
return cd_track;
|
||||
}
|
||||
|
||||
cd_track_t*
|
||||
cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb) {
|
||||
cd_track_t *cd_track=NULL;
|
||||
|
||||
if( cd_info==NULL ) return NULL;
|
||||
|
||||
cd_track = cd_info->first;
|
||||
while( cd_track!=NULL ) {
|
||||
if( cd_track->track_nb==track_nb ) {
|
||||
return cd_track;
|
||||
}
|
||||
cd_track = cd_track->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cd_info_debug(cd_info_t *cd_info, struct mp_log *log)
|
||||
{
|
||||
cd_track_t *current_track;
|
||||
mp_info(log, "================ CD INFO === start =========\n");
|
||||
if( cd_info==NULL ) {
|
||||
mp_info(log, "cd_info is NULL\n");
|
||||
return;
|
||||
}
|
||||
mp_info(log, " artist=[%s]\n", cd_info->artist);
|
||||
mp_info(log, " album=[%s]\n", cd_info->album);
|
||||
mp_info(log, " genre=[%s]\n", cd_info->genre);
|
||||
mp_info(log, " nb_tracks=%d\n", cd_info->nb_tracks);
|
||||
mp_info(log, " length= %2d:%02d.%02d\n", cd_info->min, cd_info->sec, cd_info->msec);
|
||||
|
||||
mp_info(log, "ID_CDDB_INFO_ARTIST=%s\n", cd_info->artist);
|
||||
mp_info(log, "ID_CDDB_INFO_ALBUM=%s\n", cd_info->album);
|
||||
mp_info(log, "ID_CDDB_INFO_GENRE=%s\n", cd_info->genre);
|
||||
mp_info(log, "ID_CDDB_INFO_LENGTH_MSF=%02d:%02d.%02d\n", cd_info->min, cd_info->sec, cd_info->msec);
|
||||
mp_info(log, "ID_CDDB_INFO_TRACKS=%d\n", cd_info->nb_tracks);
|
||||
|
||||
current_track = cd_info->first;
|
||||
while( current_track!=NULL ) {
|
||||
mp_info(log, " #%2d %2d:%02d.%02d @ %7ld\t[%s] \n", current_track->track_nb, current_track->min, current_track->sec, current_track->msec, current_track->frame_begin, current_track->name);
|
||||
mp_info(log, "ID_CDDB_INFO_TRACK_%d_NAME=%s\n", current_track->track_nb, current_track->name);
|
||||
mp_info(log, "ID_CDDB_INFO_TRACK_%d_MSF=%02d:%02d.%02d\n", current_track->track_nb, current_track->min, current_track->sec, current_track->msec);
|
||||
current_track = current_track->next;
|
||||
}
|
||||
mp_info(log, "================ CD INFO === end =========\n");
|
||||
}
|
||||
@@ -187,6 +187,7 @@ static int bluray_stream_control(stream_t *s, int cmd, void *arg)
|
||||
return STREAM_UNSUPPORTED;
|
||||
|
||||
*((double *) arg) = BD_TIME_TO_MP(ti->duration);
|
||||
bd_free_title_info(ti);
|
||||
return STREAM_OK;
|
||||
}
|
||||
|
||||
|
||||
+16
-68
@@ -46,8 +46,6 @@
|
||||
#include "libavutil/common.h"
|
||||
#include "compat/mpbswap.h"
|
||||
|
||||
#include "cdd.h"
|
||||
|
||||
#include "common/msg.h"
|
||||
|
||||
typedef struct {
|
||||
@@ -56,7 +54,6 @@ typedef struct {
|
||||
int sector;
|
||||
int start_sector;
|
||||
int end_sector;
|
||||
cd_info_t *cd_info;
|
||||
|
||||
// options
|
||||
int speed;
|
||||
@@ -132,8 +129,8 @@ static bool print_cdtext(stream_t *s, int track)
|
||||
#else
|
||||
cdtext_t *text = cdio_get_cdtext(p->cd->p_cdio);
|
||||
#endif
|
||||
int header = 0;
|
||||
if (text) {
|
||||
MP_INFO(s, "CD-Text (%s):\n", track ? "track" : "CD");
|
||||
for (int i = 0; i < sizeof(cdtext_name) / sizeof(cdtext_name[0]); i++) {
|
||||
const char *name = cdtext_name[i];
|
||||
#ifdef OLD_API
|
||||
@@ -141,8 +138,12 @@ static bool print_cdtext(stream_t *s, int track)
|
||||
#else
|
||||
const char *value = cdtext_get_const(text, i, track);
|
||||
#endif
|
||||
if (name && value)
|
||||
if (name && value) {
|
||||
if (!header)
|
||||
MP_INFO(s, "CD-Text (%s):\n", track ? "track" : "CD");
|
||||
header = 1;
|
||||
MP_INFO(s, " %s: '%s'\n", name, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -151,17 +152,8 @@ static bool print_cdtext(stream_t *s, int track)
|
||||
|
||||
static void print_track_info(stream_t *s, int track)
|
||||
{
|
||||
cdda_priv* p = (cdda_priv*)s->priv;
|
||||
cd_track_t *cd_track = cd_info_get_track(p->cd_info, track);
|
||||
if( cd_track!=NULL ) {
|
||||
MP_INFO(s, "\n%s\n", cd_track->name);
|
||||
MP_INFO(s, "ID_CDDA_TRACK=%d\n",
|
||||
cd_track->track_nb);
|
||||
}
|
||||
if (print_cdtext(s, track)) {
|
||||
// hack for term OSD overwriting the last line of CDTEXT
|
||||
MP_INFO(s, "\n");
|
||||
}
|
||||
MP_INFO(s, "Switched to track %d\n", track);
|
||||
print_cdtext(s, track);
|
||||
}
|
||||
|
||||
static void cdparanoia_callback(long int inpos, paranoia_cb_mode_t function)
|
||||
@@ -242,7 +234,6 @@ static void close_cdda(stream_t *s)
|
||||
cdda_priv *p = (cdda_priv *)s->priv;
|
||||
paranoia_free(p->cdp);
|
||||
cdda_close(p->cd);
|
||||
cd_info_free(p->cd_info);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@@ -273,37 +264,18 @@ static int control(stream_t *stream, int cmd, void *arg)
|
||||
*(unsigned int *)arg = end_track + 1 - start_track;
|
||||
return STREAM_OK;
|
||||
}
|
||||
case STREAM_CTRL_SEEK_TO_CHAPTER:
|
||||
case STREAM_CTRL_GET_CHAPTER_TIME:
|
||||
{
|
||||
int r;
|
||||
unsigned int track = *(unsigned int *)arg;
|
||||
int track = *(double *)arg;
|
||||
int start_track = get_track_by_sector(p, p->start_sector);
|
||||
int end_track = get_track_by_sector(p, p->end_sector);
|
||||
int seek_sector;
|
||||
if (start_track == -1 || end_track == -1)
|
||||
track += start_track + 1;
|
||||
if (track > end_track)
|
||||
return STREAM_ERROR;
|
||||
track += start_track;
|
||||
if (track > end_track) {
|
||||
seek(stream, (p->end_sector + 1) * CDIO_CD_FRAMESIZE_RAW);
|
||||
// seeking beyond EOF should not be an error,
|
||||
// the cache cannot handle changing stream pos and
|
||||
// returning error.
|
||||
return STREAM_OK;
|
||||
}
|
||||
seek_sector = track == 0 ? p->start_sector
|
||||
: p->cd->disc_toc[track].dwStartSector;
|
||||
r = seek(stream, seek_sector * CDIO_CD_FRAMESIZE_RAW);
|
||||
if (r)
|
||||
return STREAM_OK;
|
||||
break;
|
||||
}
|
||||
case STREAM_CTRL_GET_CURRENT_CHAPTER:
|
||||
{
|
||||
int start_track = get_track_by_sector(p, p->start_sector);
|
||||
int cur_track = get_track_by_sector(p, p->sector);
|
||||
if (start_track == -1 || cur_track == -1)
|
||||
return STREAM_ERROR;
|
||||
*(unsigned int *)arg = cur_track - start_track;
|
||||
int64_t sector = p->cd->disc_toc[track].dwStartSector;
|
||||
int64_t pos = sector * (CDIO_CD_FRAMESIZE_RAW + 1) - 1;
|
||||
// Assume standard audio CD: 44.1khz, 2 channels, s16 samples
|
||||
*(double *)arg = pos / (44100.0 * 2 * 2);
|
||||
return STREAM_OK;
|
||||
}
|
||||
}
|
||||
@@ -317,10 +289,7 @@ static int open_cdda(stream_t *st, int m)
|
||||
int mode = p->paranoia_mode;
|
||||
int offset = p->toc_offset;
|
||||
cdrom_drive_t *cdd = NULL;
|
||||
cd_info_t *cd_info;
|
||||
unsigned int audiolen = 0;
|
||||
int last_track;
|
||||
int i;
|
||||
|
||||
if (m != STREAM_READ) {
|
||||
return STREAM_UNSUPPORTED;
|
||||
@@ -355,29 +324,9 @@ static int open_cdda(stream_t *st, int m)
|
||||
return STREAM_ERROR;
|
||||
}
|
||||
|
||||
cd_info = cd_info_new();
|
||||
MP_INFO(st, "Found audio CD with %d tracks.\n",
|
||||
(int)cdda_tracks(cdd));
|
||||
for (i = 0; i < cdd->tracks; i++) {
|
||||
char track_name[80];
|
||||
long sec = cdda_track_firstsector(cdd, i + 1);
|
||||
long off = cdda_track_lastsector(cdd, i + 1) - sec + 1;
|
||||
|
||||
sprintf(track_name, "Track %d", i + 1);
|
||||
cd_info_add_track(cd_info, track_name, i + 1,
|
||||
(unsigned int)(off / (60 * 75)),
|
||||
(unsigned int)((off / 75) % 60),
|
||||
(unsigned int)(off % 75), sec, off);
|
||||
audiolen += off;
|
||||
}
|
||||
cd_info->min = (unsigned int)(audiolen / (60 * 75));
|
||||
cd_info->sec = (unsigned int)((audiolen / 75) % 60);
|
||||
cd_info->msec = (unsigned int)(audiolen % 75);
|
||||
|
||||
priv = malloc(sizeof(cdda_priv));
|
||||
memset(priv, 0, sizeof(cdda_priv));
|
||||
priv->cd = cdd;
|
||||
priv->cd_info = cd_info;
|
||||
|
||||
if (p->toc_bias)
|
||||
offset -= cdda_track_firstsector(cdd, 1);
|
||||
@@ -411,7 +360,6 @@ static int open_cdda(stream_t *st, int m)
|
||||
if (priv->cdp == NULL) {
|
||||
cdda_close(cdd);
|
||||
free(priv);
|
||||
cd_info_free(cd_info);
|
||||
return STREAM_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+37
-30
@@ -298,42 +298,47 @@ static void handle_cmd(stream_t *s, struct mp_nav_cmd *ev)
|
||||
|
||||
}
|
||||
|
||||
static inline bool set_event_type(struct priv *priv, int type,
|
||||
struct mp_nav_event *event)
|
||||
{
|
||||
if (!(priv->next_event & (1 << type)))
|
||||
return false;
|
||||
priv->next_event &= ~(1 << type);
|
||||
event->event = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fill_next_event(stream_t *s, struct mp_nav_event **ret)
|
||||
{
|
||||
struct priv *priv = s->priv;
|
||||
struct mp_nav_event e = {0};
|
||||
for (int n = 0; n < 30; n++) {
|
||||
if (priv->next_event & (1 << n)) {
|
||||
priv->next_event &= ~(1 << n);
|
||||
e.event = n;
|
||||
switch (e.event) {
|
||||
case MP_NAV_EVENT_HIGHLIGHT: {
|
||||
dvdnav_highlight_event_t hlev = priv->hlev;
|
||||
e.u.highlight.display = hlev.display;
|
||||
e.u.highlight.sx = hlev.sx;
|
||||
e.u.highlight.sy = hlev.sy;
|
||||
e.u.highlight.ex = hlev.ex;
|
||||
e.u.highlight.ey = hlev.ey;
|
||||
e.u.highlight.palette = hlev.palette;
|
||||
break;
|
||||
}
|
||||
case MP_NAV_EVENT_MENU_MODE:
|
||||
e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
|
||||
break;
|
||||
case MP_NAV_EVENT_STILL_FRAME:
|
||||
e.u.still_frame.seconds = priv->still_length;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!set_event_type(priv, MP_NAV_EVENT_RESET_ALL, &e))
|
||||
for (int n = 0; n < 30 && !set_event_type(priv, n, &e); n++) ;
|
||||
switch (e.event) {
|
||||
case MP_NAV_EVENT_NONE:
|
||||
return;
|
||||
case MP_NAV_EVENT_HIGHLIGHT: {
|
||||
dvdnav_highlight_event_t hlev = priv->hlev;
|
||||
e.u.highlight.display = hlev.display;
|
||||
e.u.highlight.sx = hlev.sx;
|
||||
e.u.highlight.sy = hlev.sy;
|
||||
e.u.highlight.ex = hlev.ex;
|
||||
e.u.highlight.ey = hlev.ey;
|
||||
e.u.highlight.palette = hlev.palette;
|
||||
break;
|
||||
}
|
||||
if (e.event) {
|
||||
*ret = talloc(NULL, struct mp_nav_event);
|
||||
**ret = e;
|
||||
case MP_NAV_EVENT_MENU_MODE:
|
||||
e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
|
||||
break;
|
||||
case MP_NAV_EVENT_STILL_FRAME:
|
||||
e.u.still_frame.seconds = priv->still_length;
|
||||
break;
|
||||
}
|
||||
*ret = talloc(NULL, struct mp_nav_event);
|
||||
**ret = e;
|
||||
|
||||
MP_VERBOSE(s, "DVDNAV: player event '%s'\n",
|
||||
LOOKUP_NAME(mp_nav_event_types, e.event));
|
||||
}
|
||||
MP_VERBOSE(s, "DVDNAV: player event '%s'\n",
|
||||
LOOKUP_NAME(mp_nav_event_types, e.event));
|
||||
}
|
||||
|
||||
static int fill_buffer(stream_t *s, char *buf, int max_len)
|
||||
@@ -414,6 +419,8 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
|
||||
priv->had_initial_vts = true;
|
||||
break;
|
||||
}
|
||||
// clear all previous events
|
||||
priv->next_event = 0;
|
||||
priv->next_event |= 1 << MP_NAV_EVENT_RESET;
|
||||
priv->next_event |= 1 << MP_NAV_EVENT_RESET_ALL;
|
||||
if (dvdnav_current_title_info(dvdnav, &tit, &part) == DVDNAV_STATUS_OK)
|
||||
|
||||
@@ -33,6 +33,7 @@ mf_stream_open (stream_t *stream, int mode)
|
||||
{
|
||||
stream->type = STREAMTYPE_MF;
|
||||
stream->demuxer = "mf";
|
||||
stream->allow_caching = false;
|
||||
|
||||
return STREAM_OK;
|
||||
}
|
||||
|
||||
@@ -175,6 +175,8 @@ void sub_init_from_sh(struct dec_sub *sub, struct sh_stream *sh)
|
||||
struct sd init_sd = sub->init_sd;
|
||||
init_sd.codec = sh->codec;
|
||||
init_sd.ass_track = sh->sub->track;
|
||||
init_sd.sub_stream_w = sh->sub->w;
|
||||
init_sd.sub_stream_h = sh->sub->h;
|
||||
|
||||
while (sub->num_sd < MAX_NUM_SD) {
|
||||
struct sd *sd = talloc(NULL, struct sd);
|
||||
|
||||
@@ -25,6 +25,9 @@ struct sd {
|
||||
// the resolution of the VO, nor does it have to be the OSD resolution.
|
||||
int sub_video_w, sub_video_h;
|
||||
|
||||
// Resolution hints stored in mp4 files.
|
||||
int sub_stream_w, sub_stream_h;
|
||||
|
||||
// Make sd_ass use an existing track
|
||||
struct ass_track *ass_track;
|
||||
|
||||
|
||||
+42
-2
@@ -21,12 +21,14 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/common.h>
|
||||
#include <libavutil/intreadwrite.h>
|
||||
|
||||
#include "talloc.h"
|
||||
#include "common/msg.h"
|
||||
#include "common/av_common.h"
|
||||
#include "options/options.h"
|
||||
#include "video/mp_image.h"
|
||||
#include "video/csputils.h"
|
||||
#include "sd.h"
|
||||
#include "dec_sub.h"
|
||||
|
||||
@@ -89,9 +91,42 @@ static void get_resolution(struct sd *sd, int wh[2])
|
||||
struct sd_lavc_priv *priv = sd->priv;
|
||||
wh[0] = priv->avctx->width;
|
||||
wh[1] = priv->avctx->height;
|
||||
if (wh[0] <= 0 || wh[1] <= 0) {
|
||||
wh[0] = priv->video_params.w;
|
||||
wh[1] = priv->video_params.h;
|
||||
}
|
||||
guess_resolution(priv->avctx->codec_id, &wh[0], &wh[1]);
|
||||
}
|
||||
|
||||
static void set_mp4_vobsub_idx(AVCodecContext *avctx, char *src, int w, int h)
|
||||
{
|
||||
char pal_s[128];
|
||||
int pal_s_pos = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
unsigned int e = AV_RB32(src + i * 4);
|
||||
|
||||
// lavc doesn't accept YUV palette - "does god hate me?"
|
||||
struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS;
|
||||
csp.int_bits_in = 8;
|
||||
csp.int_bits_out = 8;
|
||||
float cmatrix[3][4];
|
||||
mp_get_yuv2rgb_coeffs(&csp, cmatrix);
|
||||
int c[3] = {(e >> 16) & 0xff, (e >> 8) & 0xff, e & 0xff};
|
||||
mp_map_int_color(cmatrix, 8, c);
|
||||
e = (c[2] << 16) | (c[1] << 8) | c[0];
|
||||
|
||||
snprintf(pal_s + pal_s_pos, sizeof(pal_s) - pal_s_pos, "%06x%s", e,
|
||||
i != 15 ? ", " : "");
|
||||
pal_s_pos = strlen(pal_s);
|
||||
if (pal_s_pos >= sizeof(pal_s))
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[256] = "";
|
||||
snprintf(buf, sizeof(buf), "size: %dx%d\npalette: %s\n", w, h, pal_s);
|
||||
mp_lavc_set_extradata(avctx, buf, strlen(buf));
|
||||
}
|
||||
|
||||
static int init(struct sd *sd)
|
||||
{
|
||||
struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv);
|
||||
@@ -103,8 +138,12 @@ static int init(struct sd *sd)
|
||||
ctx = avcodec_alloc_context3(sub_codec);
|
||||
if (!ctx)
|
||||
goto error;
|
||||
ctx->extradata_size = sd->extradata_len;
|
||||
ctx->extradata = sd->extradata;
|
||||
mp_lavc_set_extradata(ctx, sd->extradata, sd->extradata_len);
|
||||
if (sd->extradata_len == 64 && sd->sub_stream_w && sd->sub_stream_h &&
|
||||
cid == AV_CODEC_ID_DVD_SUBTITLE)
|
||||
{
|
||||
set_mp4_vobsub_idx(ctx, sd->extradata, sd->sub_stream_w, sd->sub_stream_h);
|
||||
}
|
||||
if (avcodec_open2(ctx, sub_codec, NULL) < 0)
|
||||
goto error;
|
||||
priv->avctx = ctx;
|
||||
@@ -264,6 +303,7 @@ static void uninit(struct sd *sd)
|
||||
|
||||
clear(priv);
|
||||
avcodec_close(priv->avctx);
|
||||
av_free(priv->avctx->extradata);
|
||||
av_free(priv->avctx);
|
||||
talloc_free(priv);
|
||||
}
|
||||
|
||||
@@ -91,5 +91,6 @@ void mp_buffer_ref(struct FrameBuffer *buffer);
|
||||
void mp_buffer_unref(struct FrameBuffer *buffer);
|
||||
bool mp_buffer_is_unique(struct FrameBuffer *buffer);
|
||||
void mp_buffer_pool_free(struct FramePool **pool);
|
||||
bool mp_buffer_check(struct FrameBuffer *buffer);
|
||||
|
||||
#endif
|
||||
@@ -204,6 +204,16 @@ void mp_buffer_ref(struct FrameBuffer *buf)
|
||||
pool_unlock();
|
||||
}
|
||||
|
||||
bool mp_buffer_check(struct FrameBuffer *buf)
|
||||
{
|
||||
pool_lock();
|
||||
bool ok = buf->refcount > 0;
|
||||
if (ok)
|
||||
buf->refcount++;
|
||||
pool_unlock();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void mp_buffer_unref(struct FrameBuffer *buf)
|
||||
{
|
||||
FramePool *pool = buf->pool;
|
||||
|
||||
+20
-20
@@ -318,10 +318,7 @@ static void set_from_bih(AVCodecContext *avctx, uint32_t format,
|
||||
if (bih->biSize <= sizeof(*bih))
|
||||
break;
|
||||
av_opt_set_int(avctx, "extern_huff", 1, AV_OPT_SEARCH_CHILDREN);
|
||||
avctx->extradata_size = bih->biSize - sizeof(*bih);
|
||||
avctx->extradata = av_mallocz(avctx->extradata_size +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
memcpy(avctx->extradata, bih + 1, avctx->extradata_size);
|
||||
mp_lavc_set_extradata(avctx, bih + 1, bih->biSize - sizeof(*bih));
|
||||
break;
|
||||
|
||||
case MP_FOURCC('R','V','1','0'):
|
||||
@@ -331,29 +328,21 @@ static void set_from_bih(AVCodecContext *avctx, uint32_t format,
|
||||
case MP_FOURCC('R','V','4','0'):
|
||||
if (bih->biSize < sizeof(*bih) + 8) {
|
||||
// only 1 packet per frame & sub_id from fourcc
|
||||
avctx->extradata_size = 8;
|
||||
avctx->extradata = av_mallocz(avctx->extradata_size +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
((uint32_t *)avctx->extradata)[0] = 0;
|
||||
((uint32_t *)avctx->extradata)[1] =
|
||||
format == MP_FOURCC('R','V','1','3') ?
|
||||
0x10003001 : 0x10000000;
|
||||
uint32_t extradata[2] = {
|
||||
0,
|
||||
format == MP_FOURCC('R','V','1','3') ? 0x10003001 : 0x10000000,
|
||||
};
|
||||
mp_lavc_set_extradata(avctx, &extradata, 8);
|
||||
} else {
|
||||
// has extra slice header (demux_rm or rm->avi streamcopy)
|
||||
avctx->extradata_size = bih->biSize - sizeof(*bih);
|
||||
avctx->extradata = av_mallocz(avctx->extradata_size +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
memcpy(avctx->extradata, bih + 1, avctx->extradata_size);
|
||||
mp_lavc_set_extradata(avctx, bih + 1, bih->biSize - sizeof(*bih));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (bih->biSize <= sizeof(*bih))
|
||||
break;
|
||||
avctx->extradata_size = bih->biSize - sizeof(*bih);
|
||||
avctx->extradata = av_mallocz(avctx->extradata_size +
|
||||
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
memcpy(avctx->extradata, bih + 1, avctx->extradata_size);
|
||||
mp_lavc_set_extradata(avctx, bih + 1, bih->biSize - sizeof(*bih));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -717,7 +706,16 @@ static struct mp_image *image_from_decoder(struct dec_video *vd)
|
||||
mp_image_copy_attributes(mpi, &new);
|
||||
} else if (ctx->do_dr1 && pic->opaque) {
|
||||
struct FrameBuffer *fb = pic->opaque;
|
||||
mp_buffer_ref(fb); // initial reference for mpi
|
||||
// initial reference for mpi
|
||||
if (!new.planes[0] || !mp_buffer_check(fb)) {
|
||||
// Decoder returned an unreferenced buffer! Taking this would just
|
||||
// lead to an eventual double-free. Nothing we can do about this.
|
||||
// So just say "fuck you" in a nice way.
|
||||
MP_FATAL(vd,
|
||||
"Impossible condition detected! This version of Libav/FFmpeg is not\n"
|
||||
"supported anymore. Please update.\n");
|
||||
return NULL;
|
||||
}
|
||||
mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref,
|
||||
fb_is_unique, NULL);
|
||||
} else {
|
||||
@@ -763,6 +761,8 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
|
||||
// Note: potentially resets ctx->pic as it is transferred to mpi
|
||||
struct mp_image *mpi = image_from_decoder(vd);
|
||||
if (!mpi)
|
||||
return 0;
|
||||
assert(mpi->planes[0]);
|
||||
mp_image_set_params(mpi, ¶ms);
|
||||
|
||||
|
||||
@@ -126,7 +126,8 @@ static bool create_vdp_decoder(struct lavc_ctx *ctx)
|
||||
goto fail;
|
||||
}
|
||||
if (p->vid_width > maxw || p->vid_height > maxh) {
|
||||
MP_ERR(p, "Video too large.\n");
|
||||
MP_ERR(p, "Video resolution(%dx%d) is larger than the maximum size(%dx%d) supported.\n",
|
||||
p->vid_width, p->vid_height, maxw, maxh);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -599,11 +599,11 @@ void vf_set_dar(int *d_w, int *d_h, int w, int h, double dar)
|
||||
*d_w = w;
|
||||
*d_h = h;
|
||||
if (dar > 0.01) {
|
||||
*d_w = h * dar;
|
||||
*d_w = h * dar + 0.5;
|
||||
// we don't like horizontal downscale
|
||||
if (*d_w < w) {
|
||||
*d_w = w;
|
||||
*d_h = w / dar;
|
||||
*d_h = w / dar + 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +469,6 @@ int vf_open(vf_instance_t *vf)
|
||||
vf->filter = filter;
|
||||
vf->uninit = uninit;
|
||||
|
||||
vf->priv = malloc (sizeof (vf_eq2_t));
|
||||
eq2 = vf->priv;
|
||||
eq2->log = vf->log;
|
||||
|
||||
|
||||
@@ -330,9 +330,16 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
// Window dragging hack
|
||||
ReleaseCapture();
|
||||
SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
mp_input_put_key(vo->input_ctx, MP_MOUSE_BTN0 |
|
||||
MP_KEY_STATE_UP);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mouse_button & MP_KEY_STATE_DOWN)
|
||||
SetCapture(w32->window);
|
||||
else
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
@@ -647,17 +654,14 @@ int vo_w32_init(struct vo *vo)
|
||||
|
||||
HINSTANCE hInstance = GetModuleHandleW(NULL);
|
||||
|
||||
HICON mplayerIcon = LoadIconW(hInstance, L"IDI_ICON1");
|
||||
|
||||
WNDCLASSEXW wcex = {
|
||||
.cbSize = sizeof wcex,
|
||||
.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
|
||||
.lpfnWndProc = WndProc,
|
||||
.hInstance = hInstance,
|
||||
.hIcon = mplayerIcon,
|
||||
.hIcon = LoadIconW(hInstance, L"IDI_ICON1"),
|
||||
.hCursor = LoadCursor(NULL, IDC_ARROW),
|
||||
.lpszClassName = classname,
|
||||
.hIconSm = mplayerIcon,
|
||||
};
|
||||
|
||||
if (!RegisterClassExW(&wcex)) {
|
||||
|
||||
@@ -40,6 +40,7 @@ def __add_mingw_flags__(ctx):
|
||||
|
||||
def __add_cygwin_flags__(ctx):
|
||||
ctx.env.CFLAGS += ['-mwin32']
|
||||
ctx.env.CFLAGS += ['-U__STRICT_ANSI__']
|
||||
|
||||
__compiler_map__ = {
|
||||
'__GNUC__': __add_gcc_flags__,
|
||||
|
||||
@@ -6,7 +6,7 @@ def __get_version__(ctx):
|
||||
cwd=ctx.srcnode.abspath())
|
||||
process.wait()
|
||||
(version, err) = process.communicate()
|
||||
return version.strip().decode("utf-8")
|
||||
return version.strip().decode('utf-8').encode('ascii', 'ignore')
|
||||
|
||||
def __get_build_date__():
|
||||
import time
|
||||
|
||||
@@ -289,7 +289,7 @@ If you really mean to compile without libass support use --disable-libass."
|
||||
}, {
|
||||
'name': '--mpg123',
|
||||
'desc': 'mpg123 support',
|
||||
'func': check_pkg_config('libmpg123', '>= 1.2.0'),
|
||||
'func': check_pkg_config('libmpg123', '>= 1.14.0'),
|
||||
}, {
|
||||
'name': '--ladspa',
|
||||
'desc': 'LADSPA plugin support',
|
||||
@@ -504,6 +504,18 @@ video_output_features = [
|
||||
'name': 'gdi',
|
||||
'desc': 'GDI',
|
||||
'func': check_cc(lib='gdi32')
|
||||
} , {
|
||||
'name': 'winmm',
|
||||
'desc': 'WinMM',
|
||||
'func': check_cc(lib='winmm')
|
||||
} , {
|
||||
'name': 'ole',
|
||||
'desc': 'OLE',
|
||||
'func': check_cc(lib='ole32')
|
||||
} , {
|
||||
'name': 'uuid',
|
||||
'desc': 'UUID',
|
||||
'func': check_cc(lib='uuid')
|
||||
} , {
|
||||
'name': '--wayland',
|
||||
'desc': 'Wayland',
|
||||
@@ -570,7 +582,7 @@ video_output_features = [
|
||||
} , {
|
||||
'name': '--gl-win32',
|
||||
'desc': 'OpenGL Win32 Backend',
|
||||
'deps': [ 'gdi' ],
|
||||
'deps': [ 'gdi', 'winmm', 'ole', 'uuid' ],
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_statement('windows.h', 'wglCreateContext(0)',
|
||||
lib='opengl32')
|
||||
@@ -633,7 +645,7 @@ video_output_features = [
|
||||
}, {
|
||||
'name': '--direct3d',
|
||||
'desc': 'Direct3D support',
|
||||
'deps': [ 'gdi' ],
|
||||
'deps': [ 'gdi', 'winmm', 'ole', 'uuid' ],
|
||||
'func': check_cc(header_name='d3d9.h'),
|
||||
}
|
||||
]
|
||||
|
||||
@@ -239,7 +239,6 @@ def build(ctx):
|
||||
( "stream/ai_sndio.c", "sndio" ),
|
||||
( "stream/audio_in.c", "audio-input" ),
|
||||
( "stream/cache.c" ),
|
||||
( "stream/cdinfo.c", "cdda"),
|
||||
( "stream/cookies.c" ),
|
||||
( "stream/dvb_tune.c", "dvbin" ),
|
||||
( "stream/frequencies.c", "tv" ),
|
||||
|
||||
Reference in new issue
Block a user