mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-21 15:20:02 +01:00
Check in veejay 1.3
git-svn-id: svn://code.dyne.org/veejay/trunk@1135 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
This commit is contained in:
27
veejay-1.3/README
Normal file
27
veejay-1.3/README
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
|
||||
|
||||
10x0 0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 x0x1 10x0 x0x1
|
||||
0x10x0 0x0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 10x0x10x 10x0x1 10x0x1
|
||||
0x0x10 0x0x10 x10x 10x0 x0x1 10x0x10x x0x10x 10x0
|
||||
0x0x10x0 0x0x10 x10x0x10x0x1 10x0x10x0x10 x0x1 0x10 0x0 x10x0x10
|
||||
0x10x0 x10x0x x10x0x10x0x10x 10x0x10x0x10 x0x1 0x10x0x10x0 x10x0x10
|
||||
10x0x1 x0x10x x10x 10x0 x0x1 0x10x0x10x0 0x0x
|
||||
x0x10x0x10x0x1 x10x 10x0 x10x x0x1 0x10x0x10x0x10 0x0x
|
||||
x10x0x10x0 x10x0x10x0x10x 10x0x10x0x10x0 x10x 10x0 0x0x 0x10 0x0x
|
||||
0x0x10 x10x0x10x0x10x 10x0x10x0x10x0 0x010x0 0x0x 0x10 0x0x
|
||||
|
||||
version 1.3
|
||||
November 2008
|
||||
|
||||
=========================================
|
||||
|
||||
:: Veejay, a visual instrument for GNU ::
|
||||
http://veejayhq.net
|
||||
http://veejay.dyne.org
|
||||
|
||||
|
||||
|
||||
Package contents:
|
||||
veejay-server
|
||||
30
veejay-1.3/veejay-server/AUTHORS
Normal file
30
veejay-1.3/veejay-server/AUTHORS
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
veejay contributors:
|
||||
====================
|
||||
|
||||
(in no particular order)
|
||||
|
||||
Jeff Carpenter
|
||||
David Denny
|
||||
Daniel Jircik
|
||||
Pilo Chambert
|
||||
Matthijs van Henten
|
||||
Dursun Koca
|
||||
Peter de Man
|
||||
Stefan Thieme
|
||||
Andrew Wood
|
||||
Kyle Davenport
|
||||
Daniel Rohr
|
||||
Rupert Reddington
|
||||
Toni (from Germany)
|
||||
Thomas Reinhold
|
||||
Maciek Szczesniak
|
||||
|
||||
|
||||
authors:
|
||||
======================
|
||||
|
||||
Niels Elburg <nelburg@looze.net >
|
||||
|
||||
|
||||
|
||||
504
veejay-1.3/veejay-server/COPYING
Normal file
504
veejay-1.3/veejay-server/COPYING
Normal file
@@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
1
veejay-1.3/veejay-server/ChangeLog
Normal file
1
veejay-1.3/veejay-server/ChangeLog
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
234
veejay-1.3/veejay-server/INSTALL
Normal file
234
veejay-1.3/veejay-server/INSTALL
Normal file
@@ -0,0 +1,234 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
52
veejay-1.3/veejay-server/Makefile.am
Normal file
52
veejay-1.3/veejay-server/Makefile.am
Normal file
@@ -0,0 +1,52 @@
|
||||
# Process with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = aclib bio2jack libOSC libhash libvjmsg libvjmem
|
||||
SUBDIRS += libvevo liblzo libgoom libvje libsample libvjnet libyuv libel libstream liblavjpeg libsamplerec
|
||||
SUBDIRS += veejay
|
||||
SUBDIRS += man
|
||||
|
||||
EXTRA_DIST = \
|
||||
autogen.sh\
|
||||
depcomp \
|
||||
cpuinfo.sh \
|
||||
autogen.sh \
|
||||
gveejay-paths.sh.in
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = veejay.pc
|
||||
|
||||
DISTCLEANFILES = \
|
||||
veejay-config.h \
|
||||
veejay.pc \
|
||||
confdefs.h \
|
||||
config.cache \
|
||||
config.status \
|
||||
config.log \
|
||||
gveejay-paths.h
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
compile \
|
||||
depcomp \
|
||||
install-sh \
|
||||
missing \
|
||||
mkinstalldirs \
|
||||
Makefile.in \
|
||||
aclocal.m4 \
|
||||
config.guess \
|
||||
config.h.in \
|
||||
config.sub \
|
||||
configure \
|
||||
ltmain.sh \
|
||||
stamp-h.in
|
||||
|
||||
## make rpms
|
||||
rpm: Makefile
|
||||
$(MAKE) dist
|
||||
rpmbuild -ta --clean $(PACKAGE)-$(VERSION).tar.gz
|
||||
|
||||
## make debs
|
||||
deb: Makefile dist
|
||||
-chmod -R +w $(PACKAGE)-$(VERSION)
|
||||
rm -rf $(PACKAGE)-$(VERSION)
|
||||
tar xzf $(PACKAGE)-$(VERSION).tar.gz
|
||||
cd $(PACKAGE)-$(VERSION); dpkg-buildpackage -rfakeroot
|
||||
0
veejay-1.3/veejay-server/NEWS
Normal file
0
veejay-1.3/veejay-server/NEWS
Normal file
198
veejay-1.3/veejay-server/README
Normal file
198
veejay-1.3/veejay-server/README
Normal file
@@ -0,0 +1,198 @@
|
||||
|
||||
|
||||
|
||||
|
||||
10x0 0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 x0x1 10x0 x0x1
|
||||
0x10x0 0x0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 10x0x10x 10x0x1 10x0x1
|
||||
0x0x10 0x0x10 x10x 10x0 x0x1 10x0x10x x0x10x 10x0
|
||||
0x0x10x0 0x0x10 x10x0x10x0x1 10x0x10x0x10 x0x1 0x10 0x0 x10x0x10
|
||||
0x10x0 x10x0x x10x0x10x0x10x 10x0x10x0x10 x0x1 0x10x0x10x0 x10x0x10
|
||||
10x0x1 x0x10x x10x 10x0 x0x1 0x10x0x10x0 0x0x
|
||||
x0x10x0x10x0x1 x10x 10x0 x10x x0x1 0x10x0x10x0x10 0x0x
|
||||
x10x0x10x0 x10x0x10x0x10x 10x0x10x0x10x0 x10x 10x0 0x0x 0x10 0x0x
|
||||
0x0x10 x10x0x10x0x10x 10x0x10x0x10x0 0x010x0 0x0x 0x10 0x0x
|
||||
|
||||
version 1.3
|
||||
November 2008
|
||||
|
||||
=========================================
|
||||
|
||||
:: Veejay, a visual instrument for GNU ::
|
||||
http://veejayhq.net
|
||||
http://veejay.dyne.org
|
||||
|
||||
|
||||
|
||||
Veejay - a 'visual' instrument and realtime video sampler
|
||||
|
||||
Veejay is a visual instrument and real-time video sampler.
|
||||
It allows you to "play" the video like you would play a piano.
|
||||
While playing, you can record the resulting video directly to disk (video sampling).
|
||||
|
||||
|
||||
|
||||
FEATURE OVERVIEW
|
||||
|
||||
General
|
||||
-------
|
||||
# Free Software (GNU GPL) (1)
|
||||
# Servent architecture (2)
|
||||
# Soft realtime (3)
|
||||
# Frame accurate (4)
|
||||
# Loop based editing (5)
|
||||
# Native YUV processing
|
||||
# Crash recovery
|
||||
|
||||
Media
|
||||
-----
|
||||
# Codecs: MJPEG,MPNG, DV, YUV (raw)
|
||||
# Containers: AVI , Quicktime, rawDV
|
||||
# Devices: USB webcams, DV1394, TV capture cards, etc.
|
||||
# Support for unlimited capture devices
|
||||
# Support for Image files (PNG ,JPEG,TIFF,etc)
|
||||
|
||||
Editing
|
||||
-------
|
||||
# 132 built-in FX , many unique and original FX filters
|
||||
# FX chain (20 slots)
|
||||
# All FX parameters can be animated.
|
||||
# Mix up to two layers per FX slot
|
||||
# Non destructive edit decision lists (cut/copy/paste/crop video)
|
||||
# Simple text editor
|
||||
# Sample editor
|
||||
# Sequence editor
|
||||
# Live disk recorder (sampling)
|
||||
# Full deck save/restore
|
||||
# Live clip loading
|
||||
# Live sample sequencing
|
||||
|
||||
|
||||
|
||||
Trickplay
|
||||
---------
|
||||
# VIMS event recording/playback (6)
|
||||
# Various looping modes including bounce looping
|
||||
# Playback speed and direction
|
||||
# Video scratching
|
||||
# Change in-and out points of a sample (marker)
|
||||
# Slow motion audio / video (7)
|
||||
# Fast motion audio / video
|
||||
# Dynamic framerate
|
||||
# Random frame play
|
||||
# Random sample play
|
||||
# Access up to 4096 video samples instantly
|
||||
|
||||
Output
|
||||
------
|
||||
# Audio trough Jack (low latency audio server) (8)
|
||||
# SDL and OpenGL video
|
||||
# Headless
|
||||
# YUV4MPEG streaming
|
||||
# Network streaming (unicast and multicast)
|
||||
# Preview rendering
|
||||
|
||||
Interaction
|
||||
-----------
|
||||
# Programmable keyboard interface
|
||||
# VIMS (tcp/ip)
|
||||
# OSC (udp)
|
||||
# PureData trough sendVIMS external
|
||||
|
||||
Viewing
|
||||
-------
|
||||
# Full screen or windowed mode
|
||||
# Perspective and foward projection (9)
|
||||
|
||||
|
||||
Additional
|
||||
----------
|
||||
# Support for FreeFrame plugins
|
||||
# Support for Frei0r plugins
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(1) Free Software
|
||||
A matter of liberty, not price. You should think of “free” as in free speech.
|
||||
Free software is the matter of the users freedom to run, copy, distribute, study, change and improve the software.
|
||||
|
||||
(2) A servent architecture is a peer-to-peer network mode with both functionalities of a
|
||||
server and a client. The setup is designed so that each veejay-node can send and receive video,
|
||||
allowing for the creation and maintenance of ad-hoc veejay-networks.
|
||||
Reloaded , veejay's graphical interface, is a thin client and can be run from another computer
|
||||
to track one or more veejay servers.
|
||||
|
||||
(3) Soft realtime: A system is realtime if the correctness of the application not only depends on
|
||||
the logical correctness but also upon the time at which it was performed.
|
||||
Veejay tolerates such lateness and responds by dropping video frames.
|
||||
You can instruct veejay to ignore the time aspect of the video and render all frames, effectivly
|
||||
turning the server into a frame producer.
|
||||
|
||||
(4) VIMS: Veejay Internal Message System. Control data is distributed via this message system,
|
||||
each message consists of an 'event selector' with a list of arguments. VIMS is the lowest
|
||||
level control interface available. The keyboard interface and OSC server are built on top of it.
|
||||
Also all veejay clients communicate usings VIMS.
|
||||
|
||||
(5) Loop based editing: Loops are (short) sections of video (up to any length) that are repeated
|
||||
continuously. While playing, you can change the properties of the video sample, add filters to it
|
||||
and record it on the fly to a new sample (which can be used instantly).
|
||||
|
||||
(6) Frame accurate: In veejay, every frame is a key-frame (a whole image).
|
||||
As a consequence, veejay has no support for video codecs that make use of difference frames.
|
||||
|
||||
(7) In trickplay mode, veejay will always resample the audio analogous to varying the speed
|
||||
of an analogue tape recorder . Halve the speed results in the pitch going down an octave.
|
||||
Slow motion video is produced by linearly interpolating in-between frames and
|
||||
faster motion is accomplished by skipping video frames or, if playing without audio,
|
||||
by changing the framerate dynamically.
|
||||
|
||||
(8) JACK: A low latency audio server that can connect a number of different applications to an audio device,
|
||||
allowing them to share audio between themselves.
|
||||
|
||||
(9) Perspective Viewing: You can define a quadrilateral to which the rendered image will be mapped.
|
||||
This is usefull for setups where the image borders fall outside the projection screen area, or where
|
||||
the projector/camera has a (wide) angle to the projection.
|
||||
Last but not least, it can be used for on-body projection performances.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Install
|
||||
=======
|
||||
|
||||
See file 'INSTALL'
|
||||
|
||||
See doc/Howto_Compile.html
|
||||
See doc/Howto_Compile_on_Ubuntu.html
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
See the directory 'doc' in this package, it contains usefull documentation.
|
||||
|
||||
|
||||
Running
|
||||
=======
|
||||
|
||||
Start 1 or more Veejay servers:
|
||||
$ veejay my-movie-A.avi
|
||||
$ veejay -p 4490 my-movie-B.avi
|
||||
|
||||
CONTACT / FEEDBACK & HELP
|
||||
=========================
|
||||
|
||||
http://veejayhq.net
|
||||
|
||||
|
||||
BUG REPORTS / BLEEDING EDGE SOURCE CODE
|
||||
=======================================
|
||||
|
||||
Please use the ticket system !
|
||||
|
||||
http://veejay.dyne.org
|
||||
http://veejayhq.net
|
||||
|
||||
ENJOY! And let us know about your performances/installations with veejay!
|
||||
|
||||
16
veejay-1.3/veejay-server/TODO
Normal file
16
veejay-1.3/veejay-server/TODO
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
1. Extend viewport menu for mouse wheel scaling of points and quad
|
||||
2. Find functionality to mirror points in one click (pixmap rendering as sdl osd button?)
|
||||
3. Find functionality to use only 2 points to find the other 2
|
||||
|
||||
4. Re-write vj-composite
|
||||
1. Backing, push a frame to the viewport
|
||||
2. Render input source to backing viewport and take output as input
|
||||
3. Render input source to viewport
|
||||
|
||||
5. Mind different resolutions and keep track of sampling
|
||||
|
||||
6. Reduce calls to vj_yuv_get444_template, vj_yuv_get_template, VJFrame *malloc()
|
||||
|
||||
7. remove viewport in reloaded
|
||||
-
|
||||
20
veejay-1.3/veejay-server/aclib/Makefile.am
Normal file
20
veejay-1.3/veejay-server/aclib/Makefile.am
Normal file
@@ -0,0 +1,20 @@
|
||||
# # Process this file with automake to produce Makefile.in.
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(PTHREAD_CFLAGS) \
|
||||
-I$(top_srcdir)
|
||||
|
||||
noinst_LTLIBRARIES = libac.la
|
||||
|
||||
libac_la_SOURCES = \
|
||||
accore.c \
|
||||
average.c \
|
||||
imgconvert.c \
|
||||
img_rgb_packed.c \
|
||||
img_yuv_mixed.c \
|
||||
img_yuv_packed.c \
|
||||
img_yuv_planar.c \
|
||||
img_yuv_rgb.c \
|
||||
memcpy.c \
|
||||
rescale.c
|
||||
|
||||
97
veejay-1.3/veejay-server/aclib/ac.h
Normal file
97
veejay-1.3/veejay-server/aclib/ac.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* ac.h -- main aclib include
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#ifndef ACLIB_AC_H
|
||||
#define ACLIB_AC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* CPU acceleration support flags, for use with ac_init(): */
|
||||
|
||||
#define AC_IA32ASM 0x0001 /* x86-32: standard assembly (no MMX) */
|
||||
#define AC_AMD64ASM 0x0002 /* x86-64: standard assembly (no MMX) */
|
||||
#define AC_CMOVE 0x0004 /* x86: CMOVcc instruction */
|
||||
#define AC_MMX 0x0008 /* x86: MMX instructions */
|
||||
#define AC_MMXEXT 0x0010 /* x86: MMX extended instructions (AMD) */
|
||||
#define AC_3DNOW 0x0020 /* x86: 3DNow! instructions (AMD) */
|
||||
#define AC_3DNOWEXT 0x0040 /* x86: 3DNow! instructions (AMD) */
|
||||
#define AC_SSE 0x0080 /* x86: SSE instructions */
|
||||
#define AC_SSE2 0x0100 /* x86: SSE2 instructions */
|
||||
#define AC_SSE3 0x0200 /* x86: SSE3 instructions */
|
||||
|
||||
#define AC_NONE 0 /* No acceleration (vanilla C functions) */
|
||||
#define AC_ALL (~0) /* All available acceleration */
|
||||
|
||||
|
||||
/* Endianness flag: */
|
||||
#define AC_LITTLE_ENDIAN 1
|
||||
#define AC_BIG_ENDIAN 2
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Library initialization function--MUST be called before any other aclib
|
||||
* functions are used! `accel' selects the accelerations to enable:
|
||||
* AC_NONE, AC_ALL, or a combination of the other AC_* flags above. The
|
||||
* value will always be masked to the acceleration options available on the
|
||||
* actual CPU, as returned by ac_cpuinfo(). Returns 1 on success, 0 on
|
||||
* failure. This function can be called multiple times to change the set
|
||||
* of acceleration features to be used. */
|
||||
extern int ac_init(int accel);
|
||||
|
||||
/* Returns the set of acceleration features supported by this CPU. */
|
||||
extern int ac_cpuinfo(void);
|
||||
|
||||
/* Returns the endianness of this CPU (AC_BIG_ENDIAN or AC_LITTLE_ENDIAN). */
|
||||
extern int ac_endian(void);
|
||||
|
||||
/* Utility routine to convert a set of flags to a descriptive string. The
|
||||
* string is stored in a static buffer overwritten each call. */
|
||||
extern const char *ac_flagstotext(int accel);
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Acceleration-enabled functions: */
|
||||
|
||||
/* Optimized memcpy(). The copy direction is guaranteed to be ascending
|
||||
* (so ac_memcpy(ptr, ptr+1, size) will work). */
|
||||
extern void *ac_memcpy(void *dest, const void *src, size_t size);
|
||||
|
||||
/* Average of two sets of data */
|
||||
extern void ac_average(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes);
|
||||
|
||||
/* Weighted average of two sets of data (weight1+weight2 should be 65536) */
|
||||
extern void ac_rescale(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes,
|
||||
uint32_t weight1, uint32_t weight2);
|
||||
|
||||
/* Image format manipulation is available in aclib/imgconvert.h */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* ACLIB_AC_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
42
veejay-1.3/veejay-server/aclib/ac_internal.h
Normal file
42
veejay-1.3/veejay-server/aclib/ac_internal.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* ac_internal.h -- internal include file for aclib functions
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#ifndef ACLIB_AC_INTERNAL_H
|
||||
#define ACLIB_AC_INTERNAL_H
|
||||
|
||||
|
||||
/* Compiler hint that a condition is unlikely */
|
||||
#ifdef __GNUC__
|
||||
# define UNLIKELY(x) (__builtin_expect((x) != 0, 0))
|
||||
#else
|
||||
# define UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
/* Are _all_ of the given acceleration flags (`test') available? */
|
||||
#define HAS_ACCEL(accel,test) (((accel) & (test)) == (test))
|
||||
|
||||
/* Initialization subfunctions */
|
||||
extern int ac_average_init(int accel);
|
||||
extern int ac_imgconvert_init(int accel);
|
||||
extern int ac_memcpy_init(int accel);
|
||||
extern int ac_rescale_init(int accel);
|
||||
|
||||
|
||||
#endif /* ACLIB_AC_INTERNAL_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
225
veejay-1.3/veejay-server/aclib/accore.c
Normal file
225
veejay-1.3/veejay-server/aclib/accore.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* accore.c -- core aclib functions
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "ac_internal.h"
|
||||
#include "imgconvert.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||||
static int cpuinfo_x86(void);
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Library initialization function. Determines CPU features, then calls
|
||||
* all initialization subfunctions with appropriate flags. Returns 1 on
|
||||
* success, 0 on failure. This function can be called multiple times to
|
||||
* change the set of acceleration features to be used. */
|
||||
|
||||
int ac_init(int accel)
|
||||
{
|
||||
accel &= ac_cpuinfo();
|
||||
if (!ac_average_init(accel)
|
||||
|| !ac_imgconvert_init(accel)
|
||||
|| !ac_memcpy_init(accel)
|
||||
|| !ac_rescale_init(accel)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Returns the set of acceleration features supported by this CPU. */
|
||||
|
||||
int ac_cpuinfo(void)
|
||||
{
|
||||
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||||
return cpuinfo_x86();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Returns the endianness of this CPU (AC_BIG_ENDIAN or AC_LITTLE_ENDIAN). */
|
||||
|
||||
int ac_endian(void)
|
||||
{
|
||||
volatile int test;
|
||||
|
||||
test = 1;
|
||||
if (*((uint8_t *)&test))
|
||||
return AC_LITTLE_ENDIAN;
|
||||
else
|
||||
return AC_BIG_ENDIAN;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Utility routine to convert a set of flags to a descriptive string. The
|
||||
* string is stored in a static buffer overwritten each call. `filter'
|
||||
* selects whether to filter out flags not supported by the CPU. */
|
||||
|
||||
const char *ac_flagstotext(int accel)
|
||||
{
|
||||
static char retbuf[1000];
|
||||
if (!accel)
|
||||
return "none";
|
||||
snprintf(retbuf, sizeof(retbuf), "%s%s%s%s%s%s%s%s%s",
|
||||
accel & AC_SSE3 ? " sse3" : "",
|
||||
accel & AC_SSE2 ? " sse2" : "",
|
||||
accel & AC_SSE ? " sse" : "",
|
||||
accel & AC_3DNOWEXT ? " 3dnowext" : "",
|
||||
accel & AC_3DNOW ? " 3dnow" : "",
|
||||
accel & AC_MMXEXT ? " mmxext" : "",
|
||||
accel & AC_MMX ? " mmx" : "",
|
||||
accel & AC_CMOVE ? " cmove" : "",
|
||||
accel & (AC_IA32ASM|AC_AMD64ASM) ? " asm" : "");
|
||||
return *retbuf ? retbuf+1 : retbuf; /* skip initial space */
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Private functions to return acceleration flags corresponding to available
|
||||
* CPU features for various CPUs. Currently only x86 is supported. */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||||
|
||||
#ifdef ARCH_X86_64
|
||||
# define EAX "%%rax"
|
||||
# define EBX "%%rbx"
|
||||
# define ESI "%%rsi"
|
||||
# define PUSHF "pushfq"
|
||||
# define POPF "popfq"
|
||||
#else
|
||||
# define EAX "%%eax"
|
||||
# define EBX "%%ebx"
|
||||
# define ESI "%%esi"
|
||||
# define PUSHF "pushfl"
|
||||
# define POPF "popfl"
|
||||
#endif
|
||||
|
||||
/* Macro to execute the CPUID instruction with EAX = func. Results are
|
||||
* placed in ret_a (EAX), ret_b (EBX), ret_c (ECX), and ret_d (EDX), which
|
||||
* must be lvalues. Note that we save and restore EBX (RBX on x86-64)
|
||||
* because it is the PIC register. */
|
||||
#define CPUID(func,ret_a,ret_b,ret_c,ret_d) \
|
||||
asm("mov "EBX", "ESI"; cpuid; xchg "EBX", "ESI \
|
||||
: "=a" (ret_a), "=S" (ret_b), "=c" (ret_c), "=d" (ret_d) \
|
||||
: "a" (func))
|
||||
|
||||
/* Various CPUID flags. The second word of the macro name indicates the
|
||||
* function (1: function 1, X1: function 0x80000001) and register (D: EDX)
|
||||
* to which the value belongs. */
|
||||
#define CPUID_1D_CMOVE (1UL<<15)
|
||||
#define CPUID_1D_MMX (1UL<<23)
|
||||
#define CPUID_1D_SSE (1UL<<25)
|
||||
#define CPUID_1D_SSE2 (1UL<<26)
|
||||
#define CPUID_1C_SSE3 (1UL<< 0)
|
||||
#define CPUID_X1D_AMD_MMXEXT (1UL<<22) /* AMD only */
|
||||
#define CPUID_X1D_AMD_3DNOW (1UL<<31) /* AMD only */
|
||||
#define CPUID_X1D_AMD_3DNOWEXT (1UL<<30) /* AMD only */
|
||||
#define CPUID_X1D_CYRIX_MMXEXT (1UL<<24) /* Cyrix only */
|
||||
|
||||
static int cpuinfo_x86(void)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
uint32_t cpuid_max, cpuid_ext_max; /* Maximum CPUID function numbers */
|
||||
char cpu_vendor[13]; /* 12-byte CPU vendor string + trailing null */
|
||||
uint32_t cpuid_1D, cpuid_1C, cpuid_X1D;
|
||||
int accel;
|
||||
|
||||
/* First see if the CPUID instruction is even available. We try to
|
||||
* toggle bit 21 (ID) of the flags register; if the bit changes, then
|
||||
* CPUID is available. */
|
||||
asm(PUSHF" \n\
|
||||
pop "EAX" \n\
|
||||
mov %%eax, %%edx \n\
|
||||
xor $0x200000, %%eax \n\
|
||||
push "EAX" \n\
|
||||
"POPF" \n\
|
||||
"PUSHF" \n\
|
||||
pop "EAX" \n\
|
||||
xor %%edx, %%eax"
|
||||
: "=a" (eax) : : "edx");
|
||||
if (!eax)
|
||||
return 0;
|
||||
|
||||
/* Determine the maximum function number available, and save the vendor
|
||||
* string */
|
||||
CPUID(0, cpuid_max, ebx, ecx, edx);
|
||||
*((uint32_t *)(cpu_vendor )) = ebx;
|
||||
*((uint32_t *)(cpu_vendor+4)) = edx;
|
||||
*((uint32_t *)(cpu_vendor+8)) = ecx;
|
||||
cpu_vendor[12] = 0;
|
||||
cpuid_ext_max = 0; /* FIXME: how do early CPUs respond to 0x80000000? */
|
||||
CPUID(0x80000000, cpuid_ext_max, ebx, ecx, edx);
|
||||
|
||||
/* Read available features */
|
||||
cpuid_1D = cpuid_1C = cpuid_X1D = 0;
|
||||
if (cpuid_max >= 1)
|
||||
CPUID(1, eax, ebx, cpuid_1C, cpuid_1D);
|
||||
if (cpuid_ext_max >= 0x80000001)
|
||||
CPUID(0x80000001, eax, ebx, ecx, cpuid_X1D);
|
||||
|
||||
/* Convert to acceleration flags */
|
||||
#ifdef ARCH_X86_64
|
||||
accel = AC_AMD64ASM; /* but not IA32! (register size issues) */
|
||||
#else
|
||||
accel = AC_IA32ASM;
|
||||
#endif
|
||||
if (cpuid_1D & CPUID_1D_CMOVE)
|
||||
accel |= AC_CMOVE;
|
||||
if (cpuid_1D & CPUID_1D_MMX)
|
||||
accel |= AC_MMX;
|
||||
if (cpuid_1D & CPUID_1D_SSE)
|
||||
accel |= AC_SSE;
|
||||
if (cpuid_1D & CPUID_1D_SSE2)
|
||||
accel |= AC_SSE2;
|
||||
if (cpuid_1C & CPUID_1C_SSE3)
|
||||
accel |= AC_SSE3;
|
||||
if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
|
||||
if (cpuid_X1D & CPUID_X1D_AMD_MMXEXT)
|
||||
accel |= AC_MMXEXT;
|
||||
if (cpuid_X1D & CPUID_X1D_AMD_3DNOW)
|
||||
accel |= AC_3DNOW;
|
||||
if (cpuid_X1D & CPUID_X1D_AMD_3DNOWEXT)
|
||||
accel |= AC_3DNOWEXT;
|
||||
} else if (strcmp(cpu_vendor, "CyrixInstead") == 0) {
|
||||
if (cpuid_X1D & CPUID_X1D_CYRIX_MMXEXT)
|
||||
accel |= AC_MMXEXT;
|
||||
}
|
||||
|
||||
/* And return */
|
||||
return accel;
|
||||
}
|
||||
|
||||
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
243
veejay-1.3/veejay-server/aclib/average.c
Normal file
243
veejay-1.3/veejay-server/aclib/average.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* average.c -- average two sets of byte data
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "ac_internal.h"
|
||||
|
||||
static void average(const uint8_t *, const uint8_t *, uint8_t *, int);
|
||||
static void (*average_ptr)(const uint8_t *, const uint8_t *, uint8_t *, int)
|
||||
= average;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* External interface */
|
||||
|
||||
void ac_average(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes)
|
||||
{
|
||||
(*average_ptr)(src1, src2, dest, bytes);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Vanilla C version */
|
||||
|
||||
static void average(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++)
|
||||
dest[i] = (src1[i]+src2[i]+1) / 2;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */
|
||||
|
||||
static void average_mmx(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes)
|
||||
{
|
||||
if (bytes >= 8) {
|
||||
asm("\
|
||||
pxor %%mm7, %%mm7 \n\
|
||||
movq %%mm7, %%mm6 \n\
|
||||
pcmpeqw %%mm5, %%mm5 \n\
|
||||
psubw %%mm5, %%mm6 # Put 0x0001*4 in MM6 \n\
|
||||
0: \n\
|
||||
movq -8(%%esi,%%eax), %%mm0 \n\
|
||||
movq %%mm0, %%mm1 \n\
|
||||
punpcklbw %%mm7, %%mm0 \n\
|
||||
punpckhbw %%mm7, %%mm1 \n\
|
||||
movq -8(%%edx,%%eax), %%mm2 \n\
|
||||
movq %%mm2, %%mm3 \n\
|
||||
punpcklbw %%mm7, %%mm2 \n\
|
||||
punpckhbw %%mm7, %%mm3 \n\
|
||||
paddw %%mm2, %%mm0 \n\
|
||||
paddw %%mm6, %%mm0 \n\
|
||||
psrlw $1, %%mm0 \n\
|
||||
paddw %%mm3, %%mm1 \n\
|
||||
paddw %%mm6, %%mm1 \n\
|
||||
psrlw $1, %%mm1 \n\
|
||||
packuswb %%mm1, %%mm0 \n\
|
||||
movq %%mm0, -8(%%edi,%%eax) \n\
|
||||
subl $8, %%eax \n\
|
||||
jnz 0b \n\
|
||||
emms"
|
||||
: /* no outputs */
|
||||
: "S" (src1), "d" (src2), "D" (dest), "a" (bytes & ~7));
|
||||
}
|
||||
if (UNLIKELY(bytes & 7)) {
|
||||
average(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7),
|
||||
bytes & 7);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_MMX && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_SSE) && defined(ARCH_X86)
|
||||
|
||||
/* SSE has PAVGB */
|
||||
|
||||
static void average_sse(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes)
|
||||
{
|
||||
if (bytes >= 8) {
|
||||
asm("\
|
||||
testl $~0x1F, %%eax \n\
|
||||
jz 1f \n\
|
||||
0: \n\
|
||||
movq -32(%%esi,%%eax), %%mm0 \n\
|
||||
movq -24(%%esi,%%eax), %%mm1 \n\
|
||||
movq -16(%%esi,%%eax), %%mm2 \n\
|
||||
movq -8(%%esi,%%eax), %%mm3 \n\
|
||||
movq -32(%%edx,%%eax), %%mm4 \n\
|
||||
pavgb %%mm4, %%mm0 \n\
|
||||
movq -24(%%edx,%%eax), %%mm5 \n\
|
||||
pavgb %%mm5, %%mm1 \n\
|
||||
movq -16(%%edx,%%eax), %%mm6 \n\
|
||||
pavgb %%mm6, %%mm2 \n\
|
||||
movq -8(%%edx,%%eax), %%mm7 \n\
|
||||
pavgb %%mm7, %%mm3 \n\
|
||||
movntq %%mm0, -32(%%edi,%%eax) \n\
|
||||
movntq %%mm1, -24(%%edi,%%eax) \n\
|
||||
movntq %%mm2, -16(%%edi,%%eax) \n\
|
||||
movntq %%mm3, -8(%%edi,%%eax) \n\
|
||||
subl $32, %%eax \n\
|
||||
testl $~0x1F, %%eax \n\
|
||||
jnz 0b \n\
|
||||
testl %%eax, %%eax \n\
|
||||
jz 2f \n\
|
||||
1: \n\
|
||||
movq -8(%%esi,%%eax), %%mm0 \n\
|
||||
movq -8(%%edx,%%eax), %%mm1 \n\
|
||||
pavgb %%mm1, %%mm0 \n\
|
||||
movntq %%mm0, -8(%%edi,%%eax) \n\
|
||||
subl $8, %%eax \n\
|
||||
jnz 1b \n\
|
||||
2: \n\
|
||||
emms \n\
|
||||
sfence"
|
||||
: /* no outputs */
|
||||
: "S" (src1), "d" (src2), "D" (dest), "a" (bytes & ~7));
|
||||
}
|
||||
if (UNLIKELY(bytes & 7)) {
|
||||
average(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7),
|
||||
bytes & 7);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_SSE && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
|
||||
#if defined(ARCH_X86_64)
|
||||
# define EAX "%%rax"
|
||||
# define EDX "%%rdx"
|
||||
# define ESI "%%rsi"
|
||||
# define EDI "%%rdi"
|
||||
#else
|
||||
# define EAX "%%eax"
|
||||
# define EDX "%%edx"
|
||||
# define ESI "%%esi"
|
||||
# define EDI "%%edi"
|
||||
#endif
|
||||
|
||||
static void average_sse2(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes)
|
||||
{
|
||||
if (bytes >= 8) {
|
||||
asm("\
|
||||
testl $~0x3F, %%eax \n\
|
||||
jz 1f \n\
|
||||
0: \n\
|
||||
movdqu -64("ESI","EAX"), %%xmm0 \n\
|
||||
movdqu -48("ESI","EAX"), %%xmm1 \n\
|
||||
movdqu -32("ESI","EAX"), %%xmm2 \n\
|
||||
movdqu -16("ESI","EAX"), %%xmm3 \n\
|
||||
movdqu -64("EDX","EAX"), %%xmm4 \n\
|
||||
pavgb %%xmm4, %%xmm0 \n\
|
||||
movdqu -48("EDX","EAX"), %%xmm5 \n\
|
||||
pavgb %%xmm5, %%xmm1 \n\
|
||||
movdqu -32("EDX","EAX"), %%xmm6 \n\
|
||||
pavgb %%xmm6, %%xmm2 \n\
|
||||
movdqu -16("EDX","EAX"), %%xmm7 \n\
|
||||
pavgb %%xmm7, %%xmm3 \n\
|
||||
# Note that movntdq requires 16-byte alignment, which we're \n\
|
||||
# not guaranteed \n\
|
||||
movdqu %%xmm0, -64("EDI","EAX") \n\
|
||||
movdqu %%xmm1, -48("EDI","EAX") \n\
|
||||
movdqu %%xmm2, -32("EDI","EAX") \n\
|
||||
movdqu %%xmm3, -16("EDI","EAX") \n\
|
||||
subl $64, %%eax \n\
|
||||
testl $~0x3F, %%eax \n\
|
||||
jnz 0b \n\
|
||||
testl %%eax, %%eax \n\
|
||||
jz 2f \n\
|
||||
1: \n\
|
||||
movq -8("ESI","EAX"), %%mm0 \n\
|
||||
movq -8("EDX","EAX"), %%mm1 \n\
|
||||
pavgb %%mm1, %%mm0 \n\
|
||||
movq %%mm0, -8("EDI","EAX") \n\
|
||||
subl $8, %%eax \n\
|
||||
jnz 1b \n\
|
||||
2: \n\
|
||||
emms"
|
||||
: /* no outputs */
|
||||
: "S" (src1), "d" (src2), "D" (dest), "a" (bytes & ~7));
|
||||
}
|
||||
if (UNLIKELY(bytes & 7)) {
|
||||
average(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7),
|
||||
bytes & 7);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_SSE2 */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization routine. */
|
||||
|
||||
int ac_average_init(int accel)
|
||||
{
|
||||
average_ptr = average;
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86)
|
||||
if (HAS_ACCEL(accel, AC_MMX))
|
||||
average_ptr = average_mmx;
|
||||
#endif
|
||||
#if defined(HAVE_ASM_SSE) && defined(ARCH_X86)
|
||||
if (HAS_ACCEL(accel, AC_SSE))
|
||||
average_ptr = average_sse;
|
||||
#endif
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
if (HAS_ACCEL(accel, AC_SSE2))
|
||||
average_ptr = average_sse2;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
40
veejay-1.3/veejay-server/aclib/img_internal.h
Normal file
40
veejay-1.3/veejay-server/aclib/img_internal.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* img_internal.h - imgconvert internal use header
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#ifndef ACLIB_IMG_INTERNAL_H
|
||||
#define ACLIB_IMG_INTERNAL_H
|
||||
|
||||
/* Type of a conversion function */
|
||||
typedef int (*ConversionFunc)(uint8_t **src, uint8_t **dest,
|
||||
int width, int height);
|
||||
|
||||
/* Function to register a conversion */
|
||||
extern int register_conversion(ImageFormat srcfmt, ImageFormat destfmt,
|
||||
ConversionFunc function);
|
||||
|
||||
/* Initialization routines */
|
||||
extern int ac_imgconvert_init(int accel);
|
||||
extern int ac_imgconvert_init_yuv_planar(int accel);
|
||||
extern int ac_imgconvert_init_yuv_packed(int accel);
|
||||
extern int ac_imgconvert_init_yuv_mixed(int accel);
|
||||
extern int ac_imgconvert_init_yuv_rgb(int accel);
|
||||
extern int ac_imgconvert_init_rgb_packed(int accel);
|
||||
|
||||
#endif /* ACLIB_IMG_INTERNAL_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
1105
veejay-1.3/veejay-server/aclib/img_rgb_packed.c
Normal file
1105
veejay-1.3/veejay-server/aclib/img_rgb_packed.c
Normal file
File diff suppressed because it is too large
Load Diff
596
veejay-1.3/veejay-server/aclib/img_x86_common.h
Normal file
596
veejay-1.3/veejay-server/aclib/img_x86_common.h
Normal file
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
* img_x86_common.h - common x86/x86-64 assembly macros
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#ifndef ACLIB_IMG_X86_COMMON_H
|
||||
#define ACLIB_IMG_X86_COMMON_H
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Register names for pointers */
|
||||
#ifdef ARCH_X86_64
|
||||
# define EAX "%%rax"
|
||||
# define EBX "%%rbx"
|
||||
# define ECX "%%rcx"
|
||||
# define EDX "%%rdx"
|
||||
# define ESP "%%rsp"
|
||||
# define EBP "%%rbp"
|
||||
# define ESI "%%rsi"
|
||||
# define EDI "%%rdi"
|
||||
#else
|
||||
# define EAX "%%eax"
|
||||
# define EBX "%%ebx"
|
||||
# define ECX "%%ecx"
|
||||
# define EDX "%%edx"
|
||||
# define ESP "%%esp"
|
||||
# define EBP "%%ebp"
|
||||
# define ESI "%%esi"
|
||||
# define EDI "%%edi"
|
||||
#endif
|
||||
|
||||
/* Data for isolating particular bytes. Used by the SWAP32 macros; if you
|
||||
* use them, make sure to define DEFINE_MASK_DATA before including this
|
||||
* file! */
|
||||
#ifdef DEFINE_MASK_DATA
|
||||
static const struct { uint32_t n[64]; } __attribute__((aligned(16))) mask_data = {{
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x0000FF00, 0x0000FF00, 0x0000FF00, 0x0000FF00,
|
||||
0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF,
|
||||
0x00FF0000, 0x00FF0000, 0x00FF0000, 0x00FF0000,
|
||||
0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
|
||||
0x00FFFF00, 0x00FFFF00, 0x00FFFF00, 0x00FFFF00,
|
||||
0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF,
|
||||
0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
|
||||
0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF,
|
||||
0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00,
|
||||
0xFF00FFFF, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FFFF,
|
||||
0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000,
|
||||
0xFFFF00FF, 0xFFFF00FF, 0xFFFF00FF, 0xFFFF00FF,
|
||||
0xFFFFFF00, 0xFFFFFF00, 0xFFFFFF00, 0xFFFFFF00,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
}};
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Basic assembly macros, used for odd-count loops */
|
||||
|
||||
/* Swap bytes in pairs of 16-bit values */
|
||||
#define X86_SWAP16_2 \
|
||||
"movl -4("ESI","ECX",4), %%eax \n\
|
||||
movl %%eax, %%edx \n\
|
||||
shll $8, %%eax \n\
|
||||
andl $0xFF00FF00, %%eax \n\
|
||||
shrl $8, %%edx \n\
|
||||
andl $0x00FF00FF, %%edx \n\
|
||||
orl %%edx, %%eax \n\
|
||||
movl %%eax, -4("EDI","ECX",4)"
|
||||
|
||||
/* Swap words in a 32-bit value */
|
||||
#define X86_SWAP32 \
|
||||
"movl -4("ESI","ECX",4), %%eax \n\
|
||||
roll $16, %%eax \n\
|
||||
movl %%eax, -4("EDI","ECX",4)"
|
||||
|
||||
/* Swap bytes 0 and 2 of a 32-bit value */
|
||||
#define X86_SWAP32_02 \
|
||||
"movw -4("ESI","ECX",4), %%ax \n\
|
||||
movw -2("ESI","ECX",4), %%dx \n\
|
||||
xchg %%dl, %%al \n\
|
||||
movw %%ax, -4("EDI","ECX",4) \n\
|
||||
movw %%dx, -2("EDI","ECX",4)"
|
||||
|
||||
/* Swap bytes 1 and 3 of a 32-bit value */
|
||||
#define X86_SWAP32_13 \
|
||||
"movw -4("ESI","ECX",4), %%ax \n\
|
||||
movw -2("ESI","ECX",4), %%dx \n\
|
||||
xchg %%dh, %%ah \n\
|
||||
movw %%ax, -4("EDI","ECX",4) \n\
|
||||
movw %%dx, -2("EDI","ECX",4)"
|
||||
|
||||
/* Reverse the order of bytes in a 32-bit value */
|
||||
#define X86_REV32 \
|
||||
"movl -4("ESI","ECX",4), %%eax \n\
|
||||
xchg %%ah, %%al \n\
|
||||
roll $16, %%eax \n\
|
||||
xchg %%ah, %%al \n\
|
||||
movl %%eax, -4("EDI","ECX",4)"
|
||||
|
||||
/* The same, using the BSWAP instruction */
|
||||
#define X86_REV32_BSWAP \
|
||||
"movl -4("ESI","ECX",4), %%eax \n\
|
||||
bswap %%eax \n\
|
||||
movl %%eax, -4("EDI","ECX",4)"
|
||||
|
||||
/* Rotate a 32-bit value left 8 bits */
|
||||
#define X86_ROL32 \
|
||||
"movl -4("ESI","ECX",4), %%eax \n\
|
||||
roll $8, %%eax \n\
|
||||
movl %%eax, -4("EDI","ECX",4)"
|
||||
|
||||
/* Rotate a 32-bit value right 8 bits */
|
||||
#define X86_ROR32 \
|
||||
"movl -4("ESI","ECX",4), %%eax \n\
|
||||
rorl $8, %%eax \n\
|
||||
movl %%eax, -4("EDI","ECX",4)"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Basic assembly routines. Sizes are all given in 32-bit units. */
|
||||
|
||||
#define ASM_SWAP16_2_X86(size) \
|
||||
asm("0: "X86_SWAP16_2" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax", "edx")
|
||||
|
||||
#define ASM_SWAP32_X86(size) \
|
||||
asm("0: "X86_SWAP32" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax", "edx")
|
||||
|
||||
#define ASM_SWAP32_02_X86(size) \
|
||||
asm("0: "X86_SWAP32_02" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax", "edx")
|
||||
|
||||
#define ASM_SWAP32_13_X86(size) \
|
||||
asm("0: "X86_SWAP32_13" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax", "edx")
|
||||
|
||||
#define ASM_REV32_X86(size) \
|
||||
asm("0: "X86_REV32" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax")
|
||||
|
||||
#define ASM_ROL32_X86(size) \
|
||||
asm("0: "X86_ROL32" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax")
|
||||
|
||||
#define ASM_ROR32_X86(size) \
|
||||
asm("0: "X86_ROR32" \n\
|
||||
subl $1, %%ecx \n\
|
||||
jnz 0b" \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax")
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Wrapper for SIMD loops. This generates the body of an asm() construct
|
||||
* (the string only, not the input/output/clobber lists) given the data
|
||||
* block size (number of data units processed per SIMD loop iteration),
|
||||
* instructions to save and restore unclobberable registers (such as EBX),
|
||||
* and the bodies of the odd-count and main loops. The data count is
|
||||
* assumed to be preloaded in ECX. Parameters are:
|
||||
* blocksize: number of units of data processed per SIMD loop (must be
|
||||
* a power of 2); can be a constant or a numerical
|
||||
* expression containing only constants
|
||||
* push_regs: string constant containing instructions to push registers
|
||||
* that must be saved over the small loop
|
||||
* pop_regs: string constant containing instructions to pop registers
|
||||
* saved by `push_regs' (restored before the main loop)
|
||||
* small_loop: loop for handling data elements one at a time (when the
|
||||
* count is not a multiple of `blocksize'
|
||||
* main_loop: main SIMD loop for processing data
|
||||
* emms: EMMS/SFENCE instructions to end main loop with, as needed
|
||||
*/
|
||||
|
||||
#define SIMD_LOOP_WRAPPER(blocksize,push_regs,pop_regs,small_loop,main_loop,emms) \
|
||||
/* Always save ECX--GCC may rely on it being unmodified */ \
|
||||
"push "ECX"; " \
|
||||
/* Check whether the count is a multiple of the blocksize (this \
|
||||
* can cause branch mispredicts but seems to be faster overall) */ \
|
||||
"testl $(("#blocksize")-1), %%ecx; " \
|
||||
"jz 1f; " \
|
||||
/* It's not--run the small loop to align the count */ \
|
||||
push_regs"; " \
|
||||
"0: " \
|
||||
small_loop"; " \
|
||||
"subl $1, %%ecx; " \
|
||||
"testl $(("#blocksize")-1), %%ecx; " \
|
||||
"jnz 0b; " \
|
||||
pop_regs"; " \
|
||||
/* Make sure there's some data left */ \
|
||||
"testl %%ecx, %%ecx; " \
|
||||
"jz 2f; " \
|
||||
/* Now run the main SIMD loop */ \
|
||||
"1: " \
|
||||
main_loop"; " \
|
||||
"subl $("#blocksize"), %%ecx; " \
|
||||
"jnz 1b; " \
|
||||
/* Clear MMX state and/or SFENCE, as needed */ \
|
||||
emms"; " \
|
||||
/* Restore ECX and finish */ \
|
||||
"2: " \
|
||||
"pop "ECX";"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* MMX- and SSE2-optimized swap/rotate routines. These routines are
|
||||
* identical save for data size, so we use common macros to implement them,
|
||||
* with register names and data offsets replaced by parameters to the
|
||||
* macros. */
|
||||
|
||||
#define ASM_SIMD_MMX(name,size) \
|
||||
name((size), 64, \
|
||||
"movq", "movq", "movq", "", \
|
||||
"%%mm0", "%%mm1", "%%mm2", "%%mm3", \
|
||||
"%%mm4", "%%mm5", "%%mm6", "%%mm7")
|
||||
#define ASM_SIMD_SSE2(name,size) \
|
||||
name((size), 128, \
|
||||
"movdqu", "movdqa", "movdqu", "", \
|
||||
"%%xmm0", "%%xmm1", "%%xmm2", "%%xmm3",\
|
||||
"%%xmm4", "%%xmm5", "%%xmm6", "%%xmm7")
|
||||
#define ASM_SIMD_SSE2_ALIGNED(name,size) \
|
||||
name((size), 128, \
|
||||
"movdqa", "movdqa", "movntdq", "sfence",\
|
||||
"%%xmm0", "%%xmm1", "%%xmm2", "%%xmm3",\
|
||||
"%%xmm4", "%%xmm5", "%%xmm6", "%%xmm7")
|
||||
|
||||
#define ASM_SWAP16_2_MMX(size) ASM_SIMD_MMX(ASM_SWAP16_2_SIMD,(size))
|
||||
#define ASM_SWAP16_2_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP16_2_SIMD,(size))
|
||||
#define ASM_SWAP16_2_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP16_2_SIMD,(size))
|
||||
#define ASM_SWAP32_MMX(size) ASM_SIMD_MMX(ASM_SWAP32_SIMD,(size))
|
||||
#define ASM_SWAP32_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP32_SIMD,(size))
|
||||
#define ASM_SWAP32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP32_SIMD,(size))
|
||||
#define ASM_SWAP32_02_MMX(size) ASM_SIMD_MMX(ASM_SWAP32_02_SIMD,(size))
|
||||
#define ASM_SWAP32_02_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP32_02_SIMD,(size))
|
||||
#define ASM_SWAP32_02_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP32_02_SIMD,(size))
|
||||
#define ASM_SWAP32_13_MMX(size) ASM_SIMD_MMX(ASM_SWAP32_13_SIMD,(size))
|
||||
#define ASM_SWAP32_13_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP32_13_SIMD,(size))
|
||||
#define ASM_SWAP32_13_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP32_13_SIMD,(size))
|
||||
#define ASM_REV32_MMX(size) ASM_SIMD_MMX(ASM_REV32_SIMD,(size))
|
||||
#define ASM_REV32_SSE2(size) ASM_SIMD_SSE2(ASM_REV32_SIMD,(size))
|
||||
#define ASM_REV32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_REV32_SIMD,(size))
|
||||
#define ASM_ROL32_MMX(size) ASM_SIMD_MMX(ASM_ROL32_SIMD,(size))
|
||||
#define ASM_ROL32_SSE2(size) ASM_SIMD_SSE2(ASM_ROL32_SIMD,(size))
|
||||
#define ASM_ROL32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_ROL32_SIMD,(size))
|
||||
#define ASM_ROR32_MMX(size) ASM_SIMD_MMX(ASM_ROR32_SIMD,(size))
|
||||
#define ASM_ROR32_SSE2(size) ASM_SIMD_SSE2(ASM_ROR32_SIMD,(size))
|
||||
#define ASM_ROR32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_ROR32_SIMD,(size))
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Actual implementations. Note that unrolling the SIMD loops doesn't seem
|
||||
* to be a win (only 2-3% improvement at most), and in fact can lose by a
|
||||
* bit in short loops. */
|
||||
|
||||
#define ASM_SWAP16_2_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ X86_SWAP16_2, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
psrlw $8, "MM0" # MM0: - 7 - 5 - 3 - 1 \n\
|
||||
psllw $8, "MM1" # MM1: 6 - 4 - 2 - 0 - \n\
|
||||
por "MM1", "MM0" # MM0: 6 7 4 5 2 3 0 1 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax", "edx")
|
||||
|
||||
#define ASM_SWAP32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ X86_SWAP32, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
psrld $16, "MM0" # MM0: - - 7 6 - - 3 2 \n\
|
||||
pslld $16, "MM1" # MM1: 5 4 - - 1 0 - - \n\
|
||||
por "MM1", "MM0" # MM0: 5 4 7 6 1 0 3 2 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax")
|
||||
|
||||
#define ASM_SWAP32_02_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "push "EDX, \
|
||||
/* pop_regs */ "pop "EDX, \
|
||||
/* small_loop */ X86_SWAP32_02, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM2" # MM2: 7 6 5 4 3 2 1 0 \n\
|
||||
pand 16("EDX"), "MM1" # MM1: - - - 4 - - - 0 \n\
|
||||
pslld $16, "MM1" # MM1: - 4 - - - 0 - - \n\
|
||||
pand 64("EDX"), "MM2" # MM2: - 6 - - - 2 - - \n\
|
||||
psrld $16, "MM2" # MM2: - - - 6 - - - 2 \n\
|
||||
pand 160("EDX"), "MM0" # MM0: 7 - 5 - 3 - 1 - \n\
|
||||
por "MM1", "MM0" # MM0: 7 4 5 - 3 0 1 - \n\
|
||||
por "MM2", "MM0" # MM0: 7 4 5 6 3 0 1 2 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size), "d" (&mask_data), \
|
||||
"m" (mask_data) \
|
||||
: "eax")
|
||||
|
||||
#define ASM_SWAP32_13_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "push "EDX, \
|
||||
/* pop_regs */ "pop "EDX, \
|
||||
/* small_loop */ X86_SWAP32_13, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM2" # MM2: 7 6 5 4 3 2 1 0 \n\
|
||||
pand 32("EDX"), "MM1" # MM1: - - 5 - - - 1 - \n\
|
||||
pslld $16, "MM1" # MM1: 5 - - - 1 - - - \n\
|
||||
pand 128("EDX"), "MM2" # MM2: 7 - - - 3 - - - \n\
|
||||
psrld $16, "MM2" # MM2: - - 7 - - - 3 - \n\
|
||||
pand 80("EDX"), "MM0" # MM0: - 6 - 4 - 2 - 0 \n\
|
||||
por "MM1", "MM0" # MM0: 5 6 - 4 1 2 - 0 \n\
|
||||
por "MM2", "MM0" # MM0: 5 6 7 4 1 2 3 0 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size), "d" (&mask_data), \
|
||||
"m" (mask_data) \
|
||||
: "eax");
|
||||
|
||||
#define ASM_REV32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ X86_REV32_BSWAP, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM2" # MM2: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM3" # MM3: 7 6 5 4 3 2 1 0 \n\
|
||||
psrld $24, "MM0" # MM0: - - - 7 - - - 3 \n\
|
||||
pand 32("EDX"), "MM2" # MM2: - - 5 - - - 1 - \n\
|
||||
psrld $8, "MM1" # MM1: - 7 6 5 - 3 2 1 \n\
|
||||
pand 32("EDX"), "MM1" # MM1: - - 6 - - - 2 - \n\
|
||||
pslld $8, "MM2" # MM2: - 5 - - - 1 - - \n\
|
||||
pslld $24, "MM3" # MM3: 4 - - - 0 - - - \n\
|
||||
por "MM1", "MM0" # MM0: - - 6 7 - - 2 3 \n\
|
||||
por "MM2", "MM0" # MM0: - 5 6 7 - 1 2 3 \n\
|
||||
por "MM3", "MM0" # MM0: 4 5 6 7 0 1 2 3 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size), "d" (&mask_data), \
|
||||
"m" (mask_data) \
|
||||
: "eax")
|
||||
|
||||
#define ASM_ROL32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ X86_ROL32, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
pslld $8, "MM0" # MM0: 6 5 4 - 2 1 0 - \n\
|
||||
psrld $24, "MM1" # MM1: - - - 7 - - - 3 \n\
|
||||
por "MM1", "MM0" # MM0: 6 5 4 7 2 1 0 3 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax")
|
||||
|
||||
#define ASM_ROR32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ (regsize)/32, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ X86_ROR32, \
|
||||
/* main_loop */ \
|
||||
ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\
|
||||
# MM0: 7 6 5 4 3 2 1 0 \n\
|
||||
"movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\
|
||||
psrld $8, "MM0" # MM0: - 7 6 5 - 3 2 1 \n\
|
||||
pslld $24, "MM1" # MM1: 4 - - - 0 - - - \n\
|
||||
por "MM1", "MM0" # MM0: 4 7 6 5 0 3 2 1 \n\
|
||||
"stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \
|
||||
/* emms */ "emms; "sfence) \
|
||||
: /* no outputs */ \
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (size) \
|
||||
: "eax")
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* SSE2 macros to load 8 24- or 32-bit RGB pixels into XMM0/1/2 (R/G/B) as
|
||||
* 16-bit values, used for RGB->YUV and RGB->grayscale conversions.
|
||||
* ZERO is the number of the XMM register containing all zeroes. */
|
||||
|
||||
#define SSE2_LOAD_RGB24(ZERO) \
|
||||
"movl -21("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm0 # XMM0: ----- ----- ----- xBGR1 \n\
|
||||
pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xBGR1 ----- ----- ----- \n\
|
||||
movl -18("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm0 # XMM0: xBGR1 ----- ----- xBGR2 \n\
|
||||
pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xBGR2 xBGR1 ----- ----- \n\
|
||||
movl -15("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm0 # XMM0: xBGR2 xBGR1 ----- xBGR3 \n\
|
||||
pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xBGR3 xBGR2 xBGR1 ----- \n\
|
||||
movl -24("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm0 # XMM0: xBGR3 xBGR2 xBGR1 xBGR0 \n\
|
||||
movl -9("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm1 # XMM1: ----- ----- ----- xBGR5 \n\
|
||||
pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xBGR5 ----- ----- ----- \n\
|
||||
movl -6("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm1 # XMM1: xBGR5 ----- ----- xBGR6 \n\
|
||||
pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xBGR6 xBGR5 ----- ----- \n\
|
||||
movl -3("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm1 # XMM1: xBGR6 xBGR5 ----- xBGR7 \n\
|
||||
pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xBGR7 xBGR6 xBGR5 ----- \n\
|
||||
movl -12("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm1 # XMM1: xBGR7 xBGR6 xBGR5 xBGR4 \n"\
|
||||
SSE2_MASSAGE_RGBA32(ZERO)
|
||||
|
||||
#define SSE2_LOAD_BGR24(ZERO) \
|
||||
"movl -21("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm0 # XMM0: ----- ----- ----- xRGB1 \n\
|
||||
pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xRGB1 ----- ----- ----- \n\
|
||||
movl -18("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm0 # XMM0: xRGB1 ----- ----- xRGB2 \n\
|
||||
pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xRGB2 xRGB1 ----- ----- \n\
|
||||
movl -15("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm0 # XMM0: xRGB2 xRGB1 ----- xRGB3 \n\
|
||||
pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xRGB3 xRGB2 xRGB1 ----- \n\
|
||||
movl -24("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm0 # XMM0: xRGB3 xRGB2 xRGB1 xRGB0 \n\
|
||||
movl -9("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm1 # XMM1: ----- ----- ----- xRGB5 \n\
|
||||
pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xRGB5 ----- ----- ----- \n\
|
||||
movl -6("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm1 # XMM1: xRGB5 ----- ----- xRGB6 \n\
|
||||
pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xRGB6 xRGB5 ----- ----- \n\
|
||||
movl -3("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm1 # XMM1: xRGB6 xRGB5 ----- xRGB7 \n\
|
||||
pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xRGB7 xRGB6 xRGB5 ----- \n\
|
||||
movl -12("ESI","EBX"), %%eax \n\
|
||||
movd %%eax, %%xmm2 \n\
|
||||
por %%xmm2, %%xmm1 # XMM1: xRGB7 xRGB6 xRGB5 xRGB4 \n"\
|
||||
SSE2_MASSAGE_BGRA32(ZERO)
|
||||
|
||||
#define SSE2_LOAD_RGBA32(ZERO) "\
|
||||
movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: ABGR3 ABGR2 ABGR1 ABGR0 \n\
|
||||
movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: ABGR7 ABGR6 ABGR5 ABGR4 \n"\
|
||||
SSE2_MASSAGE_RGBA32(ZERO)
|
||||
#define SSE2_MASSAGE_RGBA32(ZERO) "\
|
||||
movdqa %%xmm0, %%xmm2 # XMM2: ABGR3 ABGR2 ABGR1 ABGR0 \n\
|
||||
punpcklbw %%xmm1, %%xmm0 # X0.l: A4 A0 B4 B0 G4 G0 R4 R0 \n\
|
||||
punpckhbw %%xmm1, %%xmm2 # X2.l: A6 A2 B6 B2 G6 G2 R6 R2 \n\
|
||||
movdqa %%xmm0, %%xmm1 # X1.l: A4 A0 B4 B0 G4 G0 R4 R0 \n\
|
||||
punpcklbw %%xmm2, %%xmm0 # X0.l: G6 G4 G2 G0 R6 R4 R2 R0 \n\
|
||||
punpckhbw %%xmm2, %%xmm1 # X1.l: G7 G5 G3 G1 R7 R5 R3 R1 \n\
|
||||
movdqa %%xmm0, %%xmm2 # X2.l: G6 G4 G2 G0 R6 R4 R2 R0 \n\
|
||||
punpcklbw %%xmm1, %%xmm0 # XMM0: G7.......G0 R7.......R0 \n\
|
||||
punpckhbw %%xmm1, %%xmm2 # XMM2: A7.......A0 B7.......B0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: G7.......G0 R7.......R0 \n\
|
||||
punpcklbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
punpckhbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\
|
||||
punpcklbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n"
|
||||
|
||||
#define SSE2_LOAD_BGRA32(ZERO) "\
|
||||
movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: ARGB3 ARGB2 ARGB1 ARGB0 \n\
|
||||
movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: ARGB7 ARGB6 ARGB5 ARGB4 \n"\
|
||||
SSE2_MASSAGE_BGRA32(ZERO)
|
||||
#define SSE2_MASSAGE_BGRA32(ZERO) "\
|
||||
movdqa %%xmm0, %%xmm2 # XMM2: ARGB3 ARGB2 ARGB1 ARGB0 \n\
|
||||
punpcklbw %%xmm1, %%xmm2 # X2.l: A4 A0 R4 R0 G4 G0 B4 B0 \n\
|
||||
punpckhbw %%xmm1, %%xmm0 # X0.l: A6 A2 R6 R2 G6 G2 B6 B2 \n\
|
||||
movdqa %%xmm2, %%xmm1 # X1.l: A4 A0 R4 R0 G4 G0 B4 B0 \n\
|
||||
punpcklbw %%xmm0, %%xmm2 # X2.l: G6 G4 G2 G0 B6 B4 B2 B0 \n\
|
||||
punpckhbw %%xmm0, %%xmm1 # X1.l: G7 G5 G3 G1 B7 B5 B3 B1 \n\
|
||||
movdqa %%xmm2, %%xmm0 # X0.l: G6 G4 G2 G0 B6 B4 B2 B0 \n\
|
||||
punpcklbw %%xmm1, %%xmm2 # XMM2: G7.......G0 B7.......B0 \n\
|
||||
punpckhbw %%xmm1, %%xmm0 # XMM0: A7.......A0 R7.......R0 \n\
|
||||
movdqa %%xmm2, %%xmm1 # XMM1: G7.......G0 B7.......B0 \n\
|
||||
punpcklbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
punpckhbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\
|
||||
punpcklbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n"
|
||||
|
||||
#define SSE2_LOAD_ARGB32(ZERO) "\
|
||||
movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: BGRA3 BGRA2 BGRA1 BGRA0 \n\
|
||||
movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: BGRA7 BGRA6 BGRA5 BGRA4 \n"\
|
||||
SSE2_MASSAGE_ARGB32(ZERO)
|
||||
#define SSE2_MASSAGE_ARGB32(ZERO) "\
|
||||
movdqa %%xmm0, %%xmm2 # XMM2: BGRA3 BGRA2 BGRA1 BGRA0 \n\
|
||||
punpcklbw %%xmm1, %%xmm0 # X0.l: B4 B0 G4 G0 R4 R0 A4 A0 \n\
|
||||
punpckhbw %%xmm1, %%xmm2 # X2.l: B6 B2 G6 G2 R6 R2 A6 A2 \n\
|
||||
movdqa %%xmm0, %%xmm1 # X1.l: B4 B0 G4 G0 R4 R0 A4 A0 \n\
|
||||
punpcklbw %%xmm2, %%xmm0 # X0.l: R6 R4 R2 R0 A6 A4 A2 A0 \n\
|
||||
punpckhbw %%xmm2, %%xmm1 # X1.l: R7 R5 R3 R1 A7 A5 A3 A1 \n\
|
||||
movdqa %%xmm0, %%xmm2 # X2.l: R6 R4 R2 R0 A6 A4 A2 A0 \n\
|
||||
punpcklbw %%xmm1, %%xmm0 # XMM0: R7.......G0 A7.......A0 \n\
|
||||
punpckhbw %%xmm1, %%xmm2 # XMM2: B7.......G0 G7.......G0 \n\
|
||||
movdqa %%xmm2, %%xmm1 # XMM1: B7.......B0 G7.......G0 \n\
|
||||
punpckhbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
punpcklbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\
|
||||
punpckhbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n"
|
||||
|
||||
#define SSE2_LOAD_ABGR32(ZERO) "\
|
||||
movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: RGBA3 RGBA2 RGBA1 RGBA0 \n\
|
||||
movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: RGBA7 RGBA6 RGBA5 RGBA4 \n"\
|
||||
SSE2_MASSAGE_ABGR32(ZERO)
|
||||
#define SSE2_MASSAGE_ABGR32(ZERO) "\
|
||||
movdqa %%xmm0, %%xmm2 # XMM2: RGBA3 RGBA2 RGBA1 RGBA0 \n\
|
||||
punpcklbw %%xmm1, %%xmm2 # X2.l: R4 R0 G4 G0 B4 B0 A4 A0 \n\
|
||||
punpckhbw %%xmm1, %%xmm0 # X0.l: R6 R2 G6 G2 B6 B2 A6 A2 \n\
|
||||
movdqa %%xmm2, %%xmm1 # X1.l: R4 R0 G4 G0 B4 B0 A4 A0 \n\
|
||||
punpcklbw %%xmm0, %%xmm2 # X2.l: B6 B4 B2 B0 A6 A4 A2 A0 \n\
|
||||
punpckhbw %%xmm0, %%xmm1 # X1.l: B7 B5 B3 B1 A7 A5 A3 A1 \n\
|
||||
movdqa %%xmm2, %%xmm0 # X0.l: B6 B4 B2 B0 A6 A4 A2 A0 \n\
|
||||
punpcklbw %%xmm1, %%xmm2 # XMM2: B7.......B0 A7.......A0 \n\
|
||||
punpckhbw %%xmm1, %%xmm0 # XMM0: R7.......R0 G7.......G0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: R7.......R0 G7.......G0 \n\
|
||||
punpckhbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\
|
||||
punpcklbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\
|
||||
punpckhbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* ACLIB_IMG_X86_COMMON_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
912
veejay-1.3/veejay-server/aclib/img_yuv_mixed.c
Normal file
912
veejay-1.3/veejay-server/aclib/img_yuv_mixed.c
Normal file
@@ -0,0 +1,912 @@
|
||||
/*
|
||||
* img_yuv_packed.c - YUV planar<->packed image format conversion routines
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "imgconvert.h"
|
||||
#include "img_internal.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Standard C implementations */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Wrappers for UYVY and YVYU */
|
||||
/* Note: we rely on YUY2<->{UYVY,YVYU} working for src==dest */
|
||||
/* FIXME: when converting from UYVY/YVYU, src is destroyed! */
|
||||
|
||||
static int uyvy_yvyu_wrapper(uint8_t **src, ImageFormat srcfmt,
|
||||
uint8_t **dest, ImageFormat destfmt,
|
||||
int width, int height)
|
||||
{
|
||||
if (srcfmt == IMG_UYVY || srcfmt == IMG_YVYU)
|
||||
return ac_imgconvert(src, srcfmt, src, IMG_YUY2, width, height)
|
||||
&& ac_imgconvert(src, IMG_YUY2, dest, destfmt, width, height);
|
||||
else
|
||||
return ac_imgconvert(src, srcfmt, dest, IMG_YUY2, width, height)
|
||||
&& ac_imgconvert(dest, IMG_YUY2, dest, destfmt, width, height);
|
||||
}
|
||||
|
||||
static int yuv420p_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV420P, dest, IMG_UYVY, width, height); }
|
||||
|
||||
static int yuv420p_yvyu(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV420P, dest, IMG_YVYU, width, height); }
|
||||
|
||||
static int yuv411p_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV411P, dest, IMG_UYVY, width, height); }
|
||||
|
||||
static int yuv411p_yvyu(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV411P, dest, IMG_YVYU, width, height); }
|
||||
|
||||
static int yuv422p_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV422P, dest, IMG_UYVY, width, height); }
|
||||
|
||||
static int yuv422p_yvyu(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV422P, dest, IMG_YVYU, width, height); }
|
||||
|
||||
static int yuv444p_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV444P, dest, IMG_UYVY, width, height); }
|
||||
|
||||
static int yuv444p_yvyu(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YUV444P, dest, IMG_YVYU, width, height); }
|
||||
|
||||
static int uyvy_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV420P, width, height); }
|
||||
|
||||
static int yvyu_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV420P, width, height); }
|
||||
|
||||
static int uyvy_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV411P, width, height); }
|
||||
|
||||
static int yvyu_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV411P, width, height); }
|
||||
|
||||
static int uyvy_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV422P, width, height); }
|
||||
|
||||
static int yvyu_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV422P, width, height); }
|
||||
|
||||
static int uyvy_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV444P, width, height); }
|
||||
|
||||
static int yvyu_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV444P, width, height); }
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv420p_yuy2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < (height & ~1); y++) {
|
||||
for (x = 0; x < (width & ~1); x += 2) {
|
||||
dest[0][(y*width+x)*2 ] = src[0][y*width+x];
|
||||
dest[0][(y*width+x)*2+1] = src[1][(y/2)*(width/2)+x/2];
|
||||
dest[0][(y*width+x)*2+2] = src[0][y*width+x+1];
|
||||
dest[0][(y*width+x)*2+3] = src[2][(y/2)*(width/2)+x/2];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_yuy2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < (width & ~1); x += 2) {
|
||||
dest[0][(y*width+x)*2 ] = src[0][y*width+x];
|
||||
dest[0][(y*width+x)*2+1] = src[1][y*(width/4)+x/4];
|
||||
dest[0][(y*width+x)*2+2] = src[0][y*width+x+1];
|
||||
dest[0][(y*width+x)*2+3] = src[2][y*(width/4)+x/4];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_yuy2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (width/2)*height; i++) {
|
||||
dest[0][i*4 ] = src[0][i*2];
|
||||
dest[0][i*4+1] = src[1][i];
|
||||
dest[0][i*4+2] = src[0][i*2+1];
|
||||
dest[0][i*4+3] = src[2][i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_yuy2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (width/2)*height; i++) {
|
||||
dest[0][i*4 ] = src[0][i*2];
|
||||
dest[0][i*4+1] = (src[1][i*2] + src[1][i*2+1]) / 2;
|
||||
dest[0][i*4+2] = src[0][i*2+1];
|
||||
dest[0][i*4+3] = (src[2][i*2] + src[2][i*2+1]) / 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuy2_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < (height & ~1); y++) {
|
||||
for (x = 0; x < (width & ~1); x += 2) {
|
||||
dest[0][y*width+x ] = src[0][(y*width+x)*2 ];
|
||||
dest[0][y*width+x+1] = src[0][(y*width+x)*2+2];
|
||||
if (y%2 == 0) {
|
||||
dest[1][(y/2)*(width/2)+x/2] = src[0][(y*width+x)*2+1];
|
||||
dest[2][(y/2)*(width/2)+x/2] = src[0][(y*width+x)*2+3];
|
||||
} else {
|
||||
dest[1][(y/2)*(width/2)+x/2] =
|
||||
(dest[1][(y/2)*(width/2)+x/2] + src[0][(y*width+x)*2+1] + 1) / 2;
|
||||
dest[2][(y/2)*(width/2)+x/2] =
|
||||
(dest[2][(y/2)*(width/2)+x/2] + src[0][(y*width+x)*2+3] + 1) / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < (width & ~3); x += 4) {
|
||||
dest[0][y*width+x] = src[0][(y*width+x)*2 ];
|
||||
dest[0][y*width+x+1] = src[0][(y*width+x)*2+2];
|
||||
dest[0][y*width+x+2] = src[0][(y*width+x)*2+4];
|
||||
dest[0][y*width+x+3] = src[0][(y*width+x)*2+6];
|
||||
dest[1][y*(width/4)+x/4] = (src[0][(y*width+x)*2+1]
|
||||
+ src[0][(y*width+x)*2+5] + 1) / 2;
|
||||
dest[2][y*(width/4)+x/4] = (src[0][(y*width+x)*2+3]
|
||||
+ src[0][(y*width+x)*2+7] + 1) / 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (width/2)*height; i++) {
|
||||
dest[0][i*2] = src[0][i*4 ];
|
||||
dest[1][i] = src[0][i*4+1];
|
||||
dest[0][i*2+1] = src[0][i*4+2];
|
||||
dest[2][i] = src[0][i*4+3];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (width & ~1)*height; i += 2) {
|
||||
dest[0][i] = src[0][i*2 ];
|
||||
dest[1][i] = src[0][i*2+1];
|
||||
dest[1][i+1] = src[0][i*2+1];
|
||||
dest[0][i+1] = src[0][i*2+2];
|
||||
dest[2][i] = src[0][i*2+3];
|
||||
dest[2][i+1] = src[0][i*2+3];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int y8_yuy2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height; i++) {
|
||||
dest[0][i*2 ] = src[0][i];
|
||||
dest[0][i*2+1] = 128;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height; i++) {
|
||||
dest[0][i*2 ] = 128;
|
||||
dest[0][i*2+1] = src[0][i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_y8(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height; i++)
|
||||
dest[0][i] = src[0][i*2];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uyvy_y8(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height; i++)
|
||||
dest[0][i] = src[0][i*2+1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
|
||||
/* SSE2 routines. See comments in img_x86_common.h for why we don't bother
|
||||
* unrolling the loops. */
|
||||
|
||||
/* Common macros/data for x86 code */
|
||||
#include "img_x86_common.h"
|
||||
|
||||
/* YUV420P (1 row) or YUV422P -> YUY2 (unit: 2 pixels) */
|
||||
#define YUV42XP_YUY2 \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -1("EDX","ECX"), %%bh \n\
|
||||
movb -1("ESI","ECX",2), %%bl \n\
|
||||
shll $16, %%ebx \n\
|
||||
movb -1("EAX","ECX"), %%bh \n\
|
||||
movb -2("ESI","ECX",2), %%bl \n\
|
||||
movl %%ebx, -4("EDI","ECX",4)", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",2),%%xmm0 #XM0: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
movq -8("EAX","ECX"), %%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\
|
||||
movq -8("EDX","ECX"), %%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n\
|
||||
punpcklbw %%xmm3, %%xmm2 # XMM2: V7 U7 V6 ..... U1 V0 U0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
punpcklbw %%xmm2, %%xmm0 # XMM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
punpckhbw %%xmm2, %%xmm1 # XMM1: V7 YF U7 ..... Y9 U4 Y8 \n\
|
||||
movdqu %%xmm0, -32("EDI","ECX",4) \n\
|
||||
movdqu %%xmm1, -16("EDI","ECX",4)", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUV411P -> YUY2 (unit: 4 pixels) */
|
||||
#define YUV411P_YUY2 \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -1("EDX","ECX"), %%bh \n\
|
||||
movb -1("ESI","ECX",4), %%bl \n\
|
||||
shll $16, %%ebx \n\
|
||||
movb -1("EAX","ECX"), %%bh \n\
|
||||
movb -2("ESI","ECX",4), %%bl \n\
|
||||
movl %%ebx, -4("EDI","ECX",8) \n\
|
||||
movb -1("EDX","ECX"), %%bh \n\
|
||||
movb -3("ESI","ECX",4), %%bl \n\
|
||||
shll $16, %%ebx \n\
|
||||
movb -1("EAX","ECX"), %%bh \n\
|
||||
movb -4("ESI","ECX",4), %%bl \n\
|
||||
movl %%ebx, -8("EDI","ECX",8)", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",4),%%xmm0 #XM0: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
movd -4("EAX","ECX"), %%xmm2 # XMM2: U3 U2 U1 U0 \n\
|
||||
punpcklbw %%xmm2, %%xmm2 # XMM2: U3 U3 U2 U2 U1 U1 U0 U0 \n\
|
||||
movd -4("EDX","ECX"), %%xmm3 # XMM3: V3 V2 V1 V0 \n\
|
||||
punpcklbw %%xmm3, %%xmm3 # XMM3: V3 V3 V2 V2 V1 V1 V0 V0 \n\
|
||||
punpcklbw %%xmm3, %%xmm2 # XMM2: V3 U3 V3 ..... U0 V0 U0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
punpcklbw %%xmm2, %%xmm0 # XMM0: V1 Y7 U1 ..... Y1 U0 Y0 \n\
|
||||
punpckhbw %%xmm2, %%xmm1 # XMM1: V3 YF U3 ..... Y9 U2 Y8 \n\
|
||||
movdqu %%xmm0, -32("EDI","ECX",8) \n\
|
||||
movdqu %%xmm1, -16("EDI","ECX",8)", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUV444P -> YUY2 (unit: 2 pixels) */
|
||||
#define YUV444P_YUY2 \
|
||||
/* Load 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "push "EBX"; push "EBP, \
|
||||
/* pop_regs */ "pop "EBP"; pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movzbl -1("EDX","ECX",2), %%ebx \n\
|
||||
movzbl -2("EDX","ECX",2), %%ebp \n\
|
||||
addl %%ebp, %%ebx \n\
|
||||
shrl $1, %%ebx \n\
|
||||
movb %%bl, -1("EDI","ECX",4) \n\
|
||||
movb -1("ESI","ECX",2), %%bl \n\
|
||||
movb %%bl, -2("EDI","ECX",4) \n\
|
||||
movzbl -1("EAX","ECX",2), %%ebx \n\
|
||||
movzbl -2("EAX","ECX",2), %%ebp \n\
|
||||
addl %%ebp, %%ebx \n\
|
||||
shrl $1, %%ebx \n\
|
||||
movb %%bl, -3("EDI","ECX",4) \n\
|
||||
movb -2("ESI","ECX",2), %%bl \n\
|
||||
movb %%bl, -4("EDI","ECX",4)", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",2),%%xmm0 #XM0: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
movdqu -16("EAX","ECX",2), %%xmm2 #XM2: UF UE UD ..... U2 U1 U0 \n\
|
||||
movdqu -16("EDX","ECX",2), %%xmm3 #XM3: VF VE VD ..... V2 V1 V0 \n\
|
||||
movdqa %%xmm2, %%xmm4 # XMM4: UF UE UD ..... U2 U1 U0 \n\
|
||||
pand %%xmm7, %%xmm2 # XMM2: -- UE -- ..... U2 -- U0 \n\
|
||||
psrlw $8, %%xmm4 # XMM4: -- UF -- ..... U3 -- U1 \n\
|
||||
pavgw %%xmm4, %%xmm2 # XMM2: -- u7 -- ..... u1 -- u0 \n\
|
||||
movdqa %%xmm3, %%xmm5 # XMM4: UF UE UD ..... U2 U1 U0 \n\
|
||||
pand %%xmm7, %%xmm3 # XMM3: -- VE -- ..... V2 -- V0 \n\
|
||||
psrlw $8, %%xmm5 # XMM5: -- VF -- ..... V3 -- V1 \n\
|
||||
pavgw %%xmm5, %%xmm3 # XMM3: -- v7 -- ..... v1 -- v0 \n\
|
||||
psllw $8, %%xmm3 # XMM3: v7 -- v6 ..... -- v0 -- \n\
|
||||
por %%xmm3, %%xmm2 # XMM2: v7 u7 v6 ..... u1 v0 u0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
punpcklbw %%xmm2, %%xmm0 # XMM0: v3 Y7 u3 ..... Y1 u0 Y0 \n\
|
||||
punpckhbw %%xmm2, %%xmm1 # XMM1: v7 YF u7 ..... Y9 u4 Y8 \n\
|
||||
movdqu %%xmm0, -32("EDI","ECX",4) \n\
|
||||
movdqu %%xmm1, -16("EDI","ECX",4)", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUY2 -> YUV420P (U row) (unit: 2 pixels) */
|
||||
#define YUY2_YUV420P_U \
|
||||
/* Load 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "push "EBX"; push "EBP, \
|
||||
/* pop_regs */ "pop "EBP"; pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -4("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -2("EDI","ECX",2) \n\
|
||||
movb -2("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -1("EDI","ECX",2) \n\
|
||||
movzbl -3("ESI","ECX",4), %%ebx \n\
|
||||
movzbl -3("EAX","ECX",4), %%ebp \n\
|
||||
addl %%ebp, %%ebx \n\
|
||||
shrl $1, %%ebx \n\
|
||||
movb %%bl, -1("EDX","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqu -16("EAX","ECX",4),%%xmm2 #XMM2: Vd Yh Ud ..... Yb Ua Ya \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- Vd -- ..... Va -- Ua \n\
|
||||
pavgw %%xmm2, %%xmm1 # XMM1: -- v3 -- ..... v0 -- u0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: v3 u3 v2 u2 v1 u1 v0 u0 \n\
|
||||
pand %%xmm7, %%xmm1 # XMM1: -- u3 -- u2 -- u1 -- u0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: u3 u2 u1 u0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX",2) \n\
|
||||
movd %%xmm1, -4("EDX","ECX")", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUY2 -> YUV420P (V row) (unit: 2 pixels) */
|
||||
#define YUY2_YUV420P_V \
|
||||
/* Load 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "push "EBX"; push "EBP, \
|
||||
/* pop_regs */ "pop "EBP"; pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -4("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -2("EDI","ECX",2) \n\
|
||||
movb -2("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -1("EDI","ECX",2) \n\
|
||||
movzbl -1("ESI","ECX",4), %%ebx \n\
|
||||
movzbl -1("EAX","ECX",4), %%ebp \n\
|
||||
addl %%ebp, %%ebx \n\
|
||||
shrl $1, %%ebx \n\
|
||||
movb %%bl, -1("EDX","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqu -16("EAX","ECX",4),%%xmm2 #XMM2: Vd Yh Ud ..... Yb Ua Ya \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- Vd -- ..... Va -- Ua \n\
|
||||
pavgw %%xmm1, %%xmm2 # XMM2: -- v3 -- ..... v0 -- u0 \n\
|
||||
packuswb %%xmm2, %%xmm2 # XMM2: v3 u3 v2 u2 v1 u1 v0 u0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- v3 -- v2 -- v1 -- v0 \n\
|
||||
packuswb %%xmm2, %%xmm2 # XMM2: v3 v2 v1 v0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX",2) \n\
|
||||
movd %%xmm2, -4("EDX","ECX")", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUY2 -> YUV411P (unit: 4 pixels) */
|
||||
#define YUY2_YUV411P \
|
||||
/* Load 0x000..000FFFFFFFF into XMM6, 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm6, %%xmm6; psrldq $12, %%xmm6;" \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 2, \
|
||||
/* push_regs */ "push "EBX"; push "EBP, \
|
||||
/* pop_regs */ "pop "EBP"; pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -8("ESI","ECX",8), %%bl \n\
|
||||
movb %%bl, -4("EDI","ECX",4) \n\
|
||||
movb -6("ESI","ECX",8), %%bl \n\
|
||||
movb %%bl, -3("EDI","ECX",4) \n\
|
||||
movb -4("ESI","ECX",8), %%bl \n\
|
||||
movb %%bl, -2("EDI","ECX",4) \n\
|
||||
movb -2("ESI","ECX",8), %%bl \n\
|
||||
movb %%bl, -1("EDI","ECX",4) \n\
|
||||
movzbl -7("ESI","ECX",8), %%ebx \n\
|
||||
movzbl -3("ESI","ECX",8), %%ebp \n\
|
||||
addl %%ebp, %%ebx \n\
|
||||
shrl $1, %%ebx \n\
|
||||
movb %%bl, -1("EAX","ECX") \n\
|
||||
movzbl -5("ESI","ECX",8), %%ebx \n\
|
||||
movzbl -1("ESI","ECX",8), %%ebp \n\
|
||||
addl %%ebp, %%ebx \n\
|
||||
shrl $1, %%ebx \n\
|
||||
movb %%bl, -1("EDX","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",8),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: V3 U3 V2 U2 V1 U1 V0 U0 \n\
|
||||
movdqa %%xmm1, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\
|
||||
pand %%xmm7, %%xmm1 # XMM1: -- U3 -- U2 -- U1 -- U0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- V3 -- V2 -- V1 -- V0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: U3 U2 U1 U0 \n\
|
||||
packuswb %%xmm2, %%xmm2 # XMM2: V3 V2 V1 V0 \n\
|
||||
pand %%xmm6, %%xmm1 # XMM1: -- -- -- -- U3 U2 U1 U0 \n\
|
||||
psllq $32, %%xmm2 # XMM2: V3 V2 V1 V0 -- -- -- -- \n\
|
||||
por %%xmm1, %%xmm2 # XMM2: V3 V2 V1 V0 U3 U2 U1 U0 \n\
|
||||
movdqa %%xmm2, %%xmm1 # XMM1: V3 V2 V1 V0 U3 U2 U1 U0 \n\
|
||||
pand %%xmm7, %%xmm1 # XMM1: -- V2 -- V0 -- U2 -- U0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- V3 -- V1 -- U3 -- U1 \n\
|
||||
pavgw %%xmm2, %%xmm1 # XMM1: -- v1 -- v0 -- u1 -- u0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: v1 v0 u1 u0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX",4) \n\
|
||||
movd %%xmm1, %%ebx \n\
|
||||
movw %%bx, -2("EAX","ECX") \n\
|
||||
shrl $16, %%ebx; \n\
|
||||
movw %%bx, -2("EDX","ECX")", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUY2 -> YUV422P (unit: 2 pixels) */
|
||||
#define YUY2_YUV422P \
|
||||
/* Load 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -4("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -2("EDI","ECX",2) \n\
|
||||
movb -2("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -1("EDI","ECX",2) \n\
|
||||
movb -3("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -1("EAX","ECX") \n\
|
||||
movb -1("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -1("EDX","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: V3 U3 V2 U2 V1 U1 V0 U0 \n\
|
||||
movdqa %%xmm1, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\
|
||||
pand %%xmm7, %%xmm1 # XMM1: -- U3 -- U2 -- U1 -- U0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- V3 -- V2 -- V1 -- V0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: U3 U2 U1 U0 \n\
|
||||
packuswb %%xmm2, %%xmm2 # XMM2: V3 V2 V1 V0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX",2) \n\
|
||||
movd %%xmm1, -4("EAX","ECX") \n\
|
||||
movd %%xmm2, -4("EDX","ECX")", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUY2 -> YUV444P (unit: 2 pixels) */
|
||||
#define YUY2_YUV444P \
|
||||
/* Load 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movb -4("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -2("EDI","ECX",2) \n\
|
||||
movb -2("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -1("EDI","ECX",2) \n\
|
||||
movb -3("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -2("EAX","ECX",2) \n\
|
||||
movb %%bl, -1("EAX","ECX",2) \n\
|
||||
movb -1("ESI","ECX",4), %%bl \n\
|
||||
movb %%bl, -2("EDX","ECX",2) \n\
|
||||
movb %%bl, -1("EDX","ECX",2)", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\
|
||||
packuswb %%xmm1, %%xmm1 # XMM1: V3 U3 V2 U2 V1 U1 V0 U0 \n\
|
||||
movdqa %%xmm1, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\
|
||||
pand %%xmm7, %%xmm1 # XMM1: -- U3 -- U2 -- U1 -- U0 \n\
|
||||
psrlw $8, %%xmm2 # XMM2: -- V3 -- V2 -- V1 -- V0 \n\
|
||||
movdqa %%xmm1, %%xmm3 # XMM3: -- U3 -- U2 -- U1 -- U0 \n\
|
||||
psllw $8, %%xmm3 # XMM3: U3 -- U2 -- U1 -- U0 -- \n\
|
||||
por %%xmm3, %%xmm1 # XMM1: U3 U3 U2 U2 U1 U1 U0 U0 \n\
|
||||
movdqa %%xmm2, %%xmm3 # XMM3: -- V3 -- V2 -- V1 -- V0 \n\
|
||||
psllw $8, %%xmm3 # XMM3: V3 -- V2 -- V1 -- V0 -- \n\
|
||||
por %%xmm3, %%xmm2 # XMM1: V3 V3 V2 V2 V1 V1 V0 V0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX",2) \n\
|
||||
movq %%xmm1, -8("EAX","ECX",2) \n\
|
||||
movq %%xmm2, -8("EDX","ECX",2)", \
|
||||
/* emms */ "emms")
|
||||
|
||||
|
||||
/* Y8 -> YUY2/YVYU (unit: 1 pixel) */
|
||||
#define Y8_YUY2 \
|
||||
/* Load 0x80*16 into XMM7 for interlacing U/V */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psllw $7, %%xmm7; packsswb %%xmm7, %%xmm7;"\
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 16, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movb -1("ESI","ECX"), %%al \n\
|
||||
movb %%al, -2("EDI","ECX",2) \n\
|
||||
movb $0x80, -1("EDI","ECX",2)", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX"),%%xmm0 # XMM0: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
punpcklbw %%xmm7, %%xmm0 # XMM0: 80 Y7 80 ..... Y1 80 Y0 \n\
|
||||
movdqu %%xmm0, -32("EDI","ECX",2) \n\
|
||||
punpckhbw %%xmm7, %%xmm1 # XMM1: 80 YF 80 ..... Y9 80 Y8 \n\
|
||||
movdqu %%xmm1, -16("EDI","ECX",2)", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* Y8 -> UYVY (unit: 1 pixel) */
|
||||
#define Y8_UYVY \
|
||||
/* Load 0x80*16 into XMM7 for interlacing U/V */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psllw $7, %%xmm7; packsswb %%xmm7, %%xmm7;"\
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 16, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movb -1("ESI","ECX"), %%al \n\
|
||||
movb %%al, -1("EDI","ECX",2) \n\
|
||||
movb $0x80, -2("EDI","ECX",2)", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX"),%%xmm0 # XMM0: YF YE YD ..... Y2 Y1 Y0 \n\
|
||||
movdqa %%xmm7, %%xmm1 # XMM1: 80 80 80 ..... 80 80 80 \n\
|
||||
punpcklbw %%xmm0, %%xmm1 # XMM1: Y7 80 Y6 ..... 80 Y0 80 \n\
|
||||
movdqu %%xmm1, -32("EDI","ECX",2) \n\
|
||||
movdqa %%xmm7, %%xmm2 # XMM2: 80 80 80 ..... 80 80 80 \n\
|
||||
punpckhbw %%xmm0, %%xmm2 # XMM0: YF 80 YE ..... 80 Y8 80 \n\
|
||||
movdqu %%xmm2, -16("EDI","ECX",2)", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* YUY2/YVYU -> Y8 (unit: 1 pixel) */
|
||||
#define YUY2_Y8 \
|
||||
/* Load 0x00FF*8 into XMM7 for masking */ \
|
||||
"pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movb -2("ESI","ECX",2), %%al \n\
|
||||
movb %%al, -1("EDI","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",2),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX")", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/* UYVY -> Y8 (unit: 1 pixel) */
|
||||
#define UYVY_Y8 \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movb -1("ESI","ECX",2), %%al \n\
|
||||
movb %%al, -1("EDI","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",2),%%xmm0 #XM0: Y7 V3 Y6 ..... V0 Y0 U0 \n\
|
||||
psrlw $8, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX")", \
|
||||
/* emms */ "emms")
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv420p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
for (y = 0; y < (height & ~1); y++) {
|
||||
asm(YUV42XP_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width), "a" (src[1]+(y/2)*(width/2)),
|
||||
"d" (src[2]+(y/2)*(width/2)), "D" (dest[0]+y*width*2),
|
||||
"c" (width/2));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
if (!(width & 3)) {
|
||||
asm(YUV411P_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "a" (src[1]), "d" (src[2]), "D" (dest[0]),
|
||||
"c" ((width/4)*height));
|
||||
} else {
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
asm(YUV411P_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width), "a" (src[1]+y*(width/4)),
|
||||
"d" (src[2]+y*(width/4)), "D" (dest[0]+y*width*2),
|
||||
"c" (width/4));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
if (!(width & 1)) {
|
||||
asm(YUV42XP_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "a" (src[1]), "d" (src[2]), "D" (dest[0]),
|
||||
"c" ((width/2)*height));
|
||||
} else {
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
asm(YUV42XP_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width), "a" (src[1]+y*(width/2)),
|
||||
"d" (src[2]+y*(width/2)), "D" (dest[0]+y*width*2),
|
||||
"c" (width/2));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
if (!(width & 1)) {
|
||||
asm(YUV444P_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "a" (src[1]), "d" (src[2]), "D" (dest[0]),
|
||||
"c" ((width/2)*height));
|
||||
} else {
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
asm(YUV444P_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width), "a" (src[1]+y*(width/2)),
|
||||
"d" (src[2]+y*(width/2)), "D" (dest[0]+y*width*2),
|
||||
"c" (width/2));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuy2_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
asm(YUY2_YUV420P_U
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width*2), "a" (src[0]+(y+1)*width*2),
|
||||
"D" (dest[0]+y*width), "d" (dest[1]+(y/2)*(width/2)),
|
||||
"c" (width/2));
|
||||
asm(YUY2_YUV420P_V
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+(y+1)*width*2), "a" (src[0]+y*width*2),
|
||||
"D" (dest[0]+(y+1)*width), "d" (dest[2]+(y/2)*(width/2)),
|
||||
"c" (width/2));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
if (!(width & 3)) {
|
||||
asm(YUY2_YUV411P
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "a" (dest[1]), "d" (dest[2]),
|
||||
"c" ((width/4)*height));
|
||||
} else {
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
asm(YUY2_YUV411P
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width*2), "D" (dest[0]+y*width),
|
||||
"a" (dest[1]+y*(width/4)), "d" (dest[2]+y*(width/4)),
|
||||
"c" (width/4));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_yuv422p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
if (!(width & 1)) {
|
||||
asm(YUY2_YUV422P
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "a" (dest[1]), "d" (dest[2]),
|
||||
"c" ((width/2)*height));
|
||||
} else {
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
asm(YUY2_YUV422P
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width*2), "D" (dest[0]+y*width),
|
||||
"a" (dest[1]+y*(width/2)), "d" (dest[2]+y*(width/2)),
|
||||
"c" (width/2));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
if (!(width & 1)) {
|
||||
asm(YUY2_YUV444P
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "a" (dest[1]), "d" (dest[2]),
|
||||
"c" ((width/2)*height));
|
||||
} else {
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
asm(YUY2_YUV444P
|
||||
: /* no outputs */
|
||||
: "S" (src[0]+y*width*2), "D" (dest[0]+y*width),
|
||||
"a" (dest[1]+y*width), "d" (dest[2]+y*width),
|
||||
"c" (width/2));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int y8_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
asm(Y8_YUY2
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (width*height)
|
||||
: "eax");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_uyvy_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
asm(Y8_UYVY
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (width*height)
|
||||
: "eax");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuy2_y8_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
asm(YUY2_Y8
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (width*height)
|
||||
: "eax");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uyvy_y8_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
asm(UYVY_Y8
|
||||
: /* no outputs */
|
||||
: "S" (src[0]), "D" (dest[0]), "c" (width*height)
|
||||
: "eax");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* HAVE_ASM_SSE2 */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization */
|
||||
|
||||
int ac_imgconvert_init_yuv_mixed(int accel)
|
||||
{
|
||||
if (!register_conversion(IMG_YUV420P, IMG_YUY2, yuv420p_yuy2)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUY2, yuv411p_yuy2)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUY2, yuv422p_yuy2)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUY2, yuv444p_yuy2)
|
||||
|| !register_conversion(IMG_Y8, IMG_YUY2, y8_yuy2)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_UYVY, yuv420p_uyvy)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_UYVY, yuv411p_uyvy)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_UYVY, yuv422p_uyvy)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_UYVY, yuv444p_uyvy)
|
||||
|| !register_conversion(IMG_Y8, IMG_UYVY, y8_uyvy)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_YVYU, yuv420p_yvyu)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YVYU, yuv411p_yvyu)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YVYU, yuv422p_yvyu)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YVYU, yuv444p_yvyu)
|
||||
|| !register_conversion(IMG_Y8, IMG_YVYU, y8_yuy2)
|
||||
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV420P, yuy2_yuv420p)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV411P, yuy2_yuv411p)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV422P, yuy2_yuv422p)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV444P, yuy2_yuv444p)
|
||||
|| !register_conversion(IMG_YUY2, IMG_Y8, yuy2_y8)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUV420P, uyvy_yuv420p)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUV411P, uyvy_yuv411p)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUV422P, uyvy_yuv422p)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUV444P, uyvy_yuv444p)
|
||||
|| !register_conversion(IMG_UYVY, IMG_Y8, uyvy_y8)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUV420P, yvyu_yuv420p)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUV411P, yvyu_yuv411p)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUV422P, yvyu_yuv422p)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUV444P, yvyu_yuv444p)
|
||||
|| !register_conversion(IMG_YVYU, IMG_Y8, yuy2_y8)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
if (accel & AC_SSE2) {
|
||||
if (!register_conversion(IMG_YUV420P, IMG_YUY2, yuv420p_yuy2_sse2)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUY2, yuv411p_yuy2_sse2)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUY2, yuv422p_yuy2_sse2)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUY2, yuv444p_yuy2_sse2)
|
||||
|| !register_conversion(IMG_Y8, IMG_YUY2, y8_yuy2_sse2)
|
||||
|| !register_conversion(IMG_Y8, IMG_UYVY, y8_uyvy_sse2)
|
||||
|| !register_conversion(IMG_Y8, IMG_YVYU, y8_yuy2_sse2)
|
||||
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV420P, yuy2_yuv420p_sse2)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV411P, yuy2_yuv411p_sse2)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV422P, yuy2_yuv422p_sse2)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YUV444P, yuy2_yuv444p_sse2)
|
||||
|| !register_conversion(IMG_YUY2, IMG_Y8, yuy2_y8_sse2)
|
||||
|| !register_conversion(IMG_UYVY, IMG_Y8, uyvy_y8_sse2)
|
||||
|| !register_conversion(IMG_YVYU, IMG_Y8, yuy2_y8_sse2)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
290
veejay-1.3/veejay-server/aclib/img_yuv_packed.c
Normal file
290
veejay-1.3/veejay-server/aclib/img_yuv_packed.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* img_yuv_packed.c - YUV packed image format conversion routines
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "imgconvert.h"
|
||||
#include "img_internal.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Standard C implementations */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Identity transformation, works when src==dest */
|
||||
static int yuv16_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height*2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Used for YUY2->UYVY and UYVY->YUY2, works when src==dest */
|
||||
static int yuv16_swap16(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
uint16_t *srcp = (uint16_t *)src[0];
|
||||
uint16_t *destp = (uint16_t *)dest[0];
|
||||
int i;
|
||||
for (i = 0; i < width*height; i++)
|
||||
destp[i] = srcp[i]>>8 | srcp[i]<<8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Used for YUY2->YVYU and YVYU->YUY2, works when src==dest */
|
||||
static int yuv16_swapuv(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height/2; i++) {
|
||||
uint8_t tmp = src[0][i*4+1];
|
||||
dest[0][i*4 ] = src[0][i*4 ];
|
||||
dest[0][i*4+1] = src[0][i*4+3];
|
||||
dest[0][i*4+2] = src[0][i*4+2];
|
||||
dest[0][i*4+3] = tmp;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int uyvy_yvyu(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height/2; i++) {
|
||||
dest[0][i*4 ] = src[0][i*4+1];
|
||||
dest[0][i*4+1] = src[0][i*4+2];
|
||||
dest[0][i*4+2] = src[0][i*4+3];
|
||||
dest[0][i*4+3] = src[0][i*4 ];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yvyu_uyvy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width*height/2; i++) {
|
||||
dest[0][i*4 ] = src[0][i*4+3];
|
||||
dest[0][i*4+1] = src[0][i*4 ];
|
||||
dest[0][i*4+2] = src[0][i*4+1];
|
||||
dest[0][i*4+3] = src[0][i*4+2];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||||
|
||||
/* Common macros/data for x86 code */
|
||||
#define DEFINE_MASK_DATA
|
||||
#include "img_x86_common.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Basic assembly routines */
|
||||
|
||||
static int yuv16_swap16_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_SWAP16_2_X86(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv16_swapuv_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_SWAP32_13_X86(width*height/2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uyvy_yvyu_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_ROR32_X86(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yvyu_uyvy_x86(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_ROL32_X86(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* MMX routines */
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */
|
||||
|
||||
static int yuv16_swap16_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_SWAP16_2_MMX(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv16_swapuv_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_SWAP32_13_MMX(width*height/2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uyvy_yvyu_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_ROR32_MMX(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yvyu_uyvy_mmx(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_ROL32_MMX(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_MMX && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* SSE2 routines */
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
|
||||
static int yuv16_swap16_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_SWAP16_2_SSE2(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv16_swapuv_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_SWAP32_13_SSE2(width*height/2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uyvy_yvyu_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_ROR32_SSE2(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yvyu_uyvy_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ASM_ROL32_SSE2(width*height/2);
|
||||
if (width*height % 1)
|
||||
((uint16_t *)(dest[0]))[width*height-1] =
|
||||
src[0][width*height*2-2]<<8 | src[0][width*height*2-1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_SSE2 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization */
|
||||
|
||||
int ac_imgconvert_init_yuv_packed(int accel)
|
||||
{
|
||||
if (!register_conversion(IMG_YUY2, IMG_YUY2, yuv16_copy)
|
||||
|| !register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv)
|
||||
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16)
|
||||
|| !register_conversion(IMG_UYVY, IMG_UYVY, yuv16_copy)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu)
|
||||
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv)
|
||||
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YVYU, yuv16_copy)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
||||
if (accel & (AC_IA32ASM | AC_AMD64ASM)) {
|
||||
if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_x86)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_x86)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_x86)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_x86)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_x86)
|
||||
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_x86)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86)
|
||||
if (accel & AC_MMX) {
|
||||
if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_mmx)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_mmx)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_mmx)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_mmx)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_mmx)
|
||||
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_mmx)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
if (accel & AC_SSE2) {
|
||||
if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_sse2)
|
||||
|| !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_sse2)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_sse2)
|
||||
|| !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_sse2)
|
||||
|| !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_sse2)
|
||||
|| !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_sse2)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
771
veejay-1.3/veejay-server/aclib/img_yuv_planar.c
Normal file
771
veejay-1.3/veejay-server/aclib/img_yuv_planar.c
Normal file
@@ -0,0 +1,771 @@
|
||||
/*
|
||||
* img_yuv_planar.c - YUV planar image format conversion routines
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "imgconvert.h"
|
||||
#include "img_internal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Standard C implementations */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Identity transformations */
|
||||
|
||||
static int yuv420p_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
ac_memcpy(dest[1], src[1], (width/2)*(height/2));
|
||||
ac_memcpy(dest[2], src[2], (width/2)*(height/2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
ac_memcpy(dest[1], src[1], (width/4)*height);
|
||||
ac_memcpy(dest[2], src[2], (width/4)*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
ac_memcpy(dest[1], src[1], (width/2)*height);
|
||||
ac_memcpy(dest[2], src[2], (width/2)*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
ac_memcpy(dest[1], src[1], width*height);
|
||||
ac_memcpy(dest[2], src[2], width*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_copy(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv420p_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
for (x = 0; x < (width/2 & ~1); x += 2) {
|
||||
dest[1][y*(width/4)+x/2] = (src[1][(y/2)*(width/2)+x]
|
||||
+ src[1][(y/2)*(width/2)+x+1] + 1) / 2;
|
||||
dest[2][y*(width/4)+x/2] = (src[2][(y/2)*(width/2)+x]
|
||||
+ src[2][(y/2)*(width/2)+x+1] + 1) / 2;
|
||||
}
|
||||
ac_memcpy(dest[1]+(y+1)*(width/4), dest[1]+y*(width/4), width/4);
|
||||
ac_memcpy(dest[2]+(y+1)*(width/4), dest[2]+y*(width/4), width/4);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv420p_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
ac_memcpy(dest[1]+(y )*(width/2), src[1]+(y/2)*(width/2), width/2);
|
||||
ac_memcpy(dest[1]+(y+1)*(width/2), src[1]+(y/2)*(width/2), width/2);
|
||||
ac_memcpy(dest[2]+(y )*(width/2), src[2]+(y/2)*(width/2), width/2);
|
||||
ac_memcpy(dest[2]+(y+1)*(width/2), src[2]+(y/2)*(width/2), width/2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv420p_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y += 2) {
|
||||
for (x = 0; x < width; x += 2) {
|
||||
dest[1][y*width+x ] =
|
||||
dest[1][y*width+x+1] = src[1][(y/2)*(width/2)+(x/2)];
|
||||
dest[2][y*width+x ] =
|
||||
dest[2][y*width+x+1] = src[2][(y/2)*(width/2)+(x/2)];
|
||||
}
|
||||
ac_memcpy(dest[1]+(y+1)*width, dest[1]+y*width, width);
|
||||
ac_memcpy(dest[2]+(y+1)*width, dest[2]+y*width, width);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv411p_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
for (x = 0; x < ((width/2) & ~1); x += 2) {
|
||||
dest[1][(y/2)*(width/2)+x] = (src[1][y*(width/4)+x/2]
|
||||
+ src[1][(y+1)*(width/4)+x/2] + 1) / 2;
|
||||
dest[2][(y/2)*(width/2)+x] = (src[2][y*(width/4)+x/2]
|
||||
+ src[2][(y+1)*(width/4)+x/2] + 1) / 2;
|
||||
dest[1][(y/2)*(width/2)+x+1] = dest[1][(y/2)*(width/2)+x];
|
||||
dest[2][(y/2)*(width/2)+x+1] = dest[2][(y/2)*(width/2)+x];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < ((width/2) & ~1); x += 2) {
|
||||
dest[1][y*(width/2)+x ] = src[1][y*(width/4)+x/2];
|
||||
dest[1][y*(width/2)+x+1] = src[1][y*(width/4)+x/2];
|
||||
dest[2][y*(width/2)+x ] = src[2][y*(width/4)+x/2];
|
||||
dest[2][y*(width/2)+x+1] = src[2][y*(width/4)+x/2];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < (width & ~3); x += 4) {
|
||||
dest[1][y*width+x ] = src[1][y*(width/4)+x/4];
|
||||
dest[1][y*width+x+1] = src[1][y*(width/4)+x/4];
|
||||
dest[1][y*width+x+2] = src[1][y*(width/4)+x/4];
|
||||
dest[1][y*width+x+3] = src[1][y*(width/4)+x/4];
|
||||
dest[2][y*width+x ] = src[2][y*(width/4)+x/4];
|
||||
dest[2][y*width+x+1] = src[2][y*(width/4)+x/4];
|
||||
dest[2][y*width+x+2] = src[2][y*(width/4)+x/4];
|
||||
dest[2][y*width+x+3] = src[2][y*(width/4)+x/4];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv422p_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
for (x = 0; x < width/2; x++) {
|
||||
dest[1][(y/2)*(width/2)+x] = (src[1][y*(width/2)+x]
|
||||
+ src[1][(y+1)*(width/2)+x] + 1) / 2;
|
||||
dest[2][(y/2)*(width/2)+x] = (src[2][y*(width/2)+x]
|
||||
+ src[2][(y+1)*(width/2)+x] + 1) / 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < ((width/2) & ~1); x += 2) {
|
||||
dest[1][y*(width/4)+x/2] = (src[1][y*(width/2)+x]
|
||||
+ src[1][y*(width/2)+x+1] + 1) / 2;
|
||||
dest[2][y*(width/4)+x/2] = (src[2][y*(width/2)+x]
|
||||
+ src[2][y*(width/2)+x+1] + 1) / 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < (width & ~1); x += 2) {
|
||||
dest[1][y*width+x ] = src[1][y*(width/2)+x/2];
|
||||
dest[1][y*width+x+1] = src[1][y*(width/2)+x/2];
|
||||
dest[2][y*width+x ] = src[2][y*(width/2)+x/2];
|
||||
dest[2][y*width+x+1] = src[2][y*(width/2)+x/2];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv444p_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
for (x = 0; x < (width & ~1); x += 2) {
|
||||
dest[1][(y/2)*(width/2)+x/2] = (src[1][y*width+x]
|
||||
+ src[1][y*width+x+1]
|
||||
+ src[1][(y+1)*width+x]
|
||||
+ src[1][(y+1)*width+x+1] + 2) / 4;
|
||||
dest[2][(y/2)*(width/2)+x/2] = (src[2][y*width+x]
|
||||
+ src[2][y*width+x+1]
|
||||
+ src[2][(y+1)*width+x]
|
||||
+ src[2][(y+1)*width+x+1] + 2) / 4;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < (width & ~3); x += 4) {
|
||||
dest[1][y*(width/4)+x/4] = (src[1][y*width+x]
|
||||
+ src[1][y*width+x+1]
|
||||
+ src[1][y*width+x+2]
|
||||
+ src[1][y*width+x+3] + 2) / 4;
|
||||
dest[2][y*(width/4)+x/4] = (src[2][y*width+x]
|
||||
+ src[2][y*width+x+1]
|
||||
+ src[2][y*width+x+2]
|
||||
+ src[2][y*width+x+3] + 2) / 4;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < (width & ~1); x += 2) {
|
||||
dest[1][y*(width/2)+x/2] = (src[1][y*width+x]
|
||||
+ src[1][y*width+x+1] + 1) / 2;
|
||||
dest[2][y*(width/2)+x/2] = (src[2][y*width+x]
|
||||
+ src[2][y*width+x+1] + 1) / 2;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* We treat Y8 as a planar format */
|
||||
|
||||
static int yuvp_y8(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_yuv420p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
memset(dest[1], 128, (width/2)*(height/2));
|
||||
memset(dest[2], 128, (width/2)*(height/2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_yuv411p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
memset(dest[1], 128, (width/4)*height);
|
||||
memset(dest[2], 128, (width/4)*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_yuv422p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
memset(dest[1], 128, (width/2)*height);
|
||||
memset(dest[2], 128, (width/2)*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int y8_yuv444p(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
memset(dest[1], 128, width*height);
|
||||
memset(dest[2], 128, width*height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
|
||||
/* SSE2 routines. See comments in img_x86_common.h for why we don't bother
|
||||
* unrolling the loops. */
|
||||
|
||||
/* Common macros/data for x86 code */
|
||||
#include "img_x86_common.h"
|
||||
|
||||
/* Average 2 bytes horizontally (e.g. 422P->411P) (unit: 2 source bytes) */
|
||||
#define AVG_2H(src,dest,count) \
|
||||
asm("pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" /* XMM7: 0x00FF*8 */ \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movzbl -2("ESI","ECX",2), %%eax \n\
|
||||
movzbl -1("ESI","ECX",2), %%edx \n\
|
||||
addl %%edx, %%eax \n\
|
||||
shrl $1, %%eax \n\
|
||||
movb %%al, -1("EDI","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",2),%%xmm0 #XMM0:FEDCBA9876543210 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: FEDCBA9876543210 \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: E C A 8 6 4 2 0 \n\
|
||||
psrlw $8, %%xmm1 # XMM1: F D B 9 7 5 3 1 \n\
|
||||
pavgw %%xmm1, %%xmm0 # XMM0: w v u t s r q p (avgs) \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: wvutsrqpwvutsrqp \n\
|
||||
movq %%xmm0, -8("EDI","ECX")", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src), "D" (dest), "c" (count) \
|
||||
: "eax", "edx")
|
||||
|
||||
/* Average 4 bytes horizontally (e.g. 444P->411P) (unit: 4 source bytes) */
|
||||
#define AVG_4H(src,dest,count) \
|
||||
asm("pcmpeqd %%xmm7, %%xmm7; psrld $24, %%xmm7;" /* XMM7: 0x000000FF*4 */ \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movzbl -4("ESI","ECX",4), %%eax \n\
|
||||
movzbl -3("ESI","ECX",4), %%edx \n\
|
||||
addl %%edx, %%eax \n\
|
||||
movzbl -2("ESI","ECX",4), %%edx \n\
|
||||
addl %%edx, %%eax \n\
|
||||
movzbl -1("ESI","ECX",4), %%edx \n\
|
||||
addl %%edx, %%eax \n\
|
||||
shrl $2, %%eax \n\
|
||||
movb %%al, -1("EDI","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",4),%%xmm0 #XMM0:FEDCBA9876543210 \n\
|
||||
movdqa %%xmm0, %%xmm1 # XMM1: FEDCBA9876543210 \n\
|
||||
movdqa %%xmm0, %%xmm2 # XMM2: FEDCBA9876543210 \n\
|
||||
movdqa %%xmm0, %%xmm3 # XMM3: FEDCBA9876543210 \n\
|
||||
pand %%xmm7, %%xmm0 # XMM0: C 8 4 0 \n\
|
||||
psrld $8, %%xmm1 # XMM1: FED BA9 765 321 \n\
|
||||
pand %%xmm7, %%xmm1 # XMM1: D 9 5 1 \n\
|
||||
psrld $16, %%xmm2 # XMM2: FE BA 76 32 \n\
|
||||
pand %%xmm7, %%xmm2 # XMM2: E A 6 2 \n\
|
||||
psrld $24, %%xmm3 # XMM3: F B 7 3 \n\
|
||||
pavgw %%xmm1, %%xmm0 # XMM0: C+D 8+9 4+5 0+1 (avgs) \n\
|
||||
pavgw %%xmm3, %%xmm2 # XMM2: E+F A+B 6+7 2+3 (avgs) \n\
|
||||
pavgw %%xmm2, %%xmm0 # XMM0: s r q p (avgs) \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: s r q p s r q p \n\
|
||||
packuswb %%xmm0, %%xmm0 # XMM0: srqpsrqpsrqpsrqp \n\
|
||||
movd %%xmm0, -4("EDI","ECX")", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src), "D" (dest), "c" (count) \
|
||||
: "eax", "edx")
|
||||
|
||||
/* Repeat 2 bytes horizontally (e.g. 422P->444P) (unit: 1 source byte) */
|
||||
#define REP_2H(src,dest,count) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movb -1("ESI","ECX"), %%al \n\
|
||||
movb %%al, %%ah \n\
|
||||
movw %%ax, -2("EDI","ECX",2)", \
|
||||
/* main_loop */ \
|
||||
"movq -8("ESI","ECX"), %%xmm0 # XMM0: 76543210 \n\
|
||||
punpcklbw %%xmm0, %%xmm0 # XMM0: 7766554433221100 \n\
|
||||
movdqu %%xmm0, -16("EDI","ECX",2)", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src), "D" (dest), "c" (count) \
|
||||
: "eax")
|
||||
|
||||
/* Repeat 4 bytes horizontally (e.g. 411P->444P) (unit: 1 source byte) */
|
||||
#define REP_4H(src,dest,count) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 4, \
|
||||
/* push_regs */ "", \
|
||||
/* pop_regs */ "", \
|
||||
/* small_loop */ \
|
||||
"movzbl -1("ESI","ECX"), %%eax \n\
|
||||
movb %%al, %%ah \n\
|
||||
movl %%eax, %%edx \n\
|
||||
shll $16, %%eax \n\
|
||||
orl %%edx, %%eax \n\
|
||||
movl %%eax, -4("EDI","ECX",4)", \
|
||||
/* main_loop */ \
|
||||
"movd -4("ESI","ECX"), %%xmm0 # XMM0: 3210 \n\
|
||||
punpcklbw %%xmm0, %%xmm0 # XMM0: 33221100 \n\
|
||||
punpcklwd %%xmm0, %%xmm0 # XMM0: 3333222211110000 \n\
|
||||
movdqu %%xmm0, -16("EDI","ECX",4)", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src), "D" (dest), "c" (count) \
|
||||
: "eax", "edx")
|
||||
|
||||
/* Average 2 bytes vertically and double horizontally (411P->420P)
|
||||
* (unit: 1 source byte) */
|
||||
#define AVG_411_420(src1,src2,dest,count) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movzbl -1("ESI","ECX"), %%eax \n\
|
||||
movzbl -1("EDX","ECX"), %%ebx \n\
|
||||
addl %%ebx, %%eax \n\
|
||||
shrl $1, %%eax \n\
|
||||
movb %%al, %%ah \n\
|
||||
movw %%ax, -2("EDI","ECX",2)", \
|
||||
/* main_loop */ \
|
||||
"movq -8("ESI","ECX"), %%xmm0 \n\
|
||||
movq -8("EDX","ECX"), %%xmm1 \n\
|
||||
pavgb %%xmm1, %%xmm0 \n\
|
||||
punpcklbw %%xmm0, %%xmm0 \n\
|
||||
movdqu %%xmm0, -16("EDI","ECX",2)", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src1), "d" (src2), "D" (dest), "c" (count) \
|
||||
: "eax")
|
||||
|
||||
/* Average 2 bytes vertically (422P->420P) (unit: 1 source byte) */
|
||||
#define AVG_422_420(src1,src2,dest,count) \
|
||||
asm(SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 16, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movzbl -1("ESI","ECX"), %%eax \n\
|
||||
movzbl -1("EDX","ECX"), %%ebx \n\
|
||||
addl %%ebx, %%eax \n\
|
||||
shrl $1, %%eax \n\
|
||||
movb %%al, -1("EDI","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX"), %%xmm0 \n\
|
||||
movdqu -16("EDX","ECX"), %%xmm1 \n\
|
||||
pavgb %%xmm1, %%xmm0 \n\
|
||||
movdqu %%xmm0, -16("EDI","ECX")", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src1), "d" (src2), "D" (dest), "c" (count) \
|
||||
: "eax")
|
||||
|
||||
/* Average 4 bytes, 2 horizontally and 2 vertically (444P->420P)
|
||||
* (unit: 2 source bytes) */
|
||||
#define AVG_444_420(src1,src2,dest,count) \
|
||||
asm("pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" /* XMM7: 0x00FF*8 */ \
|
||||
SIMD_LOOP_WRAPPER( \
|
||||
/* blocksize */ 8, \
|
||||
/* push_regs */ "push "EBX, \
|
||||
/* pop_regs */ "pop "EBX, \
|
||||
/* small_loop */ \
|
||||
"movzbl -2("ESI","ECX",2), %%eax \n\
|
||||
movzbl -1("ESI","ECX",2), %%ebx \n\
|
||||
addl %%ebx, %%eax \n\
|
||||
movzbl -2("EDX","ECX",2), %%ebx \n\
|
||||
addl %%ebx, %%eax \n\
|
||||
movzbl -1("EDX","ECX",2), %%ebx \n\
|
||||
addl %%ebx, %%eax \n\
|
||||
shrl $2, %%eax \n\
|
||||
movb %%al, -1("EDI","ECX")", \
|
||||
/* main_loop */ \
|
||||
"movdqu -16("ESI","ECX",2), %%xmm0 \n\
|
||||
movdqu -16("EDX","ECX",2), %%xmm2 \n\
|
||||
movdqa %%xmm0, %%xmm1 \n\
|
||||
pand %%xmm7, %%xmm0 \n\
|
||||
psrlw $8, %%xmm1 \n\
|
||||
pavgw %%xmm1, %%xmm0 \n\
|
||||
movdqa %%xmm2, %%xmm3 \n\
|
||||
pand %%xmm7, %%xmm2 \n\
|
||||
psrlw $8, %%xmm3 \n\
|
||||
pavgw %%xmm3, %%xmm2 \n\
|
||||
pavgw %%xmm2, %%xmm0 \n\
|
||||
packuswb %%xmm0, %%xmm0 \n\
|
||||
movq %%xmm0, -8("EDI","ECX")", \
|
||||
/* emms */ "emms") \
|
||||
: /* no outputs */ \
|
||||
: "S" (src1), "d" (src2), "D" (dest), "c" (count))
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv420p_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
AVG_2H(src[1]+(y/2)*(width/2), dest[1]+y*(width/4), width/4);
|
||||
ac_memcpy(dest[1]+(y+1)*(width/4), dest[1]+y*(width/4), width/4);
|
||||
AVG_2H(src[2]+(y/2)*(width/2), dest[2]+y*(width/4), width/4);
|
||||
ac_memcpy(dest[2]+(y+1)*(width/4), dest[2]+y*(width/4), width/4);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv420p_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < height; y += 2) {
|
||||
REP_2H(src[1]+(y/2)*(width/2), dest[1]+y*width, width/2);
|
||||
ac_memcpy(dest[1]+(y+1)*width, dest[1]+y*width, width);
|
||||
REP_2H(src[2]+(y/2)*(width/2), dest[2]+y*width, width/2);
|
||||
ac_memcpy(dest[2]+(y+1)*width, dest[2]+y*width, width);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv411p_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
AVG_411_420(src[1]+y*(width/4), src[1]+(y+1)*(width/4),
|
||||
dest[1]+(y/2)*(width/2), width/4);
|
||||
AVG_411_420(src[2]+y*(width/4), src[2]+(y+1)*(width/4),
|
||||
dest[2]+(y/2)*(width/2), width/4);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_yuv422p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
if (!(width & 3)) {
|
||||
/* Fast version, no bytes at end of row to skip */
|
||||
REP_2H(src[1], dest[1], (width/4)*height);
|
||||
REP_2H(src[2], dest[2], (width/4)*height);
|
||||
} else {
|
||||
/* Slow version, loop through each row */
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
REP_2H(src[1]+y*(width/4), dest[1]+y*(width/2), width/4);
|
||||
REP_2H(src[2]+y*(width/4), dest[2]+y*(width/2), width/4);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv411p_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
if (!(width & 3)) {
|
||||
/* Fast version, no bytes at end of row to skip */
|
||||
REP_4H(src[1], dest[1], (width/4)*height);
|
||||
REP_4H(src[2], dest[2], (width/4)*height);
|
||||
} else {
|
||||
/* Slow version, loop through each row */
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
REP_4H(src[1]+y*(width/4), dest[1]+y*width, width/4);
|
||||
REP_4H(src[2]+y*(width/4), dest[2]+y*width, width/4);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv422p_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
AVG_422_420(src[1]+y*(width/2), src[1]+(y+1)*(width/2),
|
||||
dest[1]+(y/2)*(width/2), width/2);
|
||||
AVG_422_420(src[2]+y*(width/2), src[2]+(y+1)*(width/2),
|
||||
dest[2]+(y/2)*(width/2), width/2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
if (!(width & 3)) {
|
||||
/* Fast version, no bytes at end of row to skip */
|
||||
AVG_2H(src[1], dest[1], (width/4)*height);
|
||||
AVG_2H(src[2], dest[2], (width/4)*height);
|
||||
} else {
|
||||
/* Slow version, loop through each row */
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
AVG_2H(src[1]+y*(width/2), dest[1]+y*(width/4), width/4);
|
||||
AVG_2H(src[2]+y*(width/2), dest[2]+y*(width/4), width/4);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv422p_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
if (!(width & 1)) {
|
||||
/* Fast version, no bytes at end of row to skip */
|
||||
REP_2H(src[1], dest[1], (width/2)*height);
|
||||
REP_2H(src[2], dest[2], (width/2)*height);
|
||||
} else {
|
||||
/* Slow version, loop through each row */
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
REP_2H(src[1]+y*(width/2), dest[1]+y*width, width/2);
|
||||
REP_2H(src[2]+y*(width/2), dest[2]+y*width, width/2);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static int yuv444p_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
int y;
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
for (y = 0; y < (height & ~1); y += 2) {
|
||||
AVG_444_420(src[1]+y*width, src[1]+(y+1)*width,
|
||||
dest[1]+(y/2)*(width/2), width/2);
|
||||
AVG_444_420(src[2]+y*width, src[2]+(y+1)*width,
|
||||
dest[2]+(y/2)*(width/2), width/2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
if (!(width & 3)) {
|
||||
/* Fast version, no bytes at end of row to skip */
|
||||
AVG_4H(src[1], dest[1], (width/4)*height);
|
||||
AVG_4H(src[2], dest[2], (width/4)*height);
|
||||
} else {
|
||||
/* Slow version, loop through each row */
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
AVG_4H(src[1]+y*width, dest[1]+y*(width/4), width/4);
|
||||
AVG_4H(src[2]+y*width, dest[2]+y*(width/4), width/4);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int yuv444p_yuv422p_sse2(uint8_t **src, uint8_t **dest, int width, int height)
|
||||
{
|
||||
ac_memcpy(dest[0], src[0], width*height);
|
||||
if (!(width & 1)) {
|
||||
/* Fast version, no bytes at end of row to skip */
|
||||
AVG_2H(src[1], dest[1], (width/2)*height);
|
||||
AVG_2H(src[2], dest[2], (width/2)*height);
|
||||
} else {
|
||||
/* Slow version, loop through each row */
|
||||
int y;
|
||||
for (y = 0; y < height; y++) {
|
||||
AVG_2H(src[1]+y*width, dest[1]+y*(width/2), width/2);
|
||||
AVG_2H(src[2]+y*width, dest[2]+y*(width/2), width/2);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* HAVE_ASM_SSE2 */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization */
|
||||
|
||||
int ac_imgconvert_init_yuv_planar(int accel)
|
||||
{
|
||||
if (!register_conversion(IMG_YUV420P, IMG_YUV420P, yuv420p_copy)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_YUV411P, yuv420p_yuv411p)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_YUV422P, yuv420p_yuv422p)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_YUV444P, yuv420p_yuv444p)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_Y8, yuvp_y8)
|
||||
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV420P, yuv411p_yuv420p)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV411P, yuv411p_copy)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV422P, yuv411p_yuv422p)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV444P, yuv411p_yuv444p)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_Y8, yuvp_y8)
|
||||
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV420P, yuv422p_yuv420p)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV411P, yuv422p_yuv411p)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV422P, yuv422p_copy)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV444P, yuv422p_yuv444p)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_Y8, yuvp_y8)
|
||||
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV420P, yuv444p_yuv420p)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV411P, yuv444p_yuv411p)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV422P, yuv444p_yuv422p)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV444P, yuv444p_copy)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_Y8, yuvp_y8)
|
||||
|
||||
|| !register_conversion(IMG_Y8, IMG_YUV420P, y8_yuv420p)
|
||||
|| !register_conversion(IMG_Y8, IMG_YUV411P, y8_yuv411p)
|
||||
|| !register_conversion(IMG_Y8, IMG_YUV422P, y8_yuv422p)
|
||||
|| !register_conversion(IMG_Y8, IMG_YUV444P, y8_yuv444p)
|
||||
|| !register_conversion(IMG_Y8, IMG_Y8, y8_copy)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
if (accel & AC_SSE2) {
|
||||
if (!register_conversion(IMG_YUV420P, IMG_YUV411P, yuv420p_yuv411p_sse2)
|
||||
|| !register_conversion(IMG_YUV420P, IMG_YUV444P, yuv420p_yuv444p_sse2)
|
||||
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV420P, yuv411p_yuv420p_sse2)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV422P, yuv411p_yuv422p_sse2)
|
||||
|| !register_conversion(IMG_YUV411P, IMG_YUV444P, yuv411p_yuv444p_sse2)
|
||||
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV420P, yuv422p_yuv420p_sse2)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV411P, yuv422p_yuv411p_sse2)
|
||||
|| !register_conversion(IMG_YUV422P, IMG_YUV444P, yuv422p_yuv444p_sse2)
|
||||
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV420P, yuv444p_yuv420p_sse2)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV411P, yuv444p_yuv411p_sse2)
|
||||
|| !register_conversion(IMG_YUV444P, IMG_YUV422P, yuv444p_yuv422p_sse2)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* ARCH_X86 || ARCH_X86_64 */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
2398
veejay-1.3/veejay-server/aclib/img_yuv_rgb.c
Normal file
2398
veejay-1.3/veejay-server/aclib/img_yuv_rgb.c
Normal file
File diff suppressed because it is too large
Load Diff
119
veejay-1.3/veejay-server/aclib/imgconvert.c
Normal file
119
veejay-1.3/veejay-server/aclib/imgconvert.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* imgconvert.c - image format conversion routines
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "imgconvert.h"
|
||||
#include "img_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static struct {
|
||||
ImageFormat srcfmt, destfmt;
|
||||
ConversionFunc func;
|
||||
} *conversions;
|
||||
static int n_conversions = 0;
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Image conversion routine. src and dest are arrays of pointers to planes
|
||||
* (for packed formats with only one plane, just use `&data'); srcfmt and
|
||||
* destfmt specify the source and destination image formats (IMG_*).
|
||||
* width and height are in pixels. Returns 1 on success, 0 on failure. */
|
||||
|
||||
int ac_imgconvert(uint8_t **src, ImageFormat srcfmt,
|
||||
uint8_t **dest, ImageFormat destfmt,
|
||||
int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Hack to handle YV12 easily, because conversion routines don't get
|
||||
* format tags */
|
||||
uint8_t *newsrc[3], *newdest[3];
|
||||
if (srcfmt == IMG_YV12) {
|
||||
srcfmt = IMG_YUV420P;
|
||||
newsrc[0] = src[0];
|
||||
newsrc[1] = src[2];
|
||||
newsrc[2] = src[1];
|
||||
src = newsrc;
|
||||
}
|
||||
if (destfmt == IMG_YV12) {
|
||||
destfmt = IMG_YUV420P;
|
||||
newdest[0] = dest[0];
|
||||
newdest[1] = dest[2];
|
||||
newdest[2] = dest[1];
|
||||
dest = newdest;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_conversions; i++) {
|
||||
if (conversions[i].srcfmt==srcfmt && conversions[i].destfmt==destfmt)
|
||||
return (*conversions[i].func)(src, dest, width, height);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Internal use only! */
|
||||
|
||||
int ac_imgconvert_init(int accel)
|
||||
{
|
||||
if (!ac_imgconvert_init_yuv_planar(accel)
|
||||
|| !ac_imgconvert_init_yuv_packed(accel)
|
||||
|| !ac_imgconvert_init_yuv_mixed(accel)
|
||||
|| !ac_imgconvert_init_yuv_rgb(accel)
|
||||
|| !ac_imgconvert_init_rgb_packed(accel)
|
||||
) {
|
||||
fprintf(stderr, "ac_imgconvert_init() failed");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int register_conversion(ImageFormat srcfmt, ImageFormat destfmt,
|
||||
ConversionFunc function)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_conversions; i++) {
|
||||
if (conversions[i].srcfmt==srcfmt && conversions[i].destfmt==destfmt) {
|
||||
conversions[i].func = function;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(conversions = realloc(conversions,
|
||||
(n_conversions+1) * sizeof(*conversions)))) {
|
||||
fprintf(stderr, "register_conversion(): out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
conversions[n_conversions].srcfmt = srcfmt;
|
||||
conversions[n_conversions].destfmt = destfmt;
|
||||
conversions[n_conversions].func = function;
|
||||
n_conversions++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
105
veejay-1.3/veejay-server/aclib/imgconvert.h
Normal file
105
veejay-1.3/veejay-server/aclib/imgconvert.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* imgconvert.h - defines for image format conversion routines
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#ifndef ACLIB_IMGCONVERT_H
|
||||
#define ACLIB_IMGCONVERT_H
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Image format defines */
|
||||
typedef enum {
|
||||
IMG_UNKNOWN = 0, /* Unknown/unset (dummy value, guaranteed to be 0) */
|
||||
/* YUV formats */
|
||||
IMG_YUV_BASE = 0x1000,
|
||||
IMG_YUV420P, /* YUV planar, 1 U/V per 2x2 Y pixels */
|
||||
IMG_YV12, /* YUV420P with U and V reversed */
|
||||
IMG_YUV411P, /* YUV planar, 1 U/V per 4x1 Y pixels */
|
||||
IMG_YUV422P, /* YUV planar, 1 U/V per 2x1 Y pixels */
|
||||
IMG_YUV444P, /* YUV planar, 1 U/V per 1x1 Y pixels */
|
||||
IMG_YUY2, /* YUV packed, 1 U/V per 2x1 Y pixels, Y:U:Y:V */
|
||||
IMG_UYVY, /* YUV packed, 1 U/V per 2x1 Y pixels, U:Y:V:Y */
|
||||
IMG_YVYU, /* YUV packed, 1 U/V per 2x1 Y pixels, Y:V:Y:U */
|
||||
IMG_Y8, /* Y-only 8-bit data */
|
||||
IMG_YUV_LAST,
|
||||
/* RGB formats */
|
||||
IMG_RGB_BASE = 0x2000,
|
||||
IMG_RGB24, /* RGB packed, 8 bits per component, R:G:B */
|
||||
IMG_BGR24, /* RGB packed, 8 bits per component, B:G:R */
|
||||
IMG_RGBA32, /* RGB+alpha packed, 8 bits per component, R:G:B:A */
|
||||
IMG_ABGR32, /* RGB+alpha packed, 8 bits per component, A:B:G:R */
|
||||
IMG_ARGB32, /* RGB+alpha packed, 8 bits per component, A:R:G:B */
|
||||
IMG_BGRA32, /* RGB+alpha packed, 8 bits per component, B:G:R:A */
|
||||
IMG_GRAY8, /* Grayscale 8-bit data */
|
||||
IMG_RGB_LAST,
|
||||
} ImageFormat;
|
||||
|
||||
/* Alias */
|
||||
#define IMG_NONE IMG_UNKNOWN
|
||||
|
||||
/* Default YUV and RGB formats */
|
||||
#define IMG_YUV_DEFAULT IMG_YUV420P
|
||||
#define IMG_RGB_DEFAULT IMG_RGB24
|
||||
|
||||
/* Is the given image format a YUV/RGB one? */
|
||||
#define IS_YUV_FORMAT(fmt) ((fmt) > IMG_YUV_BASE && (fmt) < IMG_YUV_LAST)
|
||||
#define IS_RGB_FORMAT(fmt) ((fmt) > IMG_RGB_BASE && (fmt) < IMG_RGB_LAST)
|
||||
|
||||
/* U/V plane size for YUV planar formats (Y plane size is always w*h) */
|
||||
#define UV_PLANE_SIZE(fmt,w,h) \
|
||||
((fmt)==IMG_YUV420P ? ((w)/2)*((h)/2) : \
|
||||
(fmt)==IMG_YV12 ? ((w)/2)*((h)/2) : \
|
||||
(fmt)==IMG_YUV411P ? ((w)/4)* (h) : \
|
||||
(fmt)==IMG_YUV422P ? ((w)/2)* (h) : \
|
||||
(fmt)==IMG_YUV444P ? (w) * (h) : 0)
|
||||
|
||||
/* Macro to initialize an array of planes from a buffer */
|
||||
#define YUV_INIT_PLANES(planes,buffer,fmt,w,h) \
|
||||
((planes)[0] = (buffer), \
|
||||
(planes)[1] = (planes)[0] + (w)*(h), \
|
||||
(planes)[2] = (planes)[1] + UV_PLANE_SIZE((fmt),(w),(h)))
|
||||
|
||||
#if 0
|
||||
/* Structure describing an image. FIXME: not currently used--this should
|
||||
* eventually replace the (planes,format) pairs passed to ac_imgconvert. */
|
||||
typedef struct {
|
||||
ImageFormat format; /* Format of image data */
|
||||
int width, height; /* Size of image */
|
||||
uint8_t *planes[4]; /* Data planes (use planes[0] for packed data) */
|
||||
int stride[4]; /* Length of one row in each plane, incl. padding */
|
||||
} Image;
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization routine. Returns 1 on success, 0 on failure. */
|
||||
extern int ac_imgconvert_init(int accel);
|
||||
|
||||
/* Conversion routine. Returns 1 on success, 0 on failure. */
|
||||
extern int ac_imgconvert(uint8_t **src, /* Array of source planes */
|
||||
ImageFormat srcfmt, /* Source image format */
|
||||
uint8_t **dest, /* Array of dest planes */
|
||||
ImageFormat destfmt, /* Destination image format */
|
||||
int width, /* Image width in pixels */
|
||||
int height /* Image height in pixels */
|
||||
);
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#endif /* ACLIB_IMGCONVERT_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
507
veejay-1.3/veejay-server/aclib/memcpy.c
Normal file
507
veejay-1.3/veejay-server/aclib/memcpy.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* memcpy.c - optimized memcpy() routines for aclib
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "ac_internal.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Use memmove because memcpy isn't guaranteed to be ascending */
|
||||
static void *(*memcpy_ptr)(void *, const void *, size_t) = memmove;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* External interface */
|
||||
|
||||
void *ac_memcpy(void *dest, const void *src, size_t size)
|
||||
{
|
||||
return (*memcpy_ptr)(dest, src, size);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Note the check for ARCH_X86 here: this is to prevent compilation of this
|
||||
* code on x86_64, since all x86_64 processors support SSE2, and because
|
||||
* this code is not set up to use the 64-bit registers for addressing on
|
||||
* x86_64. */
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86)
|
||||
|
||||
/* MMX-optimized routine, intended for PMMX/PII processors.
|
||||
* Nonstandard instructions used:
|
||||
* (CPUID.MMX) MOVQ
|
||||
*/
|
||||
|
||||
static void *memcpy_mmx(void *dest, const void *src, size_t bytes)
|
||||
{
|
||||
asm("\
|
||||
PENTIUM_LINE_SIZE = 32 # PMMX/PII cache line size \n\
|
||||
PENTIUM_CACHE_SIZE = 8192 # PMMX/PII total cache size \n\
|
||||
# Use only half because writes may touch the cache too (PII) \n\
|
||||
PENTIUM_CACHE_BLOCK = (PENTIUM_CACHE_SIZE/2 - PENTIUM_LINE_SIZE) \n\
|
||||
\n\
|
||||
push %%ebx # Save PIC register \n\
|
||||
push %%edi # Save destination for return value \n\
|
||||
cld # MOVS* should ascend \n\
|
||||
\n\
|
||||
mov $64, %%ebx # Constant \n\
|
||||
\n\
|
||||
cmp %%ebx, %%ecx \n\
|
||||
jb mmx.memcpy_last # Just use movs if <64 bytes \n\
|
||||
\n\
|
||||
# First align destination address to a multiple of 8 bytes \n\
|
||||
mov $8, %%eax # EAX <- (8-dest) & 7 \n\
|
||||
sub %%edi, %%eax \n\
|
||||
and $0b111, %%eax # ... which is the number of bytes to copy\n\
|
||||
lea 0f, %%edx # Use a computed jump--faster than a loop\n\
|
||||
sub %%eax, %%edx \n\
|
||||
jmp *%%edx # Execute 0-7 MOVSB's \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
0: sub %%eax, %%ecx # Update count \n\
|
||||
\n\
|
||||
# Now copy data in blocks \n\
|
||||
0: mov %%ecx, %%edx # EDX <- ECX >> 6 (cache lines to copy) \n\
|
||||
shr $6, %%edx \n\
|
||||
jz mmx.memcpy_last # <64 bytes left? Skip to end \n\
|
||||
cmp $PENTIUM_CACHE_BLOCK/64, %%edx \n\
|
||||
jb 1f # Limit size of block \n\
|
||||
mov $PENTIUM_CACHE_BLOCK/64, %%edx \n\
|
||||
1: mov %%edx, %%eax # EAX <- EDX << 6 (bytes to copy) \n\
|
||||
shl $6, %%eax \n\
|
||||
sub %%eax, %%ecx # Update remaining count \n\
|
||||
add %%eax, %%esi # Point to end of region to be block-copied\n\
|
||||
2: test %%eax, -32(%%esi) # Touch each cache line in reverse order\n\
|
||||
test %%eax, -64(%%esi) \n\
|
||||
sub %%ebx, %%esi # Update pointer \n\
|
||||
sub %%ebx, %%eax # And loop \n\
|
||||
jnz 2b \n\
|
||||
# Note that ESI now points to the beginning of the block \n\
|
||||
3: movq (%%esi), %%mm0 # Do the actual copy, 64 bytes at a time\n\
|
||||
movq 8(%%esi), %%mm1 \n\
|
||||
movq 16(%%esi), %%mm2 \n\
|
||||
movq 24(%%esi), %%mm3 \n\
|
||||
movq 32(%%esi), %%mm4 \n\
|
||||
movq 40(%%esi), %%mm5 \n\
|
||||
movq 48(%%esi), %%mm6 \n\
|
||||
movq 56(%%esi), %%mm7 \n\
|
||||
movq %%mm0, (%%edi) \n\
|
||||
movq %%mm1, 8(%%edi) \n\
|
||||
movq %%mm2, 16(%%edi) \n\
|
||||
movq %%mm3, 24(%%edi) \n\
|
||||
movq %%mm4, 32(%%edi) \n\
|
||||
movq %%mm5, 40(%%edi) \n\
|
||||
movq %%mm6, 48(%%edi) \n\
|
||||
movq %%mm7, 56(%%edi) \n\
|
||||
add %%ebx, %%esi # Update pointers \n\
|
||||
add %%ebx, %%edi \n\
|
||||
dec %%edx # And loop \n\
|
||||
jnz 3b \n\
|
||||
jmp 0b \n\
|
||||
\n\
|
||||
mmx.memcpy_last: \n\
|
||||
# Copy last <64 bytes, using the computed jump trick \n\
|
||||
mov %%ecx, %%eax # EAX <- ECX>>2 \n\
|
||||
shr $2, %%eax \n\
|
||||
lea 0f, %%edx \n\
|
||||
sub %%eax, %%edx \n\
|
||||
jmp *%%edx # Execute 0-15 MOVSD's \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
0: and $0b11, %%ecx # ECX <- ECX & 3 \n\
|
||||
lea 0f, %%edx \n\
|
||||
sub %%ecx, %%edx \n\
|
||||
jmp *%%edx # Execute 0-3 MOVSB's \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
0: \n\
|
||||
# All done! \n\
|
||||
emms # Clean up MMX state \n\
|
||||
pop %%edi # Restore destination (return value) \n\
|
||||
pop %%ebx # Restore PIC register \n\
|
||||
" : /* no outputs */
|
||||
: "D" (dest), "S" (src), "c" (bytes)
|
||||
: "%eax", "%edx"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_MMX && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_SSE) && defined(ARCH_X86)
|
||||
|
||||
/* SSE-optimized routine. Backported from AMD64 routine below.
|
||||
* Nonstandard instructions used:
|
||||
* (CPUID.CMOVE) CMOVA
|
||||
* (CPUID.MMX) MOVQ
|
||||
* (CPUID.SSE) MOVNTQ
|
||||
*/
|
||||
|
||||
static void *memcpy_sse(void *dest, const void *src, size_t bytes)
|
||||
{
|
||||
asm("\
|
||||
push %%ebx # Save PIC register \n\
|
||||
push %%edi # Save destination for return value \n\
|
||||
cld # MOVS* should ascend \n\
|
||||
\n\
|
||||
cmp $64, %%ecx # Skip block copy for small blocks \n\
|
||||
jb sse.memcpy_last \n\
|
||||
\n\
|
||||
mov $128, %%ebx # Constant used later \n\
|
||||
\n\
|
||||
# First align destination address to a multiple of 8 bytes \n\
|
||||
mov $8, %%eax # EAX <- (8-dest) & 7 \n\
|
||||
sub %%edi, %%eax \n\
|
||||
and $0b111, %%eax # ... which is the number of bytes to copy\n\
|
||||
lea 0f, %%edx # Use a computed jump--faster than a loop\n\
|
||||
sub %%eax, %%edx \n\
|
||||
jmp *%%edx # Execute 0-7 MOVSB's \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
0: sub %%eax, %%ecx # Update count \n\
|
||||
\n\
|
||||
cmp $0x10040, %%ecx # Is this a large block? (0x10040 is an \n\
|
||||
# arbitrary value where prefetching and \n\
|
||||
# write combining seem to start becoming\n\
|
||||
# faster) \n\
|
||||
jae sse.memcpy_bp # Yup, use prefetch copy \n\
|
||||
\n\
|
||||
sse.memcpy_small: # Small block copy routine--no prefetch \n"
|
||||
#if 0
|
||||
" mov %%ecx, %%edx # EDX <- bytes to copy / 8 \n\
|
||||
shr $3, %%edx \n\
|
||||
mov %%edx, %%eax # Leave remainder in ECX for later \n\
|
||||
shl $3, %%eax \n\
|
||||
sub %%eax, %%ecx \n\
|
||||
.align 16 \n\
|
||||
0: movq (%%esi), %%mm0 # Copy 8 bytes of data \n\
|
||||
movq %%mm0, (%%edi) \n\
|
||||
add $8, %%esi # Update pointers \n\
|
||||
add $8, %%edi \n\
|
||||
dec %%edx # And loop \n\
|
||||
jg 0b \n\
|
||||
jmp sse.memcpy_last # Copy any remaining bytes \n\
|
||||
\n\
|
||||
nop # Align loops below \n"
|
||||
#else
|
||||
" # It appears that a simple rep movs is faster than cleverness \n\
|
||||
# with movq... \n\
|
||||
mov %%ecx, %%edx # EDX <- ECX & 3 \n\
|
||||
and $0b11, %%edx \n\
|
||||
shr $2, %%ecx # ECX <- ECX >> 2 \n\
|
||||
rep movsl # Copy away! \n\
|
||||
mov %%edx, %%ecx # Take care of last 0-3 bytes \n\
|
||||
rep movsb \n\
|
||||
jmp sse.memcpy_end # And exit \n\
|
||||
\n\
|
||||
.align 16 \n\
|
||||
nop \n\
|
||||
nop \n"
|
||||
#endif
|
||||
"sse.memcpy_bp: # Block prefetch copy routine \n\
|
||||
0: mov %%ecx, %%edx # EDX: temp counter \n\
|
||||
shr $6, %%edx # Divide by cache line size (64 bytes) \n\
|
||||
cmp %%ebx, %%edx # ... and cap at 128 (8192 bytes) \n\
|
||||
cmova %%ebx, %%edx \n\
|
||||
shl $3, %%edx # EDX <- cache lines to copy * 8 \n\
|
||||
mov %%edx, %%eax # EAX <- cache lines to preload * 8 \n\
|
||||
# (also used as memory offset) \n\
|
||||
1: test %%eax, -64(%%esi,%%eax,8) # Preload cache lines in pairs \n\
|
||||
test %%eax, -128(%%esi,%%eax,8) # (going backwards) \n\
|
||||
# (note that test %%eax,... seems to be faster than prefetchnta \n\
|
||||
# on x86) \n\
|
||||
sub $16, %%eax # And loop \n\
|
||||
jg 1b \n\
|
||||
\n\
|
||||
# Then copy--forward, which seems to be faster than reverse for \n\
|
||||
# certain alignments \n\
|
||||
xor %%eax, %%eax \n\
|
||||
2: movq (%%esi,%%eax,8), %%mm0 # Copy 8 bytes and loop \n\
|
||||
movntq %%mm0, (%%edi,%%eax,8) \n\
|
||||
inc %%eax \n\
|
||||
cmp %%edx, %%eax \n\
|
||||
jb 2b \n\
|
||||
\n\
|
||||
# Finally, update pointers and count, and loop \n\
|
||||
shl $3, %%edx # EDX <- bytes copied \n\
|
||||
add %%edx, %%esi \n\
|
||||
add %%edx, %%edi \n\
|
||||
sub %%edx, %%ecx \n\
|
||||
cmp $64, %%ecx # At least one cache line left? \n\
|
||||
jae 0b # Yup, loop \n\
|
||||
\n\
|
||||
sse.memcpy_last: \n\
|
||||
# Copy last <64 bytes, using the computed jump trick \n\
|
||||
mov %%ecx, %%eax # EAX <- ECX>>2 \n\
|
||||
shr $2, %%eax \n\
|
||||
lea 0f, %%edx \n\
|
||||
sub %%eax, %%edx \n\
|
||||
jmp *%%edx # Execute 0-15 MOVSD's \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
movsd \n\
|
||||
0: and $0b11, %%ecx # ECX <- ECX & 3 \n\
|
||||
lea sse.memcpy_end, %%edx \n\
|
||||
sub %%ecx, %%edx \n\
|
||||
jmp *%%edx # Execute 0-3 MOVSB's \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
\n\
|
||||
sse.memcpy_end: \n\
|
||||
# All done! \n\
|
||||
emms # Clean up after MMX instructions \n\
|
||||
sfence # Flush the write buffer \n\
|
||||
pop %%edi # Restore destination (return value) \n\
|
||||
pop %%ebx # Restore PIC register \n\
|
||||
" : /* no outputs */
|
||||
: "D" (dest), "S" (src), "c" (bytes)
|
||||
: "%eax", "%edx"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_SSE && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(HAVE_ASM_SSE2) && defined(ARCH_X86_64)
|
||||
|
||||
/* AMD64-optimized routine, using SSE2. Derived from AMD64 optimization
|
||||
* guide section 5.13: Appropriate Memory Copying Routines.
|
||||
* Nonstandard instructions used:
|
||||
* (CPUID.CMOVE) CMOVA
|
||||
* (CPUID.SSE2) MOVDQA, MOVDQU, MOVNTDQ
|
||||
*
|
||||
* Note that this routine will also run more or less as-is (modulo register
|
||||
* names and label(%%rip) references) on x86 CPUs, but tests have shown the
|
||||
* SSE1 version above to be faster.
|
||||
*/
|
||||
|
||||
/* The block copying code--macroized because we use two versions of it
|
||||
* depending on whether the source is 16-byte-aligned or not. Pass either
|
||||
* movdqa or movdqu (unquoted) for the parameter. */
|
||||
#define AMD64_BLOCK_MEMCPY(movdq) \
|
||||
" # First prefetch (note that if we end on an odd number of cache \n\
|
||||
# lines, we skip prefetching the last one--faster that way than \n\
|
||||
# prefetching line by line or treating it as a special case) \n\
|
||||
0: mov %%ecx, %%edx # EDX: temp counter (always <32 bits) \n\
|
||||
shr $6, %%edx # Divide by cache line size (64 bytes) \n\
|
||||
cmp %%ebx, %%edx # ... and cap at 128 (8192 bytes) \n\
|
||||
cmova %%ebx, %%edx \n\
|
||||
shl $3, %%edx # EDX <- cache lines to copy * 8 \n\
|
||||
mov %%edx, %%eax # EAX <- cache lines to preload * 8 \n\
|
||||
# (also used as memory offset) \n\
|
||||
1: prefetchnta -64(%%rsi,%%rax,8) # Preload cache lines in pairs \n\
|
||||
prefetchnta -128(%%rsi,%%rax,8) # (going backwards) \n\
|
||||
sub $16, %%eax # And loop \n\
|
||||
jg 1b \n\
|
||||
\n\
|
||||
# Then copy--forward, which seems to be faster than reverse for \n\
|
||||
# certain alignments \n\
|
||||
xor %%eax, %%eax \n\
|
||||
2: " #movdq " (%%rsi,%%rax,8), %%xmm0 # Copy 16 bytes and loop \n\
|
||||
movntdq %%xmm0, (%%rdi,%%rax,8) \n\
|
||||
add $2, %%eax \n\
|
||||
cmp %%edx, %%eax \n\
|
||||
jb 2b \n\
|
||||
\n\
|
||||
# Finally, update pointers and count, and loop \n\
|
||||
shl $3, %%edx # EDX <- bytes copied \n\
|
||||
add %%rdx, %%rsi \n\
|
||||
add %%rdx, %%rdi \n\
|
||||
sub %%rdx, %%rcx \n\
|
||||
cmp $64, %%rcx # At least one cache line left? \n\
|
||||
jae 0b # Yup, loop \n"
|
||||
|
||||
static void *memcpy_amd64(void *dest, const void *src, size_t bytes)
|
||||
{
|
||||
asm("\
|
||||
push %%rdi # Save destination for return value \n\
|
||||
cld # MOVS* should ascend \n\
|
||||
\n\
|
||||
cmp $64, %%rcx # Skip block copy for small blocks \n\
|
||||
jb amd64.memcpy_last \n\
|
||||
\n\
|
||||
mov $128, %%ebx # Constant used later \n\
|
||||
\n\
|
||||
# First align destination address to a multiple of 16 bytes \n\
|
||||
mov $8, %%eax # EAX <- (8-dest) & 7 \n\
|
||||
sub %%edi, %%eax # (we don't care about the top 32 bits) \n\
|
||||
and $0b111, %%eax # ... which is the number of bytes to copy\n\
|
||||
lea 0f(%%rip), %%rdx # Use a computed jump--faster than a loop\n\
|
||||
sub %%rax, %%rdx \n\
|
||||
jmp *%%rdx # Execute 0-7 MOVSB's \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
0: sub %%rax, %%rcx # Update count \n\
|
||||
test $0b1000, %%edi # Is destination not 16-byte aligned? \n\
|
||||
je 1f \n\
|
||||
movsq # Then move 8 bytes to align it \n\
|
||||
sub $8, %%rcx \n\
|
||||
\n\
|
||||
1: cmp $0x38000, %%rcx # Is this a large block? (0x38000 is an \n\
|
||||
# arbitrary value where prefetching and \n\
|
||||
# write combining seem to start becoming\n\
|
||||
# faster) \n\
|
||||
jb amd64.memcpy_small # Nope, use small copy (no prefetch/WC) \n\
|
||||
test $0b1111, %%esi # Is source also 16-byte aligned? \n\
|
||||
# (use ESI to save a REX prefix byte) \n\
|
||||
jnz amd64.memcpy_normal_bp # Nope, use slow copy \n\
|
||||
jmp amd64.memcpy_fast_bp # Yup, use fast copy \n\
|
||||
\n\
|
||||
amd64.memcpy_small: # Small block copy routine--no prefetch \n\
|
||||
mov %%ecx, %%edx # EDX <- bytes to copy / 16 \n\
|
||||
shr $4, %%edx # (count known to fit in 32 bits) \n\
|
||||
mov %%edx, %%eax # Leave remainder in ECX for later \n\
|
||||
shl $4, %%eax \n\
|
||||
sub %%eax, %%ecx \n\
|
||||
.align 16 \n\
|
||||
0: movdqu (%%rsi), %%xmm0 # Copy 16 bytes of data \n\
|
||||
movdqa %%xmm0, (%%rdi) \n\
|
||||
add $16, %%rsi # Update pointers \n\
|
||||
add $16, %%rdi \n\
|
||||
dec %%edx # And loop \n\
|
||||
jnz 0b \n\
|
||||
jmp amd64.memcpy_last # Copy any remaining bytes \n\
|
||||
\n\
|
||||
.align 16 \n\
|
||||
nop \n\
|
||||
nop \n\
|
||||
amd64.memcpy_fast_bp: # Fast block prefetch loop \n"
|
||||
AMD64_BLOCK_MEMCPY(movdqa)
|
||||
" jmp amd64.memcpy_last # Copy any remaining bytes \n\
|
||||
\n\
|
||||
.align 16 \n\
|
||||
nop \n\
|
||||
nop \n\
|
||||
amd64.memcpy_normal_bp: # Normal (unaligned) block prefetch loop\n"
|
||||
AMD64_BLOCK_MEMCPY(movdqu)
|
||||
" \n\
|
||||
amd64.memcpy_last: \n\
|
||||
# Copy last <64 bytes, using the computed jump trick \n\
|
||||
mov %%ecx, %%eax # EAX <- ECX>>3 \n\
|
||||
shr $3, %%eax \n\
|
||||
lea 0f(%%rip), %%rdx \n\
|
||||
add %%eax, %%eax # Watch out, MOVSQ is 2 bytes! \n\
|
||||
sub %%rax, %%rdx \n\
|
||||
jmp *%%rdx # Execute 0-7 MOVSQ's \n\
|
||||
movsq \n\
|
||||
movsq \n\
|
||||
movsq \n\
|
||||
movsq \n\
|
||||
movsq \n\
|
||||
movsq \n\
|
||||
movsq \n\
|
||||
0: and $0b111, %%ecx # ECX <- ECX & 7 \n\
|
||||
lea 0f(%%rip), %%rdx \n\
|
||||
sub %%rcx, %%rdx \n\
|
||||
jmp *%%rdx # Execute 0-7 MOVSB's \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
movsb \n\
|
||||
0: \n\
|
||||
# All done! \n\
|
||||
emms # Clean up after MMX instructions \n\
|
||||
sfence # Flush the write buffer \n\
|
||||
pop %%rdi # Restore destination (return value) \n\
|
||||
" : /* no outputs */
|
||||
: "D" (dest), "S" (src), "c" (bytes)
|
||||
: "%rax", "%rbx", "%rdx"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_SSE2 && ARCH_X86_64 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization routine. */
|
||||
|
||||
int ac_memcpy_init(int accel)
|
||||
{
|
||||
memcpy_ptr = memmove;
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86)
|
||||
if (HAS_ACCEL(accel, AC_MMX))
|
||||
memcpy_ptr = memcpy_mmx;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ASM_SSE) && defined(ARCH_X86)
|
||||
if (HAS_ACCEL(accel, AC_CMOVE|AC_SSE))
|
||||
memcpy_ptr = memcpy_sse;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ASM_SSE2) && defined(ARCH_X86_64)
|
||||
if (HAS_ACCEL(accel, AC_CMOVE|AC_SSE2))
|
||||
memcpy_ptr = memcpy_amd64;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
280
veejay-1.3/veejay-server/aclib/rescale.c
Normal file
280
veejay-1.3/veejay-server/aclib/rescale.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* rescale.c -- take the weighted average of two sets of byte data
|
||||
* Written by Andrew Church <achurch@achurch.org>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool.
|
||||
* transcode is free software, distributable under the terms of the GNU
|
||||
* General Public License (version 2 or later). See the file COPYING
|
||||
* for details.
|
||||
*/
|
||||
|
||||
#include "ac.h"
|
||||
#include "ac_internal.h"
|
||||
|
||||
static void rescale(const uint8_t *, const uint8_t *, uint8_t *, int,
|
||||
uint32_t, uint32_t);
|
||||
static void (*rescale_ptr)(const uint8_t *, const uint8_t *, uint8_t *, int,
|
||||
uint32_t, uint32_t) = rescale;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* External interface */
|
||||
|
||||
void ac_rescale(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes, uint32_t weight1, uint32_t weight2)
|
||||
{
|
||||
if (weight1 >= 0x10000)
|
||||
ac_memcpy(dest, src1, bytes);
|
||||
else if (weight2 >= 0x10000)
|
||||
ac_memcpy(dest, src2, bytes);
|
||||
else
|
||||
(*rescale_ptr)(src1, src2, dest, bytes, weight1, weight2);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Vanilla C version */
|
||||
|
||||
static void rescale(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes,
|
||||
uint32_t weight1, uint32_t weight2)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++)
|
||||
dest[i] = (src1[i]*weight1 + src2[i]*weight2 + 32768) >> 16;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* MMX version */
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */
|
||||
|
||||
static void rescale_mmx(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes,
|
||||
uint32_t weight1, uint32_t weight2)
|
||||
{
|
||||
if (bytes >= 8) {
|
||||
/* First store weights in MM4/MM5 to relieve register pressure;
|
||||
* save time by making 2 copies ahead of time in the general
|
||||
* registers. Note that we divide by 2 for MMX due to the lack
|
||||
* of an unsigned SIMD multiply instruction (PMULHUW). */
|
||||
int half1 = weight1 / 2;
|
||||
int half2 = weight2 / 2;
|
||||
half2 += weight1 & weight2 & 1; // pick up the lost bit here
|
||||
asm("movd %%eax, %%mm4; movd %%edx, %%mm5"
|
||||
: : "a" (half1<<16|half1), "d" (half2<<16|half2));
|
||||
asm("\
|
||||
movq %%mm4, %%mm6 # MM6: 00 00 W1 W1 \n\
|
||||
psllq $32, %%mm4 # MM4: W1 W1 00 00 \n\
|
||||
por %%mm6, %%mm4 # MM4: W1 W1 W1 W1 \n\
|
||||
movq %%mm5, %%mm7 # MM7: 00 00 W2 W2 \n\
|
||||
psllq $32, %%mm5 # MM5: W2 W2 00 00 \n\
|
||||
por %%mm7, %%mm5 # MM5: W2 W2 W2 W2 \n\
|
||||
pxor %%mm7, %%mm7 # MM7: 00 00 00 00 \n\
|
||||
pxor %%mm6, %%mm6 # Put 0x0020*4 in MM6 (rounding)\n\
|
||||
pcmpeqw %%mm3, %%mm3 \n\
|
||||
psubw %%mm3, %%mm6 \n\
|
||||
psllw $5, %%mm6 \n\
|
||||
0: \n\
|
||||
movq -8(%%esi,%%ecx), %%mm0 \n\
|
||||
movq %%mm0, %%mm1 \n\
|
||||
punpcklbw %%mm7, %%mm0 \n\
|
||||
psllw $7, %%mm0 # 9.7 fixed point \n\
|
||||
pmulhw %%mm4, %%mm0 # Multiply to get 10.6 fixed \n\
|
||||
punpckhbw %%mm7, %%mm1 \n\
|
||||
psllw $7, %%mm1 \n\
|
||||
pmulhw %%mm4, %%mm1 \n\
|
||||
movq -8(%%edx,%%ecx), %%mm2 \n\
|
||||
movq %%mm2, %%mm3 \n\
|
||||
punpcklbw %%mm7, %%mm2 \n\
|
||||
psllw $7, %%mm2 \n\
|
||||
pmulhw %%mm5, %%mm2 \n\
|
||||
punpckhbw %%mm7, %%mm3 \n\
|
||||
psllw $7, %%mm3 \n\
|
||||
pmulhw %%mm5, %%mm3 \n\
|
||||
paddw %%mm2, %%mm0 \n\
|
||||
paddw %%mm6, %%mm0 \n\
|
||||
psrlw $6, %%mm0 \n\
|
||||
paddw %%mm3, %%mm1 \n\
|
||||
paddw %%mm6, %%mm1 \n\
|
||||
psrlw $6, %%mm1 \n\
|
||||
packuswb %%mm1, %%mm0 \n\
|
||||
movq %%mm0, -8(%%edi,%%ecx) \n\
|
||||
subl $8, %%ecx \n\
|
||||
jnz 0b \n\
|
||||
emms"
|
||||
: /* no outputs */
|
||||
: "S" (src1), "d" (src2), "D" (dest), "c" (bytes & ~7));
|
||||
}
|
||||
if (UNLIKELY(bytes & 7)) {
|
||||
rescale(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7),
|
||||
bytes & 7, weight1, weight2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_MMX && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* MMXEXT version (also for SSE) */
|
||||
|
||||
#if (defined(HAVE_ASM_MMXEXT) || defined(HAVE_ASM_SSE)) && defined(ARCH_X86)
|
||||
|
||||
static void rescale_mmxext(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes,
|
||||
uint32_t weight1, uint32_t weight2)
|
||||
{
|
||||
if (bytes >= 8) {
|
||||
asm("movd %%eax, %%mm4; movd %%edx, %%mm5"
|
||||
: : "a" (weight1), "d" (weight2));
|
||||
asm("\
|
||||
pshufw $0, %%mm4, %%mm4 # MM4: W1 W1 W1 W1 \n\
|
||||
pshufw $0, %%mm5, %%mm5 # MM5: W2 W2 W2 W2 \n\
|
||||
pxor %%mm6, %%mm6 # Put 0x0080*4 in MM6 (rounding)\n\
|
||||
pcmpeqw %%mm7, %%mm7 \n\
|
||||
psubw %%mm7, %%mm6 \n\
|
||||
psllw $7, %%mm6 \n\
|
||||
0: \n\
|
||||
movq -8(%%esi,%%ecx), %%mm7 \n\
|
||||
pxor %%mm0, %%mm0 # Load data into high bytes \n\
|
||||
punpcklbw %%mm7, %%mm0 # (gives 8.8 fixed point) \n\
|
||||
pmulhuw %%mm4, %%mm0 # Result: 0000..FF00 \n\
|
||||
pxor %%mm1, %%mm1 \n\
|
||||
punpckhbw %%mm7, %%mm1 \n\
|
||||
pmulhuw %%mm4, %%mm1 \n\
|
||||
movq -8(%%edx,%%ecx), %%mm7 \n\
|
||||
pxor %%mm2, %%mm2 \n\
|
||||
punpcklbw %%mm7, %%mm2 \n\
|
||||
pmulhuw %%mm5, %%mm2 \n\
|
||||
pxor %%mm3, %%mm3 \n\
|
||||
punpckhbw %%mm7, %%mm3 \n\
|
||||
pmulhuw %%mm5, %%mm3 \n\
|
||||
paddw %%mm2, %%mm0 \n\
|
||||
paddw %%mm6, %%mm0 \n\
|
||||
psrlw $8, %%mm0 # Shift back down to 00..FF \n\
|
||||
paddw %%mm3, %%mm1 \n\
|
||||
paddw %%mm6, %%mm1 \n\
|
||||
psrlw $8, %%mm1 \n\
|
||||
packuswb %%mm1, %%mm0 \n\
|
||||
movq %%mm0, -8(%%edi,%%ecx) \n\
|
||||
subl $8, %%ecx \n\
|
||||
jnz 0b \n\
|
||||
emms"
|
||||
: /* no outputs */
|
||||
: "S" (src1), "d" (src2), "D" (dest), "c" (bytes & ~7));
|
||||
}
|
||||
if (UNLIKELY(bytes & 7)) {
|
||||
rescale(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7),
|
||||
bytes & 7, weight1, weight2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* (HAVE_ASM_MMXEXT || HAVE_ASM_SSE) && ARCH_X86 */
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* SSE2 version */
|
||||
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
|
||||
#ifdef ARCH_X86_64
|
||||
# define ECX "%%rcx"
|
||||
# define EDX "%%rdx"
|
||||
# define ESI "%%rsi"
|
||||
# define EDI "%%rdi"
|
||||
#else
|
||||
# define ECX "%%ecx"
|
||||
# define EDX "%%edx"
|
||||
# define ESI "%%esi"
|
||||
# define EDI "%%edi"
|
||||
#endif
|
||||
|
||||
static void rescale_sse2(const uint8_t *src1, const uint8_t *src2,
|
||||
uint8_t *dest, int bytes,
|
||||
uint32_t weight1, uint32_t weight2)
|
||||
{
|
||||
if (bytes >= 16) {
|
||||
asm("movd %%eax, %%xmm4; movd %%edx, %%xmm5"
|
||||
: : "a" (weight1<<16|weight1), "d" (weight2<<16|weight2));
|
||||
asm("\
|
||||
pshufd $0, %%xmm4, %%xmm4 # XMM4: W1 W1 W1 W1 W1 W1 W1 W1 \n\
|
||||
pshufd $0, %%xmm5, %%xmm5 # XMM5: W2 W2 W2 W2 W2 W2 W2 W2 \n\
|
||||
pxor %%xmm6, %%xmm6 # Put 0x0080*4 in XMM6 (rounding)\n\
|
||||
pcmpeqw %%xmm7, %%xmm7 \n\
|
||||
psubw %%xmm7, %%xmm6 \n\
|
||||
psllw $7, %%xmm6 \n\
|
||||
0: \n\
|
||||
movdqu -16("ESI","ECX"), %%xmm7 \n\
|
||||
pxor %%xmm0, %%xmm0 \n\
|
||||
punpcklbw %%xmm7, %%xmm0 \n\
|
||||
pmulhuw %%xmm4, %%xmm0 \n\
|
||||
pxor %%xmm1, %%xmm1 \n\
|
||||
punpckhbw %%xmm7, %%xmm1 \n\
|
||||
pmulhuw %%xmm4, %%xmm1 \n\
|
||||
movdqu -16("EDX","ECX"), %%xmm7 \n\
|
||||
pxor %%xmm2, %%xmm2 \n\
|
||||
punpcklbw %%xmm7, %%xmm2 \n\
|
||||
pmulhuw %%xmm5, %%xmm2 \n\
|
||||
pxor %%xmm3, %%xmm3 \n\
|
||||
punpckhbw %%xmm7, %%xmm3 \n\
|
||||
pmulhuw %%xmm5, %%xmm3 \n\
|
||||
paddw %%xmm2, %%xmm0 \n\
|
||||
paddw %%xmm6, %%xmm0 \n\
|
||||
psrlw $8, %%xmm0 \n\
|
||||
paddw %%xmm3, %%xmm1 \n\
|
||||
paddw %%xmm6, %%xmm1 \n\
|
||||
psrlw $8, %%xmm1 \n\
|
||||
packuswb %%xmm1, %%xmm0 \n\
|
||||
movdqu %%xmm0, -16("EDI","ECX") \n\
|
||||
subl $16, %%ecx \n\
|
||||
jnz 0b \n\
|
||||
emms"
|
||||
: /* no outputs */
|
||||
: "S" (src1), "d" (src2), "D" (dest), "c" (bytes & ~15));
|
||||
}
|
||||
if (UNLIKELY(bytes & 15)) {
|
||||
rescale(src1+(bytes & ~15), src2+(bytes & ~15), dest+(bytes & ~15),
|
||||
bytes & 15, weight1, weight2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_ASM_SSE2 */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* Initialization routine. */
|
||||
|
||||
int ac_rescale_init(int accel)
|
||||
{
|
||||
rescale_ptr = rescale;
|
||||
|
||||
#if defined(HAVE_ASM_MMX) && defined(ARCH_X86)
|
||||
if (HAS_ACCEL(accel, AC_MMX))
|
||||
rescale_ptr = rescale_mmx;
|
||||
#endif
|
||||
#if (defined(HAVE_ASM_MMXEXT) || defined(HAVE_ASM_SSE)) && defined(ARCH_X86)
|
||||
if (HAS_ACCEL(accel, AC_MMXEXT) || HAS_ACCEL(accel, AC_SSE))
|
||||
rescale_ptr = rescale_mmxext;
|
||||
#endif
|
||||
#if defined(HAVE_ASM_SSE2)
|
||||
if (HAS_ACCEL(accel, AC_SSE2))
|
||||
rescale_ptr = rescale_sse2;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "stroustrup"
|
||||
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vim: expandtab shiftwidth=4:
|
||||
*/
|
||||
48
veejay-1.3/veejay-server/aclib/rgb-yuv-conv.pl
Executable file
48
veejay-1.3/veejay-server/aclib/rgb-yuv-conv.pl
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/perl -w
|
||||
# Calculate conversion matrices for RGB<->YUV given Kb and Kr
|
||||
|
||||
die "Usage: $0 Kb Kr [scale]\n" if @ARGV < 2;
|
||||
$scale = $ARGV[2] || 1;
|
||||
$Kb = $ARGV[0];
|
||||
$Kr = $ARGV[1];
|
||||
$Kg = 1 - $Kr - $Kb;
|
||||
$a11 = $Kr;
|
||||
$a12 = $Kg;
|
||||
$a13 = $Kb;
|
||||
$a21 = -$Kr/(1-$Kb)/2;
|
||||
$a22 = -$Kg/(1-$Kb)/2;
|
||||
$a23 = 1/2;
|
||||
$a31 = 1/2;
|
||||
$a32 = -$Kg/(1-$Kr)/2;
|
||||
$a33 = -$Kb/(1-$Kr)/2;
|
||||
print "Y [R] = ".($a11*$scale)."\n";
|
||||
print "Y [G] = ".($a12*$scale)."\n";
|
||||
print "Y [B] = ".($a13*$scale)."\n";
|
||||
print "Cb[R] = ".($a21*$scale)."\n";
|
||||
print "Cb[G] = ".($a22*$scale)."\n";
|
||||
print "Cb[B] = ".($a23*$scale)."\n";
|
||||
print "Cr[R] = ".($a31*$scale)."\n";
|
||||
print "Cr[G] = ".($a32*$scale)."\n";
|
||||
print "Cr[B] = ".($a33*$scale)."\n";
|
||||
$det = $a11*$a22*$a33 - $a11*$a23*$a32
|
||||
+ $a12*$a23*$a31 - $a12*$a21*$a33
|
||||
+ $a13*$a21*$a32 - $a13*$a22*$a31;
|
||||
$b11 = (1/$det)*($a22*$a33-$a23*$a32);
|
||||
$b12 = (1/$det)*($a13*$a32-$a12*$a33);
|
||||
$b13 = (1/$det)*($a12*$a23-$a13*$a22);
|
||||
$b21 = (1/$det)*($a23*$a31-$a21*$a33);
|
||||
$b22 = (1/$det)*($a11*$a33-$a13*$a31);
|
||||
$b23 = (1/$det)*($a13*$a21-$a11*$a23);
|
||||
$b31 = (1/$det)*($a21*$a32-$a22*$a31);
|
||||
$b32 = (1/$det)*($a12*$a31-$a11*$a32);
|
||||
$b33 = (1/$det)*($a11*$a22-$a12*$a21);
|
||||
map {$_ = 0 if abs($_) < 1e-10} ($b11,$b12,$b13,$b21,$b22,$b23,$b31,$b32,$b33);
|
||||
print "R[Y ] = ".($b11*$scale)."\n";
|
||||
print "R[Cb] = ".($b12*$scale)."\n";
|
||||
print "R[Cr] = ".($b13*$scale)."\n";
|
||||
print "G[Y ] = ".($b21*$scale)."\n";
|
||||
print "G[Cb] = ".($b22*$scale)."\n";
|
||||
print "G[Cr] = ".($b23*$scale)."\n";
|
||||
print "B[Y ] = ".($b31*$scale)."\n";
|
||||
print "B[Cb] = ".($b32*$scale)."\n";
|
||||
print "B[Cr] = ".($b33*$scale)."\n";
|
||||
5
veejay-1.3/veejay-server/autogen.sh
Executable file
5
veejay-1.3/veejay-server/autogen.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
|
||||
|
||||
autoreconf -v -f -i
|
||||
4
veejay-1.3/veejay-server/bio2jack/AUTHORS
Normal file
4
veejay-1.3/veejay-server/bio2jack/AUTHORS
Normal file
@@ -0,0 +1,4 @@
|
||||
bio2jack - a library for porting blocked io(OSS/ALSA) apps to jack
|
||||
---------------------------------------------------------
|
||||
|
||||
Chris Morgan <cmorgan@alum.wpi.edu>
|
||||
339
veejay-1.3/veejay-server/bio2jack/COPYING
Normal file
339
veejay-1.3/veejay-server/bio2jack/COPYING
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
6
veejay-1.3/veejay-server/bio2jack/INSTALL
Normal file
6
veejay-1.3/veejay-server/bio2jack/INSTALL
Normal file
@@ -0,0 +1,6 @@
|
||||
Installing bio2jack
|
||||
----------------------
|
||||
|
||||
This library is intended only for static linking as it is small and there
|
||||
is no need to require yet another library for a user to install. So
|
||||
please, statically link to this library.
|
||||
4
veejay-1.3/veejay-server/bio2jack/Makefile.am
Normal file
4
veejay-1.3/veejay-server/bio2jack/Makefile.am
Normal file
@@ -0,0 +1,4 @@
|
||||
noinst_LTLIBRARIES = libbio2jack4vj.la
|
||||
INCLUDES=-I$(top_srcdir)/libvjmem -I$(top_srcdir)/libvjmsg
|
||||
LIBS = @LIBS@ @PTHREAD_LIBS@ @JACK_LIBS@
|
||||
libbio2jack4vj_la_SOURCES = bio2jack.c bio2jack.h
|
||||
10
veejay-1.3/veejay-server/bio2jack/NEWS
Normal file
10
veejay-1.3/veejay-server/bio2jack/NEWS
Normal file
@@ -0,0 +1,10 @@
|
||||
bio2jack - NEWS
|
||||
--------
|
||||
9/12/2004 - Check out ChangeLog for news ;-)
|
||||
10/26/2003 - Updated to the new jack api, fixed a bunch of bugs
|
||||
Removed all blocking functions, blocking is BAD as it could potentially
|
||||
hold off the callback function.
|
||||
1/13/2003 - Continuing to refine the api by working on the xine plugin.
|
||||
Fixed a few bugs in the code. Uploaded newer packages to
|
||||
sourceforge.
|
||||
12/31/2002 - Sourceforge project is setup.
|
||||
30
veejay-1.3/veejay-server/bio2jack/README
Normal file
30
veejay-1.3/veejay-server/bio2jack/README
Normal file
@@ -0,0 +1,30 @@
|
||||
bio2jack
|
||||
-----------
|
||||
|
||||
To Build:
|
||||
----------
|
||||
run ./autogen.sh
|
||||
run ./configure
|
||||
run make
|
||||
enjoy ;-)
|
||||
|
||||
|
||||
Bio(blocked i/o) 2 jack.
|
||||
|
||||
A library for enabling easy porting of blocked io(OSS/ALSA) applications to
|
||||
the jack sound server(http://jackit.sourceforge.net). This library allows the
|
||||
person porting the code to simply replace the calls into OSS/ALSA with
|
||||
calls into interface functions of this library. The library buffers a
|
||||
small amount of audio data and takes care of the rest of the jack
|
||||
implementation including the linked list of audio data buffers and the jack
|
||||
callback.
|
||||
|
||||
Interface functions:
|
||||
TODO: once these become stable copy and paste from the header file
|
||||
|
||||
|
||||
Currently these drivers use the bio2jack library:
|
||||
---------------------------------------------------
|
||||
xmms-jack: Written in conjunction with this library
|
||||
xine:
|
||||
|
||||
2690
veejay-1.3/veejay-server/bio2jack/bio2jack.c
Normal file
2690
veejay-1.3/veejay-server/bio2jack/bio2jack.c
Normal file
File diff suppressed because it is too large
Load Diff
147
veejay-1.3/veejay-server/bio2jack/bio2jack.h
Normal file
147
veejay-1.3/veejay-server/bio2jack/bio2jack.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2003-2004 Chris Morgan <cmorgan@alum.wpi.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_JACK_OUT_H
|
||||
#define _H_JACK_OUT_H
|
||||
|
||||
#include <jack/jack.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
#define bool long
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define ERR_SUCCESS 0
|
||||
#define ERR_OPENING_JACK 1
|
||||
#define ERR_RATE_MISMATCH 2
|
||||
#define ERR_BYTES_PER_OUTPUT_FRAME_INVALID 3
|
||||
#define ERR_BYTES_PER_INPUT_FRAME_INVALID 4
|
||||
#define ERR_TOO_MANY_OUTPUT_CHANNELS 5
|
||||
#define ERR_PORT_NAME_OUTPUT_CHANNEL_MISMATCH 6
|
||||
#define ERR_PORT_NOT_FOUND 7
|
||||
#define ERR_TOO_MANY_INPUT_CHANNELS 8
|
||||
#define ERR_PORT_NAME_INPUT_CHANNEL_MISMATCH 9
|
||||
|
||||
enum status_enum { PLAYING, PAUSED, STOPPED, CLOSED, RESET };
|
||||
enum pos_enum { BYTES, MILLISECONDS };
|
||||
|
||||
#define PLAYED 1 /* played out of the speakers(estimated value but should be close */
|
||||
#define WRITTEN_TO_JACK 2 /* amount written out to jack */
|
||||
#define WRITTEN 3 /* amount written to the bio2jack device */
|
||||
|
||||
/**********************/
|
||||
/* External functions */
|
||||
void JACK_Init(void); /* call this before any other bio2jack calls */
|
||||
void JACK_DoSampleRateConversion(bool value); /* whether the next device that's Open()d should do
|
||||
sample rate conversion if necessary */
|
||||
void JACK_SetSampleRateConversionFunction(int converter); /* which SRC converter function should be used
|
||||
for the next Open()d device */
|
||||
int JACK_Open(int *deviceID, unsigned int bits_per_sample, unsigned long *rate, int channels); /* Note: defaults to 0 input channels
|
||||
if you need input (record) use OpenEx
|
||||
instead */
|
||||
int JACK_OpenEx(int *deviceID, unsigned int bits_per_channel,
|
||||
unsigned long *rate,
|
||||
unsigned int input_channels, unsigned int output_channels,
|
||||
const char **jack_port_name, unsigned int jack_port_name_count,
|
||||
unsigned long jack_port_flags);
|
||||
int JACK_Close(int deviceID); /* return 0 for success */
|
||||
void JACK_Reset(int deviceID); /* free all buffered data and reset several values in the device */
|
||||
long JACK_Write(int deviceID, unsigned char *data, unsigned long bytes); /* returns the number of bytes written */
|
||||
long JACK_Read(int deviceID, unsigned char *data, unsigned long bytes); /* returns the number of bytes read */
|
||||
|
||||
/* state setting values */
|
||||
/* set/get the written/played/buffered value based on a byte or millisecond input value */
|
||||
long JACK_GetPosition(int deviceID, enum pos_enum position, int type);
|
||||
void JACK_SetPosition(int deviceID, enum pos_enum position, long value);
|
||||
|
||||
long JACK_GetJackLatency(int deviceID); /* deprectated, you probably want JACK_GetJackOutputLatency */
|
||||
long JACK_GetJackOutputLatency(int deviceID); /* return the output latency in frames */
|
||||
long JACK_GetJackInputLatency(int deviceID); /* return the input latency in frames */
|
||||
|
||||
int JACK_SetState(int deviceID, enum status_enum state); /* playing, paused, stopped */
|
||||
enum status_enum JACK_GetState(int deviceID);
|
||||
|
||||
long JACK_GetMaxOutputBufferedBytes(int deviceID);
|
||||
long JACK_GetMaxInputBufferedBytes(int deviceID);
|
||||
|
||||
/* bytes that jack requests during each callback */
|
||||
unsigned long JACK_GetJackBufferedBytes(int deviceID);
|
||||
|
||||
/* Properties of the jack driver */
|
||||
|
||||
/* linear means 0 volume is silence, 100 is full volume */
|
||||
/* dbAttenuation means 0 volume is 0dB attenuation */
|
||||
/* Bio2jack defaults to linear */
|
||||
/* Note: volume controls only effect output channels for now */
|
||||
enum JACK_VOLUME_TYPE { linear, dbAttenuation };
|
||||
enum JACK_VOLUME_TYPE JACK_SetVolumeEffectType(int deviceID,
|
||||
enum JACK_VOLUME_TYPE type);
|
||||
|
||||
int JACK_SetAllVolume(int deviceID, unsigned int volume); /* returns 0 on success */
|
||||
int JACK_SetVolumeForChannel(int deviceID, unsigned int channel, unsigned int volume);
|
||||
void JACK_GetVolumeForChannel(int deviceID, unsigned int channel, unsigned int *volume);
|
||||
|
||||
|
||||
unsigned long JACK_GetOutputBytesPerSecond(int deviceID); /* bytes_per_output_frame * sample_rate */
|
||||
unsigned long JACK_GetInputBytesPerSecond(int deviceID); /* bytes_per_input_frame * sample_rate */
|
||||
unsigned long JACK_GetBytesStored(int deviceID); /* bytes currently buffered in the output buffer */
|
||||
unsigned long JACK_GetBytesFreeSpace(int deviceID); /* bytes of free space in the output buffer */
|
||||
unsigned long JACK_GetBytesUsedSpace(int deviceID); /* bytes of space used in the input buffer */
|
||||
unsigned long JACK_GetBytesPerOutputFrame(int deviceID);
|
||||
unsigned long JACK_GetBytesPerInputFrame(int deviceID);
|
||||
|
||||
/* Note: these will probably be removed in a future release */
|
||||
int JACK_GetNumInputChannels(int deviceID);
|
||||
int JACK_GetNumOutputChannels(int deviceID);
|
||||
|
||||
long JACK_GetSampleRate(int deviceID); /* samples per second */
|
||||
|
||||
void JACK_SetClientName(char *name); /* sets the name that bio2jack will use when
|
||||
creating a new jack client. name_%pid%_%deviceID%%counter%
|
||||
will be used
|
||||
NOTE: this defaults to name = bio2jack
|
||||
NOTE: we limit the size of the client name to
|
||||
jack_client_name_size() */
|
||||
|
||||
enum JACK_PORT_CONNECTION_MODE
|
||||
{
|
||||
CONNECT_ALL, /* connect to all avaliable ports */
|
||||
CONNECT_OUTPUT, /* connect only to the ports we need for output */
|
||||
CONNECT_NONE /* don't connect to any ports */
|
||||
};
|
||||
|
||||
/* set the mode for port connections */
|
||||
/* defaults to CONNECT_ALL */
|
||||
void JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode);
|
||||
|
||||
long JACK_OutputStatus(int deviceID,long int *sec, long int *usec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef JACK_OUT_H */
|
||||
1086
veejay-1.3/veejay-server/configure.ac
Normal file
1086
veejay-1.3/veejay-server/configure.ac
Normal file
File diff suppressed because it is too large
Load Diff
336
veejay-1.3/veejay-server/cpuinfo.sh
Executable file
336
veejay-1.3/veejay-server/cpuinfo.sh
Executable file
@@ -0,0 +1,336 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test x"$CC" = x; then
|
||||
CC=gcc
|
||||
fi
|
||||
|
||||
if test $# -ne 1; then
|
||||
echo "Please give the arch (ppc or x86) as an argument!" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test `uname -s` = Darwin; then
|
||||
IsDarwin=yes
|
||||
else
|
||||
IsDarwin=no
|
||||
fi
|
||||
|
||||
target=$1
|
||||
|
||||
cc_version=`$CC -dumpversion`
|
||||
_cc_major=`echo $cc_version | cut -d'.' -f1`
|
||||
_cc_minor=`echo $cc_version | cut -d'.' -f2`
|
||||
|
||||
if test $_cc_major -ge 4; then
|
||||
_opt_mcpu="-mtune"
|
||||
else
|
||||
_opt_mcpu="-mcpu"
|
||||
fi
|
||||
|
||||
do_cc()
|
||||
{
|
||||
$CC -o conftest conftest.c $@ >/dev/null 2>&1
|
||||
}
|
||||
|
||||
extcheck()
|
||||
{
|
||||
cat > conftest.c <<EOF
|
||||
#include <signal.h>
|
||||
void catch() { exit(1); }
|
||||
int main(void){
|
||||
signal(SIGILL, catch);
|
||||
__asm__ __volatile__ ("$1":::"memory");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
|
||||
do_cc
|
||||
if test -x ./conftest; then
|
||||
./conftest
|
||||
if test $? -ne 0; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
do_x86()
|
||||
{
|
||||
|
||||
CFLAGS=-O
|
||||
if test $IsDarwin = yes; then
|
||||
CFLAGS="$CFLAGS -fno-pic -Wl,-read_only_relocs -Wl,suppress"
|
||||
fi
|
||||
|
||||
if test -r /proc/cpuinfo; then
|
||||
_cpuinfo="cat /proc/cpuinfo"
|
||||
else
|
||||
$CC $CFLAGS -o cpuinfo utils/cpuinfo.c
|
||||
_cpuinfo="./cpuinfo"
|
||||
fi
|
||||
|
||||
# Cpu determination logic adapted from the MPlayer configure script.
|
||||
|
||||
pname=`$_cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -n 1`
|
||||
pvendor=`$_cpuinfo | grep 'vendor_id' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1`
|
||||
pfamily=`$_cpuinfo | grep 'cpu family' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1`
|
||||
pmodel=`$_cpuinfo | grep -v 'model name' | grep 'model' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1`
|
||||
pstep=`$_cpuinfo | grep 'stepping' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1`
|
||||
pparam=`$_cpuinfo | grep 'features' | cut -d':' -f2 | head -n 1`
|
||||
|
||||
if test -z "$pparam" ; then
|
||||
pparam=`$_cpuinfo | grep 'flags' | cut -d ':' -f 2 | head -n 1`
|
||||
fi
|
||||
|
||||
_mmx=no
|
||||
_3dnow=no
|
||||
_3dnowex=no
|
||||
_mmx2=no
|
||||
_sse=no
|
||||
_sse2=no
|
||||
_mtrr=no
|
||||
|
||||
for i in $pparam ; do
|
||||
case "$i" in
|
||||
3dnow) _3dnow=yes ;;
|
||||
3dnowext) _3dnow=yes _3dnowex=yes ;;
|
||||
mmx) _mmx=yes ;;
|
||||
mmxext) _mmx2=yes ;;
|
||||
mtrr|k6_mtrr|cyrix_arr) _mtrr=yes ;;
|
||||
xmm|sse|kni) _sse=yes _mmx2=yes ;;
|
||||
sse2) _sse2=yes ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$pvendor" in
|
||||
AuthenticAMD)
|
||||
case "$pfamily" in
|
||||
3)proc=i386
|
||||
;;
|
||||
4) proc=i486
|
||||
;;
|
||||
5) iproc=586
|
||||
# models are: K5/SSA5 K5 K5 K5 ? ? K6 K6 K6-2 K6-3
|
||||
# K6 model 13 are the K6-2+ and K6-III+
|
||||
if test "$pmodel" -eq 9 -o "$pmodel" -eq 13; then
|
||||
proc=k6-3
|
||||
elif test "$pmodel" -ge 8; then
|
||||
proc=k6-2
|
||||
elif test "$pmodel" -ge 6; then
|
||||
proc=k6
|
||||
else
|
||||
proc=i586
|
||||
fi
|
||||
;;
|
||||
6) iproc=686
|
||||
if test "$pmodel" -ge 7; then
|
||||
proc=athlon-4
|
||||
elif test "$pmodel" -ge 6; then
|
||||
if test "$_sse" = yes && test "$pstep" -ge 2; then
|
||||
proc=athlon-xp
|
||||
else
|
||||
proc=athlon-4
|
||||
fi
|
||||
elif test "$pmodel" -ge 4; then
|
||||
proc=athlon-tbird
|
||||
else
|
||||
proc=athlon
|
||||
fi
|
||||
;;
|
||||
15)
|
||||
# Despite what the gcc into says 'athlon64' is not accepted as
|
||||
# synonym for 'k8'
|
||||
proc=k8
|
||||
;;
|
||||
*) proc=athlon-xp
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
GenuineIntel)
|
||||
case "$pfamily" in
|
||||
3) proc=i386
|
||||
;;
|
||||
4) proc=i486
|
||||
;;
|
||||
5) iproc=586
|
||||
if test "$pmodel" -eq 4 || test "$pmodel" -eq 8; then
|
||||
proc=pentium-mmx # 4 is desktop, 8 is mobile
|
||||
else
|
||||
proc=i586
|
||||
fi
|
||||
;;
|
||||
6) iproc=686
|
||||
if test "$pmodel" -ge 15; then
|
||||
proc=nocona
|
||||
elif test "$pmodel" -ge 13; then
|
||||
proc=pentium-m
|
||||
elif test "$pmodel" -ge 7; then
|
||||
proc=pentium3
|
||||
elif test "$pmodel" -ge 3; then
|
||||
proc=pentium2
|
||||
else
|
||||
proc=i686
|
||||
fi
|
||||
;;
|
||||
15) proc=pentium4
|
||||
;;
|
||||
*) proc=pentium4
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
unknown)
|
||||
case "$pfamily" in
|
||||
3) proc=i386
|
||||
;;
|
||||
4) proc=i486
|
||||
;;
|
||||
*) proc=i586
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
proc=i586
|
||||
;;
|
||||
esac
|
||||
|
||||
# check that gcc supports our CPU, if not, fall back to earlier ones
|
||||
|
||||
cat > conftest.c << EOF
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
if test "$proc" = "athlon64" ; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon-xp
|
||||
fi
|
||||
|
||||
if test "$proc" = "athlon-xp" || test "$proc" = "athlon-4" || test "$proc" = "athlon-tbird"; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon
|
||||
fi
|
||||
|
||||
if test "$proc" = "k6-3" || test "$proc" = "k6-2"; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=k6
|
||||
fi
|
||||
|
||||
if test "$proc" = "k6"; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc
|
||||
if test $? -ne 0; then
|
||||
if do_cc -march=i586 $_opt_mcpu=i686; then
|
||||
proc=i586-i686
|
||||
else
|
||||
proc=i586
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$proc" = "pentium4" || test "$proc" = "pentium3" || test "$proc" = "pentium2" || test "$proc" = "athlon"; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=i686
|
||||
fi
|
||||
if test "$proc" = "i686" || test "$proc" = "pentium-mmx"; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=i586
|
||||
fi
|
||||
if test "$proc" = "i586" ; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=i486
|
||||
fi
|
||||
if test "$proc" = "i486" ; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=i386
|
||||
fi
|
||||
if test "$proc" = "i386" ; then
|
||||
do_cc -march=$proc $_opt_mcpu=$proc || proc=error
|
||||
fi
|
||||
if test "$proc" = "error" ; then
|
||||
echo "Your $_cc does not even support \"i386\" for '-march' and $_opt_mcpu."
|
||||
_mcpu=""
|
||||
_march=""
|
||||
elif test "$proc" = "i586-i686"; then
|
||||
_march="-march=i586"
|
||||
_mcpu="$_opt_mcpu=i686"
|
||||
else
|
||||
_march="-march=$proc"
|
||||
_mcpu="$_opt_mcpu=$proc"
|
||||
fi
|
||||
|
||||
if test $_cc_major -ge 3; then
|
||||
extcheck "xorps %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse"
|
||||
extcheck "xorpd %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse2"
|
||||
|
||||
if test x"$_gcc3_ext" != "x"; then
|
||||
# if we had to disable sse/sse2 because the active kernel does not
|
||||
# support this instruction set extension, we also have to tell
|
||||
# gcc3 to not generate sse/sse2 instructions for normal C code
|
||||
cat > conftest.c << EOF
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
do_cc $_march $_gcc3_ext && _march="$_march $_gcc3_ext"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo $_march $_mcpu
|
||||
rm -f conftest.c conftest cpuinfo
|
||||
return 0
|
||||
}
|
||||
|
||||
do_ppc()
|
||||
{
|
||||
# Linux on a PPC has /proc/info
|
||||
# Darwin (OS/X) has the hostinfo command
|
||||
# If neither of those we have no idea what to do - so do nothing.
|
||||
if test -r /proc/cpuinfo; then
|
||||
proc=`grep cpu /proc/cpuinfo | cut -d':' -f2 | cut -d',' -f1 | cut -b 2- | head -n 1`
|
||||
elif test $IsDarwin = yes; then
|
||||
proc=`hostinfo | grep "Processor type" | cut -f3 -d' ' | sed 's/ppc//'`
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$proc" in
|
||||
601) _march="$_opt_mcpu=601" _mcpu='-mtune=601'
|
||||
;;
|
||||
603) _march="$_opt_mcpu=603" _mcpu='-mtune=603'
|
||||
;;
|
||||
603e|603ev) _march="$_opt_mcpu=603e" _mcpu='-mtune=603e'
|
||||
;;
|
||||
604|604e|604r|604ev) _march="$_opt_mcpu=604" _mcpu='-mtune=604'
|
||||
;;
|
||||
740|740/750|745/755) _march="$_opt_mcpu=740" _mcpu='-mtune=740'
|
||||
;;
|
||||
750|750CX) _march="$_opt_mcpu=750" _mcpu='-mtune=750'
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
# gcc 3.1(.1) and up supports 7400 and 7450
|
||||
if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "1" || test "$_cc_major" -ge "4"; then
|
||||
case "$proc" in
|
||||
7400*|7410*) _march="$_opt_mcpu=7400" _mcpu='-mtune=7400' ;;
|
||||
7450*|7455*) _march="$_opt_mcpu=7450" _mcpu='-mtune=7450' ;;
|
||||
*) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# gcc 3.2 and up supports 970
|
||||
if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "3" || test "$_cc_major" -ge "4"; then
|
||||
case "$proc" in
|
||||
970*) if test $IsDarwin = yes; then
|
||||
_march="$_opt_mcpu=G5 -mpowerpc64 -mpowerpc-gpopt -falign-loops=16 -force_cpusubtype_ALL" _mcpu='-mtune=G5'
|
||||
else
|
||||
_march="$_opt_mcpu=970" _mcpu='-mtune=970'
|
||||
fi
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo $_march $_mcpu
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# The script that runs the various functions above
|
||||
#
|
||||
|
||||
if test $target = x86; then
|
||||
do_x86
|
||||
elif test $target = ppc; then
|
||||
do_ppc
|
||||
fi
|
||||
339
veejay-1.3/veejay-server/doc/COPYING
Normal file
339
veejay-1.3/veejay-server/doc/COPYING
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
8
veejay-1.3/veejay-server/doc/HowtoCache.txt
Normal file
8
veejay-1.3/veejay-server/doc/HowtoCache.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Since version 0.9.3 veejay features a caching mechanism to load frames from disk into the system's memory. The cache size is limited to the amount of RAM available in your machine. If the cache is full, Veejay must decide which frames to discard. Veejay will discard the frame furthest away from the current position.
|
||||
|
||||
You can configure the cache with two commandline options:
|
||||
|
||||
-m / --memory [percentage of available RAM to use]
|
||||
-j / --max_chain [maximum number of samples to cache]
|
||||
|
||||
The second option, '-j' is used to divide up the cache memory into a number of equal sized chunks. Veejay will cache by default up to 8 samples into your system's main memory, if you specified the -m option.
|
||||
118
veejay-1.3/veejay-server/doc/HowtoCompile.txt
Normal file
118
veejay-1.3/veejay-server/doc/HowtoCompile.txt
Normal file
@@ -0,0 +1,118 @@
|
||||
|
||||
Compiling Veejay ¶
|
||||
Prerequisities ¶
|
||||
|
||||
Required:
|
||||
|
||||
* MJPEG Tools
|
||||
* FFmpeg
|
||||
* libxml2 for saving project data
|
||||
* SDL for the video window
|
||||
* libdv for playback of DV Video
|
||||
* DirectFB for secundary head (TVOut)
|
||||
* Jack for audio playback
|
||||
* freetype2 for font rendering
|
||||
* libjpegMMX for SIMD optimized JPEG decoding
|
||||
* [http://www.gtk.org GTK-2.4 (GTK 2.6 recommended)
|
||||
* [http://www.gnome.org GdkPixbuf (comes with Gnome)
|
||||
* Cairo (needed for GVeejay Reloaded)
|
||||
* GtkCairo (needed for GVeejay Reloaded)
|
||||
* Libquicktime for Quicktime]
|
||||
* openGL library (gl.h and libGL.so) for the video window
|
||||
* Unicap API for more video input devices]
|
||||
|
||||
You should check with the package manager of your distribution to see if all development packages have been installed, among others this includes:
|
||||
|
||||
* libdv-dev
|
||||
* cairo
|
||||
* jack-dev
|
||||
* glib >= 2.4 dev
|
||||
* gtk >= 2.4 dev
|
||||
* libglade >= 2.2 dev
|
||||
* automake, autoconf, libtool, etc.
|
||||
* linux kernel header files
|
||||
|
||||
If you are one of those lucky users with a distribution without any compiler pre-installed you will need to setup a build system by installing a gcc, automake, autoconf, etc etc.
|
||||
|
||||
* Compiling On Ubuntu: doc/HowtoUbuntu.txt
|
||||
|
||||
Preperation ¶
|
||||
Configuration ¶
|
||||
|
||||
Before running configure, check if the PKG_CONFIG_PATH variable is setup correctly:
|
||||
|
||||
$ echo $PKG_CONFIG_PATH
|
||||
|
||||
If echo is silent, you must set the PKG_CONFIG_PATH to point to the directory containing all your .pc files (like for example libdv.pc or jack.pc )
|
||||
|
||||
$ find /usr -name libdv.pc
|
||||
/usr/local/lib/pkgconfig/libdv.pc
|
||||
|
||||
$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
||||
|
||||
1. Get the sources from Veejay's repository:
|
||||
|
||||
$ svn co svn://dyne.org/veejay/trunk/veejay/current
|
||||
|
||||
2. Enter the source directory and run autogen.sh
|
||||
|
||||
$ cd veejay-current
|
||||
$ sh autogen.sh
|
||||
|
||||
3. Run ./configure
|
||||
|
||||
$ ./configure
|
||||
|
||||
If you want to disable the graphical interfaces for some reason, use:
|
||||
|
||||
$ ./configure --without-gveejayreloaded --without-gveejay
|
||||
|
||||
Building ¶
|
||||
|
||||
Type 'make' to build veejay
|
||||
|
||||
$ make
|
||||
|
||||
Installing ¶
|
||||
|
||||
$ sudo make install
|
||||
|
||||
or
|
||||
|
||||
$ su
|
||||
# make install
|
||||
|
||||
Running veejay ¶
|
||||
|
||||
Test if veejay works:
|
||||
|
||||
$ veejay -d -n
|
||||
|
||||
To run veejay without accelerated display:
|
||||
|
||||
$ veejay -O5 -d -n
|
||||
|
||||
To run veejay in verbose mode:
|
||||
|
||||
$ veejay -O5 -d -n -v
|
||||
|
||||
To run veejay with openGL display:
|
||||
|
||||
$ veejay -O4 -d -n
|
||||
|
||||
Start another terminal and type:
|
||||
|
||||
$ gveejayreloaded
|
||||
|
||||
or
|
||||
|
||||
$ gveejayreloaded -n
|
||||
|
||||
Stopping veejay ¶
|
||||
|
||||
Open another terminal
|
||||
|
||||
$ sayVIMS "600:;"
|
||||
|
||||
(or press CTRL-C in the terminal running veejay)
|
||||
|
||||
13
veejay-1.3/veejay-server/doc/HowtoPlugins.txt
Normal file
13
veejay-1.3/veejay-server/doc/HowtoPlugins.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
¶
|
||||
|
||||
First, you need to create a file to tell veejay where to find plugins.
|
||||
|
||||
$ mkdir ~/.veejay
|
||||
$ vi ~/.veejay/plugins
|
||||
|
||||
The contents of the file can look like:
|
||||
|
||||
/usr/local/lib/freeframe
|
||||
/usr/local/lib/frei0r-1
|
||||
|
||||
Veejay will pick up the plugins the next time you start it.
|
||||
77
veejay-1.3/veejay-server/doc/HowtoUbuntu.txt
Normal file
77
veejay-1.3/veejay-server/doc/HowtoUbuntu.txt
Normal file
@@ -0,0 +1,77 @@
|
||||
Which packages do I need ? ¶
|
||||
|
||||
You will need about 200 megabytes of available diskspace, this includes the packages below and the space needed for building veejay.
|
||||
|
||||
* subversion
|
||||
* cvs
|
||||
* build-essentials
|
||||
* autogen
|
||||
* autotools-dev
|
||||
* autoconf
|
||||
* automake1.8
|
||||
* libtool
|
||||
* libsdl1.2-dev
|
||||
* libjack0.100.0-dev
|
||||
* libquicktime-dev
|
||||
* libxml2-dev
|
||||
* libglade2-dev
|
||||
* libgtk2.0-dev
|
||||
|
||||
Which packages do I need to compile myself ? ¶
|
||||
|
||||
* mjpegtools
|
||||
|
||||
|
||||
If there is a compile error in Region2D.hh, complaining about 'assert' insert a line in top of the file '#include <assert.h>'
|
||||
|
||||
* libunicap
|
||||
* FFmpeg
|
||||
* GTK Cairo
|
||||
|
||||
cvs -d :pserver:anoncvs@cvs.cairographics.org:/cvs/cairo co gtkcairo
|
||||
cd gtkcairo
|
||||
sh autogen.sh
|
||||
./configure && make && sudo make install
|
||||
|
||||
WARNING ¶
|
||||
|
||||
I use ffmpeg from source, I suggest you do the same. There are unmet dependencies in libavcodec-dev and libavformat-dev that relate to ogg,vorbis,theora, *1394* packages in Ubuntu 6.06.
|
||||
|
||||
$ sudo apt-get remove libavcodec-dev libavformat-dev
|
||||
$ svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
|
||||
$ cd ffmpeg
|
||||
$ ./configure --help
|
||||
|
||||
Disable what you dont need, then:
|
||||
|
||||
$ ./configure --prefix=/usr --enable-shared ...
|
||||
$ make && make install
|
||||
|
||||
And continue building veejay
|
||||
Building veejay ¶
|
||||
|
||||
Check if the PKG_CONFIG_PATH variable has been set properly.
|
||||
|
||||
$ echo $PKG_CONFIG_PATH
|
||||
|
||||
If you just ran 'configure' and 'make' for mjpegtools,libunicap etc, check if the accompanying .pc files are in /usr/local/lib/pkgconfig
|
||||
|
||||
$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
|
||||
|
||||
To get the latest veejay:
|
||||
|
||||
$ svn co svn://dyne.org/veejay/trunk/veejay-current
|
||||
|
||||
To build a veejay optimized for speed:
|
||||
|
||||
$ sh autogen.sh
|
||||
$ ./configure
|
||||
$ make && sudo make install
|
||||
|
||||
To build a veejay to send usefull bugreports:
|
||||
|
||||
$ sh autogen.sh
|
||||
$ ./configure --enable-debug
|
||||
$ make && sudo make install
|
||||
|
||||
|
||||
503
veejay-1.3/veejay-server/doc/HowtoVeejay-PureData.html
Normal file
503
veejay-1.3/veejay-server/doc/HowtoVeejay-PureData.html
Normal file
@@ -0,0 +1,503 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="SGML-Tools 1.0.9">
|
||||
<title>Using sendVIMS to write simple control paches for veejay in
|
||||
PureData</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Using sendVIMS to write simple control paches for veejay in PureData</h1>
|
||||
<h2>M. van Henten cola at looze.net</h2>
|
||||
V0.01 104-10-09
|
||||
<hr><em>
|
||||
<!--
|
||||
sendVIMS
|
||||
-->SendVIMS is a Puredata external written by Niels
|
||||
Elburg and Tom Schouten. It is a control interface to veejay, a
|
||||
realtime video processing package.
|
||||
I will explain some of my work using both tools together.</em>
|
||||
<hr>
|
||||
<h2><a name="s1">1. Introduction</a></h2>
|
||||
<p>
|
||||
<!--
|
||||
sendVIMS!introduction
|
||||
--> SendVIMS is a Puredata external written
|
||||
by Niels Elburg and Tom Schouten. It is a control interface to veejay,
|
||||
a realtime video processing package. VIMS stands for 'Veejay's Internal
|
||||
Messaging System.<br>
|
||||
I have been working with veejay
|
||||
for a long time now so I took my knowledge of what it could do and
|
||||
built a few paches that will demonstrate the power of building
|
||||
interactive controls for veejay. This might be interesting for the
|
||||
newcomers to linux video, but also for the experienced who want to know
|
||||
more about veejay, and puredata although it is not intended as step by
|
||||
step guide on how to use PureData or veejay( Especially since I'm
|
||||
rather new to PureData), but I will try to explain some basics on how
|
||||
to get this working.
|
||||
</p>
|
||||
<h2>1.1 Copyright</h2>
|
||||
<p>This document is Copyright © 104-10-09 M. van Henten.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the GNU Free Documentation License, Version 1.1 or
|
||||
any later version published by the Free Software Foundation with no
|
||||
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
|
||||
</p>
|
||||
<h2>1.2 Disclaimer</h2>
|
||||
<p>Use the information in this document at your own risk. I disavow any
|
||||
potential liability for the contents of this document. Use of the
|
||||
concepts, examples, and/or other content of this document is entirely
|
||||
at your own risk.
|
||||
</p>
|
||||
<p>All copyrights are owned by their owners, unless specifically noted
|
||||
otherwise. Use of a term in this document should not be regarded as
|
||||
affecting the validity of any trademark or service mark.
|
||||
</p>
|
||||
<p>Naming of particular products or brands should not be seen as
|
||||
endorsements.
|
||||
</p>
|
||||
<p>You are strongly recommended to take a backup of your system before
|
||||
major installation and backups at regular intervals.
|
||||
</p>
|
||||
<h2>1.3 News</h2>
|
||||
<p>9-10-2004
|
||||
Started Writing first draft to this howto, after finishing up on some
|
||||
basic patches.
|
||||
</p>
|
||||
<h2>1.4 Credits</h2>
|
||||
<p>Many thanks to of course to Tom Schouten en Niels Elburg for
|
||||
creating this tool, thanks to Niels for creating veejay after numerous
|
||||
sessions of feature dreaming, and continue working on it to create more
|
||||
then we ever fantasized about. </p>
|
||||
<p>Also, much obliged to the people in te PureData community, who
|
||||
helped me getting started in the first place.Thanks to Derek Holzer,
|
||||
who introduced me to PD and showed me how easy and fun PD was.
|
||||
</p>
|
||||
<p>A thankyou should be in place for the people at BEK (
|
||||
http://www.bek.no) Who brought a lot of video guys in the OS world
|
||||
together, and made this collaboration possible in the first place.
|
||||
</p>
|
||||
<h2><a name="s2">2. Technologies</a></h2>
|
||||
<p style="font-weight: bold;">2.1 Expected Skills<br>
|
||||
</p>
|
||||
<p>I assume that you know how to work with the linux commandline.
|
||||
Veejay is ( up to this date) mainly a console application ( besides the
|
||||
video bit of course) and you <span
|
||||
style="font-weight: bold; font-style: italic;">need to type stuff</span><span
|
||||
style="font-style: italic;"> </span>to get it working. If this is all
|
||||
too strange for you, I would advice you to get know a bit more of linux
|
||||
first, by reading some magazines, and some howto's ( <a
|
||||
href="http://www.tldp.org">the linux documentation project</a> has a
|
||||
lot of howto's) like the <a
|
||||
href="http://tldp.org/HOWTO/DOS-Win-to-Linux-HOWTO.html">windows/dos
|
||||
to linux howto</a>. <br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">2.2 Veejay</span><br>
|
||||
</p>
|
||||
<p>First of all, you need to download and install a later version of
|
||||
veejay. In this document, I used veejay-0.6.2. Any version before
|
||||
0.5.9 will not work as expected, or not at all together with SendVims. <br>
|
||||
</p>
|
||||
<p>Veejay sources are located <a href="http://veejay.sourceforge.net">http://veejay.sourceforge.net</a>,
|
||||
or go directly to the <a href="http://www.sf.net/projects/veejay">sourceforge
|
||||
download area</a>.<br>
|
||||
Installation is standard: open a shell, or terminal, unpack the package
|
||||
somehwere, go into the newly created directory, and type:<br>
|
||||
</p>
|
||||
<p>./configure<br>
|
||||
</p>
|
||||
<p>when configure has finished, something like:<br>
|
||||
</p>
|
||||
<p> <small><span
|
||||
style="font-family: courier new,courier,monospace;">veejay 0.6.2 build
|
||||
configuration :</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;"> Build
|
||||
configuration:</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
MMX
|
||||
enabled
|
||||
: true</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
MMX2
|
||||
enabled
|
||||
: false</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
SSE
|
||||
enabled
|
||||
: true</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
3DNow
|
||||
enabled
|
||||
: false</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
CMOV
|
||||
enabled
|
||||
: true</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
glibc support for >2GB files : true</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;"> Required
|
||||
dependencies:</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
POSIX Threads (pthread)
|
||||
: true</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
video4linux recording/playback : true</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
Simple Direct Media Layer : true</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
XML C library for Gnome libxml2 : true</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
libJPEG
|
||||
: true</span><br style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;"> Optional
|
||||
dependencies:</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
libDV (digital
|
||||
video)
|
||||
: true</span><br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
Jack Audio Connection Kit : true</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
DirectFB
|
||||
support
|
||||
: false</span></small><br>
|
||||
<br>
|
||||
</p>
|
||||
Should appear.<br>
|
||||
<br>
|
||||
Note that veejay depends on the <a href="http://www.xmlsoft.org/">XML
|
||||
C library</a> ( it comes as part of the GNOME libraries and desktop)
|
||||
and <a href="http://www.libsdl.org">SDL</a>, if you don't have these
|
||||
packages you should install them. <a
|
||||
href="http://libdv.sourceforge.net">Libdv</a> is optional, for being
|
||||
able to play dv type 2 format avi's, <a
|
||||
href="http://jackit.sourceforge.net">jack</a> is optional but needed
|
||||
if you want to hear sound with your movies. <br>
|
||||
<br>
|
||||
Describing how to get jack working optimal is not within the scope of
|
||||
this document, I can only say that if you have jack setup properly
|
||||
veejay should be able to output sound. <br>
|
||||
<br>
|
||||
When this is done, do a "make" followed by a "make install".<br>
|
||||
Veejay should now be installed. Get some movie to edit( you can borrow
|
||||
one from me <a href="http://cola.looze.net/sendvims/video/">here</a>) <br>
|
||||
<p style="font-weight: bold;">2.2 PureData</p>
|
||||
<p>PureData is a whole story upon itself. Please read the installation
|
||||
notes and documentation on <a href="http://www.puredata.org">http://www.puredata.org</a>.
|
||||
You can verify if everything works by just running pd, goto help en
|
||||
check out some of the example paches. Using the documentation
|
||||
from within pd you should at least get some basic understanding.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">2.3 SendVims</span><br>
|
||||
</p>
|
||||
<p>In this document I used sendVIMS-0.1. <br>
|
||||
This is compied from the README in sendVIMS-0.1.tar.gz :<br>
|
||||
<br>
|
||||
</p>
|
||||
<p><small><span style="font-family: courier new,courier,monospace;">sendVIMS
|
||||
- very simple VeeJay client for pure data</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
(C) 2002-2004 Niels Elburg <elburg@hio.hen.nl></span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">
|
||||
(C) 2004 Tom Schouten <doelie@zzz.kotnet.org></span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">This is free
|
||||
software covered under the terms of the</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">GNU GPL. See
|
||||
the file COPYING for details.</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">building:</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">./configure
|
||||
&& make && make install</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">'make
|
||||
install' copies these files to your pd directory:</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;"><prefix>/lib/pd/extra/sendVIMS.pd_linux</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;"><prefix>/lib/pd/doc/5.reference/help-sendVIMS.pd</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">the default
|
||||
<prefix> is /usr/local</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">running:</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<br style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">if the module
|
||||
is in your pd path it will be loaded automaticly.</span></small><br>
|
||||
</p>
|
||||
<h2><a name="s3">3. Implementation</a></h2>
|
||||
<p><span style="font-weight: bold;">3.1 Get veejay running</span><br>
|
||||
</p>
|
||||
<p>To start veejay, you need to start it with a video file. Veejay only
|
||||
plays avi files, so no quicktime, or mpeg movies.<br>
|
||||
Veejay only knows of two types of video codecs: mjpeg and DV type 2.0. <br>
|
||||
So to get veejay running, you need at least one mjpeg or DV type 2.0
|
||||
.avi file. These formats were chosen with some reasons, explained in
|
||||
the veejay-howto. Converting into codecs and other formats is a whole
|
||||
science upon itself, and I do intend to write a crash course into video
|
||||
and linux in the future. For creating mjpeg avi's I use the <a
|
||||
href="mjpeg.sourceforge.net">lavtools</a> and <a
|
||||
href="www.mplayerhq.hu">mplayer</a>, and veejay itself.<br>
|
||||
</p>
|
||||
<p><a href="http://cola.looze.net/sendvims/video">You can grab a one
|
||||
second mjpeg avi from here.</a><br>
|
||||
</p>
|
||||
<p>This is copyright free material I transcoded out of a movie from <a
|
||||
href="http://www.archive.org">archive.org</a><br>
|
||||
Start veejay by opening up a terminal window such as xterm and type: <br>
|
||||
</p>
|
||||
<p style="font-family: courier new,courier,monospace;"><small>veejay
|
||||
mymovie.avi</small></p>
|
||||
<p>If you used the example one second avi, it will briefly play the
|
||||
whole movie and stop at the last frame. Move your mouse into the video
|
||||
window. As long as the mouse pointer is inside the video window, you
|
||||
can use the built in keyboard controls. press keypad-5, this pauzes
|
||||
playback. now press keypad-1, to skip to the start of your movie. press
|
||||
the [ key, this marks 'clip start', press keypad-3, to skip to the end
|
||||
of the movie, and press the ] key, this marks the 'clip end'. You can
|
||||
now sellect your clip by pressing the F1 key. the movie will
|
||||
automatically keep looping. you can alterate loopmode by pressing
|
||||
keypad-*. try some other keypad keys to see what they do. See 'man
|
||||
veejay' for the other controls.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">3.2 Running PD/SendVIMS</span><br>
|
||||
</p>
|
||||
<p>Open up a terminal window such as xterm and type:<br>
|
||||
</p>
|
||||
<p><small style="font-family: courier new,courier,monospace;">pd</small><br>
|
||||
</p>
|
||||
<p>You'll need the terminal to get some feedback from pd. From the file
|
||||
menu of pd, choose 'new'. In the new window, choose 'put > object'. <br>
|
||||
A rectangular object appears under your mousepointer. Click somewhere
|
||||
in the white area of the window, and type "sendVIMS" inside the object.
|
||||
If you installed the sendVIMS external properly, you should read
|
||||
in the terminal:<br>
|
||||
</p>
|
||||
<p><small><span style="font-family: courier new,courier,monospace;">sendVIMS:
|
||||
version 0.1</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">sendVIMS: (c)
|
||||
2004 Niels Elburg & Tom Schouten</span><br
|
||||
style="font-family: courier new,courier,monospace;">
|
||||
<span style="font-family: courier new,courier,monospace;">sendVIMS:
|
||||
connected to localhost:3490</span></small><br>
|
||||
</p>
|
||||
<p>That's it! you should now be able to right-click on the sendVIMS
|
||||
object, and choose 'help' from the popup window. <br>
|
||||
You are now properly set up to use sendVIMS and veejay. Please refer to
|
||||
some of the examples I provide under 'examples' for more information.
|
||||
You should note that my examples will work right away, even without
|
||||
understanding PD in the first place, but they are not intended as a
|
||||
tutorial on how to use PD. you should see the 'help' menu and various
|
||||
resources around the web for that!.<br>
|
||||
</p>
|
||||
<p><br>
|
||||
</p>
|
||||
<h2><a name="s4">4. Troubleshooting</a></h2>
|
||||
<p><span style="font-weight: bold;">
|
||||
4.1 Veejay doesn't start!</span><br>
|
||||
</p>
|
||||
<p>You need to start veejay from a terminal, using a proper encoded avi
|
||||
file. you can use the <a href="http://cola.looze.net/sendvims/video">demo</a>
|
||||
file if you don't have one.<br>
|
||||
Please refer to veejay documentation and maillinglist.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">4.2 SendVIMS doesn't work, PD tells
|
||||
me it can't create sendvims.</span><br>
|
||||
</p>
|
||||
<p>The sendVIMS-0.1 external is not installed. please install the
|
||||
external and restart PD.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">4.3 I have a different problem,
|
||||
please help me.</span><br>
|
||||
</p>
|
||||
<p>If the problem is relevant to this document please <a
|
||||
href="mailto:cola@looze.net">mail</a> me and I'll add it here. Try the
|
||||
PD and veejay maillinglist otherwise.<br>
|
||||
</p>
|
||||
<h2><a name="s5">5. Further Information</a></h2>
|
||||
<p><span style="font-weight: bold;">5.1 HOWTO's and documentation</span><br>
|
||||
</p>
|
||||
<p>The veejay howto can be found here: <a
|
||||
href="http://veejay.sourceforge.net/veejay-HOWTO.html">http://veejay.sourceforge.net/veejay-HOWTO.html</a><br>
|
||||
PureData documentation is here: <a
|
||||
href="http://www.puredata.org">http://www.puredata.org</a><br>
|
||||
</p>
|
||||
<p>I have have been working on some more patches besides the ones in
|
||||
the examples, they're on my personal homepage:<br>
|
||||
<a href="http://cola.looze.net/sendvims/">http://cola.looze.net/sendvims/</a></p>
|
||||
<p><br>
|
||||
<span style="font-weight: bold;">5.2 Email, Mailinglists</span></p>
|
||||
<p>Please post your questions to the veejay mailinglist, you can
|
||||
subscribe <a href="http://sourceforge.net/mail/?group_id=47564">here</a>.<br>
|
||||
<br>
|
||||
</p>
|
||||
<h2><a name="s6">6. Examples</a></h2>
|
||||
<p><span style="font-weight: bold;">6.1 Basic Example: play, play
|
||||
backwards.</span><br>
|
||||
</p>
|
||||
<p>In PD, you send a message by creating a message object, type the
|
||||
message into that object, and connect the output of the message to the
|
||||
sendVIMS object.<br>
|
||||
</p>
|
||||
<p><img src="VIMS-example-play.jpg" title=""
|
||||
alt="Screenhost of example patch" style="width: 326px; height: 288px;"><br>
|
||||
</p>
|
||||
<p>In this example, I used PD aliasses: video.play.forward, and
|
||||
video.play.backward. Normally, most VIMS messages are represented as
|
||||
numbers, preceded by a 'p', for example, p100 stands for 'select and
|
||||
play sample' followed by an argument. In the following example, you can
|
||||
select different clips to play in veejay by changing the number inside
|
||||
the number box. ( you can make diferent clips in veejay when in 'plain
|
||||
video' mode, by pressing keypad '/'. Use keypad play controls to select
|
||||
different frame positions, use the [ and ] keys to mark in and
|
||||
outpoints of clips, use the function keys to select samples with the
|
||||
keyboard controls).<br>
|
||||
</p>
|
||||
<p>6.2 Set the playing clip with an argument.<br>
|
||||
</p>
|
||||
<p><img src="VIMS-example-setframe.jpg" title=""
|
||||
alt="Set the playing clip with an argument"
|
||||
style="width: 326px; height: 288px;"><br>
|
||||
</p>
|
||||
<p>The $1 takes the number from the number box, and together with the
|
||||
p100 message it gives the command "select and play sample $1" to
|
||||
veejay. Note, that since PD doesn't know how many clips we have here,
|
||||
we can select non-existing clips. We can give negative numbers. veejay
|
||||
will give an error message.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">6.3 Getting status output from
|
||||
veejay.</span><br>
|
||||
</p>
|
||||
<p>This example shows how to get information you need from veejay: for
|
||||
example the current frame. <br>
|
||||
</p>
|
||||
<p><img src="VIMS-example-getstatus.jpg" title=""
|
||||
alt="Example of getting status information"
|
||||
style="width: 326px; height: 288px;"><br>
|
||||
</p>
|
||||
<p>Now, there are two number boxes. When playing clips, the first
|
||||
number box will display the current frame, but when playing in plain
|
||||
video, the second box outputs the current frame. Veejay sends it's
|
||||
status in one big string of numbers, seperated by spaces. all
|
||||
information comes in at the same time. You can use the 'unpack' object
|
||||
to split the information in smaller chunks. notice how many outputs it
|
||||
has - there are lots of status messages to be read. I have made a patch
|
||||
that helps me remember what goes where, and I include it as a subpatch
|
||||
when working with sendVIMS. You can find it on my personal weppage: <a
|
||||
href="http://cola.looze.net/sendvims">http://cola.looze.net/sendvims</a>.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">6.4 Controlling video effects.</span><br>
|
||||
</p>
|
||||
<p>Veejay has many video effects. you can find out what kind of effects
|
||||
on veejay's homepage, in the gallery section. For this next example,
|
||||
you need two different clips. Assuming that you are working with the
|
||||
example movie, press Keypad-5 for pauze, and Keypad-1 to go to the
|
||||
start of the movie. Mark the beginning of your first clip here. Now, we
|
||||
gently scrub to frame 12 in the movie using Keypad-9 - it skips one
|
||||
frame ahead at a time - and mark the end of the first clip, and, on the
|
||||
same frame, the beginning of the second clip, and at the last frame of
|
||||
the movie, the end of the second clip( HINT: you could use the
|
||||
"video.set.frame <frame>" message here instead).<br>
|
||||
You should have two samples now, which you can select with the F1 and
|
||||
F2 keys. Lets start with selecting the first clip and have a look at
|
||||
the example:<br>
|
||||
</p>
|
||||
<p><img src="VIMS-example4-videomixer.jpg" title=""
|
||||
alt="example of effect controls" style="width: 561px; height: 414px;"><br>
|
||||
</p>
|
||||
<p>The first message sets up the effect chain. Veejay can chain
|
||||
multiple effects on top of eachother, like layers in an image editing
|
||||
program. In this example, it sets effect 4 on current playing sample (
|
||||
the number zero in the VIMS messages that control effects always stands
|
||||
for the current playing clip, as a convenience. you could also replace
|
||||
the number with a variable, and read it from veejay's output to know
|
||||
the current clip).<br>
|
||||
Effect 4 is the "Normal Overlay" effect, it simply mixes two video like
|
||||
a videomixer.<br>
|
||||
</p>
|
||||
<p>The second message controls the clip the overlay effect mixes with.
|
||||
Put it to 2 to mix with our second clip. <br>
|
||||
The third message is a PD message, that controls the boundaries of the
|
||||
slider. Normally, sliders have value 0 to 127 by default. the overlay
|
||||
effect has only one controll, opacity, and it is mesured in value 0 to
|
||||
255, so I want the slider to have boundaries ranging 0 to 255.<br>
|
||||
The slider is connected to the third message: control parameter 0 of
|
||||
the effect on chain-entry 3 of the current playing clip.<br>
|
||||
The order of these values is typical: first, tell which sample to
|
||||
select. second, what effect chain entry, third, which control
|
||||
parameter, and last, the value of that parameter. <br>
|
||||
You can make a dump of the effects numbers and the VIMS messages by
|
||||
running:<br>
|
||||
</p>
|
||||
<p><small><span style="font-family: courier new,courier,monospace;">veejay
|
||||
--dump-events -d > veejay-events.txt<br>
|
||||
</span></small></p>
|
||||
<p>The last message, "connect localhost 3490" actually (re)connects the
|
||||
sendVIMS object to veejay if not already connected. You can use the
|
||||
message "disconnect" and "quit", too, have a look at the sendVIMS
|
||||
helpfile.<br>
|
||||
</p>
|
||||
<p><span style="font-weight: bold;">6.5 More advanced playback control:
|
||||
scrubbing.</span><br>
|
||||
</p>
|
||||
<p>This example shows two things: One slider can be used to set a new
|
||||
play position in a clip, the other shows the play position in the
|
||||
current clip.<br>
|
||||
Both sliders get their boundaries updated with the starting position of
|
||||
the clip and the ending position. This only works in the 'clip' mode,
|
||||
not when playing in plain video.<br>
|
||||
</p>
|
||||
<p><img src="VIMS-example5-scrubbing.jpg" title=""
|
||||
alt="Example of controlling play position with a slider"
|
||||
style="width: 372px; height: 396px;"><br>
|
||||
</p>
|
||||
<p>From the status, the starting frame and the end frame of the current
|
||||
playing clip are read, which sets the boundaries of both sliders. The
|
||||
slider in the top of the patch controls message p089: set frame $1, the
|
||||
slider in the bottom gets updated with the 'current frame of clip'
|
||||
information.<br>
|
||||
However, when switching from clip to plain video mode, this will no
|
||||
longer work as the outputs get different status updates. Switching
|
||||
between clips wil work perfectly however.<br>
|
||||
</p>
|
||||
<p>More advanced combinations are possible. PD offers a lot of
|
||||
functionality, such as MIDI, joystick controls and controlling things
|
||||
through sound. Some more examples of my work are on my personal
|
||||
website. <br>
|
||||
</p>
|
||||
<p><br>
|
||||
</p>
|
||||
<p><br>
|
||||
</p>
|
||||
<p><br>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
83
veejay-1.3/veejay-server/doc/HowtoVideoCodecs.txt
Normal file
83
veejay-1.3/veejay-server/doc/HowtoVideoCodecs.txt
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
Video files ¶
|
||||
|
||||
A video file consists out of TWO seperate elements:
|
||||
|
||||
* container
|
||||
* codec
|
||||
|
||||
The container holds the digitally encoded data and the codec is capable of decoding/encoding this digitally encoded data.
|
||||
|
||||
Veejay supports the AVI and the Quicktime container , with the following codecs:
|
||||
|
||||
Quicktime:
|
||||
|
||||
* mpjeg,mjpa,jpeg,dmb1
|
||||
* dvsd, dv, dvcp, dvhd
|
||||
|
||||
AVI
|
||||
|
||||
* mjpeg, mjpa,jpeg,jfif,dmb1
|
||||
* dvsd, dv, dvcp, dvhd
|
||||
* i420, i422, yv16, hfyu
|
||||
|
||||
Raw DV
|
||||
|
||||
* PAL / NTSC dvsd
|
||||
|
||||
Veejay can only deal with video files that consists entirely out of whole images (only I-frames). The codecs below will only work if all frames are I-frames. Otherwise, veejay will abort with an error message.
|
||||
|
||||
AVI / Quicktime:
|
||||
|
||||
* xvid, mp4v,divx,dxsd,mp4s,m4s2
|
||||
* div3,mp43,mp42,mpg4
|
||||
* avc1,h264,x264,davc,svq1,svq3,avc1
|
||||
|
||||
Wich codec to use ¶
|
||||
|
||||
MotionJPEG ( mjpeg) is the veejay codec of choice for most applications, it gives you a good tradeof between compression, quality and compatibility. If you want speed, use AVI yv16 or i420 while recording to new samples.
|
||||
|
||||
Tools that support MJPEG:
|
||||
|
||||
* http://cvs.cinelerra.org/Cinelerra
|
||||
* http://www.kinodv.org/Kino
|
||||
* http://ronald.bitfreak.net/lvs/Linux video studio
|
||||
* http://mjpeg.sourceforge.net/mjpegtools
|
||||
* http://www.mplayerhq.huMplayer, and mencoder
|
||||
* http://lives.sf.net Lives
|
||||
|
||||
Wich resolutions to use ¶
|
||||
|
||||
Veejay can do:
|
||||
|
||||
* high definition (use MLZO/YUV avi)
|
||||
* pal: 720x576 (recommended to use MLZO/YUV avi)
|
||||
* ntsc: 720x480
|
||||
* 1/4 pal: 360x288 (any)
|
||||
* 1/4 ntsc: 360x240 (any)
|
||||
|
||||
If you load multiple video files on the commandline, make sure that all files have the same resolution and audio properties.
|
||||
How to convert ¶
|
||||
|
||||
Veejay can convert dv video to mjpeg for you, however, I prefer to use mplayer for this, wich has more flexibility.
|
||||
|
||||
From "anything" mplayer can play to mjpeg, use:
|
||||
|
||||
$ mencoder -ovc lavc -oac pcm -lavcopts vcodec=mjpeg -o <outputfile> <inputfile>
|
||||
|
||||
To scale on the fly, use:
|
||||
|
||||
$ mencoder -ovc lavc -oac pcm -lavcopts vcodec=mjpeg -vf scale=352:288 -o <outputfile> <inputfile>
|
||||
|
||||
consult mplayer documentation about other options, such as cropping and filtering out blocks in video.
|
||||
|
||||
a quick hint for bulk encoding a bunch of capture.dv files:
|
||||
|
||||
$ for i in `ls *dv`;do mencoder -ovc lavc -oac pcm -lavcopts vcodec=mjpeg -o `echo $i | sed s/.dv/.avi/` $i; done;
|
||||
|
||||
What is this dummy mode ¶
|
||||
|
||||
Dummy mode opens up a 'color stream' to start veejay without a video file.
|
||||
|
||||
If you use a video file, veejay will take that file's properties as default settings for the whole session.
|
||||
|
||||
182
veejay-1.3/veejay-server/doc/INSTALL
Normal file
182
veejay-1.3/veejay-server/doc/INSTALL
Normal file
@@ -0,0 +1,182 @@
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, a file
|
||||
`config.cache' that saves the results of its tests to speed up
|
||||
reconfiguring, and a file `config.log' containing compiler output
|
||||
(useful mainly for debugging `configure').
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. You can give `configure'
|
||||
initial values for variables by setting them in the environment. Using
|
||||
a Bourne-compatible shell, you can do that on the command line like
|
||||
this:
|
||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
||||
|
||||
Or on systems that have the `env' program, you can do it like this:
|
||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not supports the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a time
|
||||
in the source code directory. After you have installed the package for
|
||||
one architecture, use `make distclean' before reconfiguring for another
|
||||
architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' can not figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it can not guess the host type, give it the
|
||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name with three fields:
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the host type.
|
||||
|
||||
If you are building compiler tools for cross-compiling, you can also
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for and the `--build=TYPE' option to select the type of
|
||||
system on which you are compiling the package.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Operation Controls
|
||||
==================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Use and save the results of the tests in FILE instead of
|
||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
||||
debugging `configure'.
|
||||
|
||||
`--help'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--version'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
105
veejay-1.3/veejay-server/doc/NET.txt
Normal file
105
veejay-1.3/veejay-server/doc/NET.txt
Normal file
@@ -0,0 +1,105 @@
|
||||
|
||||
Veejay can stream over the Network
|
||||
=================================================
|
||||
|
||||
With -p you can give Veejay's port offset
|
||||
|
||||
TCP socket for sending commands: + 0 (sayVIMS -h)
|
||||
TCP socket for receiving status: + 1 (gveejay)
|
||||
TCP socket for querying commands:+ 2 (gveejay - editlist/sampellist etc)
|
||||
UDP multicast frame sender : + 3 (input stream multicast/other applications)
|
||||
UDP multicast for sending commands: + 4 (sayVIMS -g)
|
||||
|
||||
|
||||
How to activate:
|
||||
|
||||
1. veejay movie1.avi
|
||||
2. veejay movie2.avi -p 5000
|
||||
|
||||
(Both movie clips must have identical properties!!)
|
||||
|
||||
veejay 2 makes a connection with veejay 1
|
||||
|
||||
3. sayVIMS "245:localhost 3490;" -p 5000 -h localhost
|
||||
|
||||
4. move mouse to veejay2 video window and press 'ESC'
|
||||
|
||||
if everything is OK, the video will be playing.
|
||||
|
||||
5. stop veejay1 (CTRL-C)
|
||||
|
||||
6. veejay2 will show last frame (press ESC)
|
||||
|
||||
7. restart veejay1
|
||||
|
||||
8. press 'ESC' in veejay2 to resume streaming (auto-reconnect)
|
||||
|
||||
Veejay can stream over the Network (UDP / Multicast )
|
||||
=====================================================
|
||||
|
||||
How to activate:
|
||||
|
||||
1. veejay -V 224.0.0.50 -p 5000 -v movie1.avi
|
||||
2. veejay -d -W <movie1 width> -H <movie1 height>
|
||||
|
||||
3. sayVIMS -h localhost -p 3490 "246:5000 224.0.0.50;"
|
||||
4. press F7 to activate newest created stream
|
||||
|
||||
|
||||
Veejay can receive OSC (Open Sound Control) messages over Multicast protocol
|
||||
============================================================================
|
||||
How to activate:
|
||||
|
||||
1. veejay --multicast 224.0.0.30 movie1.avi
|
||||
|
||||
Note that you must have 'multicast' enabled in your kernel configuration.
|
||||
Use the tool 'mcastOSC' in test/OSC to send OSC messages to all
|
||||
veejay's you have started with --multicast (on multiple hosts!!)
|
||||
|
||||
2. export MCAST_ADDR=224.0.0.30
|
||||
4. mcastOSC -r 3495
|
||||
|
||||
|
||||
Veejay can send/receive VIMS (Veejay Internal Message System) packets
|
||||
over Multicast protocol
|
||||
=============================================================================
|
||||
|
||||
How to activate:
|
||||
|
||||
1. veejay --multicast-vims 224.0.0.32 movie1.avi
|
||||
2. veejay --multicast-vims 224.0.0.32 movie2.avi
|
||||
|
||||
3. sayVIMS -g 224.0.0.32 -f test/vims/magicmirror-vims.txt
|
||||
|
||||
|
||||
How to setup multicast?
|
||||
=======================
|
||||
1. enable 'multicast' in kernel configuration
|
||||
|
||||
2. type 'route add -net 224.0.0.0 netmask 255.255.255.0 dev eth0'
|
||||
(or something similar, read the man page of route to figure out
|
||||
what addresses are reserved for multicast)
|
||||
|
||||
What is multicast?
|
||||
==================
|
||||
|
||||
Multicasts enables you to (ab)use the network topology to transmit
|
||||
packets to multiple hosts.
|
||||
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
1. Veejay can only stream to another veejay
|
||||
2. All veejays must have identical video properties (fps,width,height, ... )
|
||||
3. Veejay will drop frames when it cannot keep up (or when packets are dropped)
|
||||
4. Audio is not supported
|
||||
|
||||
What header format?
|
||||
===================
|
||||
|
||||
see libvjnet/packet.h for multicast packet definition
|
||||
|
||||
for peer-to-peer streaming, the first 11 bytes of the buffer indicate
|
||||
width, height and format in plain ASCII: "%04d %04d %1d"
|
||||
|
||||
22
veejay-1.3/veejay-server/doc/README.performance
Normal file
22
veejay-1.3/veejay-server/doc/README.performance
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
Veejay's performace depends much on the memory bandwith, CPU and disk access.
|
||||
|
||||
For HDTV (1280x720) mjpeg, you need at least a 2.5 ghz. The faster the better.
|
||||
|
||||
For full PAL/NTSC resolutions (720x576 resp. 720x480) DV/Mjpeg you need at least a 1.5 ghz,
|
||||
for lower resolution (352x288) you can do fine with a 500-800 mhz PC.
|
||||
|
||||
If you need to record without framedrop, you can do so by disabling audio and
|
||||
disabling synchronization with the commandline options -a0 -c0
|
||||
|
||||
On newer PC's (pentium4) your best bet is working in RAW or MLZO (compressed)
|
||||
YUV 4:2:0 / 4:2:2 On my pentium 4 , 3.0 ghz playing a AVI file that contains RAW YUV frames
|
||||
uses about 3-4% for a full PAL movie and 10-12% for mixing 2 movies.
|
||||
The tradeoff here is your diskspeed. You could use compression, this reduces the
|
||||
size of the videofile anywhere between 0-30% .
|
||||
|
||||
Typical for laptops is slow diskspeed access, on my 1.8 ghz dell latitude laptop
|
||||
the best I get is an average of about 20.0 mb/sec which is barely sufficient
|
||||
for playing full PAL avi's containing RAW YUV.
|
||||
(you can test yours with hdparm -T -t /dev/hdX)
|
||||
|
||||
110
veejay-1.3/veejay-server/doc/README.quickstart
Normal file
110
veejay-1.3/veejay-server/doc/README.quickstart
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
It is advised to read the howto and the MAN page as well.
|
||||
|
||||
You can launch veejay with
|
||||
|
||||
$ veejay -d
|
||||
|
||||
This should show some moving black/white footage. Most of the effects will be boring on this footage,
|
||||
so you can try to open your video4linux device with
|
||||
|
||||
sayVIMS "240:0 1;" (device 0, channel 1)
|
||||
|
||||
Or, to use mplayer, create a FIFO first:
|
||||
|
||||
$ mkfifo stream.yuv
|
||||
|
||||
Use something like 'mplayer -vo yuv4mpeg -x 352 -y 288 -vf scale -zoom'
|
||||
|
||||
and open the stream in veejay's console:
|
||||
|
||||
sayVIMS "243:stream.yuv;"
|
||||
|
||||
Move your mouse pointer to the SDL window (so it dissapears) and press 'ESC' to
|
||||
switch from the dummy footage to the last created or played video stream.
|
||||
|
||||
Try loading an AVI file with something like:
|
||||
|
||||
$ veejay -v mjpeg-video-file.avi
|
||||
|
||||
The '-v' commandline option generates extra debugging output.
|
||||
|
||||
By default, veejay uses a SDL window for displaying video. You can specify veejay to
|
||||
write to STDOUT :
|
||||
|
||||
$ veejay -O3 -o stdout mjpeg-video-file.avi | yuvplay
|
||||
|
||||
In this mode, the console input and SDL keyboard functions are disabled. You must use
|
||||
the sendVIMS commandline utility to interact with veejay or with an alternative utility like sendOSC.
|
||||
Refer to the howto for more information.
|
||||
|
||||
|
||||
Once you have loaded veejay (preferably with a videofile)
|
||||
|
||||
(see man veejay for an overview of both console input and SDL keyboard events)
|
||||
|
||||
press 'KP 1' , 'left bracket', 'KP 3', 'right bracket' , 'F1'
|
||||
|
||||
This will create a virtual clip (in memory) from your entire video file.
|
||||
|
||||
If you press 'KP divide' , veejay will return to plain video mode so you can create more clips.
|
||||
If you press 'ESC' , veejay will switch from playing streams to playing clips or vice versa
|
||||
|
||||
Press F1 to F12 to select a clip,
|
||||
press 1 to 9 to select a bank (1 = clips 1 to 12, 2 = clips 12 to 24, etc )
|
||||
|
||||
Once you are playing a clip/stream, simply press
|
||||
'Cursor UP' , 'ENTER'
|
||||
|
||||
If you add a video effect, try pressing '-' and '=' to select another channel and '/' to
|
||||
toggle between clip/stream sources
|
||||
|
||||
|
||||
Veejay supports chaining of effects since day 0, a number of keys have some importance
|
||||
|
||||
'-' ,'=' and '/'
|
||||
|
||||
'END' for enabling/disabling the chain
|
||||
'KP -' for selecting the previous entry
|
||||
'KP +' for selecting the next entry
|
||||
'ALT+END' for enabling/disabling the current selected entry
|
||||
'ENTER' for adding an effect from the list to the chain
|
||||
'DEL' for removing an effect from the chain
|
||||
|
||||
|
||||
Also, you can press 'HOME' to see clip or stream information.
|
||||
|
||||
Try the keys 'A' to 'L' to increase/decrease playback speed.
|
||||
|
||||
|
||||
Also, you can load some predefined custom effect chain templates that
|
||||
will put a template on your effect chain when you press SHIFT + some alphabetic character
|
||||
|
||||
First, load an action file
|
||||
|
||||
$ veejay -l test/livecinema/action-file.xml
|
||||
|
||||
Or in veejay's console
|
||||
|
||||
> al test/livecinema/action-file.xml
|
||||
|
||||
(activate a stream or clip and) press SHIFT+S or SHIFT+B or SHIFT+ ...
|
||||
|
||||
|
||||
Except all that, try this:
|
||||
|
||||
|
||||
sayVIMS -h localhost -p 3490 "241:63;"
|
||||
(press F7)
|
||||
|
||||
to open your dv1394 firewire device
|
||||
|
||||
or
|
||||
sayVIMS -h localhost -p 3490 "240:0 1;"
|
||||
(press F7)
|
||||
|
||||
to open your video4linux device /dev/video0, channel 1
|
||||
|
||||
|
||||
|
||||
Enjoy!
|
||||
16
veejay-1.3/veejay-server/doc/README.whatis
Normal file
16
veejay-1.3/veejay-server/doc/README.whatis
Normal file
@@ -0,0 +1,16 @@
|
||||
Veejay is a live performance tool featuring simple non-linear editing and mixing from multiple sources. You can load multiple video clips, cut and paste portions of video/audio and save it as an EditList. Also, you can record new clips from existing clips or (live) streams. With these clips you can change playback speed (slow motion/acceleration), change the looptype and set markers.
|
||||
|
||||
With both clips and streams you can edit the effect chain and mix from multiple sources to one. Veejay has a 84+ effects, divided into two categories: Image and Video Effects, only with Video Effects you can select a channel to mix in.
|
||||
|
||||
Veejay has many frame blending methods, some of these are: Additive,Substractive,Difference Negate, Relative Addition and Selective Replacement. Next to blending, you can key on Luma and Chroma seperatly or combined or simply use Transitions or other effects.
|
||||
|
||||
Most edit and navigation commands are mapped to single key press commands, this allows you to control, depending on the playback mode, video navigation, the effect chain, effect parameters and clip properties at playback time.
|
||||
|
||||
Also, you can record a new clip on the fly from a live feed or from the video clip you are playing. If requested, the recorded videofile will be added to the edit descision list and activated as a new video clip. This is particular usefull for time-looping,rebouncing and rough clip scratching/editing
|
||||
|
||||
Veejay can be remotely controled through using OSC (Open Sound Control) or via its own internal message interface 'VIMS'. 'VIMS' allows you to create/load/save effect chain templates and to add customized events which can be triggered by a keypress or a remote message.
|
||||
|
||||
Veejay supports streaming from multiple video sources to one, this can be a Video4Linux device , a vloopback device or a yuv4mpeg stream. You can chain several veejays with effectv and vice versa to create some amazing footage.
|
||||
|
||||
|
||||
veejay is licensed as Free Software (GNU).
|
||||
318
veejay-1.3/veejay-server/doc/VIMS.txt
Normal file
318
veejay-1.3/veejay-server/doc/VIMS.txt
Normal file
@@ -0,0 +1,318 @@
|
||||
1. VIMS is Veejay's IMS (Internal Message System)
|
||||
=================================================
|
||||
|
||||
All control data is distributed via VIMS. Each (atomical) message consists of an Action Identifier
|
||||
and a list of zero or more Arguments which can be used to control Video Clips, Video Streams,
|
||||
the Effect Chain and many other things.
|
||||
|
||||
VIMS allows events to be triggered through:
|
||||
|
||||
SDL Keyboard Event (libsdl)
|
||||
OSC (OpenSoundControl)
|
||||
IMP (Internal Message Protocol)
|
||||
|
||||
|
||||
After intalling veejay, you will have a commandline utility 'sayVIMS'
|
||||
|
||||
This document describes what messages you can send to veejay through using VIMS
|
||||
|
||||
Inside of veejay's source package you will find a test/ directory containing various examples demonstrating
|
||||
how to load an ActionFile, how to use Perl for batch like video processing and how to attach message bundles to
|
||||
keyboard events.
|
||||
|
||||
|
||||
Use the command
|
||||
|
||||
$ veejay -u -n |less
|
||||
|
||||
to see documentation generated by veejay on using Effects, VIMS and OSC.
|
||||
If there is an error in the documentation, you have found a bug in veejay
|
||||
and should report it :)
|
||||
|
||||
1.1 Message Format
|
||||
==================
|
||||
|
||||
A message is described as:
|
||||
|
||||
<Action Identifer> : <Argument List> ;
|
||||
|
||||
Example:
|
||||
|
||||
080:;
|
||||
099:0 0;
|
||||
|
||||
|
||||
<Action Identifier>
|
||||
The action identifier is a 3 digit number describing a Network Event
|
||||
The colon is used to indicate the start of the Argument List and must be given.
|
||||
|
||||
|
||||
<Argument List>
|
||||
The Argument List is described by a printf() style formatted template
|
||||
which describes the number and type of arguments to be used.
|
||||
|
||||
The semicolon must be given to indicate the end of this message
|
||||
|
||||
|
||||
|
||||
1.2 Bundled Messages
|
||||
====================
|
||||
|
||||
A message bundle is a special message that contains an ordered list of at least 1 or more messages. Each message is executed from left to right (first in, first out) while parsing the bundle.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
5032|BUN:002{361:0 3 56 230 93 0;361:0 4 1 7;}|
|
||||
5033|BUN:003{361:0 3 56 230 93 0;361:0 4 1 7;361:0 5 1 7;}|
|
||||
5034|BUN:003{361:0 3 56 230 93 0;361:0 4 1 7;361:0 5 1 8;}|
|
||||
|
||||
|
||||
A message bundle is described as:
|
||||
|
||||
BUN: <Number of Messages> {
|
||||
<Action Idenfifier> : <Argument List> ;
|
||||
<Action Identifier> : <Argument List> ;
|
||||
...
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
The token 'BUN:' indicates the start of a messaage bundle, the first 3 digit numeric value represents the total number of messages in the bundle. The '{' symbol indicates the start of a message block and is ended with '};' or just '}'.
|
||||
|
||||
|
||||
1.3 Format of an Action File/Attaching Keys to Bundles
|
||||
======================================================
|
||||
|
||||
<501 - 599> | <message bundle> |
|
||||
|
||||
The contents of some action file can be :
|
||||
|
||||
516|BUN:001{355:;}|
|
||||
|
||||
|
||||
|
||||
The message bundle BUN sends '355' for clear effect chain.
|
||||
This message bundle is attached to action identifier 516.
|
||||
|
||||
A key is attached to this function trough using the GUI (GVeejay)
|
||||
or by using:
|
||||
|
||||
|
||||
DYNAMIC KEYMAPPING:
|
||||
==================
|
||||
|
||||
"083:516 <sdl symbol> <modifier> <optional arguments>;"
|
||||
|
||||
|
||||
The message bundle can be attached to a key , for example 'SHIFT + A' by sending
|
||||
|
||||
083:516 97 3;
|
||||
|
||||
Which attaches bundle '516' to SDL key '97' using a modifier '3', which is SHIFT.
|
||||
|
||||
Modifiers: 0 = none, 1 = alt , 2 = ctrl, 3 = shift
|
||||
Keys : see SDLkeysym.h somewhere in include/SDL/
|
||||
|
||||
If the number 0 is used for an event number, a given key combination can be
|
||||
unset (wiped) :
|
||||
|
||||
083:0 97 3;
|
||||
|
||||
Alternativly, you can bind keys to any action identifier. The complete
|
||||
list can be viewd by typing veejay -u |less or with Gveejay.
|
||||
|
||||
083:20 97 0 4;
|
||||
|
||||
The example above sets key 'a' to 'change video speed to 4'
|
||||
|
||||
|
||||
|
||||
General description of VIMS messages
|
||||
=====================================
|
||||
|
||||
|
||||
Some reserved numbers:
|
||||
|
||||
clip id 0 : select currently playing clip
|
||||
clip id -1 : select highest clip number
|
||||
chain entry -1 : select current chain entry
|
||||
stream id 0 : select currently playing stream
|
||||
stream id -1 : select highest stream number
|
||||
key modifier : 0 = normal, 1= alt , 2 = ctrl, 3 = shift
|
||||
frame -1 : use highest possible frame number (usually num video frames)
|
||||
playback mode : 0 = clip, 1 = stream, 2 = plain
|
||||
data format : yv16 (yuv 4:2:2 raw) , mpeg4, divx, msmpeg4v3,
|
||||
div3, dvvideo, dvsd, mjpeg, i420 and yv12 (yuv 4:2:0 raw)
|
||||
loop type : 0 = no looping, 1 = normal loop, 2 = pingpong (bounce) loop
|
||||
|
||||
|
||||
What follows now is a general description of argument formatting and its ordering.
|
||||
In the future, veejay -u will describe all VIMS arguments as well.
|
||||
I wont put it into this document, since auto documentation will work much better
|
||||
(eliminating the need to update this documentation when things change).
|
||||
|
||||
all EditList commands, the arguments represent frame numbers (from 0 - max frames)
|
||||
|
||||
For example;
|
||||
021:10 100; will copy frames 10-100 into a temporary buffer
|
||||
020:100; will insert the frames 10-100 from the temporary buffer on frame 100
|
||||
|
||||
|
||||
For all Clip commands, the first argument always represent the clip number except for 099
|
||||
(create new clip) which takes 2 arguments ; starting and ending positions.
|
||||
The arguments that may follow usually represent a number to describe either a property setting
|
||||
(like speed, slow motion or looptype) and in other cases relative or real frame numbers.
|
||||
|
||||
Idem for Streams.
|
||||
|
||||
In general, for Chain commands the first argument is also the clip or stream number.
|
||||
The second (or following arguments) usually represent the property setting or some value.
|
||||
|
||||
For example; 178 (fade in) takes 2 arguments. The first is to identify the clip number,
|
||||
the second describes the duration (in frames) for the fade in.
|
||||
|
||||
181 (set effect with defaults) takes 3 arguments. Again, the first is to identify a clip or
|
||||
stream, the second for the chain entry and the last for the effect number.
|
||||
Idem for 182, but here starting from the 4th argument it takes preset values
|
||||
|
||||
|
||||
|
||||
|
||||
2. OSC - Open Sound Control
|
||||
============================
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
|
||||
(quote from the website)
|
||||
|
||||
OpenSound Control ("OSC") is a protocol for communication among computers, sound synthesizers
|
||||
and other multimedia devices that is optimized for modern networking technology.
|
||||
|
||||
Veejay starts up an OSC server that listens on port number VJ_PORT + 2 (usually 3492).
|
||||
In the veejay/libOMC/send+dump you can compile a test application that sends OSC strings to veejay.
|
||||
Bundled messages are handled automatically by libOMC
|
||||
|
||||
|
||||
Type veejay -u |less to see an overview of all actions, it includes OSC. The OSC messages
|
||||
are mapped onto its respective VIMS Action Identifiers.
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
To create a new clip and play it:
|
||||
|
||||
/clip/new 100 200
|
||||
/clip/select 0
|
||||
|
||||
To record from a clip and auto play the recording after 10 seconds of PAL video:
|
||||
|
||||
/clip/record/start 250 1
|
||||
|
||||
To add Effect 45 to the clip's Effect Chain
|
||||
|
||||
/clip/chain/entry/add 45
|
||||
|
||||
To fade in the Effect Chain in 4 seconds
|
||||
|
||||
/clip/chain/fade_in 100
|
||||
|
||||
To add Effect 45 on Entry 4 of clip 2's Effect Chain
|
||||
|
||||
/clip/chain/add 2 4 45
|
||||
|
||||
To play newest clip
|
||||
|
||||
/clip/select
|
||||
|
||||
To record from a clip and auto play the new clip after recording
|
||||
|
||||
/clip/record 100 1
|
||||
|
||||
|
||||
|
||||
currently, OSC support in veejay is meant for triggering only.
|
||||
Some users have showed genuine interest in building user interfaces for Veejay using
|
||||
this protocol. However, for such thing bi-directional communication is required
|
||||
(i.e. current frame number, current playing clip, total number of clips, etc etc)
|
||||
|
||||
In veejay, VIMS provides a status port that can be read which will provide all kind
|
||||
of status information but it is not mapped to OSC yet.
|
||||
|
||||
Also, in the veejay source package you will find a utility 'mcastOSC'
|
||||
(which is not installed by default)
|
||||
|
||||
Build instructions (from veejay top source directory)
|
||||
|
||||
$ cd test/OSC
|
||||
$ cd libOSC
|
||||
$ make
|
||||
$ cd ..
|
||||
$ cd send+dump
|
||||
$ make
|
||||
|
||||
Start veejay with -M or --multicast-osc , and use mcastOSC to control
|
||||
all instances of veejay listening on the given multicast address.
|
||||
(One tool to rule all).
|
||||
|
||||
|
||||
SAVING/RESTORING Veejay states
|
||||
===============================
|
||||
Example configuration file (with most options)
|
||||
|
||||
<config>
|
||||
<run_settings>
|
||||
<port_num>3490</port_num>
|
||||
<!- the port number veejay listens on ->
|
||||
<SDLwidth>352</SDLwidth>
|
||||
<SDLheight>288</SDLheight>
|
||||
<!- SDL video window dimensions ->
|
||||
<audio>1</audio>
|
||||
<!- Start with audio turned on ->
|
||||
<sync>1</sync>
|
||||
<!- Try to keep in sync ->
|
||||
<timer>2</timer>
|
||||
<!- Use system clock ->
|
||||
<output_fps>3</output_fps>
|
||||
<!- Set a different output framerate (only affects playback) ->
|
||||
<Xgeom_x>0</Xgeom_x>
|
||||
<Xgeom_y>0</Xgeom_y>
|
||||
<!- Use X geometry offset (from root window) ->
|
||||
<bezerk>1</bezerk>
|
||||
<!- Bezerk is enabled by default ->
|
||||
<nocolor>0</nocolor>
|
||||
<!- No colored console output ->
|
||||
<chrominance_level>1</chrominance_level>
|
||||
<!- YUV 4:2:2 ->
|
||||
<output_width>352</output_width>
|
||||
<output_height>288</output_height>
|
||||
<!- Output video dimensions (real width and height) ->
|
||||
<dummy_fps>0.000000</dummy_fps>
|
||||
<video_norm>0</video_norm>
|
||||
<dummy>0</dummy>
|
||||
<mcast_osc>0</mcast_osc>
|
||||
<!- Dont use OSC multicast send/receive ->
|
||||
<mcast_vims>0</mcast_vims>
|
||||
<!- Dont use VIMS multicast send/receive ->
|
||||
<output_scaler>0</output_scaler>
|
||||
<!- Dont use the software output scaler (depends on output_widhth ->
|
||||
<!- and output_height ) ->
|
||||
</run_settings>
|
||||
</config>
|
||||
|
||||
|
||||
Initially, you can setup veejay on the commandline and tell it to save
|
||||
its settings in a configuration file.
|
||||
|
||||
veejay -z 1 -W 720 -H 576 /tmp/videofile.avi -p 5000
|
||||
|
||||
(in another terminal)
|
||||
|
||||
sayVIMS -h localhost -p 5000 "084:/tmp/config.tmp 1;"
|
||||
|
||||
In this file, not only the configuration is stored :
|
||||
Bundled VIMS events, valid VIMS identifiers and Keymappings are
|
||||
stored here.
|
||||
|
||||
|
||||
23
veejay-1.3/veejay-server/doc/YCbCr.txt
Normal file
23
veejay-1.3/veejay-server/doc/YCbCr.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
Veejay processing
|
||||
=================
|
||||
|
||||
Veejay processes nativly in YUV, this is to keep colorspace conversions
|
||||
to a minimum.
|
||||
|
||||
YUV 4:2:0 Planar ( 1 Cr and 1 Cb sample per 2x2 Y samples)
|
||||
YUV 4:2:2 Planar ( 1 Cr and 1 Cr sample per 1x2 Y samples)
|
||||
(both full range JPEG and clipped to 16-235 / 16-240)
|
||||
|
||||
Places where veejay uses software conversion:
|
||||
Conversion from RGB to YUV is for webcam devices.
|
||||
Conversion from YUV to RGB is for preview image
|
||||
Some FX convert the frame to RGB
|
||||
|
||||
Why YUV ?
|
||||
=========
|
||||
|
||||
- Many video codecs decode into some YUV flavour
|
||||
- Many capture devices deliver YUV
|
||||
- Software conversion of RGB <-> YUV is expensive
|
||||
- Consumes less bandwith then RGB
|
||||
|
||||
1439
veejay-1.3/veejay-server/doc/veejay-HOWTO.html
Normal file
1439
veejay-1.3/veejay-server/doc/veejay-HOWTO.html
Normal file
File diff suppressed because it is too large
Load Diff
1
veejay-1.3/veejay-server/libOSC/AUTHORS
Normal file
1
veejay-1.3/veejay-server/libOSC/AUTHORS
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
16
veejay-1.3/veejay-server/libOSC/Makefile.am
Normal file
16
veejay-1.3/veejay-server/libOSC/Makefile.am
Normal file
@@ -0,0 +1,16 @@
|
||||
INCLUDES = -I$(top_srcdir)/libOSC -I$(includedir)
|
||||
AM_CFLAGS=$(OP_CFLAGS)
|
||||
OSC_LIB_FILE = libOSC.la
|
||||
noinst_LTLIBRARIES = $(OSC_LIB_FILE)
|
||||
libOSC_la_CFLAGS = $(AM_CFLAGS)
|
||||
libOSC_la_SOURCES = OSC-address-space.c \
|
||||
OSC-callbacklist.c \
|
||||
OSC-drop.c \
|
||||
OSC-pattern-match.c \
|
||||
OSC-priority-queue.c \
|
||||
OSC-receive.c \
|
||||
OSC-string-help.c \
|
||||
OSC-common.c \
|
||||
OSC-timetag.c \
|
||||
NetworkReturnAddress.c
|
||||
|
||||
0
veejay-1.3/veejay-server/libOSC/NEWS
Normal file
0
veejay-1.3/veejay-server/libOSC/NEWS
Normal file
58
veejay-1.3/veejay-server/libOSC/NetworkReturnAddress.c
Normal file
58
veejay-1.3/veejay-server/libOSC/NetworkReturnAddress.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
/*
|
||||
NetworkReturnAddress.c
|
||||
|
||||
This version implements UDP return addresses on SGI
|
||||
|
||||
Matt Wright,
|
||||
9/11/98
|
||||
*/
|
||||
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-address-space.h>
|
||||
#include <libOSC/NetworkReturnAddress.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <libOSC/NetworkUDP.h>
|
||||
|
||||
|
||||
|
||||
int SizeOfNetworkReturnAddress(void) {
|
||||
return sizeof(struct NetworkReturnAddressStruct);
|
||||
}
|
||||
|
||||
Boolean NetworkSendReturnMessage(NetworkReturnAddressPtr addr,
|
||||
int n,
|
||||
void *buf) {
|
||||
if (addr == 0) return FALSE;
|
||||
|
||||
return n == sendto(addr->sockfd, buf, n, 0, &(addr->cl_addr), addr->clilen);
|
||||
}
|
||||
52
veejay-1.3/veejay-server/libOSC/NetworkReturnAddress.h
Normal file
52
veejay-1.3/veejay-server/libOSC/NetworkReturnAddress.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
NetworkReturnAddress.h
|
||||
|
||||
API that the OSC Kit uses to deal with network return addresses. You will
|
||||
fill in parts of this file and write NetworkReturnAddress.c to implement
|
||||
this API via whatever network services you use.
|
||||
|
||||
NB: This API is the only interface the Kit uses for dealing with network
|
||||
addresses, but of course the part of the application that accepts incoming
|
||||
packets needs to know about network return addresses so it can fill in the
|
||||
correct return address when it receives a packet.
|
||||
|
||||
Matt Wright,
|
||||
6/3/98
|
||||
*/
|
||||
|
||||
/* Return sizeof(struct NetworkReturnAddressStruct). */
|
||||
int SizeOfNetworkReturnAddress(void);
|
||||
|
||||
/* Send a packet back to the client, or do nothing if addr==0 */
|
||||
Boolean NetworkSendReturnMessage(NetworkReturnAddressPtr addr,
|
||||
int n,
|
||||
void *buf);
|
||||
7
veejay-1.3/veejay-server/libOSC/NetworkUDP.h
Normal file
7
veejay-1.3/veejay-server/libOSC/NetworkUDP.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct NetworkReturnAddressStruct {
|
||||
struct sockaddr_in cl_addr;
|
||||
int clilen;
|
||||
int sockfd;
|
||||
};
|
||||
599
veejay-1.3/veejay-server/libOSC/OSC-address-space.c
Normal file
599
veejay-1.3/veejay-server/libOSC/OSC-address-space.c
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
OSC-address-space.c
|
||||
Matt Wright, 3/16/98
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-address-space.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_ALIASES_PER_CONTAINER 3
|
||||
#define MAX_CHILDREN_PER_CONTAINER 20
|
||||
#define MAX_METHODS_PER_CONTAINER 30
|
||||
#define BASE_NUM_TO_REALLOCATE 10
|
||||
|
||||
|
||||
struct OSCContainerStruct {
|
||||
struct OSCContainerStruct *parent;
|
||||
int numChildren;
|
||||
Name childrenNames[MAX_CHILDREN_PER_CONTAINER];
|
||||
struct OSCContainerStruct *children[MAX_CHILDREN_PER_CONTAINER];
|
||||
int numMethods;
|
||||
Name methodNames[MAX_METHODS_PER_CONTAINER];
|
||||
OSCMethod methods[MAX_METHODS_PER_CONTAINER];
|
||||
struct OSCContainerQueryResponseInfoStruct QueryResponseInfo;
|
||||
struct OSCContainerStruct *next;
|
||||
};
|
||||
|
||||
struct OSCMethodStruct {
|
||||
methodCallback callback;
|
||||
void *context;
|
||||
struct OSCMethodQueryResponseInfoStruct QueryResponseInfo;
|
||||
struct OSCMethodStruct *next;
|
||||
};
|
||||
|
||||
/* Globals */
|
||||
static Boolean Initialized = FALSE;
|
||||
static OSCcontainer OSCTopLevelContainer;
|
||||
static OSCcontainer freeContainers; /* Linked list via next field. */
|
||||
static OSCMethod freeMethods; /* Linked list via next field. */
|
||||
static void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||
|
||||
|
||||
/* Note: The free list of containers should actually be a "free forest", so
|
||||
that all the subcontainers recursively under a freed container are
|
||||
automatically freed.
|
||||
|
||||
FREE: just stick the freed subtree on the front of the list.
|
||||
|
||||
ALLOC: Take all the children of the first container on the list and
|
||||
insert them in the free list, then return that first container.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/************************ Initialization and Memory ************************/
|
||||
|
||||
static void MakeFreeContainersList(int n) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i+1 < n; ++i) {
|
||||
freeContainers[i].next = &(freeContainers[i+1]);
|
||||
}
|
||||
freeContainers[n-1].next = 0;
|
||||
}
|
||||
|
||||
static void MakeFreeMethodsList(int n) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i+1 < n; ++i) {
|
||||
freeMethods[i].next = &(freeMethods[i+1]);
|
||||
}
|
||||
freeMethods[n-1].next = 0;
|
||||
}
|
||||
|
||||
OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) {
|
||||
int bytesNeeded;
|
||||
|
||||
if (Initialized)
|
||||
fatal_error("OSCInitAddressSpace: already initialized!");
|
||||
Initialized = TRUE;
|
||||
|
||||
RealTimeMemoryAllocator = t->RealTimeMemoryAllocator;
|
||||
|
||||
bytesNeeded = (1 + t->initNumContainers) * sizeof(*freeContainers);
|
||||
freeContainers = (OSCcontainer) (*(t->InitTimeMemoryAllocator))(bytesNeeded);
|
||||
if (freeContainers == 0) {
|
||||
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers",
|
||||
bytesNeeded, t->initNumContainers);
|
||||
}
|
||||
|
||||
OSCTopLevelContainer = &freeContainers[t->initNumContainers];
|
||||
MakeFreeContainersList(t->initNumContainers);
|
||||
|
||||
bytesNeeded = t->initNumMethods * sizeof(*freeMethods);
|
||||
freeMethods = (OSCMethod) (*(t->InitTimeMemoryAllocator))(bytesNeeded);
|
||||
if (freeMethods == 0) {
|
||||
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d methods",
|
||||
bytesNeeded, t->initNumMethods);
|
||||
}
|
||||
MakeFreeMethodsList(t->initNumMethods);
|
||||
|
||||
/* Initialize the top-level container */
|
||||
OSCTopLevelContainer->parent = 0;
|
||||
OSCTopLevelContainer->numChildren = 0;
|
||||
OSCTopLevelContainer->numMethods = 0;
|
||||
OSCTopLevelContainer->QueryResponseInfo.comment = "OSC top-level container";
|
||||
OSCTopLevelContainer->next = 0;
|
||||
|
||||
return OSCTopLevelContainer;
|
||||
}
|
||||
|
||||
|
||||
/* Container and method memory management: linked lists of free objects */
|
||||
|
||||
static OSCcontainer AllocContainer(void) {
|
||||
static int numExtraAllocs = 0;
|
||||
|
||||
OSCcontainer result;
|
||||
if (freeContainers != 0) {
|
||||
result = freeContainers;
|
||||
freeContainers = freeContainers->next;
|
||||
return result;
|
||||
}
|
||||
|
||||
OSCWarning("Out of memory for containers; trying to allocate more in real time");
|
||||
{
|
||||
int num = BASE_NUM_TO_REALLOCATE * ++numExtraAllocs;
|
||||
freeContainers = (*RealTimeMemoryAllocator)(num * sizeof(*freeContainers));
|
||||
if (freeContainers == 0) {
|
||||
OSCWarning("Real-time allocation failed");
|
||||
return 0;
|
||||
}
|
||||
MakeFreeContainersList(num);
|
||||
return AllocContainer();
|
||||
}
|
||||
}
|
||||
|
||||
//static void FreeContainer(OSCcontainer c) {
|
||||
// c->next = freeContainers;
|
||||
// freeContainers = c;
|
||||
//}
|
||||
|
||||
static OSCMethod AllocMethod(void) {
|
||||
static int numExtraAllocs = 0;
|
||||
OSCMethod result;
|
||||
|
||||
if (freeMethods != 0) {
|
||||
result = freeMethods;
|
||||
freeMethods = freeMethods->next;
|
||||
return result;
|
||||
}
|
||||
|
||||
OSCWarning("Out of memory for methods; trying to allocate more in real time");
|
||||
{
|
||||
int num = BASE_NUM_TO_REALLOCATE * ++numExtraAllocs;
|
||||
freeMethods = (*RealTimeMemoryAllocator)(num * sizeof(*freeMethods));
|
||||
if (freeMethods == 0) {
|
||||
OSCWarning("Real-time allocation failed");
|
||||
return 0;
|
||||
}
|
||||
MakeFreeMethodsList(num);
|
||||
return AllocMethod();
|
||||
}
|
||||
}
|
||||
|
||||
//static void FreeMethod(OSCMethod c) {
|
||||
// c->next = freeMethods;
|
||||
// freeMethods = c;
|
||||
//}
|
||||
|
||||
|
||||
/**************************** Containers ****************************/
|
||||
|
||||
/* Managing the tree of containers and subcontainers, with aliases */
|
||||
|
||||
void AddSubContainer(OSCcontainer parent, OSCcontainer child, Name name) {
|
||||
if (parent->numChildren >= MAX_CHILDREN_PER_CONTAINER) {
|
||||
fatal_error("AddSubContainer: exceeded MAX_CHILDREN_PER_CONTAINER (%d)\n"
|
||||
"Increase the value in OSC-address-space.c and recompile.",
|
||||
MAX_CHILDREN_PER_CONTAINER);
|
||||
}
|
||||
|
||||
parent->childrenNames[parent->numChildren] = name;
|
||||
parent->children[parent->numChildren] = child;
|
||||
++(parent->numChildren);
|
||||
}
|
||||
|
||||
|
||||
Boolean OSCAddContainerAlias(OSCcontainer container, Name otherName) {
|
||||
if (container->parent->numChildren >= MAX_CHILDREN_PER_CONTAINER) {
|
||||
return FALSE;
|
||||
}
|
||||
AddSubContainer(container->parent, container, otherName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void RemoveSubContainer(OSCcontainer parent, OSCcontainer child) {
|
||||
int i, numRemoved;
|
||||
|
||||
/* Remove every pointer to the container, even if it has multiple aliases */
|
||||
|
||||
numRemoved = 0;
|
||||
for (i = 0; i < parent->numChildren; ++i) {
|
||||
if (parent->children[i] != child) {
|
||||
parent->children[i-numRemoved] = parent->children[i];
|
||||
parent->childrenNames[i-numRemoved] = parent->childrenNames[i];
|
||||
} else {
|
||||
++numRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
parent->numChildren -= numRemoved;
|
||||
|
||||
if (numRemoved == 0) {
|
||||
fatal_error("RemoveSubContainer: subcontainer not found!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Boolean OSCRemoveContainerAlias(OSCcontainer container, Name otherName) {
|
||||
int i, j;
|
||||
OSCcontainer parent = container->parent;
|
||||
Boolean found = FALSE;
|
||||
|
||||
for (i = 0; i < parent->numChildren; ++i) {
|
||||
if (parent->childrenNames[i] == otherName) {
|
||||
if (parent->children[i] != container) {
|
||||
fatal_error("OSCRemoveContainerAlias: %s is actually a sibling's name!",
|
||||
otherName);
|
||||
}
|
||||
found = TRUE;
|
||||
for (j = i+1; j < parent->numChildren; ++j) {
|
||||
parent->children[j-1] = parent->children[j];
|
||||
parent->childrenNames[j-1] = parent->childrenNames[j];
|
||||
--(parent->numChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fatal_error("OSCRemoveContainerAlias: %s not found!", otherName);
|
||||
}
|
||||
|
||||
/* Now make sure the child still exists under another name */
|
||||
for (i = 0; i < parent->numChildren; ++i) {
|
||||
if (parent->children[i] == container) return TRUE;
|
||||
}
|
||||
|
||||
OSCWarning("OSCRemoveContainerAlias: %s was the last name for that subcontainer");
|
||||
|
||||
/* xxx should recursively free the container and its children... */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
OSCcontainer OSCNewContainer(Name name, OSCcontainer parent,
|
||||
struct OSCContainerQueryResponseInfoStruct *QueryResponseInfo) {
|
||||
OSCcontainer me;
|
||||
|
||||
me = AllocContainer();
|
||||
if (me == 0) return 0;
|
||||
|
||||
if (strchr(name, '/') != NULL) {
|
||||
OSCProblem("Container name \"%s\" contains a slash --- not good.",
|
||||
name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
me->parent = parent;
|
||||
AddSubContainer(me->parent, me, name);
|
||||
me->numChildren = 0;
|
||||
me->numMethods = 0;
|
||||
me->QueryResponseInfo = (*QueryResponseInfo);
|
||||
return me;
|
||||
}
|
||||
|
||||
|
||||
static const char *ContainerName(OSCcontainer c) {
|
||||
/* Return the first name associated with me in my parent's child list.
|
||||
(Assume all later ones are aliases.) */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c->parent->numChildren; ++i) {
|
||||
if (c->parent->children[i] == c) {
|
||||
return c->parent->childrenNames[i];
|
||||
}
|
||||
}
|
||||
fatal_error("ContainerName: Container %p isn't in its parent's child list.", c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gasHelp(char *target, int maxlength, OSCcontainer c );
|
||||
|
||||
Boolean OSCGetAddressString(char *target, int maxLength, OSCcontainer c) {
|
||||
int lenNeeded;
|
||||
|
||||
if (maxLength <= 1) return FALSE;
|
||||
|
||||
lenNeeded = gasHelp(target, maxLength-1, c) + 1; /* -1, +1 are for null char. */
|
||||
if (lenNeeded > maxLength) {
|
||||
OSCProblem("Address string too long (room for %d chars; need %d)",
|
||||
maxLength, lenNeeded);
|
||||
target[0] = '\0';
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int gasHelp(char *target, int maxLength, OSCcontainer c) {
|
||||
int sublength, length;
|
||||
const char *myName;
|
||||
|
||||
/* printf("*** gasHelp %s %d %p %s\n", target, maxLength, c, c->name); */
|
||||
|
||||
if (c == OSCTopLevelContainer) {
|
||||
target[0] = '/';
|
||||
target[1] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
myName = ContainerName(c);
|
||||
sublength = gasHelp(target, maxLength, c->parent);
|
||||
length = sublength + strlen(myName) + 1; /* +1 is for trailing slash */
|
||||
if (length > maxLength) {
|
||||
return length;
|
||||
}
|
||||
|
||||
strcpy(target+sublength, myName);
|
||||
target[length-1] = '/';
|
||||
target[length] = '\0';
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/**************************** Methods ****************************/
|
||||
|
||||
#define LONG_ADDR_SIZE 1000 /* Just for error messages */
|
||||
|
||||
OSCMethod OSCNewMethod(Name name, OSCcontainer me, methodCallback callback,
|
||||
void *context, struct OSCMethodQueryResponseInfoStruct *QueryResponseInfo) {
|
||||
|
||||
char addr[LONG_ADDR_SIZE];
|
||||
OSCMethod m;
|
||||
|
||||
if (strchr(name, '/') != NULL) {
|
||||
OSCProblem("Method name \"%s\" contains a slash --- not good.",
|
||||
name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (me->numMethods >= MAX_METHODS_PER_CONTAINER) {
|
||||
addr[0] = '\0';
|
||||
OSCGetAddressString(addr, LONG_ADDR_SIZE, me);
|
||||
OSCProblem("OSCNewMethod: container %s already has %d methods; can't add another\n"
|
||||
"Change MAX_METHODS_PER_CONTAINER in OSC-address-space.c and recompile.",
|
||||
addr, me->numMethods);
|
||||
return 0;
|
||||
}
|
||||
|
||||
m = AllocMethod();
|
||||
if (!m) return 0;
|
||||
|
||||
m->callback = callback;
|
||||
m->context = context;
|
||||
m->QueryResponseInfo = *QueryResponseInfo;
|
||||
|
||||
me->methodNames[me->numMethods] = name;
|
||||
me->methods[me->numMethods] = m;
|
||||
++(me->numMethods);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**************************** Queries ****************************/
|
||||
|
||||
void OSCInitContainerQueryResponseInfo(struct OSCContainerQueryResponseInfoStruct *i) {
|
||||
i->comment = 0;
|
||||
}
|
||||
|
||||
void OSCInitMethodQueryResponseInfo(struct OSCMethodQueryResponseInfoStruct *i) {
|
||||
i->description = 0;
|
||||
i->pvq = 0;
|
||||
}
|
||||
|
||||
/******************************* Debug ********************************/
|
||||
|
||||
|
||||
static int ContainerAliases(OSCcontainer c, char *target) {
|
||||
/* Write a space-delimited list of alias names in the given string,
|
||||
and return the number */
|
||||
int i, n;
|
||||
|
||||
if (c == OSCTopLevelContainer) return 0;
|
||||
target[0] = '\0';
|
||||
n = 0;
|
||||
|
||||
for (i = 0; i < c->parent->numChildren; ++i) {
|
||||
if (c->parent->children[i] == c) {
|
||||
if (n > 0) {
|
||||
strcat(target, " ");
|
||||
strcat(target, c->parent->childrenNames[i]);
|
||||
}
|
||||
++n;
|
||||
}
|
||||
}
|
||||
if (n == 0) fatal_error("ContainerAliases: internal inconsistency");
|
||||
|
||||
return n-1;
|
||||
}
|
||||
|
||||
#define BIG_ADDRESS 50
|
||||
|
||||
static void PrintHelp(OSCcontainer c) {
|
||||
char addr[BIG_ADDRESS];
|
||||
char aliasNames[1000];
|
||||
|
||||
int i, j, numAliases;
|
||||
|
||||
if (OSCGetAddressString(addr, BIG_ADDRESS, c) == FALSE) {
|
||||
printf(" /.../%s", ContainerName(c));
|
||||
} else {
|
||||
printf(" %s", addr);
|
||||
}
|
||||
|
||||
numAliases = ContainerAliases(c, aliasNames);
|
||||
if (numAliases > 0) {
|
||||
printf(" (%d aliases:%s)", numAliases, aliasNames);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < c->numMethods; ++i) {
|
||||
printf(" %s%s: %s\n", addr, c->methodNames[i],
|
||||
c->methods[i]->QueryResponseInfo.description);
|
||||
}
|
||||
|
||||
/* Forgive this quadratic kludge: */
|
||||
for (i = 0; i < c->numChildren; ++i) {
|
||||
int matches = 0;
|
||||
for (j = 0; j < i; ++j) {
|
||||
if (c->children[j] == c->children[i]) {
|
||||
/* c->children[i] is just an alias to c->children[j],
|
||||
which we already printed, so ignore it. */
|
||||
matches ++;
|
||||
}
|
||||
}
|
||||
|
||||
if(matches == 0 ) PrintHelp(c->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void OSCPrintWholeAddressSpace(void) {
|
||||
printf("\n----- The OSC address space -----\n");
|
||||
PrintHelp(OSCTopLevelContainer);
|
||||
printf("...end of OSC address space.\n\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************** Dispatching *****************************/
|
||||
|
||||
#include <libOSC/OSC-dispatch.h>
|
||||
#include <libOSC/OSC-callbacklist.h>
|
||||
#include <libOSC/OSC-pattern-match.h>
|
||||
|
||||
/* To do quick concatenation of singly-linked lists, we pass around
|
||||
this data structure that points to the first and last elements: */
|
||||
|
||||
typedef struct callbackListEnds_struct {
|
||||
callbackList begin;
|
||||
callbackList end;
|
||||
} callbackListEnds;
|
||||
|
||||
/* Helper proc. declarations */
|
||||
static callbackListEnds DispatchSubMessage(char *pattern, OSCcontainer c);
|
||||
static char *NextSlashOrNull(char *p);
|
||||
|
||||
|
||||
callbackList OSCDispatchMessage(char *pattern) {
|
||||
callbackListEnds result;
|
||||
|
||||
if (pattern[0] != '/') {
|
||||
OSCProblem("Invalid address \"%s\" does not begin with /", pattern);
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = DispatchSubMessage(pattern+1, OSCTopLevelContainer);
|
||||
|
||||
return result.begin;
|
||||
}
|
||||
|
||||
#define LONG_ADDR_LEN 100
|
||||
|
||||
|
||||
static callbackListEnds DispatchSubMessage(char *pattern, OSCcontainer c) {
|
||||
callbackListEnds result;
|
||||
char *nextSlash, *restOfPattern;
|
||||
char offendingAddr[LONG_ADDR_LEN];
|
||||
int i;
|
||||
|
||||
result.begin = result.end = 0;
|
||||
nextSlash = NextSlashOrNull(pattern);
|
||||
|
||||
if (*nextSlash == '\0') {
|
||||
/* Base case: the pattern names methods of this container. */
|
||||
for (i = 0; i < c->numMethods; i++) {
|
||||
if (PatternMatch(pattern, c->methodNames[i])) {
|
||||
callbackList node = AllocCallbackListNode(c->methods[i]->callback,
|
||||
c->methods[i]->context,
|
||||
result.begin);
|
||||
if (node == 0) {
|
||||
/* Excuse the hairyness of the code to generate the error message. */
|
||||
if (OSCGetAddressString(offendingAddr,
|
||||
LONG_ADDR_LEN-strlen(c->methodNames[i]),
|
||||
c)) {
|
||||
strcat(offendingAddr, c->methodNames[i]);
|
||||
} else {
|
||||
strcpy(offendingAddr, c->methodNames[i]);
|
||||
}
|
||||
|
||||
OSCWarning("No memory for callback node; not invoking %s",
|
||||
offendingAddr);
|
||||
} else {
|
||||
if (result.end == 0) {
|
||||
result.end = node;
|
||||
}
|
||||
result.begin = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Recursive case: in the middle of an address, so the job at this
|
||||
step is to look for containers that match. We temporarily turn
|
||||
the next slash into a null so pattern will be a null-terminated
|
||||
string of the stuff between the slashes. */
|
||||
*nextSlash = '\0';
|
||||
restOfPattern = nextSlash + 1;
|
||||
|
||||
for (i = 0; i < c->numChildren; ++i) {
|
||||
if (PatternMatch(pattern, c->childrenNames[i])) {
|
||||
callbackListEnds subResult =
|
||||
DispatchSubMessage(restOfPattern, c->children[i]);
|
||||
if (result.end == 0) {
|
||||
result = subResult;
|
||||
} else {
|
||||
subResult.end->next = result.begin;
|
||||
result.begin = subResult.begin;
|
||||
}
|
||||
}
|
||||
}
|
||||
*nextSlash = '/';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static char *NextSlashOrNull(char *p) {
|
||||
while (*p != '/' && *p != '\0') {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
364
veejay-1.3/veejay-server/libOSC/OSC-address-space.h
Normal file
364
veejay-1.3/veejay-server/libOSC/OSC-address-space.h
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
OSC-address-space.h
|
||||
Matt Wright, 11/20/97
|
||||
Version 2.0 5/28/98
|
||||
|
||||
C interface for registering the nodes in the OSC address space for an
|
||||
application.
|
||||
|
||||
include OSC-timetag.h before this file
|
||||
|
||||
****************************** Introduction ******************************
|
||||
|
||||
|
||||
The model is based on our original C++ design and consists of two kinds of
|
||||
objects:
|
||||
|
||||
methods are the leaf nodes of the address space hierarchy. A complete OSC
|
||||
address corresponds to a particular method, which has a corresponding
|
||||
callback procedure that will be invoked to implement commands sent by an
|
||||
OSC client.
|
||||
|
||||
containers are branch nodes of the address space hierarchy, and contain
|
||||
methods and other containers. Each container has a single namespace;
|
||||
it cannot contain a method and a subcontainer with the same name.
|
||||
|
||||
For example, let's examine the OSC message "/resonators/foo/decay 2.5". The
|
||||
address of this message is "/resonators/foo/decay" and the message has a
|
||||
single argument, 2.5. We'd say that the object corresponding to the prefix
|
||||
"/resonators" is a container, and that it contains another container whose
|
||||
address is "/resonators/foo". The "/resonators/foo" container has a method
|
||||
"decay".
|
||||
|
||||
The memory model used by this module is pre-allocation of fixed-size objects
|
||||
for containers, methods, and other internal objects. This preallocated
|
||||
memory is dynamically managed internally by a custom high-performance memory
|
||||
allocator. When the preallocated memory runs out, this module calls an
|
||||
optional realtime memory allocator that you provide. If your memory allocator
|
||||
gives this module more memory, it will add it to the pool of objects and
|
||||
never free the memory. If your system does not have a realtime memory
|
||||
allocator, provide a procedure that always returns 0.
|
||||
*/
|
||||
|
||||
/*************************** Type Definitions ******************************/
|
||||
|
||||
/* Users of this module don't get to see what's inside these objects */
|
||||
typedef struct OSCContainerStruct *OSCcontainer;
|
||||
typedef struct OSCMethodStruct *OSCMethod;
|
||||
|
||||
/* This makes it easy to change the way we represent symbolic names: */
|
||||
typedef const char *Name;
|
||||
|
||||
|
||||
/************************ Initialization and Memory ************************/
|
||||
|
||||
/* You will fill an OSCAddressSpaceMemoryTuner struct with the parameters that
|
||||
determine how memory will be allocated.
|
||||
|
||||
initNumContainers is the number of containers that will be allocated at
|
||||
initialization time. This should be the maximum number of containers you
|
||||
ever expect to have in your address space.
|
||||
|
||||
initNumMethods is the number of methods that will be allocated at
|
||||
initialization time. If you register the same method callback procedure
|
||||
multiple times at different places in the address space, each of these
|
||||
locations counts as a separate method as far as memory allocation is
|
||||
concerned.
|
||||
|
||||
The MemoryAllocator fields are procedures you will provide that allocate
|
||||
memory. Like malloc(), they take the number of bytes as arguments and return
|
||||
either a pointer to the new memory or 0 for failure. This memory will never
|
||||
be freed.
|
||||
|
||||
The InitTimeMemoryAllocator will be called only at initialization time,
|
||||
i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's
|
||||
a fatal error.
|
||||
|
||||
The RealTimeMemoryAllocator will be called if, while the application is
|
||||
running, the address space grows larger than can fit in what was allocated
|
||||
at initialization time. If the RealTimeMemoryAllocator() returns 0, the
|
||||
operation attempting to grow the address space will fail. If your system
|
||||
does not have real-time memory allocation, RealTimeMemoryAllocator should
|
||||
be a procedure that always returns 0.
|
||||
*/
|
||||
|
||||
struct OSCAddressSpaceMemoryTuner {
|
||||
int initNumContainers;
|
||||
int initNumMethods;
|
||||
void *(*InitTimeMemoryAllocator)(int numBytes);
|
||||
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||
};
|
||||
|
||||
/* Given an OSCAddressSpaceMemoryTuner, return the number of bytes of
|
||||
memory that would be allocated if OSCInitAddressSpace() were called
|
||||
on it. */
|
||||
int OSCAddressSpaceMemoryThatWouldBeAllocated(struct OSCAddressSpaceMemoryTuner *t);
|
||||
|
||||
|
||||
/* Call this before you call anything else. It returns the container that
|
||||
corresponds to the address "/" and is the root of the address space tree.
|
||||
*/
|
||||
OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t);
|
||||
|
||||
|
||||
/**************************** Containers ****************************/
|
||||
|
||||
/* Here's how this system deals with the standard OSC queries addressed to
|
||||
containers. This module handles the details of listening for these queries
|
||||
and returning a correctly-formatted answer; all it needs from you is the
|
||||
actual data that constitute the answers to these queries.
|
||||
|
||||
You pass this data in an OSCContainerQueryResponseInfo structure. Future versions
|
||||
of this module may have new kinds of queries that they can deal with, so
|
||||
the list of fields in this structure may grow. That's why your code should
|
||||
call OSCInitContainerQueryResponseInfo() on your struct before putting new values
|
||||
into it; this procedure will initialize all of the fields to 0, meaning
|
||||
"don't have that information", which will cause the associated queries to
|
||||
fail.
|
||||
|
||||
The "null" message, i.e., a message with a trailing slash, requesting the
|
||||
list of addresses under a given container, is handled automatically.
|
||||
*/
|
||||
|
||||
struct OSCContainerQueryResponseInfoStruct {
|
||||
char *comment;
|
||||
/* Other fields may go here */
|
||||
};
|
||||
|
||||
void OSCInitContainerQueryResponseInfo(struct OSCContainerQueryResponseInfoStruct *i);
|
||||
|
||||
|
||||
/* Allocate a new container and initialize it. Returns 0 if it cannot
|
||||
allocate a new container, e.g., if you've exceeded the initNumContainers
|
||||
limit of the OSCAddressSpaceMemoryTuner() and the RealTimeMemoryAllocator()
|
||||
didn't return any new memory.
|
||||
|
||||
This procedure doesn't make a copy of the name string or any of the
|
||||
contents of the OSCContainerQueryResponseInfoStruct. It does copy the fields
|
||||
of the OSCContainerQueryResponseInfoStruct.
|
||||
*/
|
||||
OSCcontainer OSCNewContainer(Name name, OSCcontainer parent,
|
||||
struct OSCContainerQueryResponseInfoStruct *queryInfo);
|
||||
|
||||
|
||||
/* Remove a container from the address space. This also removes all the
|
||||
container's methods and recursively removes all sub-containers. Memory
|
||||
freed by removing a container is kept in this module's internal pool.
|
||||
*/
|
||||
void OSCRemoveContainer(OSCcontainer container);
|
||||
|
||||
|
||||
/* Given a pointer to a container, and another name for that container, add or
|
||||
remove that name as an alias for the container. Return FALSE for failure. */
|
||||
Boolean OSCAddContainerAlias(OSCcontainer container, Name otherName);
|
||||
Boolean OSCRemoveContainerAlias(OSCcontainer container, Name otherName);
|
||||
|
||||
|
||||
/* Write the OSC address of the given container into the given string.
|
||||
Return FALSE if the address won't fit in the string. */
|
||||
Boolean OSCGetAddressString(char *target, int maxLength, OSCcontainer c);
|
||||
|
||||
|
||||
/* Given an address (not a pattern!), return the single OSCcontainer it names,
|
||||
or 0 if there is no container at that address */
|
||||
OSCcontainer OSCLookUpContainer(Name address);
|
||||
|
||||
|
||||
/**************************** Methods ****************************/
|
||||
|
||||
/* A methodCallback is a procedure that you write that will be called at the
|
||||
time that an OSC message is to take effect. It will be called with 5
|
||||
arguments:
|
||||
- A context pointer that was registered with the methodNode
|
||||
this is a method of. (Something like the C++ "this" pointer.)
|
||||
- The number of bytes of argument data
|
||||
- A pointer to the argument portion of the OSC message
|
||||
- The time tag at which this message is supposed to take effect.
|
||||
- A "return address" object you can use to send a message back to the
|
||||
client that sent this message. This return channel is guaranteed
|
||||
to be usable only during the invocation of your method, so your method
|
||||
must use the return address immediately or ignore it, not store it away
|
||||
for later use.
|
||||
*/
|
||||
typedef struct NetworkReturnAddressStruct *NetworkReturnAddressPtr;
|
||||
/* removed const */
|
||||
|
||||
typedef void (*methodCallback)(void *context, int arglen, const void *args,
|
||||
OSCTimeTag when, NetworkReturnAddressPtr returnAddr);
|
||||
|
||||
|
||||
/* A ParamValQuerier is a procedure that the OSC system will call when the
|
||||
user wants to know the current value of a parameter. It will be passed the
|
||||
same context pointer as the associated method. It should write its return
|
||||
value in the given buffer in the same format as the associated
|
||||
methodCallback would expect its "args" argument, and should return the
|
||||
length of data just like the method would expect in its "arglen" argument.
|
||||
It doesn't have to worry about the address portion of the OSC message.
|
||||
*/
|
||||
typedef char OSCData; /* For pointers to OSC-formatted data */
|
||||
typedef int (*ParamValQuerier)(OSCData *result, void *context);
|
||||
|
||||
|
||||
/* This system deals with other standard per-method queries, such as
|
||||
documentation, valid parameter types and ranges, units, default values,
|
||||
etc., pretty much just like per-container queries.
|
||||
*/
|
||||
|
||||
struct OSCMethodQueryResponseInfoStruct {
|
||||
char *description;
|
||||
ParamValQuerier pvq;
|
||||
/* For each argument of the method:
|
||||
min, max, default, units */
|
||||
};
|
||||
|
||||
void OSCInitMethodQueryResponseInfo(struct OSCMethodQueryResponseInfoStruct *i);
|
||||
|
||||
|
||||
/* Allocate a new method, initialize it, and add it to a container. Returns 0
|
||||
for failure, e.g., if you've exceeded the initNumMethods limit of the
|
||||
OSCAddressSpaceMemoryTuner() and the RealTimeMemoryAllocator() didn't return any
|
||||
new memory.
|
||||
|
||||
This procedure doesn't make a copy of the name string or any of the
|
||||
contents of the OSCMethodQueryResponseInfoStruct.
|
||||
*/
|
||||
|
||||
OSCMethod OSCNewMethod(Name name, OSCcontainer container, methodCallback meth,
|
||||
void *context, struct OSCMethodQueryResponseInfoStruct *queryInfo);
|
||||
|
||||
|
||||
|
||||
/******************************* Debug ********************************/
|
||||
|
||||
|
||||
void OSCPrintWholeAddressSpace(void);
|
||||
|
||||
|
||||
/**************************** Sample Code *****************************/
|
||||
|
||||
/* Here's a gross approximation of how your application will invoke the
|
||||
procedures in this module. It registers an address space with
|
||||
containers with addresses "/foo", "/foo/foochild", and "/bar",
|
||||
and gives each of them "play" and "shuddup" messages.
|
||||
|
||||
|
||||
#include "OSC-common.h"
|
||||
#include "OSC-timetag.h"
|
||||
#include "OSC-address-space.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
int playing;
|
||||
int param;
|
||||
float otherParam;
|
||||
} Player;
|
||||
|
||||
void PlayCallback(void *context, int arglen, const void *vargs,
|
||||
OSCTimeTag when, NetworkReturnAddressPtr ra) {
|
||||
Player *p = context;
|
||||
const int *args = vargs;
|
||||
|
||||
|
||||
p->playing = 1;
|
||||
if (arglen >= 4) {
|
||||
p->param = args[0];
|
||||
}
|
||||
}
|
||||
|
||||
void ShuddupCallback(void *context, int arglen, const void *vargs,
|
||||
OSCTimeTag when, NetworkReturnAddressPtr ra) {
|
||||
Player *p = context;
|
||||
const float *args = vargs;
|
||||
|
||||
|
||||
p->playing = 0;
|
||||
if (arglen >= 4) {
|
||||
p->otherParam = args[0];
|
||||
}
|
||||
}
|
||||
|
||||
void *InitTimeMalloc(int numBytes) {
|
||||
return malloc(numBytes);
|
||||
}
|
||||
|
||||
void *NoRealTimeMalloc(int numBytes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
main() {
|
||||
struct OSCAddressSpaceMemoryTuner oasmt;
|
||||
OSCcontainer topLevelContainer, foo, foochild, bar;
|
||||
struct OSCContainerQueryResponseInfoStruct ocqris;
|
||||
struct OSCMethodQueryResponseInfoStruct omqris;
|
||||
|
||||
Player *players;
|
||||
|
||||
players = (Player *) malloc(3 * sizeof(*players));
|
||||
if (!players) exit(1);
|
||||
|
||||
oasmt.initNumContainers = 10;
|
||||
oasmt.initNumMethods = 10;
|
||||
oasmt.InitTimeMemoryAllocator = InitTimeMalloc;
|
||||
oasmt.RealTimeMemoryAllocator = NoRealTimeMalloc;
|
||||
|
||||
topLevelContainer = OSCInitAddressSpace(&oasmt);
|
||||
|
||||
OSCInitContainerQueryResponseInfo(&ocqris);
|
||||
ocqris.comment = "Foo for you";
|
||||
foo = OSCNewContainer("foo", topLevelContainer, &ocqris);
|
||||
|
||||
OSCInitContainerQueryResponseInfo(&ocqris);
|
||||
ocqris.comment = "Beware the son of foo!";
|
||||
foochild = OSCNewContainer("foochild", foo, &ocqris);
|
||||
|
||||
OSCInitContainerQueryResponseInfo(&ocqris);
|
||||
ocqris.comment = "Belly up to the bar";
|
||||
bar = OSCNewContainer("bar", topLevelContainer, &ocqris);
|
||||
|
||||
if (foo == 0 || foochild == 0 || bar == 0) {
|
||||
fprintf(stderr, "Problem!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
OSCInitMethodQueryResponseInfo(&omqris);
|
||||
OSCNewMethod("play", foo, PlayCallback, &(players[0]), &omqris);
|
||||
OSCNewMethod("shuddup", foo, ShuddupCallback, &(players[0]), &omqris);
|
||||
|
||||
OSCNewMethod("play", foochild, PlayCallback, &(players[1]), &omqris);
|
||||
OSCNewMethod("shuddup", foochild, ShuddupCallback, &(players[1]), &omqris);
|
||||
|
||||
OSCNewMethod("play", bar, PlayCallback, &(players[2]), &omqris);
|
||||
OSCNewMethod("shuddup", bar, ShuddupCallback, &(players[2]), &omqris);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
95
veejay-1.3/veejay-server/libOSC/OSC-callbacklist.c
Normal file
95
veejay-1.3/veejay-server/libOSC/OSC-callbacklist.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
OSC-callbacklist.c
|
||||
Linked lists of methods
|
||||
|
||||
Matt Wright, 11/20/97
|
||||
|
||||
Allocator is a simple linked list of free nodes.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-address-space.h>
|
||||
#include <libOSC/OSC-dispatch.h>
|
||||
#include <libOSC/OSC-callbacklist.h>
|
||||
|
||||
static callbackList allNodes;
|
||||
static callbackList freeNodes;
|
||||
|
||||
/* Call this before you call anything else */
|
||||
Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)) {
|
||||
int i;
|
||||
|
||||
allNodes = (*InitTimeMalloc)(numNodes * sizeof(*allNodes));
|
||||
if (allNodes == 0) return FALSE;
|
||||
|
||||
/* Initialize list of freeNodes */
|
||||
freeNodes = &(allNodes[0]);
|
||||
for (i = 0; i < numNodes-1; ++i) {
|
||||
allNodes[i].next = &(allNodes[i+1]);
|
||||
}
|
||||
allNodes[numNodes-1].next = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
callbackList AllocCallbackListNode(methodCallback callback, void *context,
|
||||
struct callbackListNode *next) {
|
||||
callbackList result;
|
||||
if (freeNodes == 0) {
|
||||
/* OSCProblem("Out of memory for callback lists!"); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = freeNodes;
|
||||
freeNodes = freeNodes->next;
|
||||
|
||||
result->callback = callback;
|
||||
result->context = context;
|
||||
result->next = next;
|
||||
#ifdef DEBUG_CBL
|
||||
printf("AllocCallbackListNode: returning %p (cb %p, context %p, next %p)\n",
|
||||
result, result->callback, result->context, result->next);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void FreeCallbackListNode(callbackList cb) {
|
||||
#ifdef DEBUG_CBL
|
||||
printf("FreeCallbackListNode(%p)\n", cb);
|
||||
#endif
|
||||
cb->next = freeNodes;
|
||||
freeNodes = cb;
|
||||
}
|
||||
49
veejay-1.3/veejay-server/libOSC/OSC-callbacklist.h
Normal file
49
veejay-1.3/veejay-server/libOSC/OSC-callbacklist.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
OSC-callbacklist.h
|
||||
Linked lists of methods
|
||||
|
||||
Matt Wright, 3/13/98
|
||||
|
||||
include "OSC-dispatch.h" before this file.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Call this before you call anything else. */
|
||||
Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes));
|
||||
|
||||
callbackList AllocCallbackListNode(methodCallback callback, void *context,
|
||||
struct callbackListNode *next);
|
||||
|
||||
void FreeCallbackListNode(callbackList);
|
||||
|
||||
|
||||
87
veejay-1.3/veejay-server/libOSC/OSC-common.c
Normal file
87
veejay-1.3/veejay-server/libOSC/OSC-common.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* OSC-system-dependent.c
|
||||
|
||||
Matt Wright, 3/13/98
|
||||
|
||||
File of procedures OSC has to call that are not part of the OSC package
|
||||
and that you, the developer adding OSC addressability to an application,
|
||||
must write in a way that makes sense in the context of your system.
|
||||
|
||||
You should also look at OSC-timetag.c and see if there's a better way
|
||||
to handle time tags on your system.
|
||||
|
||||
*/
|
||||
|
||||
#include <libOSC/OSC-common.h>
|
||||
|
||||
/* Printing stuff: for now, use stderr. Some cleverer stuff we could do:
|
||||
|
||||
- Make a silent mode where these don't do anything.
|
||||
- Return error messages via OSC to some client
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void fatal_error(char *s, ...) {
|
||||
va_list ap;
|
||||
fprintf(stderr, "Fatal error: ");
|
||||
va_start(ap, s);
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
exit(-321);
|
||||
}
|
||||
|
||||
void OSCProblem(char *s, ...) {
|
||||
va_list ap;
|
||||
fprintf(stderr, "OSC Problem: ");
|
||||
va_start(ap, s);
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void OSCWarning(char *s, ...) {
|
||||
/* va_list ap;
|
||||
fprintf(stderr, "OSC Warning: ");
|
||||
va_start(ap, s);
|
||||
vfprintf(stderr, s, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);*/
|
||||
}
|
||||
60
veejay-1.3/veejay-server/libOSC/OSC-common.h
Normal file
60
veejay-1.3/veejay-server/libOSC/OSC-common.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* OSC-common.h
|
||||
Simple stuff to #include everywhere in the OSC package
|
||||
|
||||
by Matt Wright, 3/13/98
|
||||
*/
|
||||
|
||||
/* Boolean type */
|
||||
|
||||
#ifndef TRUE
|
||||
typedef int Boolean;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Fixed byte width types */
|
||||
typedef int int4; /* 4 byte int */
|
||||
|
||||
/* Printing type procedures. All take printf-style format string */
|
||||
|
||||
/* Catastrophic failure: print message and halt system */
|
||||
void fatal_error(char *s, ...);
|
||||
|
||||
/* Error message for user */
|
||||
void OSCProblem(char *s, ...);
|
||||
|
||||
/* Warning for user */
|
||||
void OSCWarning(char *s, ...);
|
||||
|
||||
|
||||
52
veejay-1.3/veejay-server/libOSC/OSC-dispatch.h
Normal file
52
veejay-1.3/veejay-server/libOSC/OSC-dispatch.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-dispatch.h
|
||||
|
||||
Given an OSC message pattern from an incoming message, match the
|
||||
pattern against the OSC address space and produce a list of the
|
||||
callbacks corresponding to all the addresses that were matched.
|
||||
|
||||
Matt Wright, 6/5/98
|
||||
*/
|
||||
|
||||
/***************************** Dispatching *****************************/
|
||||
|
||||
typedef struct callbackListNode {
|
||||
methodCallback callback;
|
||||
void *context;
|
||||
struct callbackListNode *next;
|
||||
} *callbackList;
|
||||
|
||||
|
||||
/* Given an OSC message pattern from an incoming message, match the
|
||||
pattern against the OSC address space and produce a list of the
|
||||
callbacks corresponding to all the addresses that were matched. */
|
||||
callbackList OSCDispatchMessage(char *pattern);
|
||||
|
||||
58
veejay-1.3/veejay-server/libOSC/OSC-drop.c
Normal file
58
veejay-1.3/veejay-server/libOSC/OSC-drop.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-drop.c
|
||||
|
||||
This implementation just prints a warning.
|
||||
|
||||
Matt Wright, 3/16/98
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-address-space.h>
|
||||
#include <libOSC/NetworkReturnAddress.h>
|
||||
#include <libOSC/OSC-receive.h>
|
||||
#include <libOSC/OSC-drop.h>
|
||||
|
||||
void DropPacket(OSCPacketBuffer p) {
|
||||
OSCWarning("Packet dropped.");
|
||||
}
|
||||
|
||||
void DropBundle(char *buf, int n, OSCPacketBuffer p) {
|
||||
OSCWarning("Bundle dropped.");
|
||||
}
|
||||
|
||||
void DropMessage(char *buf, int n, OSCPacketBuffer p) {
|
||||
OSCWarning("Message dropped.");
|
||||
}
|
||||
|
||||
43
veejay-1.3/veejay-server/libOSC/OSC-drop.h
Normal file
43
veejay-1.3/veejay-server/libOSC/OSC-drop.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-drop.h
|
||||
|
||||
These procedures will be called on a packet, bundle, or message that's
|
||||
being dropped for whatever reason. They can do nothing, print (or
|
||||
otherwise inform the user of) a warning, save the offending data somewhere,
|
||||
etc.
|
||||
|
||||
Matt Wright, 3/16/98
|
||||
*/
|
||||
|
||||
void DropPacket(OSCPacketBuffer p);
|
||||
void DropBundle(char *buf, int n, OSCPacketBuffer p);
|
||||
void DropMessage(char *buf, int n, OSCPacketBuffer p);
|
||||
|
||||
70
veejay-1.3/veejay-server/libOSC/OSC-internal-messages.h
Normal file
70
veejay-1.3/veejay-server/libOSC/OSC-internal-messages.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-internal-messages.h
|
||||
|
||||
Interface for having an application send OSC messages to itself
|
||||
internally.
|
||||
|
||||
All these procedures return FALSE if unable to deliver the message.
|
||||
|
||||
Matt Wright, 3/17/98
|
||||
|
||||
*/
|
||||
|
||||
/* Send a message immediately, with no return address. This procedure
|
||||
returns after the message has been sent (or has failed to be sent),
|
||||
so the memory for address and args can be on the stack. Returns FALSE
|
||||
if there's a problem; TRUE otherwise. */
|
||||
Boolean OSCSendInternalMessage(char *address, int arglen, void *args);
|
||||
|
||||
|
||||
/* Same thing, but with a return address supplied. */
|
||||
Boolean OSCSendInternalMessageWithRSVP(char *address, int arglen, void *args,
|
||||
NetworkReturnAddressPtr returnAddr);
|
||||
|
||||
|
||||
/* Schedule some messages to occur at a given time. This allocates one of the
|
||||
OSCPacketBuffer structures (see OSC-receive.h) to hold the addresses and argument
|
||||
data until the messages take effect, so if you're going to call this, you
|
||||
should take this use of packets into account in setting the
|
||||
numReceiveBuffers argument to OSCInitReceive().
|
||||
|
||||
This provides an less general interface than OSC's bundle mechanism, because
|
||||
the bundle of messages you provide cannot include subbundles.
|
||||
|
||||
The addresses, arglens, and args arguments are arrays of size numMessages.
|
||||
|
||||
There's no return address argument because you're not allowed to save a network
|
||||
return address for later use.
|
||||
*/
|
||||
|
||||
Boolean OSCScheduleInternalMessages(OSCTimeTag when, int numMessages,
|
||||
char **addresses, int *arglens,
|
||||
void **args);
|
||||
193
veejay-1.3/veejay-server/libOSC/OSC-pattern-match.c
Normal file
193
veejay-1.3/veejay-server/libOSC/OSC-pattern-match.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
OSC-pattern-match.c
|
||||
Matt Wright, 3/16/98
|
||||
Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury
|
||||
*/
|
||||
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-pattern-match.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
static const char *theWholePattern; /* Just for warning messages */
|
||||
|
||||
static Boolean MatchBrackets (const char *pattern, const char *test);
|
||||
static Boolean MatchList (const char *pattern, const char *test);
|
||||
|
||||
Boolean PatternMatch (const char * pattern, const char * test) {
|
||||
theWholePattern = pattern;
|
||||
|
||||
if (pattern == 0 || pattern[0] == 0) {
|
||||
return test[0] == 0;
|
||||
}
|
||||
|
||||
if (test[0] == 0) {
|
||||
if (pattern[0] == '*')
|
||||
return PatternMatch (pattern+1,test);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (pattern[0]) {
|
||||
case 0 : return test[0] == 0;
|
||||
case '?' : return PatternMatch (pattern + 1, test + 1);
|
||||
case '*' :
|
||||
if (PatternMatch (pattern+1, test)) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return PatternMatch (pattern, test+1);
|
||||
}
|
||||
case ']' :
|
||||
case '}' :
|
||||
OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern);
|
||||
return FALSE;
|
||||
case '[' :
|
||||
return MatchBrackets (pattern,test);
|
||||
case '{' :
|
||||
return MatchList (pattern,test);
|
||||
case '\\' :
|
||||
if (pattern[1] == 0) {
|
||||
return test[0] == 0;
|
||||
} else if (pattern[1] == test[0]) {
|
||||
return PatternMatch (pattern+2,test+1);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
default :
|
||||
if (pattern[0] == test[0]) {
|
||||
return PatternMatch (pattern+1,test+1);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* we know that pattern[0] == '[' and test[0] != 0 */
|
||||
|
||||
static Boolean MatchBrackets (const char *pattern, const char *test) {
|
||||
Boolean result;
|
||||
Boolean negated = FALSE;
|
||||
const char *p = pattern;
|
||||
|
||||
if (pattern[1] == 0) {
|
||||
OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pattern[1] == '!') {
|
||||
negated = TRUE;
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p != ']') {
|
||||
if (*p == 0) {
|
||||
OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
|
||||
return FALSE;
|
||||
}
|
||||
if (p[1] == '-' && p[2] != 0) {
|
||||
if (test[0] >= p[0] && test[0] <= p[2]) {
|
||||
result = !negated;
|
||||
goto advance;
|
||||
}
|
||||
}
|
||||
if (p[0] == test[0]) {
|
||||
result = !negated;
|
||||
goto advance;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
result = negated;
|
||||
|
||||
advance:
|
||||
|
||||
if (!result)
|
||||
return FALSE;
|
||||
|
||||
while (*p != ']') {
|
||||
if (*p == 0) {
|
||||
OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern);
|
||||
return FALSE;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return PatternMatch (p+1,test+1);
|
||||
}
|
||||
|
||||
static Boolean MatchList (const char *pattern, const char *test) {
|
||||
|
||||
const char *restOfPattern, *tp = test;
|
||||
|
||||
|
||||
for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) {
|
||||
if (*restOfPattern == 0) {
|
||||
OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
restOfPattern++; /* skip close curly brace */
|
||||
|
||||
|
||||
pattern++; /* skip open curly brace */
|
||||
|
||||
while (1) {
|
||||
|
||||
if (*pattern == ',') {
|
||||
if (PatternMatch (restOfPattern, tp)) {
|
||||
return TRUE;
|
||||
} else {
|
||||
tp = test;
|
||||
++pattern;
|
||||
}
|
||||
} else if (*pattern == '}') {
|
||||
return PatternMatch (restOfPattern, tp);
|
||||
} else if (*pattern == *tp) {
|
||||
++pattern;
|
||||
++tp;
|
||||
} else {
|
||||
tp = test;
|
||||
while (*pattern != ',' && *pattern != '}') {
|
||||
pattern++;
|
||||
}
|
||||
if (*pattern == ',') {
|
||||
pattern++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
veejay-1.3/veejay-server/libOSC/OSC-pattern-match.h
Normal file
35
veejay-1.3/veejay-server/libOSC/OSC-pattern-match.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
OSC-pattern-match.h
|
||||
*/
|
||||
|
||||
Boolean PatternMatch (const char *pattern, const char *test);
|
||||
|
||||
190
veejay-1.3/veejay-server/libOSC/OSC-priority-queue.c
Normal file
190
veejay-1.3/veejay-server/libOSC/OSC-priority-queue.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-priority-queue.c
|
||||
Priority queue used by OSC time tag scheduler
|
||||
|
||||
This is the most trivial implementation, an unsorted array of queued
|
||||
objects, mostly for debug purposes.
|
||||
|
||||
Matt Wright, 9/17/98
|
||||
*/
|
||||
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-priority-queue.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#define PRINT_PRIORITY_QUEUE
|
||||
|
||||
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||
#define PRINT_PRIORITY_QUEUE
|
||||
#endif
|
||||
|
||||
#if defined(PRINT_PRIORITY_QUEUE) || defined(DEBUG_OSC_PRIORITY_QUEUE)
|
||||
|
||||
#include <stdio.h>
|
||||
void OSCQueuePrint(OSCQueue q);
|
||||
#endif
|
||||
|
||||
#define CAPACITY 1000
|
||||
|
||||
|
||||
struct OSCQueueStruct {
|
||||
OSCSchedulableObject list[CAPACITY];
|
||||
int n;
|
||||
int scanIndex;
|
||||
};
|
||||
|
||||
|
||||
OSCQueue OSCNewQueue(int maxItems, void *(*InitTimeMalloc)(int numBytes)) {
|
||||
OSCQueue result;
|
||||
|
||||
if (maxItems > CAPACITY) fatal_error("Increase CAPACITY in OSC-priority-queue.c");
|
||||
|
||||
result = (*InitTimeMalloc)(sizeof(*result));
|
||||
if (result == 0) return 0;
|
||||
|
||||
result->n = 0;
|
||||
|
||||
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||
OSCQueuePrint(result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
int OSCQueueInsert(OSCQueue q, OSCSchedulableObject new) {
|
||||
if (q->n == CAPACITY) return FALSE;
|
||||
|
||||
q->list[q->n] = new;
|
||||
++(q->n);
|
||||
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||
printf("OSCQueueInsert: just inserted %p\n", new);
|
||||
OSCQueuePrint(q);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
OSCTimeTag OSCQueueEarliestTimeTag(OSCQueue q) {
|
||||
int i;
|
||||
OSCTimeTag smallest = OSCTT_BiggestPossibleTimeTag();
|
||||
|
||||
for (i = 0; i < q->n; ++i) {
|
||||
if (OSCTT_Compare(smallest, q->list[i]->timetag) > 0) {
|
||||
smallest = q->list[i]->timetag;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||
printf("OSCQueueEarliestTimeTag: about to return %llx\n", smallest);
|
||||
OSCQueuePrint(q);
|
||||
#endif
|
||||
return smallest;
|
||||
}
|
||||
|
||||
|
||||
static void RemoveElement(int goner, OSCQueue q) {
|
||||
int i;
|
||||
--(q->n);
|
||||
|
||||
for (i = goner; i < q->n; ++i) {
|
||||
q->list[i] = q->list[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
OSCSchedulableObject OSCQueueRemoveEarliest(OSCQueue q) {
|
||||
OSCSchedulableObject result;
|
||||
int i, smallestIndex;
|
||||
|
||||
if (q->n == 0) {
|
||||
OSCWarning("OSCQueueRemoveEarliest: empty queue");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||
printf("OSCQueueRemoveEarliest: begin\n");
|
||||
OSCQueuePrint(q);
|
||||
#endif
|
||||
|
||||
smallestIndex = 0;
|
||||
for (i = 1; i < q->n; ++i) {
|
||||
if (OSCTT_Compare(q->list[smallestIndex]->timetag, q->list[i]->timetag) > 0) {
|
||||
smallestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
result = q->list[smallestIndex];
|
||||
|
||||
RemoveElement(smallestIndex, q);
|
||||
|
||||
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||
printf("OSCQueueRemoveEarliest: done\n");
|
||||
OSCQueuePrint(q);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef PRINT_PRIORITY_QUEUE
|
||||
|
||||
void OSCQueuePrint(OSCQueue q) {
|
||||
int i;
|
||||
printf("OSC Priority queue at %p has %d elements:\n", q, q->n);
|
||||
|
||||
for (i = 0; i < q->n; ++i) {
|
||||
printf(" list[%2d] is %p, timetag = %llx\n", i, q->list[i], q->list[i]->timetag);
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void OSCQueueScanStart(OSCQueue q) {
|
||||
q->scanIndex = 0;
|
||||
}
|
||||
|
||||
OSCSchedulableObject OSCQueueScanNext(OSCQueue q) {
|
||||
if (q->scanIndex >= q->n) return 0;
|
||||
|
||||
return (q->list[(q->scanIndex)++]);
|
||||
}
|
||||
|
||||
void OSCQueueRemoveCurrentScanItem(OSCQueue q) {
|
||||
/* Remember that q->scanIndex is the index of the *next*
|
||||
item that will be returned, so the "current" item, i.e.,
|
||||
the one most recently returned by OSCQueueScanNext(),
|
||||
is q->scanIndex-1. */
|
||||
|
||||
RemoveElement(q->scanIndex-1, q);
|
||||
--(q->scanIndex);
|
||||
}
|
||||
|
||||
void CheckWholeQueue(void) {
|
||||
}
|
||||
90
veejay-1.3/veejay-server/libOSC/OSC-priority-queue.h
Normal file
90
veejay-1.3/veejay-server/libOSC/OSC-priority-queue.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-priority-queue.h
|
||||
Interface to priority queue used by OSC time tag scheduler
|
||||
|
||||
Matt Wright, 3/13/98
|
||||
|
||||
*/
|
||||
|
||||
/* include OSC-timetag.h before this file. */
|
||||
|
||||
/* This queue manages pointers to data objects. It doesn't care what's in the
|
||||
objects except that the first element has to be an OSCTimeTag. So whatever
|
||||
data you want to store, cast your pointer to it to a pointer to this type. */
|
||||
|
||||
typedef struct {
|
||||
OSCTimeTag timetag;
|
||||
/* There will be other stuff... */
|
||||
} *OSCSchedulableObject;
|
||||
|
||||
typedef struct OSCQueueStruct *OSCQueue;
|
||||
|
||||
/* Make a new queue, or return 0 for failure. */
|
||||
OSCQueue OSCNewQueue(int maxItems, void *(*InitTimeMalloc)(int numBytes));
|
||||
|
||||
/* Put something into the queue. Return FALSE if quque is full. */
|
||||
Boolean OSCQueueInsert(OSCQueue q, OSCSchedulableObject o);
|
||||
|
||||
/* What's the time tag of the earliest item in the queue?
|
||||
Return OSCTT_BiggestPossibleTimeTag() if queue is empty. */
|
||||
OSCTimeTag OSCQueueEarliestTimeTag(OSCQueue q);
|
||||
|
||||
/* Remove the item from the front of the queue. Fatal error
|
||||
if the queue is empty. */
|
||||
OSCSchedulableObject OSCQueueRemoveEarliest(OSCQueue q);
|
||||
|
||||
|
||||
/* Interface for examining items currently stored on the queue:
|
||||
|
||||
- To start, call OSCQueueScanStart().
|
||||
|
||||
- Then each subsequent call to OSCQueueScanNext() returns a pointer to an
|
||||
OSCSchedulableObject that is stored on the queue, until
|
||||
OSCQueueScanNext() returns 0 to indicate that all objects on the queue
|
||||
have been scanned.
|
||||
|
||||
The objects returned by OSCQueueScanNext() come in chronological order (or
|
||||
approximately chronological order, depending on the underlying queue data
|
||||
structure).
|
||||
|
||||
If you call OSCQueueRemoveCurrentScanItem(), the object most recently
|
||||
returned by OSCQueueScanNext() will be removed from the queue.
|
||||
|
||||
If there are any insertions or deletions to the queue, the sequence of
|
||||
scanned objects must still include every object in the queue. This may
|
||||
cause a particular object to be returned more than once by
|
||||
OSCQueueScanNext().
|
||||
*/
|
||||
|
||||
|
||||
void OSCQueueScanStart(OSCQueue q);
|
||||
OSCSchedulableObject OSCQueueScanNext(OSCQueue q);
|
||||
void OSCQueueRemoveCurrentScanItem(OSCQueue q);
|
||||
893
veejay-1.3/veejay-server/libOSC/OSC-receive.c
Normal file
893
veejay-1.3/veejay-server/libOSC/OSC-receive.c
Normal file
@@ -0,0 +1,893 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
#define PARANOID 0
|
||||
/*
|
||||
OSC-receive.c
|
||||
Matt Wright, 3/13/98, 6/3/98
|
||||
|
||||
Adapted from OSC-addressability.c (and seriously cleaned up!)
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-address-space.h>
|
||||
#include <libOSC/NetworkReturnAddress.h>
|
||||
#include <libOSC/OSC-receive.h>
|
||||
#include <libOSC/OSC-priority-queue.h>
|
||||
#include <libOSC/OSC-string-help.h>
|
||||
#include <libOSC/OSC-drop.h>
|
||||
#include <libOSC/OSC-dispatch.h>
|
||||
#include <libOSC/NetworkUDP.h>
|
||||
#include <libOSC/OSC-callbacklist.h>
|
||||
#if defined(DEBUG_INTERNAL) || defined(DEBUG) || defined(DEBUG_PACKET_MEM) || defined(DEBUG_QD_MEM) || defined(DEBUG_8BYTE_ALIGN) || defined(SUSPECT_QD_PROB)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
static int use_mcast_ = 0;
|
||||
static char mcast_groupname[200];
|
||||
|
||||
struct {
|
||||
OSCQueue TheQueue; /* The Priority Queue */
|
||||
OSCTimeTag lastTimeTag; /* Best approximation to current time */
|
||||
Boolean timePassed; /* TRUE if OSCInvokeMessagesThatAreReady() has been
|
||||
called since the last time OSCBeProductiveWhileWaiting() was. */
|
||||
int recvBufSize; /* Size of all receive buffers */
|
||||
void *(*InitTimeMalloc)(int numBytes);
|
||||
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||
} globals;
|
||||
|
||||
|
||||
/* Data structures */
|
||||
|
||||
struct OSCPacketBuffer_struct {
|
||||
char *buf; /* Contents of network packet go here */
|
||||
int n; /* Overall size of packet */
|
||||
int refcount; /* # queued things using memory from this buffer */
|
||||
struct OSCPacketBuffer_struct *nextFree; /* For linked list of free packets */
|
||||
|
||||
Boolean returnAddrOK; /* Because returnAddr points to memory we need to
|
||||
store future return addresses, we set this
|
||||
field to FALSE in situations where a packet
|
||||
buffer "has no return address" instead of
|
||||
setting returnAddr to 0 */
|
||||
|
||||
NetworkReturnAddressPtr returnAddr;
|
||||
//void *returnAddr; /* Addr of client this packet is from */
|
||||
/* This was of type NetworkReturnAddressPtr, but the constness
|
||||
was making it impossible for me to initialize it. There's
|
||||
probably a better way that I don't understand. */
|
||||
|
||||
};
|
||||
|
||||
/* These are the data objects that are inserted and removed from the
|
||||
scheduler. The idea is that we can insert a single message or
|
||||
an entire bundle on the scheduler, and we can leave it in various
|
||||
states of being parsed and pattern matched. */
|
||||
|
||||
#define NOT_DISPATCHED_YET ((callbackList) -1)
|
||||
|
||||
typedef struct queuedDataStruct {
|
||||
OSCTimeTag timetag; /* When this bundle or message is supposed to happen */
|
||||
OSCPacketBuffer myPacket; /* Ptr. to buffer this is contained in */
|
||||
|
||||
enum {MESSAGE, BUNDLE} type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
char *bytes;
|
||||
int length;
|
||||
} bundle;
|
||||
|
||||
struct {
|
||||
char *messageName; /* Ptr. into receive buffer */
|
||||
int length; /* Includes name and arugments */
|
||||
void *args; /* 0 if not yet parsed */
|
||||
int argLength;
|
||||
callbackList callbacks; /* May be NOT_DISPATCHED_YET */
|
||||
} message;
|
||||
} data;
|
||||
|
||||
struct queuedDataStruct *nextFree; /* For linked list of free structures */
|
||||
} queuedData;
|
||||
|
||||
|
||||
|
||||
/* Static procedure declatations */
|
||||
static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numReceiveBuffers);
|
||||
static Boolean InitQueuedData(int numQueuedObjects);
|
||||
static queuedData *AllocQD(void);
|
||||
static void FreeQD(queuedData *qd);
|
||||
static void CallWholeCallbackList(callbackList l, int argLength, void *args, OSCTimeTag when, NetworkReturnAddressPtr returnAddr);
|
||||
static void InsertBundleOrMessage(char *buf, int n, OSCPacketBuffer packet, OSCTimeTag enclosingTimeTag);
|
||||
static void ParseBundle(queuedData *qd);
|
||||
static Boolean ParseMessage(queuedData *qd);
|
||||
/* static void CheckPacketRefcount(OSCPacketBuffer packet); */
|
||||
static void PacketAddRef(OSCPacketBuffer packet);
|
||||
static void PacketRemoveRef(OSCPacketBuffer packet);
|
||||
|
||||
|
||||
/**************************************************
|
||||
Initialization and memory pre-allocation
|
||||
**************************************************/
|
||||
|
||||
|
||||
Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) {
|
||||
globals.recvBufSize = t->receiveBufferSize;
|
||||
globals.InitTimeMalloc = t->InitTimeMemoryAllocator;
|
||||
globals.RealTimeMemoryAllocator = t->RealTimeMemoryAllocator;
|
||||
|
||||
globals.TheQueue = OSCNewQueue(t->numQueuedObjects, t->InitTimeMemoryAllocator);
|
||||
if (globals.TheQueue == 0) return FALSE;
|
||||
|
||||
globals.lastTimeTag = OSCTT_Immediately();
|
||||
globals.timePassed = TRUE;
|
||||
|
||||
if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(),
|
||||
t->numReceiveBuffers) == FALSE) return FALSE;
|
||||
if (InitQueuedData(t->numQueuedObjects) == FALSE) return FALSE;
|
||||
if (InitCallbackListNodes(t->numCallbackListNodes, t->InitTimeMemoryAllocator)
|
||||
== FALSE) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************
|
||||
Managing packet data structures
|
||||
**************************************************/
|
||||
|
||||
static struct OSCPacketBuffer_struct *freePackets;
|
||||
|
||||
#ifdef DEBUG_PACKET_MEM
|
||||
static void PrintPacketFreeList(void) {
|
||||
struct OSCPacketBuffer_struct *p;
|
||||
printf("- freePackets:");
|
||||
if (freePackets == 0) {
|
||||
printf(" [none]");
|
||||
}
|
||||
for (p = freePackets; p != 0; p = p->nextFree) {
|
||||
printf(" %p", p);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MIN_REASONABLE_RCV_BUFSIZE 128
|
||||
|
||||
void OSCFreeReceiver(void)
|
||||
{
|
||||
if( freePackets) free(freePackets);
|
||||
if( globals.TheQueue ) free( globals.TheQueue );
|
||||
}
|
||||
|
||||
|
||||
static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numReceiveBuffers) {
|
||||
int i;
|
||||
struct OSCPacketBuffer_struct *allPackets;
|
||||
|
||||
if (receiveBufferSize < MIN_REASONABLE_RCV_BUFSIZE) {
|
||||
fatal_error("OSCInitReceive: receiveBufferSize of %d is unreasonably small.",
|
||||
receiveBufferSize);
|
||||
}
|
||||
|
||||
allPackets = (*(globals.InitTimeMalloc))(numReceiveBuffers * sizeof(*allPackets));
|
||||
if (allPackets == 0) return FALSE;
|
||||
|
||||
for (i = 0; i < numReceiveBuffers; ++i) {
|
||||
allPackets[i].returnAddr = (*(globals.InitTimeMalloc))(clientAddrSize);
|
||||
if (allPackets[i].returnAddr == 0) return FALSE;
|
||||
|
||||
allPackets[i].buf = (*(globals.InitTimeMalloc))(receiveBufferSize);
|
||||
if (allPackets[i].buf == 0) return FALSE;
|
||||
|
||||
allPackets[i].nextFree = &(allPackets[i+1]);
|
||||
}
|
||||
allPackets[numReceiveBuffers-1].nextFree = ((struct OSCPacketBuffer_struct *) 0);
|
||||
freePackets = allPackets;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char *OSCPacketBufferGetBuffer(OSCPacketBuffer p) {
|
||||
return p->buf;
|
||||
}
|
||||
|
||||
int *OSCPacketBufferGetSize(OSCPacketBuffer p) {
|
||||
return &(p->n);
|
||||
}
|
||||
|
||||
int OSCGetReceiveBufferSize(void) {
|
||||
return globals.recvBufSize;
|
||||
}
|
||||
|
||||
NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p) {
|
||||
return p->returnAddr;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void PrintPacket(OSCPacketBuffer p) {
|
||||
printf("Packet %p. buf %p, n %d, refcount %d, nextFree %p\n",
|
||||
p, p->buf, p->n, p->refcount, p->nextFree);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
OSCPacketBuffer OSCAllocPacketBuffer(void) {
|
||||
OSCPacketBuffer result;
|
||||
if (freePackets == 0) {
|
||||
/* Could try to call the real-time memory allocator here */
|
||||
OSCWarning("OSCAllocPacketBuffer: no free packets!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = freePackets;
|
||||
freePackets = result->nextFree;
|
||||
result->refcount = 0;
|
||||
|
||||
#ifdef DEBUG_PACKET_MEM
|
||||
printf("OSCAllocPacketBuffer: allocating %p ", result);
|
||||
PrintPacketFreeList();
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void OSCFreePacket(OSCPacketBuffer p) {
|
||||
#ifdef PARANOID
|
||||
if (p->refcount != 0) {
|
||||
OSCWarning("OSCFreePacket: %p's refcount is %d!\n", p, p->refcount);
|
||||
}
|
||||
#endif
|
||||
|
||||
p->nextFree = freePackets;
|
||||
freePackets = p;
|
||||
|
||||
#ifdef DEBUG_PACKET_MEM
|
||||
printf("OSCFreePacket: freed %p ", p);
|
||||
PrintPacketFreeList();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**************************************************
|
||||
Dealing with OpenSoundControl packets and
|
||||
making the messages take effect.
|
||||
**************************************************/
|
||||
|
||||
static queuedData *freeQDList;
|
||||
|
||||
#ifdef DEBUG_QD_MEM
|
||||
static void PrintQDFreeList(void) {
|
||||
static queuedData *p;
|
||||
printf("- freeQDList:");
|
||||
if (freeQDList == 0) {
|
||||
printf(" [none]");
|
||||
}
|
||||
for (p = freeQDList; p != 0; p = p->nextFree) {
|
||||
printf(" %p", p);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static Boolean InitQueuedData(int numQueuedObjects) {
|
||||
int i;
|
||||
queuedData *allQD;
|
||||
|
||||
allQD = (*(globals.InitTimeMalloc))(numQueuedObjects * (sizeof(*allQD)));
|
||||
if (allQD == 0) return FALSE;
|
||||
|
||||
for (i = 0; i < numQueuedObjects; ++i) {
|
||||
allQD[i].nextFree = &(allQD[i+1]);
|
||||
}
|
||||
allQD[numQueuedObjects-1].nextFree = 0;
|
||||
freeQDList = &(allQD[0]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static queuedData *AllocQD(void) {
|
||||
queuedData *result;
|
||||
|
||||
if (freeQDList == 0) {
|
||||
/* Could try to call realtime malloc() */
|
||||
OSCWarning("AllocQD: no QD objects free now; returning 0.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = freeQDList;
|
||||
freeQDList = freeQDList->nextFree;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void FreeQD(queuedData *qd) {
|
||||
qd->nextFree = freeQDList;
|
||||
freeQDList = qd;
|
||||
}
|
||||
|
||||
|
||||
void OSCAcceptPacket(OSCPacketBuffer packet) {
|
||||
if ((packet->n % 4) != 0) {
|
||||
OSCProblem("OSC packet size (%d bytes) not a multiple of 4.", packet->n);
|
||||
DropPacket(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("OSCAcceptPacket(OSCPacketBuffer %p, buf %p, size %d)\n",
|
||||
packet, packet->buf, packet->n);
|
||||
#endif
|
||||
|
||||
/* If the packet came from the user, it's return address is OK. */
|
||||
packet->returnAddrOK = TRUE;
|
||||
|
||||
InsertBundleOrMessage(packet->buf, packet->n, packet, OSCTT_Immediately());
|
||||
|
||||
#ifdef PARANOID
|
||||
if (packet->refcount == 0) {
|
||||
if (freePackets != packet) {
|
||||
fatal_error("OSCAcceptPacket: packet refcount 0, but it's not the head of the free list!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
OSCInvokeAllMessagesThatAreReady(globals.lastTimeTag);
|
||||
}
|
||||
|
||||
Boolean OSCBeProductiveWhileWaiting(void) {
|
||||
/* Here's where we could be clever if an allocation fails.
|
||||
(I.e., if we're out of QD objects, we should avoid
|
||||
parsing bundles.) The code isn't that smart yet. */
|
||||
|
||||
queuedData *qd;
|
||||
|
||||
if (globals.timePassed) {
|
||||
OSCQueueScanStart(globals.TheQueue);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
qd = (queuedData *) OSCQueueScanNext(globals.TheQueue);
|
||||
if (qd == 0) return FALSE;
|
||||
|
||||
if (qd->type == BUNDLE) {
|
||||
ParseBundle(qd);
|
||||
OSCQueueRemoveCurrentScanItem(globals.TheQueue);
|
||||
return TRUE;
|
||||
} else {
|
||||
if (qd->data.message.callbacks == NOT_DISPATCHED_YET) {
|
||||
if (ParseMessage(qd) == FALSE) {
|
||||
/* Problem with this message - flush it. */
|
||||
DropMessage(qd->data.message.messageName,
|
||||
qd->data.message.length,
|
||||
qd->myPacket);
|
||||
OSCQueueRemoveCurrentScanItem(globals.TheQueue);
|
||||
PacketRemoveRef(qd->myPacket);
|
||||
FreeQD(qd);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
/* The item we found was an already-dispatched message,
|
||||
so continue the while loop. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now) {
|
||||
queuedData *x;
|
||||
OSCTimeTag thisTimeTag;
|
||||
|
||||
globals.lastTimeTag = now;
|
||||
globals.timePassed = TRUE;
|
||||
|
||||
thisTimeTag = OSCQueueEarliestTimeTag(globals.TheQueue);
|
||||
|
||||
if (OSCTT_Compare(thisTimeTag, now) > 0) {
|
||||
/* No messages ready yet. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("OSCInvokeMessagesThatAreReady(%llx) - yes, some are ready; earliest %llx\n", now, thisTimeTag);
|
||||
#endif
|
||||
|
||||
while (OSCTT_Compare(thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)) == 0) {
|
||||
x = (queuedData *) OSCQueueRemoveEarliest(globals.TheQueue);
|
||||
if (!x) return FALSE;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("...Just removed earliest entry from queue: %p, TT %llx, %s\n",
|
||||
x, x->timetag, x->type == MESSAGE ? "message" : "bundle");
|
||||
if (x->type == MESSAGE) {
|
||||
printf("...message %s, len %d, args %p, arglen %d, callbacks %p\n",
|
||||
x->data.message.messageName, x->data.message.length, x->data.message.args,
|
||||
x->data.message.argLength, x->data.message.callbacks);
|
||||
} else {
|
||||
if (x->data.bundle.length == 0) {
|
||||
printf("...bundle is empty.\n");
|
||||
} else {
|
||||
printf("...bundle len %d, first count %d, first msg %s\n",
|
||||
x->data.bundle.length, *((int *) x->data.bundle.bytes), x->data.bundle.bytes+4);
|
||||
}
|
||||
}
|
||||
PrintPacket(x->myPacket);
|
||||
#endif
|
||||
|
||||
if (x->type == BUNDLE) {
|
||||
ParseBundle(x);
|
||||
} else {
|
||||
if (x->data.message.callbacks == NOT_DISPATCHED_YET) {
|
||||
if (ParseMessage(x) == FALSE) {
|
||||
/* Problem with this message - flush it. */
|
||||
PacketRemoveRef(x->myPacket);
|
||||
FreeQD(x);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CallWholeCallbackList(x->data.message.callbacks,
|
||||
x->data.message.argLength,
|
||||
x->data.message.args,
|
||||
thisTimeTag,
|
||||
x->myPacket->returnAddrOK ? x->myPacket->returnAddr : 0);
|
||||
|
||||
PacketRemoveRef(x->myPacket);
|
||||
FreeQD(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef PARANOID
|
||||
if (OSCTT_Compare(thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)) > 0) {
|
||||
fatal_error("OSCInvokeMessagesThatAreReady: corrupt queue!\n"
|
||||
" just did %llx; earliest in queue is now %llx",
|
||||
thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue));
|
||||
}
|
||||
#endif
|
||||
|
||||
return OSCTT_Compare(OSCQueueEarliestTimeTag(globals.TheQueue), now) <= 0;
|
||||
}
|
||||
|
||||
void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now) {
|
||||
while (OSCInvokeMessagesThatAreReady(now)) {
|
||||
/* Do nothing */
|
||||
}
|
||||
}
|
||||
|
||||
static void CallWholeCallbackList(callbackList l, int argLength, void *args, OSCTimeTag when,
|
||||
NetworkReturnAddressPtr returnAddr) {
|
||||
/* In a multithreaded application, this might run in a different thread
|
||||
than the thread that deals with the priority queue. */
|
||||
|
||||
callbackList next;
|
||||
|
||||
while (l != 0) {
|
||||
(*(l->callback))(l->context, argLength, args, when, returnAddr);
|
||||
next = l->next;
|
||||
FreeCallbackListNode(l);
|
||||
l = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void InsertBundleOrMessage(char *buf, int n, OSCPacketBuffer packet, OSCTimeTag enclosingTimeTag) {
|
||||
Boolean IsBundle;
|
||||
queuedData *qd;
|
||||
|
||||
/* We add the reference first thing so in case any of the upcoming
|
||||
potential failure situations come we can call PacketRemoveRef, thereby
|
||||
freeing the packet if necessary. */
|
||||
PacketAddRef(packet);
|
||||
|
||||
if ((n % 4) != 0) {
|
||||
OSCProblem("OSC message or bundle size (%d bytes) not a multiple of 4.", n);
|
||||
DropMessage(buf, n, packet);
|
||||
PacketRemoveRef(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) {
|
||||
IsBundle = TRUE;
|
||||
|
||||
if (n < 16) {
|
||||
OSCProblem("Bundle message too small (%d bytes) for time tag.", n);
|
||||
DropBundle(buf, n, packet);
|
||||
PacketRemoveRef(packet);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
IsBundle = FALSE;
|
||||
}
|
||||
|
||||
|
||||
qd = AllocQD();
|
||||
|
||||
if (qd == 0) {
|
||||
OSCProblem("Not enough memory for queued data!");
|
||||
DropBundle(buf, n, packet);
|
||||
PacketRemoveRef(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
qd->myPacket = packet;
|
||||
qd->type = IsBundle ? BUNDLE : MESSAGE;
|
||||
|
||||
if (IsBundle) {
|
||||
/* Be careful of 8-byte alignment when copying the time tag. Here's a good
|
||||
way to get a bus error when buf happens not to be 8-byte aligned:
|
||||
qd->timetag = *((OSCTimeTag *)(buf+8));
|
||||
*/
|
||||
memcpy(&(qd->timetag), buf+8, sizeof(OSCTimeTag));
|
||||
|
||||
if (OSCTT_Compare(qd->timetag, enclosingTimeTag) < 0) {
|
||||
OSCProblem("Time tag of sub-bundle is before time tag of enclosing bundle.");
|
||||
DropBundle(buf, n, packet);
|
||||
PacketRemoveRef(packet);
|
||||
FreeQD(qd);
|
||||
return;
|
||||
}
|
||||
qd->data.bundle.bytes = buf + 16;
|
||||
qd->data.bundle.length = n - 16;
|
||||
} else {
|
||||
qd->timetag = enclosingTimeTag;
|
||||
qd->data.message.messageName = buf;
|
||||
qd->data.message.length = n;
|
||||
qd->data.message.callbacks = NOT_DISPATCHED_YET;
|
||||
}
|
||||
|
||||
OSCQueueInsert(globals.TheQueue, (OSCSchedulableObject) qd);
|
||||
}
|
||||
|
||||
|
||||
static void ParseBundle(queuedData *qd) {
|
||||
/* A queued bundle has been removed from the scheduler queue, and now it's
|
||||
time to parse all the stuff inside it and schedule the enclosed
|
||||
messages and bundles. Once all the contents of the bundle have been
|
||||
parsed and scheduled, we trash the bundle, decrementing the packet
|
||||
count and freeing the QD. */
|
||||
|
||||
int size;
|
||||
int i = 0;
|
||||
|
||||
if (qd->type != BUNDLE) {
|
||||
fatal_error("This can't happen: bundle isn't a bundle!");
|
||||
}
|
||||
|
||||
while (i < qd->data.bundle.length) {
|
||||
size = *((int *) (qd->data.bundle.bytes + i));
|
||||
if ((size % 4) != 0) {
|
||||
OSCProblem("Bad size count %d in bundle (not a multiple of 4).", size);
|
||||
DropBundle(qd->data.bundle.bytes, qd->data.bundle.length, qd->myPacket);
|
||||
goto bag;
|
||||
}
|
||||
if ((size + i + 4) > qd->data.bundle.length) {
|
||||
OSCProblem("Bad size count %d in bundle (only %d bytes left in entire bundle).",
|
||||
size, qd->data.bundle.length-i-4);
|
||||
DropBundle(qd->data.bundle.bytes, qd->data.bundle.length, qd->myPacket);
|
||||
goto bag;
|
||||
}
|
||||
|
||||
/* Recursively handle element of bundle */
|
||||
InsertBundleOrMessage(qd->data.bundle.bytes+i+4, size, qd->myPacket, qd->timetag);
|
||||
i += 4 + size;
|
||||
}
|
||||
|
||||
if (i != qd->data.bundle.length) {
|
||||
fatal_error("This can't happen: internal logic error parsing bundle");
|
||||
}
|
||||
|
||||
bag:
|
||||
/* If we got here successfully, we've added to the packet's reference count for
|
||||
each message or subbundle by calling InsertBundleOrMessage(), so we remove the one
|
||||
reference for bundle that we just parsed. If we got here by "goto bag", there's a
|
||||
problem with the bundle so we also want to lose the reference count. */
|
||||
|
||||
PacketRemoveRef(qd->myPacket);
|
||||
FreeQD(qd);
|
||||
}
|
||||
|
||||
|
||||
static Boolean ParseMessage(queuedData *qd) {
|
||||
/* Fill in all the information we'll need to execute the message as
|
||||
quickly as possible when the time comes. This means figuring out where
|
||||
the address ends and the arguments begin, and also pattern matching the
|
||||
address to find the callbacks associated with it.
|
||||
|
||||
The message may be something we have to invoke now, or it may be some
|
||||
message scheduled for the future that's just waiting on the queue; this
|
||||
procedure doesn't care. */
|
||||
|
||||
|
||||
char *args; /* char * so we can do pointer subtraction */
|
||||
int messageLen;
|
||||
char *DAAS_errormsg;
|
||||
|
||||
|
||||
if (qd->type != MESSAGE) {
|
||||
fatal_error("This can't happen: message isn't a message!");
|
||||
}
|
||||
|
||||
args = OSCDataAfterAlignedString(qd->data.message.messageName,
|
||||
qd->data.message.messageName+qd->data.message.length,
|
||||
&DAAS_errormsg);
|
||||
|
||||
if (args == 0) {
|
||||
OSCProblem("Bad message name string: %s\n", DAAS_errormsg);
|
||||
DropMessage(qd->data.message.messageName, qd->data.message.length, qd->myPacket);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
qd->data.message.args = args;
|
||||
messageLen = args - qd->data.message.messageName;
|
||||
qd->data.message.argLength = qd->data.message.length - messageLen;
|
||||
|
||||
qd->data.message.callbacks = OSCDispatchMessage(qd->data.message.messageName);
|
||||
|
||||
if (qd->data.message.callbacks == 0) {
|
||||
OSCWarning("Message pattern \"%s\" did not correspond to any address in the synth.",
|
||||
qd->data.message.messageName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void PacketAddRef(OSCPacketBuffer packet) {
|
||||
++(packet->refcount);
|
||||
}
|
||||
|
||||
static void PacketRemoveRef(OSCPacketBuffer packet) {
|
||||
--(packet->refcount);
|
||||
if (packet->refcount == 0) {
|
||||
OSCFreePacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************
|
||||
Implementation of procedures declared in
|
||||
OSC-internal-messages.h
|
||||
**************************************************/
|
||||
|
||||
#include <libOSC/OSC-internal-messages.h>
|
||||
|
||||
Boolean OSCSendInternalMessage(char *address, int arglen, void *args) {
|
||||
return OSCSendInternalMessageWithRSVP(address, arglen, args, 0);
|
||||
}
|
||||
|
||||
Boolean OSCSendInternalMessageWithRSVP(char *address, int arglen, void *args,
|
||||
NetworkReturnAddressPtr returnAddr) {
|
||||
callbackList l = OSCDispatchMessage(address);
|
||||
|
||||
if (l == 0) return FALSE;
|
||||
|
||||
CallWholeCallbackList(l, arglen, args, OSCTT_Immediately(), returnAddr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Boolean OSCScheduleInternalMessages(OSCTimeTag when, int numMessages,
|
||||
char **addresses, int *arglens, void **args) {
|
||||
int i, bufSizeNeeded;
|
||||
OSCPacketBuffer p;
|
||||
queuedData *qd;
|
||||
char *bufPtr;
|
||||
|
||||
|
||||
|
||||
/* Figure out how big of a buffer we'll need to hold this huge bundle.
|
||||
We don't store the "#bundle" string or the time tag, just the 4-byte
|
||||
size counts, the addresses, possible extra null padding for the
|
||||
addresses, and the arguments. */
|
||||
|
||||
bufSizeNeeded = 0;
|
||||
for (i = 0; i < numMessages; ++i) {
|
||||
bufSizeNeeded += 4 + OSCPaddedStrlen(addresses[i]) + arglens[i];
|
||||
}
|
||||
|
||||
if (bufSizeNeeded > OSCGetReceiveBufferSize()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Now try to allocate the data objects to hold these messages */
|
||||
qd = AllocQD();
|
||||
if (qd == 0) return FALSE;
|
||||
|
||||
p = OSCAllocPacketBuffer();
|
||||
if (p == 0) {
|
||||
FreeQD(qd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Now fill in the buffer with a fake #bundle message. This is almost like
|
||||
putting a real #bundle message in the buffer and then calling OSCAcceptPacket,
|
||||
except that we save a little time and memory by not writing "#bundle" or the time tag,
|
||||
and by pre-parsing the messages a little. Thus, this code duplicates a lot
|
||||
of what's in InsertBundleOrMessage() */
|
||||
|
||||
bufPtr = p->buf;
|
||||
|
||||
for (i = 0; i < numMessages; ++i) {
|
||||
/* First the size count of this bundle element */
|
||||
*((int4 *) bufPtr) = OSCPaddedStrlen(addresses[i]) + arglens[i];
|
||||
bufPtr += sizeof(int4);
|
||||
|
||||
/* Then the address */
|
||||
bufPtr = OSCPaddedStrcpy(bufPtr, addresses[i]);
|
||||
|
||||
/* Then the arguments */
|
||||
memcpy(bufPtr, args[i], arglens[i]);
|
||||
bufPtr += arglens[i];
|
||||
}
|
||||
|
||||
#ifdef PARANOID
|
||||
if (bufPtr != p->buf+bufSizeNeeded) {
|
||||
fatal_error("OSCScheduleInternalMessages: internal error");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill in the rest of the packet fields */
|
||||
p->n = bufSizeNeeded;
|
||||
p->returnAddrOK = FALSE;
|
||||
PacketAddRef(p);
|
||||
|
||||
/* Now fill in the queuedData object */
|
||||
qd->timetag = when;
|
||||
qd->myPacket = p;
|
||||
qd->type = BUNDLE;
|
||||
qd->data.bundle.length = bufSizeNeeded;
|
||||
qd->data.bundle.bytes = p->buf;
|
||||
|
||||
/* Now we can put it into the scheduling queue. */
|
||||
OSCQueueInsert(globals.TheQueue, (OSCSchedulableObject) qd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Boolean NetworkPacketWaiting(OSCPacketBuffer packet) {
|
||||
int n;
|
||||
NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet);
|
||||
|
||||
// if( use_mcast_ )
|
||||
// {
|
||||
fd_set fds;
|
||||
struct timeval no_wait;
|
||||
int status;
|
||||
memset( &no_wait, 0, sizeof(no_wait));
|
||||
FD_ZERO(&fds);
|
||||
FD_SET( na->sockfd , &fds );
|
||||
status = select( na->sockfd + 1, &fds, 0, 0, &no_wait );
|
||||
if(status <= 0)
|
||||
return FALSE;
|
||||
if(FD_ISSET( na->sockfd, &fds ))
|
||||
return TRUE;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if( ioctl( na->sockfd, FIONREAD, &n, 0)==-1) return FALSE;
|
||||
// if( n==0 ) return FALSE;
|
||||
// }
|
||||
// return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Boolean NetworkReceivePacket( OSCPacketBuffer packet ) {
|
||||
int n;
|
||||
NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet);
|
||||
|
||||
if( use_mcast_ )
|
||||
{
|
||||
n = recv( na->sockfd, packet->buf, 100, 0 );
|
||||
if( n<= 0)
|
||||
return FALSE;
|
||||
packet->n = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = recvfrom( na->sockfd, packet->buf, 100, 0,
|
||||
(struct sockaddr*) &(na->cl_addr), &(na->clilen));
|
||||
if(n<=0) {
|
||||
return FALSE;
|
||||
}
|
||||
packet->n = n;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void GoMultiCast( const char *group_name )
|
||||
{
|
||||
use_mcast_ = 1;
|
||||
strncpy( mcast_groupname, group_name, strlen(group_name ));
|
||||
}
|
||||
|
||||
int IsMultiCast( char *dst )
|
||||
{
|
||||
if(use_mcast_)
|
||||
sprintf(dst, "%s", mcast_groupname );
|
||||
return use_mcast_;
|
||||
}
|
||||
|
||||
Boolean NetworkStartUDPServer(OSCPacketBuffer packet, int port_id) {
|
||||
struct sockaddr_in my_addr;
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(port_id);
|
||||
my_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
memset( &(my_addr.sin_zero), 0, 8);
|
||||
|
||||
if( use_mcast_ )
|
||||
{
|
||||
struct ip_mreq mcast_req;
|
||||
int on = 1;
|
||||
int err= 0;
|
||||
memset( &mcast_req, 0, sizeof(mcast_req));
|
||||
packet->returnAddr->sockfd = socket( AF_INET, SOCK_DGRAM, 0);
|
||||
#ifdef SO_REUSEADDR
|
||||
setsockopt( packet->returnAddr->sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
setsockopt( packet->returnAddr->sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
|
||||
#endif
|
||||
err = bind( packet->returnAddr->sockfd, (struct sockaddr*) &my_addr, sizeof( my_addr ));
|
||||
if( err < 0 )
|
||||
return FALSE;
|
||||
|
||||
mcast_req.imr_multiaddr.s_addr = inet_addr( mcast_groupname );
|
||||
mcast_req.imr_interface.s_addr = htonl( INADDR_ANY );
|
||||
setsockopt( packet->returnAddr->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&mcast_req, sizeof(mcast_req) );
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->returnAddr->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if( bind( packet->returnAddr->sockfd,
|
||||
(struct sockaddr*) &my_addr,
|
||||
sizeof(struct sockaddr)) == -1) return FALSE;
|
||||
|
||||
packet->returnAddr->clilen = sizeof(struct sockaddr);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
242
veejay-1.3/veejay-server/libOSC/OSC-receive.h
Normal file
242
veejay-1.3/veejay-server/libOSC/OSC-receive.h
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
OSC-receive.h
|
||||
Matt Wright, 11/18/97
|
||||
|
||||
include OSC-timetag.h and NetworkReturnAddress.h before this file.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************************
|
||||
Initialization and memory pre-allocation
|
||||
**************************************************/
|
||||
|
||||
/* The memory model used by this module is pre-allocation of fixed-size
|
||||
objects for network buffers and other internal objects. This preallocated
|
||||
memory is dynamically managed internally by a custom high-performance memory
|
||||
allocator. When the preallocated memory runs out, this module calls an
|
||||
optional realtime memory allocator that you provide. If your memory
|
||||
allocator gives this module more memory, it will add it to the pool of
|
||||
objects and never free the memory. If your system does not have a realtime
|
||||
memory allocator, provide a procedure that always returns 0.
|
||||
|
||||
You will fill an OSCReceiveMemoryTuner struct with the parameters that
|
||||
determine how memory will be allocated.
|
||||
|
||||
The MemoryAllocator fields are procedures you will provide that allocate
|
||||
memory. Like malloc(), they take the number of bytes as arguments and return
|
||||
either a pointer to the new memory or 0 for failure. This memory will never
|
||||
be freed.
|
||||
|
||||
- The InitTimeMemoryAllocator will be called only at initialization time,
|
||||
i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's
|
||||
a fatal error.
|
||||
|
||||
- The RealTimeMemoryAllocator will be called if, while the application is
|
||||
running, the address space grows larger than can fit in what was allocated
|
||||
at initialization time. If the RealTimeMemoryAllocator() returns 0, the
|
||||
operation attempting to grow the address space will fail. If your system
|
||||
does not have real-time memory allocation, RealTimeMemoryAllocator should
|
||||
be a procedure that always returns 0.
|
||||
|
||||
The remaining fields say how much memory to allocate at initialization time:
|
||||
|
||||
- receiveBufferSize is the maximum packet size that can be received. Is the
|
||||
maximum UDP packet size 4096? OSC clients can send a query to this system
|
||||
asking for this maximum packet size.
|
||||
|
||||
- numReceiveBuffers determines how many packets at a time can be sitting
|
||||
on the scheduler with messages waiting to take effect. If all the
|
||||
receive buffers are tied up like this, you won't be able to receive
|
||||
new packets.
|
||||
|
||||
- numQueuedObjects is the number of messages and packets that can be sitting
|
||||
on the scheduler waiting to take effect.
|
||||
|
||||
- Because a message pattern may be dispatched before the message takes effect,
|
||||
we need memory to store the callback pointers corresponding to a message.
|
||||
numCallbackListNodes is the number of callbacks that may be stored in this
|
||||
fashion. It must be at least as large as the maximum number of methods that
|
||||
any one message pattern may match, but if you want to take advantage of
|
||||
pre-dispatching, this should be large enough to hold all the callbacks for
|
||||
all the messages waiting in the scheduler.
|
||||
|
||||
*/
|
||||
|
||||
struct OSCReceiveMemoryTuner {
|
||||
void *(*InitTimeMemoryAllocator)(int numBytes);
|
||||
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||
int receiveBufferSize;
|
||||
int numReceiveBuffers;
|
||||
int numQueuedObjects;
|
||||
int numCallbackListNodes;
|
||||
};
|
||||
|
||||
/* Given an OSCReceiveMemoryTuner, return the number of bytes of
|
||||
memory that would be allocated if OSCInitReceive() were called
|
||||
on it. */
|
||||
int OSCReceiveMemoryThatWouldBeAllocated(struct OSCReceiveMemoryTuner *t);
|
||||
|
||||
/* Returns FALSE if it fails to initialize */
|
||||
Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t);
|
||||
|
||||
/**************************************************
|
||||
Managing packet data structures
|
||||
**************************************************/
|
||||
|
||||
|
||||
/* You don't get to know what's in an OSCPacketBuffer. */
|
||||
typedef struct OSCPacketBuffer_struct *OSCPacketBuffer;
|
||||
|
||||
/* Get an unused packet. Returns 0 if none are free. If you get a packet
|
||||
with this procedure, it is your responsibility either to call
|
||||
OSCAcceptPacket() on it (in which case the internals of the OSC Kit free
|
||||
the OSCPacketBuffer after the last message in it takes effect) or to call
|
||||
OSCFreePacket() on it. */
|
||||
OSCPacketBuffer OSCAllocPacketBuffer(void);
|
||||
|
||||
/* Free. This is called automatically after the last message that was
|
||||
in the packet is invoked. You shouldn't need to call this unless
|
||||
you get a packet with OSCAllocPacketBuffer() and then for some reason
|
||||
decide not to call OSCAcceptPacket() on it. */
|
||||
void OSCFreePacket(OSCPacketBuffer p);
|
||||
|
||||
void OSCFreeReceiver(void);
|
||||
|
||||
/* Whatever code actually gets packets from the network should use these
|
||||
three selectors to access the fields in the packet structure that need
|
||||
to be filled in with the data from the network. */
|
||||
|
||||
/* Selector to get the buffer from a packet. This buffer's size will be
|
||||
equal to the receiveBufferSize you passed to OSCInitReceive(). */
|
||||
char *OSCPacketBufferGetBuffer(OSCPacketBuffer p);
|
||||
|
||||
/* Selector to get a pointer to the int that's the size count for the
|
||||
data currently in a packet. (Not the capacity of the packet's buffer,
|
||||
but the size of the packet that's actually stored in the buffer.) */
|
||||
int *OSCPacketBufferGetSize(OSCPacketBuffer);
|
||||
|
||||
/* Selector to get the client's network address from a packet. This buffer's
|
||||
size will be equal to the clientAddrSize you passed to OSCInitReceive().
|
||||
Note that the NetworkReturnAddressPtr type is full of "const"s, so your
|
||||
code that fills in the return address will probably have to cast the return
|
||||
value of this procedure to some non-const type to be able to write into it. */
|
||||
NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p);
|
||||
|
||||
/* Returns the capacity of packet buffers (the receiveBufferSize you passed
|
||||
to OSCInitReceive()). */
|
||||
int OSCGetReceiveBufferSize(void);
|
||||
|
||||
|
||||
/**************************************************
|
||||
Dealing with OpenSoundControl packets and
|
||||
making the messages take effect.
|
||||
**************************************************/
|
||||
|
||||
/* Call this as soon as a packet comes in from the network.
|
||||
It will take care of anything that has to happen immediately,
|
||||
but put off as much as possible of the work of parsing the
|
||||
packet. (This tries to be as fast as possible in case a
|
||||
lot of packets come in.) */
|
||||
void OSCAcceptPacket(OSCPacketBuffer packet);
|
||||
|
||||
/* Call this during an otherwise idle time. It goes through
|
||||
everything that's sitting in the OSC scheduler waiting to
|
||||
happen and does some of the work of parsing, pattern
|
||||
matching, dispatching, etc., that will have to be done
|
||||
at some point before the scheduled messages can take
|
||||
effect.
|
||||
|
||||
The return value indicates whether there is more work of
|
||||
this sort that could be done. (Each time you call this,
|
||||
it does only a small unit of this kind of work. If it
|
||||
returns TRUE and you still have time before the next thing
|
||||
you have to do, call it again.) */
|
||||
Boolean OSCBeProductiveWhileWaiting(void);
|
||||
|
||||
/* Call this whenever enough time has passed that you want to see which
|
||||
messages are now ready and have them take effect. (For example, in a
|
||||
synthesizer, you might call this once per synthesis frame, just before
|
||||
synthesizing the audio for that frame.)
|
||||
|
||||
This procedure finds the earliest time tag of all the queued messages
|
||||
and invokes *all* of the queued messages with that time tag. (OSC
|
||||
guarantees that messages with the same tag take effect atomically.)
|
||||
If there are more messages that are ready, but with a different time
|
||||
tag, this procedure does not invoke them, but returns TRUE to indicate
|
||||
that more messages are ready.
|
||||
*/
|
||||
Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now);
|
||||
|
||||
/* Same thing, but invokes all of the messages whose time has come. */
|
||||
void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now);
|
||||
|
||||
Boolean NetworkReceivePacket(OSCPacketBuffer packet);
|
||||
|
||||
Boolean NetworkStartUDPServer(OSCPacketBuffer packet, int port_id);
|
||||
|
||||
Boolean NetworkPacketWaiting(OSCPacketBuffer packet);
|
||||
|
||||
void GoMultiCast(const char *groupname);
|
||||
|
||||
int IsMultiCast( char *dst);
|
||||
|
||||
/**************************************************
|
||||
How to use this stuff
|
||||
**************************************************/
|
||||
|
||||
/* Here's a gross approximation of how your application will invoke the
|
||||
procedures in this module:
|
||||
|
||||
while (1) {
|
||||
OSCTimeTag now = CurrentTime();
|
||||
do {
|
||||
if (WeAreSoLateThatWeNeedToDelayOSCMessagesToAvoidACrisis()) break;
|
||||
} while (OSCInvokeMessagesThatAreReady(now) == TRUE);
|
||||
|
||||
SynthesizeSomeSound();
|
||||
if (NetworkPacketWaiting()) {
|
||||
OSCPacketBuffer p = OSCAllocPacketBuffer();
|
||||
if (!p) {
|
||||
Bummer();
|
||||
} else {
|
||||
NetworkReceivePacket(p);
|
||||
OSCAcceptPacket(p);
|
||||
}
|
||||
}
|
||||
while (TimeLeftBeforeWeHaveDoSomething()) {
|
||||
if (!OSCBeProductiveWhileWaiting()) break;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
123
veejay-1.3/veejay-server/libOSC/OSC-string-help.c
Normal file
123
veejay-1.3/veejay-server/libOSC/OSC-string-help.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-string-help.c
|
||||
Procedures that could be useful to programmers writing OSC methods that
|
||||
take string arguments.
|
||||
|
||||
by Matt Wright, 3/19/98
|
||||
*/
|
||||
|
||||
#include <libOSC/OSC-common.h> /* For Boolean */
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#define STRING_ALIGN_PAD 4
|
||||
|
||||
char *OSCDataAfterAlignedString(const char *string, const char *boundary, char **errorMsg) {
|
||||
|
||||
int i;
|
||||
|
||||
if ((boundary - string) %4 != 0) {
|
||||
fatal_error("DataAfterAlignedString: bad boundary\n");
|
||||
}
|
||||
|
||||
for (i = 0; string[i] != '\0'; i++) {
|
||||
if (string + i >= boundary) {
|
||||
(*errorMsg) = "DataAfterAlignedString: Unreasonably long string";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now string[i] is the first null character */
|
||||
i++;
|
||||
|
||||
for (; (i % STRING_ALIGN_PAD) != 0; i++) {
|
||||
if (string + i >= boundary) {
|
||||
(*errorMsg) = "Unreasonably long string";
|
||||
return 0;
|
||||
}
|
||||
if (string[i] != '\0') {
|
||||
(*errorMsg) = "Incorrectly padded string.";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (char *) (string+i);
|
||||
}
|
||||
|
||||
int OSCPaddedStrlen(const char *s) {
|
||||
int i;
|
||||
|
||||
for (i = 0; *s != '\0'; s++, i++) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* Now i is the length with no null bytes. We need 1-4 null bytes,
|
||||
to make the total length a multiple of 4. So we add 4, as if
|
||||
we need 4 null bytes, then & 0xfffffffc to round down to the nearest
|
||||
multiple of 4. */
|
||||
|
||||
return (i + 4) & 0xfffffffc;
|
||||
}
|
||||
|
||||
char *OSCPaddedStrcpy(char *target, const char *source) {
|
||||
while ( (*target++) = (*source++)) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* That copied one null byte */
|
||||
while (((int) target) % 4 != 0) {
|
||||
*target = '\0';
|
||||
target++;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
Boolean OSCParseStringList(const char *result[], int *numStrings, int maxStrings,
|
||||
const char *args, int numBytes) {
|
||||
int numFound;
|
||||
const char *p;
|
||||
const char *boundary = args + numBytes;
|
||||
char *errorMessage;
|
||||
|
||||
p = args;
|
||||
|
||||
for (numFound = 0; numFound < maxStrings; ++numFound) {
|
||||
if (p == boundary) {
|
||||
*numStrings = numFound;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
result[numFound] = p;
|
||||
p = OSCDataAfterAlignedString(p, boundary, &errorMessage);
|
||||
if (p == 0) return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
70
veejay-1.3/veejay-server/libOSC/OSC-string-help.h
Normal file
70
veejay-1.3/veejay-server/libOSC/OSC-string-help.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-string-help.h
|
||||
Procedures that could be useful to programmers writing OSC methods that
|
||||
take string arguments.
|
||||
|
||||
by Matt Wright, 3/19/98
|
||||
*/
|
||||
|
||||
/* Use this to deal with OSC null-padded 4 byte-aligned strings
|
||||
|
||||
The argument is a block of data beginning with a string. The string
|
||||
has (presumably) been padded with extra null characters so that the
|
||||
overall length is a multiple of 4 bytes. Return a pointer to the next
|
||||
byte after the null byte(s). The boundary argument points to the
|
||||
character after the last valid character in the buffer---if the string
|
||||
hasn't ended by there, something's wrong.
|
||||
|
||||
If the data looks wrong, return 0, and set *errorMsg */
|
||||
|
||||
char *OSCDataAfterAlignedString(const char *string, const char *boundary, char **errorMsg);
|
||||
|
||||
|
||||
/* Given a normal C-style string with a single padding byte, return the
|
||||
length of the string including the necessary 1-4 padding bytes.
|
||||
(Basically strlen()+1 rounded up to the next multiple of 4.) */
|
||||
int OSCPaddedStrlen(const char *s);
|
||||
|
||||
/* Copy a given C-style string into the given destination, including the
|
||||
requisite padding byte(s). Unlike strcpy(), this returns a pointer to
|
||||
the next character after the copied string's null bytes, like
|
||||
what OSCDataAfterAlignedString() returns. */
|
||||
char *OSCPaddedStrcpy(char *target, const char *source);
|
||||
|
||||
|
||||
/* Given an args pointer that should be nothing but a list of strings, fill
|
||||
result[] with pointers to the beginnings of each string, and set
|
||||
*numStrings to be the number of strings found. maxStrings gives the size
|
||||
of the result array. Return FALSE if any strings are malformatted or if
|
||||
there are more than maxStrings many strings. */
|
||||
|
||||
Boolean OSCParseStringList(const char *result[], int *numStrings, int maxStrings,
|
||||
const char *args, int numBytes);
|
||||
56
veejay-1.3/veejay-server/libOSC/OSC-struct.h
Normal file
56
veejay-1.3/veejay-server/libOSC/OSC-struct.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef OSCH
|
||||
#define OSCH
|
||||
#ifndef TRUE
|
||||
typedef int Boolean;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Fixed byte width types */
|
||||
typedef int int4; /* 4 byte int */
|
||||
typedef struct NetworkReturnAddressStruct_t {
|
||||
struct sockaddr_in cl_addr; /* client information */
|
||||
struct sockaddr_in my_addr; /* us */
|
||||
int clilen;
|
||||
int sockfd;
|
||||
fd_set readfds;
|
||||
struct timeval tv;
|
||||
int fdmax;
|
||||
} NetworkReturnAddressStruct;
|
||||
|
||||
|
||||
typedef struct OSCPacketBuffer_struct {
|
||||
char *buf; /* Contents of network packet go here */
|
||||
int n; /* Overall size of packet */
|
||||
int refcount; /* # queued things using memory from this buffer */
|
||||
struct OSCPacketBuffer_struct *nextFree; /* For linked list of free packets */
|
||||
|
||||
Boolean returnAddrOK; /* Because returnAddr points to memory we need to
|
||||
store future return addresses, we set this
|
||||
field to FALSE in situations where a packet
|
||||
buffer "has no return address" instead of
|
||||
setting returnAddr to 0 */
|
||||
|
||||
void *returnAddr; /* Addr of client this packet is from */
|
||||
/* This was of type NetworkReturnAddressPtr, but the constness
|
||||
was making it impossible for me to initialize it. There's
|
||||
probably a better way that I don't understand. */
|
||||
|
||||
} OSCPacketBuffer;
|
||||
|
||||
struct OSCReceiveMemoryTuner {
|
||||
void *(*InitTimeMemoryAllocator)(int numBytes);
|
||||
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||
int receiveBufferSize;
|
||||
int numReceiveBuffers;
|
||||
int numQueuedObjects;
|
||||
int numCallbackListNodes;
|
||||
};
|
||||
|
||||
#endif
|
||||
174
veejay-1.3/veejay-server/libOSC/OSC-timetag.c
Normal file
174
veejay-1.3/veejay-server/libOSC/OSC-timetag.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
OSC_timeTag.c: library for manipulating OSC time tags
|
||||
Matt Wright, 5/29/97
|
||||
|
||||
Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
|
||||
|
||||
*/
|
||||
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef HAS8BYTEINT
|
||||
#define TWO_TO_THE_32_FLOAT 4294967296.0f
|
||||
|
||||
OSCTimeTag OSCTT_Immediately(void) {
|
||||
return (OSCTimeTag) 1;
|
||||
}
|
||||
|
||||
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
|
||||
return (OSCTimeTag) 0xffffffffffffffff;
|
||||
}
|
||||
|
||||
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
|
||||
int8 offset = (int8) (secondsOffset * TWO_TO_THE_32_FLOAT);
|
||||
|
||||
/* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original,
|
||||
secondsOffset, offset, original + offset); */
|
||||
|
||||
return original + offset;
|
||||
}
|
||||
|
||||
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
|
||||
#if 0
|
||||
printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right,
|
||||
(left<right) ? -1 : ((left == right) ? 0 : 1));
|
||||
#endif
|
||||
if (left < right) {
|
||||
return -1;
|
||||
} else if (left == right) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __sgi
|
||||
#include <sys/time.h>
|
||||
|
||||
#define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */
|
||||
#define TWO_TO_THE_32_OVER_ONE_MILLION 4295
|
||||
|
||||
|
||||
OSCTimeTag OSCTT_CurrentTime(void) {
|
||||
uint8 result;
|
||||
uint4 usecOffset;
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
BSDgettimeofday(&tv, &tz);
|
||||
|
||||
/* First get the seconds right */
|
||||
result = (unsigned) SECONDS_FROM_1900_to_1970 +
|
||||
(unsigned) tv.tv_sec -
|
||||
(unsigned) 60 * tz.tz_minuteswest +
|
||||
(unsigned) (tz.tz_dsttime ? 3600 : 0);
|
||||
|
||||
#if 0
|
||||
/* No timezone, no DST version ... */
|
||||
result = (unsigned) SECONDS_FROM_1900_to_1970 +
|
||||
(unsigned) tv.tv_sec;
|
||||
#endif
|
||||
|
||||
|
||||
/* make seconds the high-order 32 bits */
|
||||
result = result << 32;
|
||||
|
||||
/* Now get the fractional part. */
|
||||
usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION;
|
||||
/* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */
|
||||
|
||||
result += usecOffset;
|
||||
|
||||
/* printf("* OSCTT_CurrentTime is %llx\n", result); */
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* __sgi */
|
||||
|
||||
/* Instead of asking your operating system what time it is, it might be
|
||||
clever to find out the current time at the instant your application
|
||||
starts audio processing, and then keep track of the number of samples
|
||||
output to know how much time has passed. */
|
||||
|
||||
/* Loser version for systems that have no ability to tell the current time: */
|
||||
OSCTimeTag OSCTT_CurrentTime(void) {
|
||||
return (OSCTimeTag) 1;
|
||||
}
|
||||
|
||||
#endif /* __sgi */
|
||||
|
||||
|
||||
#else /* Not HAS8BYTEINT */
|
||||
|
||||
OSCTimeTag OSCTT_CurrentTime(void) {
|
||||
OSCTimeTag result;
|
||||
result.seconds = 0;
|
||||
result.fraction = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
|
||||
OSCTimeTag result;
|
||||
result.seconds = 0xffffffff;
|
||||
result.fraction = 0xffffffff;
|
||||
return result;
|
||||
}
|
||||
|
||||
OSCTimeTag OSCTT_Immediately(void) {
|
||||
OSCTimeTag result;
|
||||
result.seconds = 0;
|
||||
result.fraction = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
|
||||
OSCTimeTag result;
|
||||
result.seconds = 0;
|
||||
result.fraction = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
|
||||
/* Untested! */
|
||||
int highResult = left.seconds - right.seconds;
|
||||
|
||||
if (highResult != 0) return highResult;
|
||||
|
||||
return left.fraction - right.fraction;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAS8BYTEINT */
|
||||
|
||||
91
veejay-1.3/veejay-server/libOSC/OSC-timetag.h
Normal file
91
veejay-1.3/veejay-server/libOSC/OSC-timetag.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||
University of California, Berkeley.
|
||||
|
||||
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||
of this software and its documentation without fee and without a signed
|
||||
licensing agreement, is hereby granted, provided that the above copyright
|
||||
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||
modifications, and distributions.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
|
||||
The OpenSound Control WWW page is
|
||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
OSC_timeTag.h: library for manipulating OSC time tags
|
||||
Matt Wright, 5/29/97
|
||||
|
||||
Time tags in OSC have the same format as in NTP: 64 bit fixed point, with the
|
||||
top 32 bits giving number of seconds sinve midnight 1/1/1900 and the bottom
|
||||
32 bits giving fractional parts of a second. We represent this by an 8-byte
|
||||
unsigned long if possible, or else a struct.
|
||||
|
||||
NB: On many architectures with 8-byte ints, it's illegal (like maybe a bus error)
|
||||
to dereference a pointer to an 8 byte int that's not 8-byte aligned.
|
||||
*/
|
||||
|
||||
#ifndef OSC_TIMETAG
|
||||
#define OSC_TIMETAG
|
||||
|
||||
#ifdef __sgi
|
||||
#define HAS8BYTEINT
|
||||
/* You may have to change this typedef if there's some other
|
||||
way to specify 8 byte ints on your system */
|
||||
typedef long long int8;
|
||||
typedef unsigned long long uint8;
|
||||
typedef unsigned long uint4;
|
||||
#else
|
||||
/* You may have to redefine this typedef if ints on your system
|
||||
aren't 4 bytes. */
|
||||
typedef unsigned int uint4;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAS8BYTEINT
|
||||
typedef uint8 OSCTimeTag;
|
||||
#else
|
||||
typedef struct {
|
||||
uint4 seconds;
|
||||
uint4 fraction;
|
||||
} OSCTimeTag;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Return a time tag representing the current time (as of when this
|
||||
procedure is called). */
|
||||
OSCTimeTag OSCTT_CurrentTime(void);
|
||||
|
||||
/* Return the time tag 0x0000000000000001, indicating to the receiving device
|
||||
that it should process the message immediately. */
|
||||
OSCTimeTag OSCTT_Immediately(void);
|
||||
|
||||
/* Return the time tag 0xffffffffffffffff, a time so far in the future that
|
||||
it's effectively infinity. */
|
||||
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void);
|
||||
|
||||
/* Given a time tag and a number of seconds to add to the time tag, return
|
||||
the new time tag */
|
||||
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset);
|
||||
|
||||
/* Compare two time tags. Return negative if first is < second, 0 if
|
||||
they're equal, and positive if first > second. */
|
||||
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right);
|
||||
|
||||
#endif /* OSC_TIMETAG */
|
||||
26
veejay-1.3/veejay-server/libOSC/libosc.h
Normal file
26
veejay-1.3/veejay-server/libOSC/libosc.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _LIBOSC_H_INCLUDED
|
||||
#define _LIBOSC_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <libOSC/OSC-common.h>
|
||||
#include <libOSC/OSC-timetag.h>
|
||||
#include <libOSC/OSC-address-space.h>
|
||||
#include <libOSC/OSC-dispatch.h>
|
||||
#include <libOSC/OSC-receive.h>
|
||||
#include <libOSC/OSC-callbacklist.h>
|
||||
#include <libOSC/OSC-drop.h>
|
||||
#include <libOSC/OSC-internal-messages.h>
|
||||
#include <libOSC/OSC-pattern-match.h>
|
||||
#include <libOSC/OSC-priority-queue.h>
|
||||
#include <libOSC/OSC-string-help.h>
|
||||
#include <libOSC/NetworkReturnAddress.h>
|
||||
#include <libOSC/NetworkUDP.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
12
veejay-1.3/veejay-server/libel/Makefile.am
Normal file
12
veejay-1.3/veejay-server/libel/Makefile.am
Normal file
@@ -0,0 +1,12 @@
|
||||
# Makefile for veejay
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
AM_CFLAGS=$(OP_CFLAGS)
|
||||
INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/vjmem \
|
||||
-I$(top_srcdir)/vjmsg \
|
||||
$(MJPEGTOOLS_CFLAGS) $(FFMPEG_CFLAGS) $(PIXBUF_CFLAGS) \
|
||||
$(LIBQUICKTIME_CFLAGS)
|
||||
|
||||
VJEL_LIB_FILE = libel.la
|
||||
noinst_LTLIBRARIES = $(VJEL_LIB_FILE)
|
||||
libel_la_SOURCES = vj-mmap.c elcache.c avilib.c lav_io.c vj-dv.c rawdv.c pixbuf.c vj-avcodec.c vj-el.c
|
||||
3785
veejay-1.3/veejay-server/libel/avilib.c
Normal file
3785
veejay-1.3/veejay-server/libel/avilib.c
Normal file
File diff suppressed because it is too large
Load Diff
464
veejay-1.3/veejay-server/libel/avilib.h
Normal file
464
veejay-1.3/veejay-server/libel/avilib.h
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* avilib.h
|
||||
*
|
||||
* Copyright (C) Thomas <20>streich - June 2001
|
||||
* multiple audio track support Copyright (C) 2002 Thomas <20>streich
|
||||
*
|
||||
* Original code:
|
||||
* Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
|
||||
*
|
||||
* This file is part of transcode, a video stream processing tool
|
||||
*
|
||||
* transcode 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* transcode 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 GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libel/vj-mmap.h>
|
||||
|
||||
#ifndef AVILIB_H
|
||||
#define AVILIB_H
|
||||
|
||||
#define AVI_MAX_TRACKS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
off_t key;
|
||||
off_t pos;
|
||||
off_t len;
|
||||
} video_index_entry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
off_t pos;
|
||||
off_t len;
|
||||
off_t tot;
|
||||
} audio_index_entry;
|
||||
|
||||
|
||||
// Index types
|
||||
|
||||
|
||||
#define AVI_INDEX_OF_INDEXES 0x00 // when each entry in aIndex
|
||||
// array points to an index chunk
|
||||
#define AVI_INDEX_OF_CHUNKS 0x01 // when each entry in aIndex
|
||||
// array points to a chunk in the file
|
||||
#define AVI_INDEX_IS_DATA 0x80 // when each entry is aIndex is
|
||||
// really the data
|
||||
// bIndexSubtype codes for INDEX_OF_CHUNKS
|
||||
//
|
||||
#define AVI_INDEX_2FIELD 0x01 // when fields within frames
|
||||
// are also indexed
|
||||
|
||||
|
||||
|
||||
typedef struct _avisuperindex_entry {
|
||||
uint64_t qwOffset; // absolute file offset
|
||||
uint32_t dwSize; // size of index chunk at this offset
|
||||
uint32_t dwDuration; // time span in stream ticks
|
||||
} avisuperindex_entry;
|
||||
|
||||
typedef struct _avistdindex_entry {
|
||||
uint32_t dwOffset; // qwBaseOffset + this is absolute file offset
|
||||
uint32_t dwSize; // bit 31 is set if this is NOT a keyframe
|
||||
} avistdindex_entry;
|
||||
|
||||
// Standard index
|
||||
typedef struct _avistdindex_chunk {
|
||||
char fcc[4]; // ix##
|
||||
uint32_t dwSize; // size of this chunk
|
||||
uint16_t wLongsPerEntry; // must be sizeof(aIndex[0])/sizeof(DWORD)
|
||||
uint8_t bIndexSubType; // must be 0
|
||||
uint8_t bIndexType; // must be AVI_INDEX_OF_CHUNKS
|
||||
uint32_t nEntriesInUse; //
|
||||
char dwChunkId[4]; // '##dc' or '##db' or '##wb' etc..
|
||||
uint64_t qwBaseOffset; // all dwOffsets in aIndex array are relative to this
|
||||
uint32_t dwReserved3; // must be 0
|
||||
avistdindex_entry *aIndex;
|
||||
} avistdindex_chunk;
|
||||
|
||||
|
||||
// Base Index Form 'indx'
|
||||
typedef struct _avisuperindex_chunk {
|
||||
char fcc[4];
|
||||
uint32_t dwSize; // size of this chunk
|
||||
uint16_t wLongsPerEntry; // size of each entry in aIndex array (must be 8 for us)
|
||||
uint8_t bIndexSubType; // future use. must be 0
|
||||
uint8_t bIndexType; // one of AVI_INDEX_* codes
|
||||
uint32_t nEntriesInUse; // index of first unused member in aIndex array
|
||||
char dwChunkId[4]; // fcc of what is indexed
|
||||
uint32_t dwReserved[3]; // meaning differs for each index type/subtype.
|
||||
// 0 if unused
|
||||
avisuperindex_entry *aIndex; // where are the ix## chunks
|
||||
avistdindex_chunk **stdindex; // the ix## chunks itself (array)
|
||||
} avisuperindex_chunk;
|
||||
|
||||
|
||||
|
||||
typedef struct track_s
|
||||
{
|
||||
|
||||
long a_fmt; /* Audio format, see #defines below */
|
||||
long a_chans; /* Audio channels, 0 for no audio */
|
||||
long a_rate; /* Rate in Hz */
|
||||
long a_bits; /* bits per audio sample */
|
||||
long mp3rate; /* mp3 bitrate kbs*/
|
||||
long a_vbr; /* 0 == no Variable BitRate */
|
||||
long padrate; /* byte rate used for zero padding */
|
||||
|
||||
long audio_strn; /* Audio stream number */
|
||||
off_t audio_bytes; /* Total number of bytes of audio data */
|
||||
long audio_chunks; /* Chunks of audio data in the file */
|
||||
|
||||
char audio_tag[4]; /* Tag of audio data */
|
||||
long audio_posc; /* Audio position: chunk */
|
||||
long audio_posb; /* Audio position: byte within chunk */
|
||||
|
||||
off_t a_codech_off; /* absolut offset of audio codec information */
|
||||
off_t a_codecf_off; /* absolut offset of audio codec information */
|
||||
|
||||
audio_index_entry *audio_index;
|
||||
avisuperindex_chunk *audio_superindex;
|
||||
|
||||
} track_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bi_size;
|
||||
uint32_t bi_width;
|
||||
uint32_t bi_height;
|
||||
uint16_t bi_planes;
|
||||
uint16_t bi_bit_count;
|
||||
uint32_t bi_compression;
|
||||
uint32_t bi_size_image;
|
||||
uint32_t bi_x_pels_per_meter;
|
||||
uint32_t bi_y_pels_per_meter;
|
||||
uint32_t bi_clr_used;
|
||||
uint32_t bi_clr_important;
|
||||
} alBITMAPINFOHEADER;
|
||||
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint16_t w_format_tag;
|
||||
uint16_t n_channels;
|
||||
uint32_t n_samples_per_sec;
|
||||
uint32_t n_avg_bytes_per_sec;
|
||||
uint16_t n_block_align;
|
||||
uint16_t w_bits_per_sample;
|
||||
uint16_t cb_size;
|
||||
} alWAVEFORMATEX;
|
||||
|
||||
typedef struct __attribute__((__packed__))
|
||||
{
|
||||
uint32_t fcc_type;
|
||||
uint32_t fcc_handler;
|
||||
uint32_t dw_flags;
|
||||
uint32_t dw_caps;
|
||||
uint16_t w_priority;
|
||||
uint16_t w_language;
|
||||
uint32_t dw_scale;
|
||||
uint32_t dw_rate;
|
||||
uint32_t dw_start;
|
||||
uint32_t dw_length;
|
||||
uint32_t dw_initial_frames;
|
||||
uint32_t dw_suggested_buffer_size;
|
||||
uint32_t dw_quality;
|
||||
uint32_t dw_sample_size;
|
||||
uint32_t dw_left;
|
||||
uint32_t dw_top;
|
||||
uint32_t dw_right;
|
||||
uint32_t dw_bottom;
|
||||
uint32_t dw_edit_count;
|
||||
uint32_t dw_format_change_count;
|
||||
char sz_name[64];
|
||||
} alAVISTREAMINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
long fdes; /* File descriptor of AVI file */
|
||||
long mode; /* 0 for reading, 1 for writing */
|
||||
|
||||
long width; /* Width of a video frame */
|
||||
long height; /* Height of a video frame */
|
||||
double fps; /* Frames per second */
|
||||
char compressor[8]; /* Type of compressor, 4 bytes + padding for 0 byte */
|
||||
char compressor2[8]; /* Type of compressor, 4 bytes + padding for 0 byte */
|
||||
long video_strn; /* Video stream number */
|
||||
long video_frames; /* Number of video frames */
|
||||
char video_tag[4]; /* Tag of video data */
|
||||
long video_pos; /* Number of next frame to be read
|
||||
(if index present) */
|
||||
|
||||
uint32_t max_len; /* maximum video chunk present */
|
||||
|
||||
track_t track[AVI_MAX_TRACKS]; // up to AVI_MAX_TRACKS audio tracks supported
|
||||
|
||||
off_t pos; /* position in file */
|
||||
long n_idx; /* number of index entries actually filled */
|
||||
long max_idx; /* number of index entries actually allocated */
|
||||
|
||||
off_t v_codech_off; /* absolut offset of video codec (strh) info */
|
||||
off_t v_codecf_off; /* absolut offset of video codec (strf) info */
|
||||
|
||||
uint8_t (*idx)[16]; /* index entries (AVI idx1 tag) */
|
||||
|
||||
video_index_entry *video_index;
|
||||
avisuperindex_chunk *video_superindex; /* index of indices */
|
||||
int is_opendml; /* set to 1 if this is an odml file with multiple index chunks */
|
||||
|
||||
off_t last_pos; /* Position of last frame written */
|
||||
uint32_t last_len; /* Length of last frame written */
|
||||
int must_use_index; /* Flag if frames are duplicated */
|
||||
off_t movi_start;
|
||||
int total_frames; /* total number of frames if dmlh is present */
|
||||
|
||||
int anum; // total number of audio tracks
|
||||
int aptr; // current audio working track
|
||||
int comment_fd; // Read avi header comments from this fd
|
||||
char *index_file; // read the avi index from this file
|
||||
|
||||
alBITMAPINFOHEADER *bitmap_info_header;
|
||||
alWAVEFORMATEX *wave_format_ex[AVI_MAX_TRACKS];
|
||||
|
||||
void* extradata;
|
||||
unsigned long extradata_size;
|
||||
|
||||
mmap_region_t *mmap_region;
|
||||
off_t mmap_offset;
|
||||
size_t mmap_size;
|
||||
int ffmpeg_codec_id;
|
||||
} avi_t;
|
||||
|
||||
#define AVI_MODE_WRITE 0
|
||||
#define AVI_MODE_READ 1
|
||||
|
||||
/* The error codes delivered by avi_open_input_file */
|
||||
|
||||
#define AVI_ERR_SIZELIM 1 /* The write of the data would exceed
|
||||
the maximum size of the AVI file.
|
||||
This is more a warning than an error
|
||||
since the file may be closed safely */
|
||||
|
||||
#define AVI_ERR_OPEN 2 /* Error opening the AVI file - wrong path
|
||||
name or file nor readable/writable */
|
||||
|
||||
#define AVI_ERR_READ 3 /* Error reading from AVI File */
|
||||
|
||||
#define AVI_ERR_WRITE 4 /* Error writing to AVI File,
|
||||
disk full ??? */
|
||||
|
||||
#define AVI_ERR_WRITE_INDEX 5 /* Could not write index to AVI file
|
||||
during close, file may still be
|
||||
usable */
|
||||
|
||||
#define AVI_ERR_CLOSE 6 /* Could not write header to AVI file
|
||||
or not truncate the file during close,
|
||||
file is most probably corrupted */
|
||||
|
||||
#define AVI_ERR_NOT_PERM 7 /* Operation not permitted:
|
||||
trying to read from a file open
|
||||
for writing or vice versa */
|
||||
|
||||
#define AVI_ERR_NO_MEM 8 /* malloc failed */
|
||||
|
||||
#define AVI_ERR_NO_AVI 9 /* Not an AVI file */
|
||||
|
||||
#define AVI_ERR_NO_HDRL 10 /* AVI file has no has no header list,
|
||||
corrupted ??? */
|
||||
|
||||
#define AVI_ERR_NO_MOVI 11 /* AVI file has no has no MOVI list,
|
||||
corrupted ??? */
|
||||
|
||||
#define AVI_ERR_NO_VIDS 12 /* AVI file contains no video data */
|
||||
|
||||
#define AVI_ERR_NO_IDX 13 /* The file has been opened with
|
||||
getIndex==0, but an operation has been
|
||||
performed that needs an index */
|
||||
|
||||
#define AVI_ERR_EMPTY 14 /* AVI file is empty (header only)*/
|
||||
|
||||
/* Possible Audio formats */
|
||||
|
||||
#ifndef WAVE_FORMAT_PCM
|
||||
#define WAVE_FORMAT_UNKNOWN (0x0000)
|
||||
#define WAVE_FORMAT_PCM (0x0001)
|
||||
#define WAVE_FORMAT_ADPCM (0x0002)
|
||||
#define WAVE_FORMAT_IBM_CVSD (0x0005)
|
||||
#define WAVE_FORMAT_ALAW (0x0006)
|
||||
#define WAVE_FORMAT_MULAW (0x0007)
|
||||
#define WAVE_FORMAT_OKI_ADPCM (0x0010)
|
||||
#define WAVE_FORMAT_DVI_ADPCM (0x0011)
|
||||
#define WAVE_FORMAT_DIGISTD (0x0015)
|
||||
#define WAVE_FORMAT_DIGIFIX (0x0016)
|
||||
#define WAVE_FORMAT_YAMAHA_ADPCM (0x0020)
|
||||
#define WAVE_FORMAT_DSP_TRUESPEECH (0x0022)
|
||||
#define WAVE_FORMAT_GSM610 (0x0031)
|
||||
#define IBM_FORMAT_MULAW (0x0101)
|
||||
#define IBM_FORMAT_ALAW (0x0102)
|
||||
#define IBM_FORMAT_ADPCM (0x0103)
|
||||
#endif
|
||||
|
||||
avi_t* AVI_open_output_file(char * filename);
|
||||
void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor);
|
||||
int AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format);
|
||||
int AVI_write_frame(avi_t *AVI, char *data, long bytes);
|
||||
int AVI_dup_frame(avi_t *AVI);
|
||||
int AVI_write_audio(avi_t *AVI, char *data, long bytes);
|
||||
int AVI_append_audio(avi_t *AVI, char *data, long bytes);
|
||||
long AVI_bytes_remain(avi_t *AVI);
|
||||
int AVI_close(avi_t *AVI);
|
||||
long AVI_bytes_written(avi_t *AVI);
|
||||
|
||||
avi_t *AVI_open_input_file(char *filename, int getIndex, int mmap_size);
|
||||
avi_t *AVI_open_input_indexfile(char *filename, int getIndex, char *indexfile);
|
||||
avi_t *AVI_open_fd(int fd, int getIndex, int mmap_size);
|
||||
avi_t *AVI_open_indexfd(int fd, int getIndex, char *indexfile);
|
||||
int avi_parse_input_file(avi_t *AVI, int getIndex);
|
||||
int avi_parse_index_from_file(avi_t *AVI, char *filename);
|
||||
long AVI_audio_mp3rate(avi_t *AVI);
|
||||
long AVI_audio_padrate(avi_t *AVI);
|
||||
long AVI_video_frames(avi_t *AVI);
|
||||
int AVI_video_width(avi_t *AVI);
|
||||
int AVI_video_height(avi_t *AVI);
|
||||
double AVI_frame_rate(avi_t *AVI);
|
||||
char* AVI_video_compressor(avi_t *AVI);
|
||||
|
||||
int AVI_audio_channels(avi_t *AVI);
|
||||
int AVI_audio_bits(avi_t *AVI);
|
||||
int AVI_audio_format(avi_t *AVI);
|
||||
long AVI_audio_rate(avi_t *AVI);
|
||||
long AVI_audio_bytes(avi_t *AVI);
|
||||
long AVI_audio_chunks(avi_t *AVI);
|
||||
int AVI_can_read_audio(avi_t *AVI);
|
||||
|
||||
long AVI_max_video_chunk(avi_t *AVI);
|
||||
|
||||
long AVI_frame_size(avi_t *AVI, long frame);
|
||||
long AVI_audio_size(avi_t *AVI, long frame);
|
||||
int AVI_seek_start(avi_t *AVI);
|
||||
int AVI_set_video_position(avi_t *AVI, long frame);
|
||||
long AVI_get_video_position(avi_t *AVI, long frame);
|
||||
long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe);
|
||||
|
||||
int AVI_set_audio_position(avi_t *AVI, long byte);
|
||||
int AVI_set_audio_bitrate(avi_t *AVI, long bitrate);
|
||||
|
||||
long AVI_get_audio_position_index(avi_t *AVI);
|
||||
int AVI_set_audio_position_index(avi_t *AVI, long indexpos);
|
||||
|
||||
long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes);
|
||||
long AVI_read_audio_chunk(avi_t *AVI, char *audbuf);
|
||||
|
||||
long AVI_audio_codech_offset(avi_t *AVI);
|
||||
long AVI_audio_codecf_offset(avi_t *AVI);
|
||||
long AVI_video_codech_offset(avi_t *AVI);
|
||||
long AVI_video_codecf_offset(avi_t *AVI);
|
||||
|
||||
int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf,
|
||||
char *audbuf, long max_audbuf,
|
||||
long *len);
|
||||
|
||||
void AVI_print_error(char *str);
|
||||
char *AVI_strerror(void);
|
||||
char *AVI_syserror(void);
|
||||
|
||||
int AVI_scan(char *name);
|
||||
int AVI_dump(char *name, int mode);
|
||||
|
||||
char *AVI_codec2str(short cc);
|
||||
int AVI_file_check(char *import_file);
|
||||
|
||||
void AVI_info(avi_t *avifile);
|
||||
uint64_t AVI_max_size(void);
|
||||
int avi_update_header(avi_t *AVI);
|
||||
|
||||
int AVI_set_audio_track(avi_t *AVI, int track);
|
||||
int AVI_get_audio_track(avi_t *AVI);
|
||||
int AVI_audio_tracks(avi_t *AVI);
|
||||
|
||||
void AVI_set_audio_vbr(avi_t *AVI, long is_vbr);
|
||||
long AVI_get_audio_vbr(avi_t *AVI);
|
||||
|
||||
void AVI_set_comment_fd(avi_t *AVI, int fd);
|
||||
int AVI_get_comment_fd(avi_t *AVI);
|
||||
|
||||
struct riff_struct
|
||||
{
|
||||
uint8_t id[4]; /* RIFF */
|
||||
uint32_t len;
|
||||
uint8_t wave_id[4]; /* WAVE */
|
||||
};
|
||||
|
||||
|
||||
struct chunk_struct
|
||||
{
|
||||
uint8_t id[4];
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct common_struct
|
||||
{
|
||||
uint16_t wFormatTag;
|
||||
uint16_t wChannels;
|
||||
uint32_t dwSamplesPerSec;
|
||||
uint32_t dwAvgBytesPerSec;
|
||||
uint16_t wBlockAlign;
|
||||
uint16_t wBitsPerSample; /* Only for PCM */
|
||||
};
|
||||
|
||||
struct wave_header
|
||||
{
|
||||
struct riff_struct riff;
|
||||
struct chunk_struct format;
|
||||
struct common_struct common;
|
||||
struct chunk_struct data;
|
||||
};
|
||||
|
||||
// Simple WAV IO
|
||||
int AVI_read_wave_header( int fd, struct wave_header * wave );
|
||||
int AVI_write_wave_header( int fd, const struct wave_header * wave );
|
||||
size_t AVI_read_wave_pcm_data( int fd, void * buffer, size_t buflen );
|
||||
size_t AVI_write_wave_pcm_data( int fd, const void * buffer, size_t buflen );
|
||||
int AVI_video_compressor_type(avi_t *AVI);
|
||||
int AVI_fileno(avi_t *AVI);
|
||||
|
||||
struct AVIStreamHeader {
|
||||
long fccType;
|
||||
long fccHandler;
|
||||
long dwFlags;
|
||||
long dwPriority;
|
||||
long dwInitialFrames;
|
||||
long dwScale;
|
||||
long dwRate;
|
||||
long dwStart;
|
||||
long dwLength;
|
||||
long dwSuggestedBufferSize;
|
||||
long dwQuality;
|
||||
long dwSampleSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
207
veejay-1.3/veejay-server/libel/elcache.c
Normal file
207
veejay-1.3/veejay-server/libel/elcache.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2006 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Cache frames from file to memory
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <libvjmem/vjmem.h>
|
||||
#include <libvjmsg/vj-msg.h>
|
||||
#include <libel/elcache.h>
|
||||
#ifdef STRICT_CHECKING
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int size;
|
||||
int fmt;
|
||||
long num;
|
||||
void *buffer;
|
||||
} cache_slot_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cache_slot_t **cache;
|
||||
int len;
|
||||
long *index;
|
||||
} cache_t;
|
||||
|
||||
static int cache_free_slot(cache_t *v)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < v->len; i ++ )
|
||||
if( v->index[i] == -1 ) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long total_mem_used_ = 0;
|
||||
|
||||
static void cache_claim_slot(cache_t *v, int free_slot, uint8_t *linbuf, long frame_num,int buf_len, int decoder_id)
|
||||
{
|
||||
// create new node
|
||||
cache_slot_t *data = (cache_slot_t*) vj_malloc(sizeof(cache_slot_t));
|
||||
data->size = buf_len;
|
||||
data->num = frame_num;
|
||||
data->fmt = decoder_id;
|
||||
data->buffer = vj_malloc( buf_len );
|
||||
#ifdef STRICT_CHECKING
|
||||
assert( v->index[free_slot] != frame_num );
|
||||
#endif
|
||||
// clear old buffer
|
||||
if( v->index[free_slot] >= 0 )
|
||||
{
|
||||
cache_slot_t *del_slot = v->cache[free_slot];
|
||||
total_mem_used_ -= del_slot->size;
|
||||
free( del_slot->buffer );
|
||||
free( del_slot );
|
||||
v->cache[free_slot] = NULL;
|
||||
}
|
||||
|
||||
veejay_memcpy( data->buffer, linbuf, buf_len );
|
||||
v->index[ free_slot ] = frame_num;
|
||||
v->cache[ free_slot ] = data;
|
||||
total_mem_used_ += buf_len;
|
||||
}
|
||||
|
||||
static int cache_find_slot( cache_t *v, long frame_num )
|
||||
{
|
||||
int i;
|
||||
int k = 0;
|
||||
long n = 0;
|
||||
for( i = 0; i < v->len ; i ++ )
|
||||
{
|
||||
long d = abs( v->index[i] - frame_num );
|
||||
if( d > n )
|
||||
{ n = d; k = i ; }
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
static int cache_locate_slot( cache_t *v, long frame_num)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < v->len ; i ++ )
|
||||
if( v->index[i] == frame_num )
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void *init_cache( unsigned int n_slots )
|
||||
{
|
||||
if(n_slots <= 0)
|
||||
return NULL;
|
||||
cache_t *v = (cache_t*) vj_calloc(sizeof(cache_t));
|
||||
v->len = n_slots;
|
||||
v->cache = (cache_slot_t**) vj_calloc(sizeof(cache_slot_t*) * v->len );
|
||||
if(!v->cache)
|
||||
{
|
||||
free(v);
|
||||
return NULL;
|
||||
}
|
||||
v->index = (long*) vj_malloc(sizeof(long) * v->len );
|
||||
int n;
|
||||
for( n = 0; n < v->len ; n ++ )
|
||||
v->index[n] = -1;
|
||||
return (void*) v;
|
||||
}
|
||||
|
||||
void reset_cache(void *cache)
|
||||
{
|
||||
int i = 0;
|
||||
cache_t *v = (cache_t*) cache;
|
||||
|
||||
for( i = 0; i < v->len; i ++ )
|
||||
{
|
||||
v->index[i] = -1;
|
||||
if( v->cache[i] )
|
||||
{
|
||||
total_mem_used_ -= v->cache[i]->size;
|
||||
if(v->cache[i]->buffer)
|
||||
free(v->cache[i]->buffer);
|
||||
free(v->cache[i]);
|
||||
v->cache[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cache_avail_mb()
|
||||
{
|
||||
return ( total_mem_used_ == 0 ? 0 : total_mem_used_ / (1024 * 1024 ));
|
||||
}
|
||||
|
||||
|
||||
void free_cache(void *cache)
|
||||
{
|
||||
cache_t *v = (cache_t*) cache;
|
||||
reset_cache( cache );
|
||||
free(v->cache);
|
||||
free(v->index);
|
||||
free(v);
|
||||
v = NULL;
|
||||
}
|
||||
|
||||
void cache_frame( void *cache, uint8_t *linbuf, int buflen, long frame_num , int decoder_id)
|
||||
{
|
||||
cache_t *v = (cache_t*) cache;
|
||||
#ifdef STRICT_CHECKING
|
||||
assert( cache != NULL );
|
||||
assert( linbuf != NULL );
|
||||
assert( buflen > 0 );
|
||||
assert( frame_num >= 0 );
|
||||
#else
|
||||
if( buflen <= 0 )
|
||||
return;
|
||||
#endif
|
||||
int slot_num = cache_free_slot( cache );
|
||||
if( slot_num == -1 )
|
||||
slot_num = cache_find_slot( v, frame_num );
|
||||
|
||||
#ifdef STRICT_CHECKING
|
||||
assert(slot_num >= 0 );
|
||||
#endif
|
||||
cache_claim_slot(v, slot_num, linbuf, frame_num, buflen, decoder_id);
|
||||
}
|
||||
|
||||
uint8_t *get_cached_frame( void *cache, long frame_num, int *buf_len, int *decoder_id )
|
||||
{
|
||||
cache_t *v = (cache_t*) cache;
|
||||
int slot = cache_locate_slot( v, frame_num );
|
||||
if( slot == -1 )
|
||||
return NULL;
|
||||
|
||||
cache_slot_t *data = v->cache[ slot ];
|
||||
#ifdef STRICT_CHECKING
|
||||
assert( data->size > 0 );
|
||||
assert( data->buffer != NULL );
|
||||
#endif
|
||||
|
||||
*buf_len = data->size;
|
||||
*decoder_id = data->fmt;
|
||||
#ifdef STRICT_CHECKING
|
||||
assert( data->num == frame_num );
|
||||
#endif
|
||||
return (uint8_t*) data->buffer;
|
||||
}
|
||||
30
veejay-1.3/veejay-server/libel/elcache.h
Normal file
30
veejay-1.3/veejay-server/libel/elcache.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2006 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ELCACHE_H
|
||||
#define ELCACHE_H
|
||||
|
||||
uint8_t *get_cached_frame( void *cache, long frame_num, int *buf_len, int *decoder_id );
|
||||
void cache_frame( void *cache, uint8_t *linbuf, int buflen, long frame_num , int decoder_id);
|
||||
void free_cache(void *cache);
|
||||
void *init_cache( unsigned int n_slots );
|
||||
void reset_cache(void *cache);
|
||||
int cache_avail_mb();
|
||||
|
||||
#endif
|
||||
1866
veejay-1.3/veejay-server/libel/lav_io.c
Normal file
1866
veejay-1.3/veejay-server/libel/lav_io.c
Normal file
File diff suppressed because it is too large
Load Diff
120
veejay-1.3/veejay-server/libel/lav_io.h
Normal file
120
veejay-1.3/veejay-server/libel/lav_io.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
This program 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.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef LAV_IO_H
|
||||
#define LAV_IO_H
|
||||
|
||||
#include <config.h>
|
||||
#include <libel/avilib.h>
|
||||
#include <libvje/vje.h>
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
#include <libel/rawdv.h>
|
||||
#endif
|
||||
// play with mlt here, avformat producer/several consumers (we can write to)
|
||||
// for normalized output (720x576/480) , dv1394 capture and playback
|
||||
|
||||
#include <yuv4mpeg.h>
|
||||
|
||||
#define LAV_INTER_UNKNOWN Y4M_UNKNOWN
|
||||
#define LAV_NOT_INTERLACED Y4M_ILACE_NONE
|
||||
#define LAV_INTER_TOP_FIRST Y4M_ILACE_TOP_FIRST
|
||||
#define LAV_INTER_BOTTOM_FIRST Y4M_ILACE_BOTTOM_FIRST
|
||||
|
||||
|
||||
/* chroma_format */
|
||||
#define CHROMAUNKNOWN 0
|
||||
#define CHROMA420 1
|
||||
#define CHROMA422 2
|
||||
#define CHROMA444 3
|
||||
#define CHROMA411 4
|
||||
|
||||
/* raw data format of a single frame */
|
||||
#define DATAFORMAT_MJPG 0
|
||||
#define DATAFORMAT_DV2 1
|
||||
#define DATAFORMAT_YUV420 2
|
||||
#define DATAFORMAT_YUV422 3
|
||||
#define DATAFORMAT_DIVX 4
|
||||
#define DATAFORMAT_MPEG4 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
avi_t *avi_fd;
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
dv_t *dv_fd;
|
||||
#endif
|
||||
void *qt_fd;
|
||||
int jpeg_fd;
|
||||
char *jpeg_filename;
|
||||
#ifdef USE_GDK_PIXBUF
|
||||
void *picture;
|
||||
#endif
|
||||
int format;
|
||||
int interlacing;
|
||||
int sar_w; /* "clip aspect ratio" width */
|
||||
int sar_h; /* "clip aspect ratio" height */
|
||||
int has_audio;
|
||||
int bps;
|
||||
int is_MJPG;
|
||||
int MJPG_chroma;
|
||||
int mmap_size;
|
||||
int bogus_len;
|
||||
} lav_file_t;
|
||||
|
||||
|
||||
int lav_detect_endian (void);
|
||||
int lav_query_APP_marker(char format);
|
||||
int lav_query_APP_length(char format);
|
||||
int lav_query_polarity(char format);
|
||||
lav_file_t *lav_open_output_file(char *filename, char format,
|
||||
int width, int height, int interlaced, double fps,
|
||||
int asize, int achans, long arate);
|
||||
int lav_close(lav_file_t *lav_file);
|
||||
int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count);
|
||||
int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps);
|
||||
long lav_video_frames(lav_file_t *lav_file);
|
||||
int lav_video_width(lav_file_t *lav_file);
|
||||
int lav_video_height(lav_file_t *lav_file);
|
||||
double lav_frame_rate(lav_file_t *lav_file);
|
||||
int lav_video_interlacing(lav_file_t *lav_file);
|
||||
void lav_video_clipaspect(lav_file_t *lav_file, int *sar_w, int *sar_h);
|
||||
int lav_video_is_MJPG(lav_file_t *lav_file);
|
||||
int lav_is_DV(lav_file_t *lav_file);
|
||||
int lav_video_MJPG_chroma(lav_file_t *lav_file);
|
||||
const char *lav_video_compressor(lav_file_t *lav_file);
|
||||
int lav_video_compressor_type(lav_file_t *lav_file);
|
||||
int lav_audio_channels(lav_file_t *lav_file);
|
||||
int lav_audio_bits(lav_file_t *lav_file);
|
||||
long lav_audio_rate(lav_file_t *lav_file);
|
||||
long lav_audio_clips(lav_file_t *lav_file);
|
||||
long lav_frame_size(lav_file_t *lav_file, long frame);
|
||||
int lav_seek_start(lav_file_t *lav_file);
|
||||
int lav_set_video_position(lav_file_t *lav_file, long frame);
|
||||
int lav_read_frame(lav_file_t *lav_file, uint8_t *vidbuf);
|
||||
int lav_set_audio_position(lav_file_t *lav_file, long clip);
|
||||
int lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps);
|
||||
int lav_filetype(lav_file_t *lav_file);
|
||||
lav_file_t *lav_open_input_file(char *filename, int mmap_size);
|
||||
int lav_get_field_size(uint8_t * jpegdata, long jpeglen);
|
||||
const char *lav_strerror(void);
|
||||
int lav_fileno( lav_file_t *lav_file );
|
||||
void lav_set_default_chroma(int c);
|
||||
int lav_bogus_video_length( lav_file_t *lav_file );
|
||||
void lav_bogus_set_length( lav_file_t *lav_file , int len );
|
||||
#ifdef USE_GDK_PIXBUF
|
||||
VJFrame *lav_get_frame_ptr( lav_file_t *lav_file );
|
||||
void lav_set_project( int w, int h, float fps, int shift );
|
||||
#endif
|
||||
#endif
|
||||
445
veejay-1.3/veejay-server/libel/pixbuf.c
Normal file
445
veejay-1.3/veejay-server/libel/pixbuf.c
Normal file
@@ -0,0 +1,445 @@
|
||||
/* veejay - Linux VeeJay
|
||||
* (C) 2002-2005 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <config.h>
|
||||
#ifdef USE_GDK_PIXBUF
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libvjmsg/vj-msg.h>
|
||||
#include <libvjmem/vjmem.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <libvje/vje.h>
|
||||
#include <libvje/effects/common.h>
|
||||
#include <libyuv/yuvconv.h>
|
||||
#include <libel/pixbuf.h>
|
||||
#include <veejay/vims.h>
|
||||
#include AVCODEC_INC
|
||||
#include SWSCALE_INC
|
||||
#include <libyuv/yuvconv.h>
|
||||
#ifdef STRICT_CHECKING
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#define RUP8(num)(((num)+8)&~8)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
VJFrame *picA;
|
||||
VJFrame *picB;
|
||||
VJFrame *img;
|
||||
uint8_t *space;
|
||||
int display_w;
|
||||
int display_h;
|
||||
int real_w;
|
||||
int real_h;
|
||||
int fmt;
|
||||
} vj_pixbuf_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
char *type;
|
||||
int out_w;
|
||||
int out_h;
|
||||
} vj_pixbuf_out_t;
|
||||
|
||||
static int __initialized = 0;
|
||||
|
||||
extern int get_ffmpeg_pixfmt(int id);
|
||||
|
||||
extern uint8_t *vj_perform_get_preview_buffer();
|
||||
|
||||
static VJFrame *open_pixbuf( const char *filename, int dst_w, int dst_h, int dst_fmt,
|
||||
uint8_t *dY, uint8_t *dU, uint8_t *dV )
|
||||
{
|
||||
GdkPixbuf *image =
|
||||
gdk_pixbuf_new_from_file( filename, NULL );
|
||||
if(!image)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Unable to load image '%s'", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* convert image to veejay frame in proper dimensions, free image */
|
||||
|
||||
int img_fmt = PIX_FMT_RGB24;
|
||||
if( gdk_pixbuf_get_has_alpha( image ))
|
||||
img_fmt = PIX_FMT_RGBA;
|
||||
|
||||
VJFrame *dst = yuv_yuv_template( dY, dU, dV, dst_w, dst_h, dst_fmt );
|
||||
VJFrame *src = yuv_rgb_template(
|
||||
(uint8_t*) gdk_pixbuf_get_pixels( image ),
|
||||
gdk_pixbuf_get_width( image ),
|
||||
gdk_pixbuf_get_height( image ),
|
||||
img_fmt // PIX_FMT_RGB24
|
||||
);
|
||||
int stride = gdk_pixbuf_get_rowstride(image);
|
||||
|
||||
if( stride != src->stride[0] )
|
||||
src->stride[0] = stride;
|
||||
|
||||
veejay_msg(VEEJAY_MSG_DEBUG,"Image is %dx%d (src=%d, stride=%d, dstfmt=%d), scaling to %dx%d",
|
||||
src->width,src->height,img_fmt, stride,dst_fmt,dst->width,dst->height );
|
||||
|
||||
yuv_convert_any_ac( src, dst, src->format, dst->format );
|
||||
|
||||
gdk_pixbuf_unref( image );
|
||||
|
||||
free(src);
|
||||
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void vj_picture_cleanup( void *pic )
|
||||
{
|
||||
vj_pixbuf_t *picture = ( vj_pixbuf_t*) pic;
|
||||
if(picture)
|
||||
{
|
||||
if( picture->filename )
|
||||
free(picture->filename );
|
||||
if(picture->img)
|
||||
free( picture->img );
|
||||
if(picture->space)
|
||||
free(picture->space);
|
||||
if( picture )
|
||||
free(picture);
|
||||
}
|
||||
picture = NULL;
|
||||
}
|
||||
|
||||
|
||||
VJFrame *vj_picture_get(void *pic)
|
||||
{
|
||||
if(!pic)
|
||||
return NULL;
|
||||
vj_pixbuf_t *picture = (vj_pixbuf_t*) pic;
|
||||
return picture->img;
|
||||
}
|
||||
|
||||
int vj_picture_get_height( void *pic )
|
||||
{
|
||||
vj_pixbuf_t *picture = (vj_pixbuf_t*) pic;
|
||||
if(!picture)
|
||||
return 0;
|
||||
return picture->real_h;
|
||||
}
|
||||
|
||||
int vj_picture_get_width( void *pic )
|
||||
{
|
||||
vj_pixbuf_t *picture = (vj_pixbuf_t*) pic;
|
||||
if(!picture)
|
||||
return 0;
|
||||
return picture->real_w;
|
||||
}
|
||||
|
||||
void *vj_picture_open( const char *filename, int v_outw, int v_outh, int v_outf )
|
||||
{
|
||||
vj_pixbuf_t *pic = NULL;
|
||||
if(filename == NULL )
|
||||
{
|
||||
veejay_msg(0, "No image filename given");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(v_outw <= 0 || v_outh <= 0 )
|
||||
{
|
||||
veejay_msg(0, "No image dimensions setup");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pic = (vj_pixbuf_t*) vj_calloc(sizeof(vj_pixbuf_t));
|
||||
if(!pic)
|
||||
{
|
||||
veejay_msg(0, "Memory allocation error in %s", __FUNCTION__ );
|
||||
return NULL;
|
||||
}
|
||||
pic->filename = strdup( filename );
|
||||
pic->display_w = v_outw;
|
||||
pic->display_h = v_outh;
|
||||
pic->fmt = v_outf;
|
||||
|
||||
int len = v_outw * v_outh;
|
||||
int ulen = len;
|
||||
switch( v_outf )
|
||||
{
|
||||
case PIX_FMT_YUV420P:
|
||||
case PIX_FMT_YUVJ420P:
|
||||
ulen = len / 4;
|
||||
break;
|
||||
case PIX_FMT_YUV422P:
|
||||
case PIX_FMT_YUVJ422P:
|
||||
ulen = len / 2;
|
||||
break;
|
||||
default:
|
||||
#ifdef STRICT_CHECKING
|
||||
assert(0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
pic->space = (uint8_t*) vj_malloc( sizeof(uint8_t) * (3 * len));
|
||||
#ifdef STRICT_CHECKING
|
||||
assert(pic->space != NULL );
|
||||
#endif
|
||||
pic->img = open_pixbuf(
|
||||
filename,
|
||||
v_outw,
|
||||
v_outh,
|
||||
v_outf,
|
||||
pic->space,
|
||||
pic->space + len,
|
||||
pic->space + len + ulen );
|
||||
|
||||
return (void*) pic;
|
||||
}
|
||||
|
||||
int vj_picture_probe( const char *filename )
|
||||
{
|
||||
int ret = 0;
|
||||
GdkPixbuf *image =
|
||||
gdk_pixbuf_new_from_file( filename, NULL );
|
||||
if(image)
|
||||
{
|
||||
ret = 1;
|
||||
gdk_pixbuf_unref( image );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* image saving */
|
||||
|
||||
static void add_if_writeable( GdkPixbufFormat *data, GSList **list)
|
||||
{
|
||||
if( gdk_pixbuf_format_is_writable( data ))
|
||||
*list = g_slist_prepend( *list, data );
|
||||
gchar *name = gdk_pixbuf_format_get_name( data );
|
||||
if(name) g_free(name);
|
||||
}
|
||||
|
||||
char *vj_picture_get_filename( void *pic )
|
||||
{
|
||||
vj_pixbuf_out_t *p = (vj_pixbuf_out_t*) pic;
|
||||
if(!p) return NULL;
|
||||
return p->filename;
|
||||
}
|
||||
|
||||
void * vj_picture_prepare_save(
|
||||
const char *filename, char *type, int out_w, int out_h)
|
||||
{
|
||||
if(!type || !filename )
|
||||
{
|
||||
veejay_msg(0, "Missing filename or file extension");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vj_pixbuf_out_t *pic = (vj_pixbuf_out_t*) vj_calloc(sizeof(vj_pixbuf_out_t));
|
||||
|
||||
if(!pic)
|
||||
return NULL;
|
||||
|
||||
if(filename)
|
||||
pic->filename = strdup( filename );
|
||||
else
|
||||
pic->filename = NULL;
|
||||
|
||||
if(strncasecmp(type,"jpg",3 ) == 0)
|
||||
pic->type = strdup("jpeg");
|
||||
else
|
||||
pic->type = strdup( type );
|
||||
|
||||
pic->out_w = out_w;
|
||||
pic->out_h = out_h;
|
||||
|
||||
return (void*) pic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void display_if_writeable( GdkPixbufFormat *data, GSList **list)
|
||||
{
|
||||
if( gdk_pixbuf_format_is_writable( data ))
|
||||
*list = g_slist_prepend( *list, data );
|
||||
gchar *name = gdk_pixbuf_format_get_name( data );
|
||||
if( name ) g_free(name);
|
||||
}
|
||||
void vj_picture_display_formats()
|
||||
{
|
||||
GSList *f = gdk_pixbuf_get_formats();
|
||||
GSList *res = NULL;
|
||||
|
||||
g_slist_foreach( f, display_if_writeable, &res);
|
||||
|
||||
g_slist_free( f );
|
||||
g_slist_free( res );
|
||||
}
|
||||
|
||||
static void vj_picture_out_cleanup( vj_pixbuf_out_t *pic )
|
||||
{
|
||||
if(pic)
|
||||
{
|
||||
if(pic->filename)
|
||||
free(pic->filename);
|
||||
if(pic->type)
|
||||
free(pic->type);
|
||||
free(pic);
|
||||
}
|
||||
pic = NULL;
|
||||
}
|
||||
|
||||
static void *pic_scaler_ = NULL;
|
||||
static int pic_data_[3] = { 0,0,0};
|
||||
static int pic_changed_ = 0;
|
||||
static sws_template *pic_template_ = NULL;
|
||||
|
||||
void vj_picture_init( void *templ )
|
||||
{
|
||||
if(!__initialized)
|
||||
{
|
||||
// cool stuff
|
||||
g_type_init();
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "Using gdk pixbuf %s", gdk_pixbuf_version );
|
||||
__initialized = 1;
|
||||
}
|
||||
|
||||
pic_template_ = (sws_template*) templ;
|
||||
|
||||
}
|
||||
|
||||
int vj_picture_save( void *picture, uint8_t **frame, int w, int h , int fmt )
|
||||
{
|
||||
int ret = 0;
|
||||
vj_pixbuf_out_t *pic = (vj_pixbuf_out_t*) picture;
|
||||
|
||||
GdkPixbuf *img_ = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, w, h );
|
||||
if(!img_)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cant allocate buffer for RGB");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert frame to yuv
|
||||
VJFrame *src = yuv_yuv_template( frame[0],frame[1],frame[2],w,h, fmt );
|
||||
VJFrame *dst = yuv_rgb_template(
|
||||
(uint8_t*) gdk_pixbuf_get_pixels( img_ ),
|
||||
gdk_pixbuf_get_width( img_ ),
|
||||
gdk_pixbuf_get_height( img_ ),
|
||||
PIX_FMT_RGB24
|
||||
);
|
||||
|
||||
yuv_convert_any_ac( src, dst, fmt, PIX_FMT_RGB24 );
|
||||
|
||||
if( gdk_pixbuf_savev( img_, pic->filename, pic->type, NULL, NULL, NULL ))
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_INFO, "Save frame as %s of type %s",
|
||||
pic->filename, pic->type );
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR,
|
||||
"Cant save file as %s (%s) size %d x %d", pic->filename,pic->type, pic->out_w, pic->out_h);
|
||||
}
|
||||
|
||||
if( img_ )
|
||||
gdk_pixbuf_unref( img_ );
|
||||
|
||||
free(src);
|
||||
free(dst);
|
||||
|
||||
vj_picture_out_cleanup( pic );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vj_picture_free()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#define pic_has_changed(a,b,c) ( (a == pic_data_[0] && b == pic_data_[1] && c == pic_data_[2] ) ? 0: 1)
|
||||
#define update_pic_data(a,b,c) { pic_data_[0] = a; pic_data_[1] = b; pic_data_[2] = c;}
|
||||
|
||||
void vj_fast_picture_save_to_mem( VJFrame *frame, int out_w, int out_h, int pixfmt )
|
||||
{
|
||||
VJFrame *src1 = yuv_yuv_template( frame->data[0],frame->data[1],frame->data[2],
|
||||
frame->width,frame->height, pixfmt );
|
||||
|
||||
uint8_t *dest[3];
|
||||
dest[0] = vj_perform_get_preview_buffer();
|
||||
dest[1] = dest[0] + (out_w * out_h);
|
||||
dest[2] = dest[1] + ( (out_w * out_h)/4 );
|
||||
|
||||
VJFrame *dst1 = yuv_yuv_template( dest[0], dest[1], dest[2], out_w, out_h, PIX_FMT_YUV420P );
|
||||
|
||||
pic_changed_ = pic_has_changed( out_w,out_h, pixfmt );
|
||||
|
||||
if(pic_changed_ )
|
||||
{
|
||||
if(pic_scaler_)
|
||||
yuv_free_swscaler( pic_scaler_ );
|
||||
pic_scaler_ = yuv_init_swscaler( src1,dst1, pic_template_, yuv_sws_get_cpu_flags());
|
||||
update_pic_data( out_w, out_h, pixfmt );
|
||||
}
|
||||
|
||||
if( frame->width == out_w && frame->height == out_h )
|
||||
yuv_convert_any_ac( src1, dst1, src1->format, dst1->format );
|
||||
else
|
||||
yuv_convert_and_scale( pic_scaler_, src1,dst1);
|
||||
|
||||
free(src1);
|
||||
free(dst1);
|
||||
}
|
||||
|
||||
void vj_fastbw_picture_save_to_mem( VJFrame *frame, int out_w, int out_h, int pixfmt )
|
||||
{
|
||||
VJFrame *src1 = yuv_yuv_template( frame->data[0],frame->data[1],frame->data[2],
|
||||
frame->width,frame->height, pixfmt );
|
||||
|
||||
uint8_t *planes[3];
|
||||
|
||||
planes[0] = vj_perform_get_preview_buffer();
|
||||
planes[1] = planes[0] + (out_w * out_h );
|
||||
planes[2] = planes[1] + (out_w * out_h );
|
||||
|
||||
VJFrame *dst1 = yuv_yuv_template( planes[0], planes[1], planes[2],
|
||||
out_w , out_h, PIX_FMT_GRAY8 );
|
||||
pic_changed_ = pic_has_changed( out_w,out_h, pixfmt );
|
||||
|
||||
if(pic_changed_ )
|
||||
{
|
||||
if(pic_scaler_)
|
||||
yuv_free_swscaler( pic_scaler_ );
|
||||
pic_scaler_ = yuv_init_swscaler( src1,dst1, pic_template_, yuv_sws_get_cpu_flags());
|
||||
update_pic_data( out_w, out_h, pixfmt );
|
||||
}
|
||||
|
||||
|
||||
if( frame->width == out_w && frame->height == out_h )
|
||||
yuv_convert_any_ac( src1,dst1,src1->format, dst1->format );
|
||||
else
|
||||
yuv_convert_and_scale( pic_scaler_, src1, dst1);
|
||||
|
||||
free(src1);
|
||||
free(dst1);
|
||||
}
|
||||
|
||||
#endif
|
||||
53
veejay-1.3/veejay-server/libel/pixbuf.h
Normal file
53
veejay-1.3/veejay-server/libel/pixbuf.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* veejay - Linux VeeJay
|
||||
* (C) 2002-2005 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef VJ_PIXBUF_H
|
||||
#define VJ_PIXBUF_H
|
||||
#include <config.h>
|
||||
#include <libvje/vje.h>
|
||||
typedef struct
|
||||
{
|
||||
int w;
|
||||
int h;
|
||||
} veejay_image_t;
|
||||
|
||||
#ifdef USE_GDK_PIXBUF
|
||||
void vj_picture_init(void *templ);
|
||||
void vj_picture_cleanup( void *pic );
|
||||
VJFrame *vj_picture_get( void *pic );
|
||||
int vj_picture_probe( const char *filename );
|
||||
void *vj_picture_open( const char *filename, int v_outw, int v_outh, int v_outf );
|
||||
int vj_picture_get_width(void *pic);
|
||||
int vj_picture_get_height(void *pic);
|
||||
void vj_picture_display_formats(void);
|
||||
char *vj_picture_get_filename( void *pic );
|
||||
void * vj_picture_prepare_save( const char *filename, char *type, int out_w, int out_h);
|
||||
int vj_picture_save( void *picture, uint8_t **frame, int w, int h , int fmt );
|
||||
void vj_picture_display_formats(void);
|
||||
|
||||
veejay_image_t *vj_picture_save_bw_to_memory( uint8_t **frame, int w, int h , int out_w, int out_h, int fmt );
|
||||
veejay_image_t *vj_picture_save_to_memory( uint8_t **frame, int w, int h , int out_w, int out_h, int fmt );
|
||||
void vj_fastbw_picture_save_to_mem( VJFrame *f, int out_w, int out_h, int fmt );
|
||||
void vj_fast_picture_save_to_mem(VJFrame *f, int out_w, int out_h, int fmt );
|
||||
|
||||
void vj_picture_free();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
329
veejay-1.3/veejay-server/libel/rawdv.c
Normal file
329
veejay-1.3/veejay-server/libel/rawdv.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Linux VeeJay
|
||||
*
|
||||
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
#include <libel/rawdv.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <libvjmsg/vj-msg.h>
|
||||
#include <libvjmem/vjmem.h>
|
||||
#include <libel/vj-mmap.h>
|
||||
#include <libdv/dv.h>
|
||||
#include <ffmpeg/avcodec.h>
|
||||
|
||||
#include <errno.h>
|
||||
#define DV_PAL_SIZE 144000
|
||||
#define DV_NTSC_SIZE 120000
|
||||
|
||||
static void rawdv_free(dv_t *dv)
|
||||
{
|
||||
if(dv->filename) free(dv->filename);
|
||||
if(dv->buf) free(dv->buf);
|
||||
if(dv) free(dv);
|
||||
}
|
||||
|
||||
int rawdv_close(dv_t *dv)
|
||||
{
|
||||
close(dv->fd);
|
||||
mmap_free(dv->mmap_region);
|
||||
rawdv_free( dv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rawdv_sampling(dv_t *dv)
|
||||
{
|
||||
switch(dv->fmt)
|
||||
{
|
||||
case e_dv_sample_411: return 4;
|
||||
case e_dv_sample_422: return 2;
|
||||
case e_dv_sample_420: return 1;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
#define DV_HEADER_SIZE 120000
|
||||
dv_t *rawdv_open_input_file(const char *filename, int mmap_size)
|
||||
{
|
||||
dv_t *dv = (dv_t*) vj_malloc(sizeof(dv_t));
|
||||
if(!dv) return NULL;
|
||||
memset(dv, 0, sizeof(dv_t));
|
||||
dv_decoder_t *decoder = NULL;
|
||||
|
||||
uint8_t *tmp = (uint8_t*) vj_malloc(sizeof(uint8_t) * DV_HEADER_SIZE);
|
||||
memset( tmp, 0, sizeof(uint8_t) * DV_HEADER_SIZE);
|
||||
off_t file_size = 0;
|
||||
int n = 0;
|
||||
|
||||
decoder = dv_decoder_new( 1,0,0);
|
||||
dv->fd = open( filename, O_RDONLY );
|
||||
|
||||
if(!dv->fd)
|
||||
{
|
||||
dv_decoder_free(decoder);
|
||||
rawdv_free(dv);
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cannot open '%s'",filename);
|
||||
if(tmp)free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
/* fseek sometimes lies about filesize - seek to end (lseek returns file offset from start)*/
|
||||
file_size = lseek( dv->fd, 0, SEEK_END );
|
||||
if( file_size < DV_HEADER_SIZE)
|
||||
{
|
||||
dv_decoder_free(decoder);
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "% is too small! ", filename);
|
||||
rawdv_free(dv);
|
||||
if(tmp) free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
/* And back to start offset */
|
||||
if( lseek(dv->fd,0, SEEK_SET ) < 0)
|
||||
{
|
||||
dv_decoder_free(decoder);
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Seek errror");
|
||||
rawdv_free(dv);
|
||||
if(tmp) free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dv->mmap_region = NULL;
|
||||
if( mmap_size > 0 ) // user wants mmap
|
||||
{
|
||||
dv->mmap_region = mmap_file( dv->fd, 0, (mmap_size * 720 * 576 * 3),
|
||||
file_size );
|
||||
}
|
||||
|
||||
if( dv->mmap_region == NULL )
|
||||
{
|
||||
if(mmap_size>0)
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "Mmap failed - fallback to read");
|
||||
n = read( dv->fd, tmp, DV_HEADER_SIZE );
|
||||
}
|
||||
else
|
||||
{
|
||||
n = mmap_read( dv->mmap_region, 0, DV_HEADER_SIZE, tmp );
|
||||
}
|
||||
|
||||
if( n <= 0 )
|
||||
{
|
||||
dv_decoder_free(decoder);
|
||||
rawdv_free(dv);
|
||||
if(tmp) free(tmp);
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cannot read from '%s'", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( dv_parse_header( decoder, tmp) < 0 )
|
||||
{
|
||||
dv_decoder_free( decoder );
|
||||
rawdv_free(dv);
|
||||
if(tmp) free(tmp);
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cannot parse header");
|
||||
return NULL;
|
||||
}
|
||||
/* if(decoder->sampling == e_dv_sample_411)
|
||||
{
|
||||
dv_decoder_free( decoder );
|
||||
rawdv_free(dv);
|
||||
if(tmp) free(tmp);
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
|
||||
if(dv_is_PAL( decoder ) )
|
||||
dv->chunk_size = DV_PAL_SIZE;
|
||||
else
|
||||
dv->chunk_size = DV_NTSC_SIZE;
|
||||
|
||||
dv->width = decoder->width;
|
||||
dv->height = decoder->height;
|
||||
dv->audio_rate = decoder->audio->frequency;
|
||||
dv->audio_chans = decoder->audio->num_channels;
|
||||
dv->audio_qbytes = decoder->audio->quantization;
|
||||
dv->fps = ( dv_is_PAL( decoder) ? 25.0 : 29.97 );
|
||||
dv->size = decoder->frame_size;
|
||||
dv->num_frames = (file_size - DV_HEADER_SIZE) / dv->size;
|
||||
dv->fmt = decoder->sampling;
|
||||
// dv->fmt = ( decoder->sampling == e_dv_sample_422 ? 1 : 0);
|
||||
dv->buf = (uint8_t*) vj_malloc(sizeof(uint8_t*) * dv->size);
|
||||
dv->offset = 0;
|
||||
|
||||
veejay_msg(VEEJAY_MSG_DEBUG,
|
||||
"DV properties %d x %d, %f, %d frames, %d sampling",
|
||||
dv->width,dv->height, dv->fps, dv->num_frames,
|
||||
dv->fmt );
|
||||
|
||||
dv_decoder_free( decoder );
|
||||
|
||||
if(tmp)
|
||||
free(tmp);
|
||||
|
||||
/* if(dv->audio_rate)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < 4; i ++ )
|
||||
dv->audio_buffers[i] = (int16_t*) vj_malloc(sizeof(int16_t) * 2 * DV_AUDIO_MAX_SAMPLES);
|
||||
}*/
|
||||
|
||||
/*
|
||||
veejay_msg(VEEJAY_MSG_DEBUG,
|
||||
"rawDV: num frames %ld, dimensions %d x %d, at %2.2f in %s",
|
||||
dv->num_frames,
|
||||
dv->width,
|
||||
dv->height,
|
||||
dv->fps,
|
||||
(dv->fmt==1?"422":"420"));
|
||||
veejay_msg(VEEJAY_MSG_DEBUG,
|
||||
"rawDV: frame size %d, rate %d, channels %d, bits %d",
|
||||
dv->size,
|
||||
dv->audio_rate,
|
||||
dv->audio_chans,
|
||||
dv->audio_qbytes);*/
|
||||
|
||||
return dv;
|
||||
}
|
||||
|
||||
|
||||
int rawdv_set_position(dv_t *dv, long nframe)
|
||||
{
|
||||
off_t offset = nframe * dv->size;
|
||||
|
||||
if(nframe <= 0 )
|
||||
offset = 0;
|
||||
else
|
||||
if(nframe > dv->num_frames)
|
||||
offset = dv->num_frames * dv->size;
|
||||
|
||||
dv->offset = offset;
|
||||
|
||||
if( lseek( dv->fd, offset, SEEK_SET ) < 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rawdv_read_frame(dv_t *dv, uint8_t *buf )
|
||||
{
|
||||
int n = 0;
|
||||
if(dv->mmap_region == NULL)
|
||||
{
|
||||
n = read( dv->fd, dv->buf, dv->size );
|
||||
memcpy( buf, dv->buf, dv->size );
|
||||
}
|
||||
else
|
||||
{
|
||||
n = mmap_read( dv->mmap_region, dv->offset, dv->size, buf );
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int rawdv_read_audio_frame(dv_t *dv, uint8_t *audio )
|
||||
{
|
||||
|
||||
return 0;
|
||||
/*
|
||||
int n = dv_decode_full_audio( dv->decoder, dv->buf, dv->audio_buffers );
|
||||
// interleave buffers to audio
|
||||
int n_samples = dv_get_num_samples( dv->decoder );
|
||||
int n_chans = dv->audio_chans;
|
||||
int16_t *ch0 = dv->audio_buffers[0];
|
||||
int16_t *ch1 = dv->audio_buffers[1];
|
||||
int i,j;
|
||||
for( i = 0; i < n_samples; i ++ )
|
||||
{
|
||||
*(audio) = *(ch0) & 0xff;
|
||||
*(audio+1) = (*(ch0) << 8) & 0xff;
|
||||
*(audio+2) = *(ch1) & 0xff;
|
||||
*(audio+3) = (*(ch1)<<8) & 0xff;
|
||||
*(ch0) ++;
|
||||
*(ch1) ++;
|
||||
*(audio) += 4;
|
||||
}
|
||||
return n_samples * 4;
|
||||
*/
|
||||
}
|
||||
|
||||
int rawdv_video_frames(dv_t *dv)
|
||||
{
|
||||
return dv->num_frames;
|
||||
}
|
||||
|
||||
int rawdv_width(dv_t *dv)
|
||||
{
|
||||
return dv->width;
|
||||
}
|
||||
|
||||
int rawdv_height(dv_t *dv)
|
||||
{
|
||||
return dv->height;
|
||||
}
|
||||
|
||||
double rawdv_fps(dv_t *dv)
|
||||
{
|
||||
return (double) dv->fps;
|
||||
}
|
||||
|
||||
int rawdv_compressor(dv_t *dv)
|
||||
{
|
||||
return CODEC_ID_DVVIDEO;
|
||||
}
|
||||
|
||||
char *rawdv_video_compressor(dv_t *dv)
|
||||
{
|
||||
char *res = "dvsd\0";
|
||||
return res;
|
||||
}
|
||||
|
||||
int rawdv_audio_channels(dv_t *dv)
|
||||
{
|
||||
return dv->audio_chans;
|
||||
}
|
||||
|
||||
int rawdv_audio_bits(dv_t *dv)
|
||||
{
|
||||
return dv->audio_qbytes;
|
||||
}
|
||||
|
||||
int rawdv_audio_format(dv_t *dv)
|
||||
{
|
||||
// pcm wave format
|
||||
return (0x0001);
|
||||
}
|
||||
|
||||
int rawdv_audio_rate(dv_t *dv)
|
||||
{
|
||||
return dv->audio_rate;
|
||||
}
|
||||
|
||||
int rawdv_audio_bps(dv_t *dv)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
int rawdv_frame_size(dv_t *dv)
|
||||
{
|
||||
return dv->size;
|
||||
}
|
||||
|
||||
int rawdv_interlacing(dv_t *dv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
67
veejay-1.3/veejay-server/libel/rawdv.h
Normal file
67
veejay-1.3/veejay-server/libel/rawdv.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef RAWDV_H
|
||||
#define RAWDV_H
|
||||
/*
|
||||
* Linux VeeJay
|
||||
*
|
||||
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <libdv/dv.h>
|
||||
#include <libel/vj-mmap.h>
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
char *filename;
|
||||
long num_frames;
|
||||
int width;
|
||||
int height;
|
||||
float fps;
|
||||
int chunk_size;
|
||||
long audio_rate;
|
||||
int audio_chans;
|
||||
int audio_qbytes;
|
||||
dv_decoder_t *decoder;
|
||||
int16_t *audio_buffers[4];
|
||||
off_t offset;
|
||||
uint8_t *buf;
|
||||
int size;
|
||||
int fmt;
|
||||
mmap_region_t *mmap_region;
|
||||
} dv_t;
|
||||
|
||||
int rawdv_sampling(dv_t *dv);
|
||||
int rawdv_close(dv_t *dv);
|
||||
dv_t *rawdv_open_input_file(const char *filename, int mmap_size);
|
||||
int rawdv_set_position(dv_t *dv, long nframe);
|
||||
int rawdv_read_frame(dv_t *dv, uint8_t *buf );
|
||||
int rawdv_read_audio_frame(dv_t *dv, uint8_t *buf);
|
||||
int rawdv_video_frames(dv_t *dv);
|
||||
int rawdv_width(dv_t *dv);
|
||||
int rawdv_height(dv_t *dv);
|
||||
double rawdv_fps(dv_t *dv);
|
||||
int rawdv_compressor(dv_t *dv);
|
||||
char *rawdv_video_compressor(dv_t *dv);
|
||||
int rawdv_audio_channels(dv_t *dv);
|
||||
int rawdv_audio_bits(dv_t *dv);
|
||||
int rawdv_audio_format(dv_t *dv);
|
||||
int rawdv_audio_rate(dv_t *dv);
|
||||
int rawdv_audio_bps(dv_t *dv);
|
||||
int rawdv_frame_size(dv_t *dv);
|
||||
int rawdv_interlacing(dv_t *dv);
|
||||
|
||||
#endif
|
||||
475
veejay-1.3/veejay-server/libel/vj-avcodec.c
Normal file
475
veejay-1.3/veejay-server/libel/vj-avcodec.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/* veejay - Linux VeeJay
|
||||
* (C) 2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <libel/vj-avcodec.h>
|
||||
#include <libel/vj-el.h>
|
||||
#include <libvjmsg/vj-msg.h>
|
||||
#include <libvjmem/vjmem.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <libyuv/yuvconv.h>
|
||||
#include <liblzo/lzo.h>
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
#define __FALLBACK_LIBDV
|
||||
#include <libel/vj-dv.h>
|
||||
#endif
|
||||
#include AVCODEC_INC
|
||||
#include AVUTIL_INC
|
||||
#define YUV420_ONLY_CODEC(id) ( ( id == CODEC_ID_MJPEG || id == CODEC_ID_MJPEGB || id == CODEC_ID_MSMPEG4V3 || id == CODEC_ID_MPEG4) ? 1: 0)
|
||||
|
||||
|
||||
static int out_pixel_format = FMT_420;
|
||||
|
||||
char* vj_avcodec_get_codec_name(int codec_id )
|
||||
{
|
||||
char name[20];
|
||||
switch(codec_id)
|
||||
{
|
||||
case CODEC_ID_MJPEG: sprintf(name, "MJPEG"); break;
|
||||
case CODEC_ID_MPEG4: sprintf(name, "MPEG4"); break;
|
||||
case CODEC_ID_MSMPEG4V3: sprintf(name, "DIVX"); break;
|
||||
case CODEC_ID_DVVIDEO: sprintf(name, "DVVideo"); break;
|
||||
case 999 : sprintf(name, "RAW YUV 4:2:0 Planar"); break;
|
||||
case 998 : sprintf(name, "RAW YUV 4:2:2 Planar"); break;
|
||||
case 900 : sprintf(name, "LZO YUV 4:2:2 Planar"); break;
|
||||
default:
|
||||
sprintf(name, "Unknown"); break;
|
||||
}
|
||||
char *res = strdup(name);
|
||||
return res;
|
||||
}
|
||||
|
||||
static vj_encoder *vj_avcodec_new_encoder( int id, editlist *el, int pixel_format)
|
||||
{
|
||||
vj_encoder *e = (vj_encoder*) vj_calloc(sizeof(vj_encoder));
|
||||
if(!e) return NULL;
|
||||
|
||||
if( YUV420_ONLY_CODEC(id ))
|
||||
{
|
||||
e->data[0] = (uint8_t*) vj_calloc(sizeof(uint8_t) *
|
||||
el->video_width * el->video_height );
|
||||
e->data[1] = (uint8_t*) vj_calloc(sizeof(uint8_t) *
|
||||
el->video_width * el->video_height /2 );
|
||||
e->data[2] = (uint8_t*) vj_calloc(sizeof(uint8_t) *
|
||||
el->video_width * el->video_height /2);
|
||||
}
|
||||
|
||||
if( id == 900 )
|
||||
{
|
||||
e->lzo = lzo_new();
|
||||
}
|
||||
|
||||
if(id != 998 && id != 999 && id != 900)
|
||||
{
|
||||
#ifdef __FALLBACK_LIBDV
|
||||
if(id != CODEC_ID_DVVIDEO)
|
||||
{
|
||||
#endif
|
||||
e->codec = avcodec_find_encoder( id );
|
||||
if(!e->codec)
|
||||
{
|
||||
char *descr = vj_avcodec_get_codec_name(id);
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cannot find Encoder codec %s", descr );
|
||||
free(descr);
|
||||
}
|
||||
#ifdef __FALLBACK_LIBDV
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if( id != 998 && id != 999 && id!= 900)
|
||||
{
|
||||
#ifdef __FALLBACK_LIBDV
|
||||
if(id != CODEC_ID_DVVIDEO )
|
||||
{
|
||||
#endif
|
||||
e->context = avcodec_alloc_context();
|
||||
e->context->bit_rate = 2750 * 1024;
|
||||
e->context->width = el->video_width;
|
||||
e->context->height = el->video_height;
|
||||
#if LIBAVCODEC_BUILD > 5010
|
||||
e->context->time_base = (AVRational) { 1, el->video_fps };
|
||||
#else
|
||||
e->context->frame_rate = el->video_fps;
|
||||
e->context->frame_rate_base = 1;
|
||||
#endif
|
||||
e->context->qcompress = 0.0;
|
||||
e->context->qblur = 0.0;
|
||||
e->context->max_b_frames = 0;
|
||||
e->context->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
|
||||
e->context->flags = CODEC_FLAG_QSCALE;
|
||||
e->context->gop_size = 0;
|
||||
e->context->sub_id = 0;
|
||||
e->context->me_method = 0; // motion estimation algorithm
|
||||
e->context->workaround_bugs = FF_BUG_AUTODETECT;
|
||||
e->context->prediction_method = 0;
|
||||
e->context->dct_algo = FF_DCT_AUTO; //global_quality?
|
||||
|
||||
switch(pixel_format)
|
||||
{
|
||||
case FMT_420:
|
||||
e->context->pix_fmt = PIX_FMT_YUV420P;
|
||||
break;
|
||||
case FMT_420F:
|
||||
e->context->pix_fmt = PIX_FMT_YUVJ420P;
|
||||
break;
|
||||
case FMT_422F:
|
||||
e->context->pix_fmt = PIX_FMT_YUVJ422P;
|
||||
break;
|
||||
default:
|
||||
e->context->pix_fmt = PIX_FMT_YUV422P;
|
||||
break;
|
||||
}
|
||||
char *descr = vj_avcodec_get_codec_name( id );
|
||||
|
||||
if ( avcodec_open( e->context, e->codec ) < 0 )
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cannot open codec '%s'" , descr );
|
||||
if(e->context) free(e->context);
|
||||
if(e) free(e);
|
||||
if(descr) free(descr);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "\tOpened encoder %s", descr );
|
||||
free(descr);
|
||||
}
|
||||
#ifdef __FALLBACK_LIBDV
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
e->len = el->video_width * el->video_height;
|
||||
|
||||
if(el->pixel_format == FMT_422 || el->pixel_format == FMT_422F)
|
||||
e->uv_len = e->len / 2;
|
||||
else
|
||||
e->uv_len = e->len / 4;
|
||||
e->width = el->video_width;
|
||||
e->height = el->video_height;
|
||||
|
||||
e->out_fmt = el->pixel_format;
|
||||
e->encoder_id = id;
|
||||
|
||||
/*
|
||||
if( el->has_audio )
|
||||
{
|
||||
e->audiocodec = avcodec_find_encoder( CODEC_ID_PCM_U8 );
|
||||
if(!e->audiocodec)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Error initializing audio codec");
|
||||
if(e) free(e);
|
||||
}
|
||||
e->context->sample_rate = el->audio_rate;
|
||||
e->context->channels = el->audio_chans;
|
||||
if( avcodec_open( e->context, e->audiocodec ) < 0)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "Cannot open audio context");
|
||||
if(e) free(e);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
return e;
|
||||
}
|
||||
void vj_avcodec_close_encoder( vj_encoder *av )
|
||||
{
|
||||
if(av)
|
||||
{
|
||||
if(av->context)
|
||||
{
|
||||
avcodec_close( av->context );
|
||||
free(av->context);
|
||||
av->context = NULL;
|
||||
}
|
||||
if(av->data[0])
|
||||
free(av->data[0]);
|
||||
if(av->data[1])
|
||||
free(av->data[1]);
|
||||
if(av->data[2])
|
||||
free(av->data[2]);
|
||||
if(av->lzo)
|
||||
lzo_free(av->lzo);
|
||||
free(av);
|
||||
}
|
||||
av = NULL;
|
||||
}
|
||||
|
||||
int vj_avcodec_find_codec( int encoder )
|
||||
{
|
||||
switch( encoder)
|
||||
{
|
||||
case ENCODER_MJPEG:
|
||||
case ENCODER_QUICKTIME_MJPEG:
|
||||
return CODEC_ID_MJPEG;
|
||||
case ENCODER_DVVIDEO:
|
||||
case ENCODER_QUICKTIME_DV:
|
||||
return CODEC_ID_DVVIDEO;
|
||||
case ENCODER_YUV420:
|
||||
return 999;
|
||||
case ENCODER_YUV422:
|
||||
return 998;
|
||||
case ENCODER_MPEG4:
|
||||
return CODEC_ID_MPEG4;
|
||||
case ENCODER_DIVX:
|
||||
return CODEC_ID_MSMPEG4V3;
|
||||
case ENCODER_LZO:
|
||||
return 900;
|
||||
default:
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "Unknown format %d selected", encoder );
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int vj_avcodec_stop( void *encoder , int fmt)
|
||||
{
|
||||
if(!encoder)
|
||||
return 0;
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
if( fmt == CODEC_ID_DVVIDEO )
|
||||
{
|
||||
vj_dv_free_encoder(encoder);
|
||||
encoder = NULL;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if( fmt == 900 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
vj_encoder *env = (vj_encoder*) encoder;
|
||||
vj_avcodec_close_encoder( env );
|
||||
encoder = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *vj_avcodec_start( editlist *el, int encoder )
|
||||
{
|
||||
int codec_id = vj_avcodec_find_codec( encoder );
|
||||
void *ee = NULL;
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
if(codec_id == CODEC_ID_DVVIDEO )
|
||||
{
|
||||
if(!is_dv_resolution(el->video_width, el->video_height ))
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR,"\tVideo dimensions do not match required resolution");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ee = (void*)vj_dv_init_encoder( (void*)el , out_pixel_format);
|
||||
return ee;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if( codec_id == CODEC_ID_DVVIDEO )
|
||||
return NULL;
|
||||
#endif
|
||||
ee = vj_avcodec_new_encoder( codec_id, el , encoder );
|
||||
if(!ee)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "\tFailed to start encoder %x",encoder);
|
||||
return NULL;
|
||||
}
|
||||
return ee;
|
||||
}
|
||||
|
||||
|
||||
int vj_avcodec_init( int pixel_format, int verbose)
|
||||
{
|
||||
out_pixel_format = pixel_format;
|
||||
if( !verbose )
|
||||
av_log_set_level( AV_LOG_QUIET);
|
||||
else
|
||||
av_log_set_level( AV_LOG_VERBOSE );
|
||||
|
||||
av_register_all();
|
||||
|
||||
veejay_msg(VEEJAY_MSG_INFO, "FFmpeg AVCodec initialized (http://ffmpeg.sourceforge.net)");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vj_avcodec_free()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long2str(unsigned char *dst, int32_t n)
|
||||
{
|
||||
dst[0] = (n )&0xff;
|
||||
dst[1] = (n>> 8)&0xff;
|
||||
dst[2] = (n>>16)&0xff;
|
||||
dst[3] = (n>>24)&0xff;
|
||||
}
|
||||
|
||||
|
||||
static int vj_avcodec_lzo( vj_encoder *av, uint8_t *src[3], uint8_t *dst , int buf_len )
|
||||
{
|
||||
uint8_t *dstI = dst + (3 * 4);
|
||||
int size1 = 0, size2=0,size3=0;
|
||||
int i;
|
||||
|
||||
i = lzo_compress( av->lzo, src[0], dstI, &size1 , av->len);
|
||||
if( i == 0 )
|
||||
{
|
||||
veejay_msg(0,"\tunable to compress Y plane");
|
||||
return 0;
|
||||
}
|
||||
dstI += size1;
|
||||
|
||||
i = lzo_compress( av->lzo, src[1], dstI, &size2 , av->uv_len );
|
||||
if( i == 0 )
|
||||
{
|
||||
veejay_msg(0,"\tunable to compress U plane");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dstI += size2;
|
||||
i = lzo_compress( av->lzo, src[2], dstI, &size3 , av->uv_len );
|
||||
if( i == 0 )
|
||||
{
|
||||
veejay_msg(0,"\tunable to compress V plane");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long2str( dst, size1 );
|
||||
long2str( dst+4,size2);
|
||||
long2str( dst+8,size3);
|
||||
|
||||
return (size1 + size2 + size3 + 12);
|
||||
}
|
||||
static int vj_avcodec_copy_frame( vj_encoder *av, uint8_t *src[3], uint8_t *dst )
|
||||
{
|
||||
if(!av)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "No encoder !!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( (av->encoder_id == 999 && (av->out_fmt == FMT_420 ||av->out_fmt == FMT_420F)) || (av->encoder_id == 998 && (av->out_fmt == FMT_422||av->out_fmt == FMT_422F)))
|
||||
{
|
||||
/* copy */
|
||||
veejay_memcpy( dst, src[0], av->len );
|
||||
veejay_memcpy( dst+(av->len), src[1], av->uv_len );
|
||||
veejay_memcpy( dst+(av->len+av->uv_len) , src[2], av->uv_len);
|
||||
return ( av->len + av->uv_len + av->uv_len );
|
||||
}
|
||||
/* copy by converting */
|
||||
if( av->encoder_id == 999 && (av->out_fmt == FMT_422 || av->out_fmt==FMT_422F))
|
||||
{
|
||||
VJFrame *srci= yuv_yuv_template( src[0],src[1],src[2], av->width,av->height, get_ffmpeg_pixfmt( av->out_fmt));
|
||||
VJFrame *dsti= yuv_yuv_template( dst,dst+av->len,dst+av->len+(av->len/4), av->width,av->height, PIX_FMT_YUV420P );
|
||||
|
||||
yuv_convert_any_ac( srci,dsti, srci->format, dsti->format );
|
||||
|
||||
free(srci);
|
||||
free(dsti);
|
||||
|
||||
return ( av->len + (av->len/4) + (av->len/4));
|
||||
}
|
||||
|
||||
if( av->encoder_id == 998 && (av->out_fmt == FMT_420||av->out_fmt==FMT_420F))
|
||||
{
|
||||
VJFrame *srci = yuv_yuv_template( src[0],src[1],src[2], av->width,av->height,get_ffmpeg_pixfmt(av->out_fmt));
|
||||
VJFrame *dsti = yuv_yuv_template( dst, dst + av->len, dst + (av->len + (av->len/2)),
|
||||
av->width,av->height, PIX_FMT_YUV422P);
|
||||
|
||||
free(srci);
|
||||
free(dsti);
|
||||
|
||||
return ( av->len + av->len );
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int vj_avcodec_encode_frame(void *encoder, int nframe,int format, uint8_t *src[3], uint8_t *buf, int buf_len)
|
||||
{
|
||||
AVFrame pict;
|
||||
int res=0;
|
||||
memset( &pict, 0, sizeof(pict));
|
||||
|
||||
if(format == ENCODER_LZO )
|
||||
return vj_avcodec_lzo( encoder, src, buf, buf_len );
|
||||
|
||||
if(format == ENCODER_YUV420 || format == ENCODER_YUV422) // no compression, just copy
|
||||
return vj_avcodec_copy_frame( encoder,src, buf );
|
||||
|
||||
#ifdef __FALLBACK_LIBDV
|
||||
if(format == ENCODER_DVVIDEO || format == ENCODER_QUICKTIME_DV )
|
||||
return vj_dv_encode_frame( encoder,src, buf );
|
||||
#endif
|
||||
|
||||
vj_encoder *av = (vj_encoder*) encoder;
|
||||
|
||||
pict.quality = 1;
|
||||
pict.pts = (int64_t)( (int64_t)nframe );
|
||||
|
||||
int src_fmt = get_ffmpeg_pixfmt( out_pixel_format );
|
||||
|
||||
if(av->context->pix_fmt != src_fmt )
|
||||
{
|
||||
pict.data[0] = av->data[0];
|
||||
pict.data[1] = av->data[1];
|
||||
pict.data[2] = av->data[2];
|
||||
pict.linesize[0] = av->context->width;
|
||||
pict.linesize[1] = av->context->width >> 1;
|
||||
pict.linesize[2] = av->context->width >> 1;
|
||||
|
||||
VJFrame *srci = yuv_yuv_template( src[0],src[1],src[2], av->context->width,av->context->height, src_fmt );
|
||||
VJFrame *dsti = yuv_yuv_template( av->data[0],av->data[1],av->data[2],av->context->width,av->context->height,
|
||||
av->context->pix_fmt );
|
||||
|
||||
yuv_convert_any_ac( srci,dsti, srci->format, dsti->format );
|
||||
|
||||
free(srci);
|
||||
free(dsti);
|
||||
}
|
||||
else
|
||||
{
|
||||
pict.data[0] = src[0];
|
||||
pict.data[1] = src[1];
|
||||
pict.data[2] = src[2];
|
||||
pict.linesize[0] = av->context->width;
|
||||
pict.linesize[1] = pict.linesize[0]>>1;
|
||||
pict.linesize[2] = pict.linesize[0]>>1;
|
||||
}
|
||||
|
||||
res = avcodec_encode_video( av->context, buf, buf_len, &pict );
|
||||
return res;
|
||||
}
|
||||
|
||||
int vj_avcodec_encode_audio( void *encoder, int format, uint8_t *src, uint8_t *dst, int len, int nsamples )
|
||||
{
|
||||
if(format == ENCODER_YUV420 || ENCODER_YUV422 == format)
|
||||
return 0;
|
||||
vj_encoder *av = encoder;
|
||||
int ret = avcodec_encode_audio( av->context, src, len, nsamples );
|
||||
return ret;
|
||||
}
|
||||
82
veejay-1.3/veejay-server/libel/vj-avcodec.h
Normal file
82
veejay-1.3/veejay-server/libel/vj-avcodec.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* veejay - Linux VeeJay
|
||||
* (C) 2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef VJ_AVCODEC_H
|
||||
#define VJ_AVCODEC_H
|
||||
//bad
|
||||
#include AVCODEC_INC
|
||||
#include "vj-el.h"
|
||||
|
||||
#define ENCODER_MJPEG 0
|
||||
#define ENCODER_DVVIDEO 1
|
||||
#define ENCODER_DIVX 2
|
||||
#define ENCODER_MPEG4 3
|
||||
#define ENCODER_YUV420 4
|
||||
#define ENCODER_YUV422 5
|
||||
#define ENCODER_QUICKTIME_DV 6
|
||||
#define ENCODER_QUICKTIME_MJPEG 7
|
||||
#define ENCODER_LZO 8
|
||||
#define NUM_ENCODERS 9
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AVCodec *codec;
|
||||
AVCodec *audiocodec;
|
||||
AVFrame *frame;
|
||||
AVCodecContext *context;
|
||||
int out_fmt;
|
||||
int uv_len;
|
||||
int len;
|
||||
int sub_sample;
|
||||
int super_sample;
|
||||
int encoder_id;
|
||||
int width;
|
||||
int height;
|
||||
uint8_t *data[3];
|
||||
void *lzo;
|
||||
} vj_encoder;
|
||||
|
||||
int vj_avcodec_init(int pix, int verbose);
|
||||
|
||||
int vj_avcodec_encode_frame(void *encoder,int nframe, int format, uint8_t *src[3], uint8_t *dst, int dst_len);
|
||||
|
||||
int vj_avcodec_free();
|
||||
|
||||
/* color space conversion routines, should go somewhere else someday
|
||||
together with subsample.c/colorspace.c into some lib
|
||||
*/
|
||||
|
||||
void yuv_planar_to_rgb24(uint8_t *src[3], int fmt, uint8_t *dst, int w, int h );
|
||||
|
||||
// from yuv 4:2:0 planar to yuv 4:2:2 planar
|
||||
int yuv420p_to_yuv422p( uint8_t *Y, uint8_t *Cb, uint8_t *Cr, uint8_t *dst[3], int w, int h );
|
||||
|
||||
void yuv422p_to_yuv420p2( uint8_t *src[3], uint8_t *dst[3], int w, int h, int f );
|
||||
|
||||
int yuv420p_to_yuv422p2( uint8_t *sY,uint8_t *sCb, uint8_t *sCr, uint8_t *dst[3], int w, int h );
|
||||
|
||||
void yuv422p_to_yuv420p3( uint8_t *src, uint8_t *dst[3], int w, int h);
|
||||
|
||||
void *vj_avcodec_start( editlist *el, int encoder );
|
||||
|
||||
int vj_avcodec_stop( void *encoder , int fmt);
|
||||
|
||||
void vj_avcodec_close_encoder( vj_encoder *av );
|
||||
|
||||
|
||||
#endif
|
||||
370
veejay-1.3/veejay-server/libel/vj-dv.c
Normal file
370
veejay-1.3/veejay-server/libel/vj-dv.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Linux VeeJay
|
||||
*
|
||||
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
#include <libvjmem/vjmem.h>
|
||||
#include <libvjmsg/vj-msg.h>
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
#include <libdv/dv.h>
|
||||
#include <libel/vj-el.h>
|
||||
#include <stdint.h>
|
||||
#include <libel/vj-dv.h>
|
||||
#include <libel/vj-avcodec.h>
|
||||
#include <libyuv/yuvconv.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NTSC_W 720
|
||||
#define NTSC_H 480
|
||||
#define PAL_W 720
|
||||
#define PAL_H 576
|
||||
#define DV_PAL_SIZE 144000
|
||||
#define DV_NTSC_SIZE 120000
|
||||
#define DV_AUDIO_MAX_SAMPLES 1944
|
||||
|
||||
#ifdef STRICT_CHECKING
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
int is_dv_resolution(int w, int h)
|
||||
{
|
||||
if( h == NTSC_H && w == NTSC_W )
|
||||
return 1;
|
||||
if( h == PAL_H && w == PAL_W )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init the dv decoder and decode buffer*/
|
||||
vj_dv_decoder *vj_dv_decoder_init(int quality, int width, int height, int pixel_format)
|
||||
{
|
||||
int dv_q = DV_QUALITY_COLOR;
|
||||
vj_dv_decoder *d = (vj_dv_decoder*)vj_malloc(sizeof(vj_dv_decoder));
|
||||
if(!d) return NULL;
|
||||
d->decoder = dv_decoder_new( 1,1,0 );
|
||||
if( quality == 0 )
|
||||
dv_q = DV_QUALITY_FASTEST;
|
||||
if( quality == 1 )
|
||||
dv_q = DV_QUALITY_BEST;
|
||||
|
||||
d->decoder->quality = dv_q;
|
||||
d->dv_video = (uint8_t*) vj_malloc(sizeof(uint8_t) * width * height * 4);
|
||||
memset( d->dv_video, 0, (width*height*4));
|
||||
d->fmt = pixel_format;
|
||||
d->audio = 0; // audio off
|
||||
return d;
|
||||
}
|
||||
|
||||
/* init the dv encoder and encode buffer */
|
||||
vj_dv_encoder *vj_dv_init_encoder(void * edl, int pixel_format)
|
||||
{
|
||||
editlist *el = (editlist*) edl;
|
||||
vj_dv_encoder *e = (vj_dv_encoder*) vj_malloc(sizeof(vj_dv_encoder));
|
||||
if(!e) return NULL;
|
||||
e->encoder = dv_encoder_new(0,0,0);
|
||||
e->encoder->isPAL = (el->video_norm == 'p' ? 1 : 0);
|
||||
e->encoder->is16x9 = (el->video_width / el->video_height >= 1.777 ? 1: 0);
|
||||
e->encoder->vlc_encode_passes = 3;
|
||||
e->encoder->static_qno = 0;
|
||||
e->encoder->force_dct = DV_DCT_AUTO;
|
||||
e->fmt = pixel_format;
|
||||
|
||||
e->dv_video =
|
||||
(uint8_t *) vj_malloc(sizeof(uint8_t) *
|
||||
(e->encoder->isPAL ?
|
||||
DV_PAL_SIZE : DV_NTSC_SIZE));
|
||||
memset( e->dv_video, 0 ,
|
||||
(e->encoder->isPAL ? DV_PAL_SIZE: DV_NTSC_SIZE ) );
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/* encode frame to dv format, dv frame will be in output_buf */
|
||||
int vj_dv_encode_frame(vj_dv_encoder *encoder, uint8_t *input_buf[3], uint8_t *output_buf)
|
||||
{
|
||||
|
||||
time_t now = time(NULL);
|
||||
uint8_t *pixels[3];
|
||||
int w=0; int h = 0;
|
||||
if (!input_buf)
|
||||
return 0;
|
||||
|
||||
pixels[0] = (uint8_t *) encoder->dv_video;
|
||||
|
||||
if (encoder->encoder->isPAL)
|
||||
{
|
||||
h = PAL_H;
|
||||
w = PAL_W;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = NTSC_H;
|
||||
w = NTSC_W;
|
||||
}
|
||||
|
||||
if( encoder->fmt == FMT_420 || encoder->fmt == FMT_420F)
|
||||
{
|
||||
pixels[1] = (uint8_t *) encoder->dv_video + (w * h);
|
||||
pixels[2] = (uint8_t *) encoder->dv_video + (w * h * 5) / 4;
|
||||
yuv420p_to_yuv422(input_buf, encoder->dv_video, w, h );
|
||||
}
|
||||
else
|
||||
{ // convert 422 planar to packed
|
||||
int off = w * h / 2;
|
||||
pixels[1] = (uint8_t *) encoder->dv_video + (w * h );
|
||||
pixels[2] = (uint8_t *) encoder->dv_video + (w * h) + off;
|
||||
yuv422p_to_yuv422(input_buf,encoder->dv_video,w,h);
|
||||
}
|
||||
|
||||
dv_encode_full_frame( encoder->encoder, pixels, e_dv_color_yuv,
|
||||
output_buf);
|
||||
dv_encode_metadata(output_buf, encoder->encoder->isPAL,
|
||||
encoder->encoder->is16x9, &now, 0);
|
||||
dv_encode_timecode(output_buf, encoder->encoder->isPAL, 0);
|
||||
|
||||
if(encoder->encoder->isPAL) return DV_PAL_SIZE;
|
||||
return DV_NTSC_SIZE;
|
||||
}
|
||||
|
||||
void vj_dv_free_encoder(vj_dv_encoder *e)
|
||||
{
|
||||
if(e)
|
||||
{
|
||||
if(e->encoder)
|
||||
dv_encoder_free( e->encoder);
|
||||
if(e->dv_video)
|
||||
free(e->dv_video);
|
||||
free(e);
|
||||
}
|
||||
}
|
||||
|
||||
void vj_dv_free_decoder(vj_dv_decoder *d) {
|
||||
if(d->decoder)
|
||||
dv_decoder_free( d->decoder );
|
||||
if(d->dv_video)
|
||||
free(d->dv_video);
|
||||
if(d)
|
||||
free(d);
|
||||
}
|
||||
|
||||
void vj_dv_decoder_set_audio(vj_dv_decoder *d, int audio)
|
||||
{
|
||||
}
|
||||
|
||||
void vj_dv_decoder_get_audio(vj_dv_decoder *d, uint8_t *audio_buf)
|
||||
{
|
||||
|
||||
if(!d->audio) return;
|
||||
|
||||
int n_samples = dv_get_num_samples( d->decoder);
|
||||
// int channels = dv_get_num_channels( d->decoder );
|
||||
int i;
|
||||
int16_t *ch0 = d->audio_buffers[0];
|
||||
int16_t *ch1 = d->audio_buffers[1];
|
||||
// convert short to uint8_t,
|
||||
// interleave audio into single buffer
|
||||
for(i = 0; i < n_samples; i ++ )
|
||||
{
|
||||
*(audio_buf) = ch0[i] & 0xff; //lo
|
||||
*(audio_buf+1) = (ch0[i] >> 8) & 0xff; //hi
|
||||
*(audio_buf+2) = ch1[i] & 0xff; //lo
|
||||
*(audio_buf+3) = (ch1[i] >> 8) & 0xff; //hi
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
* Unpack libdv's 4:2:2-packed into our 4:2:0-planar or 4:2:2-planar,
|
||||
* treating each interlaced field independently
|
||||
*
|
||||
*/
|
||||
static inline void frame_YUV422_to_planar(uint8_t **output, uint8_t *input,
|
||||
int width, int height, int chroma422)
|
||||
{
|
||||
int i, j, w2;
|
||||
uint8_t *y, *cb, *cr;
|
||||
|
||||
w2 = width/2;
|
||||
y = output[0];
|
||||
cb = output[1];
|
||||
cr = output[2];
|
||||
|
||||
for (i=0; i<height;) {
|
||||
/* process two scanlines (one from each field, interleaved) */
|
||||
/* ...top-field scanline */
|
||||
for (j=0; j<w2; j++) {
|
||||
/* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
|
||||
*(y++) = *(input++);
|
||||
*(cb++) = *(input++);
|
||||
*(y++) = *(input++);
|
||||
*(cr++) = *(input++);
|
||||
}
|
||||
i++;
|
||||
/* ...bottom-field scanline */
|
||||
for (j=0; j<w2; j++) {
|
||||
/* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
|
||||
*(y++) = *(input++);
|
||||
*(cb++) = *(input++);
|
||||
*(y++) = *(input++);
|
||||
*(cr++) = *(input++);
|
||||
}
|
||||
i++;
|
||||
if (chroma422)
|
||||
continue;
|
||||
/* process next two scanlines (one from each field, interleaved) */
|
||||
/* ...top-field scanline */
|
||||
for (j=0; j<w2; j++) {
|
||||
/* skip every second line for U and V */
|
||||
*(y++) = *(input++);
|
||||
input++;
|
||||
*(y++) = *(input++);
|
||||
input++;
|
||||
}
|
||||
i++;
|
||||
/* ...bottom-field scanline */
|
||||
for (j=0; j<w2; j++) {
|
||||
/* skip every second line for U and V */
|
||||
*(y++) = *(input++);
|
||||
input++;
|
||||
*(y++) = *(input++);
|
||||
input++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int vj_dv_scan_frame( vj_dv_decoder *d, uint8_t * input_buf )
|
||||
{
|
||||
if (dv_parse_header(d->decoder, input_buf) < 0)
|
||||
{
|
||||
veejay_msg(0, "Unable to read DV header");
|
||||
return -1;
|
||||
}
|
||||
if( d->decoder->system == e_dv_system_none )
|
||||
{
|
||||
veejay_msg(0, "No valid PAL or NTSC video frame detected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char sampling[8];
|
||||
switch( d->decoder->sampling )
|
||||
{
|
||||
case e_dv_sample_411:
|
||||
veejay_msg(0, "YUV 4:1:1 not supported.");
|
||||
return -1;
|
||||
case e_dv_sample_420:
|
||||
sprintf(sampling, "4:2:0"); break;
|
||||
case e_dv_sample_422:
|
||||
sprintf(sampling, "4:2:2"); break;
|
||||
case e_dv_sample_none:
|
||||
veejay_msg(0 ,"No sampling format, cant handle this file (yet)");
|
||||
return -1;
|
||||
default:
|
||||
veejay_msg(0, "Unknown sampling format in DV file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
veejay_msg( VEEJAY_MSG_DEBUG, "\tDetected DV sampling format %s", sampling );
|
||||
|
||||
if ( d->decoder->sampling == e_dv_sample_422)
|
||||
return FMT_422;
|
||||
if( d->decoder->sampling == e_dv_sample_420 )
|
||||
return FMT_420;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vj_dv_decode_frame(vj_dv_decoder *d, uint8_t * input_buf, uint8_t * Y,
|
||||
uint8_t * Cb, uint8_t * Cr, int width, int height, int fmt)
|
||||
{
|
||||
|
||||
int pitches[3];
|
||||
if (!input_buf)
|
||||
return 0;
|
||||
|
||||
if (dv_parse_header(d->decoder, input_buf) < 0)
|
||||
{
|
||||
veejay_msg(0, "Unable to read DV header");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( d->decoder->system == e_dv_system_none )
|
||||
{
|
||||
veejay_msg(0, "No valid PAL or NTSC video frame detected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( d->decoder->system == e_dv_system_625_50 )
|
||||
{
|
||||
d->yuy2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
d->yuy2 = 1;
|
||||
}
|
||||
|
||||
if (!((d->decoder->num_dif_seqs == 10)
|
||||
|| (d->decoder->num_dif_seqs == 12)))
|
||||
{
|
||||
veejay_msg(0, "Dont know how to handle %d dif seqs",
|
||||
d->decoder->num_dif_seqs );
|
||||
return 0;
|
||||
}
|
||||
#ifdef STRICT_CHECKING
|
||||
// if ( d->decoder->sampling == e_dv_sample_420 )
|
||||
// assert( d->fmt == FMT_420 || d->fmt == FMT_420F );
|
||||
// if ( d->decoder->sampling == e_dv_sample_422 )
|
||||
// assert( d->fmt == FMT_422 || d->fmt == FMT_422F );
|
||||
#endif
|
||||
|
||||
if ( d->decoder->sampling == e_dv_sample_422)
|
||||
{
|
||||
pitches[0] = width * 2;
|
||||
pitches[1] = 0;
|
||||
pitches[2] = 0;
|
||||
uint8_t *pixels[3] = { Y , Cb, Cr };
|
||||
|
||||
dv_decode_full_frame(d->decoder, input_buf,
|
||||
e_dv_color_yuv, pixels, pitches);
|
||||
|
||||
frame_YUV422_to_planar( pixels, pixels[0], width, height, fmt );
|
||||
|
||||
return 1;
|
||||
} else if( d->decoder->sampling == e_dv_sample_420 )
|
||||
{
|
||||
uint8_t *pixels[3];
|
||||
pixels[0] = d->dv_video;
|
||||
pixels[1] = d->dv_video + (width * height);
|
||||
pixels[2] = d->dv_video + (width * height * 5)/4;
|
||||
pitches[0] = width * 2;
|
||||
pitches[1] = 0;
|
||||
pitches[2] = 0;
|
||||
|
||||
dv_decode_full_frame( d->decoder, input_buf, e_dv_color_yuv, pixels,pitches);
|
||||
|
||||
if(fmt==FMT_422 || fmt == FMT_422F)
|
||||
yuy2toyv16( Y,Cb,Cr, d->dv_video, width ,height );
|
||||
else //@ FIXME broken!
|
||||
vj_yuy2toyv12( Y,Cb,Cr, d->dv_video, width, height );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
61
veejay-1.3/veejay-server/libel/vj-dv.h
Normal file
61
veejay-1.3/veejay-server/libel/vj-dv.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Linux VeeJay
|
||||
*
|
||||
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
*/
|
||||
#ifndef VJ_DV_H
|
||||
#define VJ_DV_H
|
||||
#include <config.h>
|
||||
#ifdef SUPPORT_READ_DV2
|
||||
#include <libdv/dv.h>
|
||||
typedef struct
|
||||
{
|
||||
dv_decoder_t *decoder;
|
||||
uint8_t *dv_video;
|
||||
int fmt;
|
||||
int yuy2;
|
||||
int audio;
|
||||
int16_t **audio_buffers;
|
||||
} vj_dv_decoder;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dv_encoder_t *encoder;
|
||||
uint8_t *dv_video;
|
||||
int fmt;
|
||||
} vj_dv_encoder;
|
||||
|
||||
|
||||
vj_dv_decoder *vj_dv_decoder_init(int quality,int width, int height, int pixel_format);
|
||||
|
||||
vj_dv_encoder *vj_dv_init_encoder(void * el, int pixel_format);
|
||||
|
||||
void vj_dv_decoder_get_audio(vj_dv_decoder *d, uint8_t *audio_buf);
|
||||
|
||||
int vj_dv_scan_frame( vj_dv_decoder *d, uint8_t * input_buf );
|
||||
|
||||
void vj_dv_decoder_set_audio(vj_dv_decoder *d, int audio);
|
||||
|
||||
|
||||
int vj_dv_decode_frame(vj_dv_decoder *d,uint8_t * in, uint8_t * Y,
|
||||
uint8_t * Cb, uint8_t * Cr, int w, int h, int fmt);
|
||||
|
||||
int vj_dv_encode_frame(vj_dv_encoder *e,uint8_t * in[3], uint8_t * out);
|
||||
void vj_dv_free_encoder(vj_dv_encoder *e);
|
||||
void vj_dv_free_decoder(vj_dv_decoder *d);
|
||||
int is_dv_resolution( int w, int h );
|
||||
#endif
|
||||
#endif
|
||||
2447
veejay-1.3/veejay-server/libel/vj-el.c
Normal file
2447
veejay-1.3/veejay-server/libel/vj-el.c
Normal file
File diff suppressed because it is too large
Load Diff
151
veejay-1.3/veejay-server/libel/vj-el.h
Normal file
151
veejay-1.3/veejay-server/libel/vj-el.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/* veejay - Linux VeeJay
|
||||
* (C) 2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef VJ_MLT_EL_H
|
||||
#define VJ_MLT_EL_H
|
||||
#include <config.h>
|
||||
#include <libel/lav_io.h>
|
||||
#include <libvje/vje.h>
|
||||
#include <veejay/vims.h>
|
||||
#define N_EL_FRAME(x) ( (x)&0xfffffffffffffLLU )
|
||||
#define N_EL_FILE(x) (uint32_t) ( ((x)>>52)&0xfffU )
|
||||
/* ((file)&0xfff<<52) */
|
||||
#define EL_ENTRY(file,frame) ( ((file)<<52) | ((frame)& 0xfffffffffffffLLU) )
|
||||
|
||||
//#define FMT_420 0
|
||||
//#define FMT_422 1
|
||||
//#define MAX_EDITLIST_FILES 4096
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int has_video;
|
||||
int is_empty;
|
||||
int video_width;
|
||||
int video_height;
|
||||
int video_inter;
|
||||
float video_fps;
|
||||
int video_sar_width;
|
||||
int video_sar_height;
|
||||
char video_norm;
|
||||
|
||||
int has_audio;
|
||||
long audio_rate;
|
||||
int audio_chans;
|
||||
int audio_bits;
|
||||
int audio_bps;
|
||||
|
||||
long video_frames;
|
||||
long total_frames;
|
||||
long num_video_files;
|
||||
|
||||
long max_frame_size;
|
||||
int MJPG_chroma;
|
||||
|
||||
char *(video_file_list[MAX_EDIT_LIST_FILES]);
|
||||
lav_file_t *(lav_fd[MAX_EDIT_LIST_FILES]);
|
||||
int yuv_taste[MAX_EDIT_LIST_FILES];
|
||||
|
||||
long num_frames[MAX_EDIT_LIST_FILES];
|
||||
uint64_t *frame_list;
|
||||
|
||||
int last_afile;
|
||||
long last_apos;
|
||||
int auto_deinter;
|
||||
|
||||
int pixel_format;
|
||||
void *cache;
|
||||
|
||||
int is_clone;
|
||||
} editlist;
|
||||
|
||||
int test_video_frame( lav_file_t *lav,int out_pix_fmt);
|
||||
|
||||
|
||||
editlist *vj_el_init_with_args(char **filenames, int n, int flags, int deinter, int force, char norm, int fmt);
|
||||
|
||||
int vj_el_cache_size();
|
||||
|
||||
void vj_el_prepare(void); // reset cache
|
||||
|
||||
void vj_el_init(int out);
|
||||
|
||||
void vj_el_init_chunk(int n);
|
||||
|
||||
int vj_el_is_dv(editlist *el);
|
||||
|
||||
|
||||
void vj_el_free(editlist *el);
|
||||
|
||||
int vj_el_get_audio_frame_at(editlist *el, uint32_t nframe, uint8_t *dst, int speed );
|
||||
|
||||
int vj_el_append_video_file(editlist *el, char *filename);
|
||||
|
||||
int vj_el_write_editlist( char *filename, long start, long end, editlist *el );
|
||||
|
||||
int vj_el_get_video_frame(editlist *el, long nframe, uint8_t *dst[3]);
|
||||
|
||||
void vj_el_break_cache( editlist *el );
|
||||
|
||||
void vj_el_setup_cache( editlist *el );
|
||||
|
||||
int vj_el_get_audio_frame(editlist *el, uint32_t nframe, uint8_t *dst);
|
||||
|
||||
int vj_el_get_file_fourcc(editlist *el, int num, char *buf);
|
||||
|
||||
void vj_el_print(editlist *el);
|
||||
|
||||
int vj_el_init_420_frame(editlist *el, VJFrame *frame);
|
||||
int vj_el_init_422_frame(editlist *el, VJFrame *frame);
|
||||
|
||||
void vj_el_frame_cache(int n);
|
||||
|
||||
void vj_el_show_formats(void);
|
||||
|
||||
editlist *vj_el_dummy(int flags, int deinterlace, int chroma, char norm, int width, int height, float fps, int fmt);
|
||||
|
||||
int vj_el_get_file_entry( editlist *el,long *start_pos, long *end_pos, long entry );
|
||||
|
||||
editlist *vj_el_clone(editlist *el);
|
||||
|
||||
editlist *vj_el_soft_clone(editlist *el);
|
||||
|
||||
int vj_el_framelist_clone( editlist *src, editlist *dst);
|
||||
|
||||
char *vj_el_write_line_ascii( editlist *el, int *bytes_written );
|
||||
|
||||
void vj_el_deinit();
|
||||
|
||||
void vj_el_clear_cache( editlist *el );
|
||||
|
||||
int get_ffmpeg_pixfmt( int pf );
|
||||
|
||||
void vj_el_set_image_output_size(editlist *el,int w, int h, float fps, int pf);
|
||||
|
||||
int open_video_file(char *filename, editlist * el, int preserve_pathname, int deinter, int force, char override_norm);
|
||||
|
||||
void vj_el_set_caching(int status);
|
||||
|
||||
int vj_el_bogus_length( editlist *el, long nframe );
|
||||
|
||||
int vj_el_set_bogus_length( editlist *el, long nframe, int len );
|
||||
|
||||
void vj_el_get_video_fourcc(editlist *el, int num, char *fourcc);
|
||||
|
||||
|
||||
#endif
|
||||
139
veejay-1.3/veejay-server/libel/vj-mmap.c
Normal file
139
veejay-1.3/veejay-server/libel/vj-mmap.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Linux VeeJay
|
||||
*
|
||||
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
*/
|
||||
#include <libel/vj-mmap.h>
|
||||
#include <libvjmsg/vj-msg.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <libvjmem/vjmem.h>
|
||||
#define PADDED(a,m) ( a > 0 ? (a / m->page_size) * m->page_size : 0)
|
||||
|
||||
void mmap_free(mmap_region_t *map)
|
||||
{
|
||||
if(map)
|
||||
{
|
||||
if(map->map_start)
|
||||
munmap_file(map);
|
||||
free(map);
|
||||
}
|
||||
map = NULL;
|
||||
}
|
||||
|
||||
mmap_region_t * mmap_file(int fd, int offset, int length, int fs)
|
||||
{
|
||||
mmap_region_t *map = (mmap_region_t*) malloc(sizeof( mmap_region_t ));
|
||||
memset( map, 0, sizeof( mmap_region_t ));
|
||||
|
||||
map->fd = fd;
|
||||
map->page_size = getpagesize();
|
||||
map->map_length = length;
|
||||
map->map_start = NULL;
|
||||
map->eof = fs;
|
||||
map->mem_offset = offset;
|
||||
remap_file( map, offset );
|
||||
veejay_msg(VEEJAY_MSG_DEBUG, "Memory map region is %f Mb",
|
||||
( (float) length / 1048576.0 ) );
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
int is_mapped( mmap_region_t *map, int offset, int size )
|
||||
{
|
||||
// check if memory is in mapped region
|
||||
off_t real_offset = PADDED( offset, map );
|
||||
size_t padding = offset % map->page_size;
|
||||
|
||||
long rel_o = (map->mem_offset > 0 ? offset - map->mem_offset : offset );
|
||||
|
||||
if( (rel_o + size) > map->map_length )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( real_offset >= map->start_region &&
|
||||
real_offset + size <= map->end_region )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remap_file( mmap_region_t *map, int offset )
|
||||
{
|
||||
size_t padding = offset % map->page_size;
|
||||
size_t new_length = map->map_length;
|
||||
size_t real_length = 0;
|
||||
off_t real_offset = PADDED( offset, map );
|
||||
|
||||
real_length = (padding + new_length);
|
||||
if( real_length > map->eof )
|
||||
{
|
||||
real_length = PADDED(map->eof ,map);
|
||||
}
|
||||
if(map->map_start != NULL)
|
||||
{
|
||||
munmap_file( map );
|
||||
}
|
||||
|
||||
map->mem_offset = offset;
|
||||
map->map_start = mmap( 0, real_length, PROT_READ, MAP_SHARED, map->fd, real_offset );
|
||||
if( map->map_start == MAP_FAILED)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "mmap error %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
map->data_start = map->map_start + padding;
|
||||
|
||||
map->start_region = real_offset;
|
||||
map->end_region = real_length + real_offset;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int munmap_file( mmap_region_t *map )
|
||||
{
|
||||
if(map->map_start == NULL)
|
||||
return 1;
|
||||
|
||||
int n = munmap( map->map_start, map->map_length );
|
||||
if(n==-1)
|
||||
{
|
||||
veejay_msg(VEEJAY_MSG_ERROR, "leaving garbage %s",
|
||||
strerror(errno));
|
||||
}
|
||||
map->map_start = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
int mmap_read( mmap_region_t *map,int offset, int bytes, uint8_t *buf )
|
||||
{
|
||||
size_t padding = offset % map->page_size;
|
||||
if( !is_mapped( map, offset, bytes ))
|
||||
{
|
||||
remap_file( map, offset );
|
||||
}
|
||||
|
||||
int rel_offset = (map->mem_offset > 0 ? offset - map->mem_offset : offset );
|
||||
|
||||
uint8_t *d1 = map->data_start + rel_offset;
|
||||
veejay_memcpy( buf, d1, bytes );
|
||||
return bytes;
|
||||
}
|
||||
53
veejay-1.3/veejay-server/libel/vj-mmap.h
Normal file
53
veejay-1.3/veejay-server/libel/vj-mmap.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Linux VeeJay
|
||||
*
|
||||
* Copyright(C)2002-2004 Niels Elburg <nelburg@looze.net>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
*/
|
||||
#ifndef VJ_MMAP_H
|
||||
#define VJ_MMAP_H
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *map_start; /* result of mmap() */
|
||||
unsigned char *data_start; /* start of data */
|
||||
uint64_t start_region;
|
||||
uint64_t end_region;
|
||||
off_t mem_offset; /* start of image */
|
||||
int fd; /* file descriptor */
|
||||
size_t page_size; /* page size */
|
||||
size_t map_length; /* requested map size */
|
||||
long eof; /* file size */
|
||||
} mmap_region_t;
|
||||
|
||||
// map file portion to memory, return mapped region
|
||||
mmap_region_t * mmap_file(int fd, int offset, int length, int fs);
|
||||
|
||||
// see if requested boundaries is mapped in memory
|
||||
int is_mapped( mmap_region_t *map, int offset, int size );
|
||||
|
||||
// remap a portion of a file in memory
|
||||
int remap_file( mmap_region_t *map, int offset );
|
||||
|
||||
// unmap memory
|
||||
int munmap_file( mmap_region_t *map );
|
||||
|
||||
void mmap_free(mmap_region_t *map );
|
||||
|
||||
int mmap_read( mmap_region_t *map, int offset, int bytes, uint8_t *buf);
|
||||
|
||||
#endif
|
||||
9
veejay-1.3/veejay-server/libgoom/AUTHORS
Normal file
9
veejay-1.3/veejay-server/libgoom/AUTHORS
Normal file
@@ -0,0 +1,9 @@
|
||||
What a GOOM!
|
||||
============
|
||||
|
||||
Copyright (c)2000-2004, Jean-Christophe Hoelt <jeko@ios-software.com>
|
||||
Programmer and Software Designer at iOS software.
|
||||
|
||||
iTunes port/PowerPC/Core-Hacking: Guillaume Borios <gyom@ios-software.com>
|
||||
WINAMP/WMP port: Fred
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user