From: David Schleef Date: Sun, 27 Jul 2003 05:24:15 +0000 (+0000) Subject: Moved to gst-libs/ext/mplex X-Git-Tag: 1.19.3~507^2~24255 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d1f62e8a4f976e11634d2f9187821e8686cec76d;p=platform%2Fupstream%2Fgstreamer.git Moved to gst-libs/ext/mplex Original commit message from CVS: Moved to gst-libs/ext/mplex --- diff --git a/ext/mplex/COPYING b/ext/mplex/COPYING deleted file mode 100644 index a43ea21..0000000 --- a/ext/mplex/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - 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. - - - Copyright (C) 19yy - - 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. - - , 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. diff --git a/ext/mplex/INSTRUCT b/ext/mplex/INSTRUCT deleted file mode 100644 index e75d4cf..0000000 --- a/ext/mplex/INSTRUCT +++ /dev/null @@ -1,67 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// // -// INSTRUCTIONS FOR MPLEX - THE MPEG1/SYSTEMS MULTIPLEXER // -// // -////////////////////////////////////////////////////////////////////////// - - -Please note that I do not have a comprehensive instruction manual for this -release. I suggest you try the program out with some default values and -learn something more about ISO/IEC 11172-1 (aka MPEG1/Systems). - -For those of you that can read *German*, you can download a postscript -paper discussing implementation and problems of this software, with -introductions to MPEG1/Audio, MPEG1/Video and MPEG1/Systems. -You should find the paper with the same distribution you got this -program from. - -If not, you should find the postscript version of this 40-page paper -on - -ftp.informatik.tu-muenchen.de in /pub/comp/graphics/mpeg/mplex - -(121822 bytes, Jun 30 , 1994 , mpeg_systems_paper_0.99.ps.gz) - -If you have any questions you cannot figure out by running the -program, feel free to ask me. - --------------------------------------------------------------------------- - -One more thing that might save me many emails: - -when asked about the startup packet delay, try something like -half the video buffer size divided by your sector size. Say you -have a 40 kByte video buffer and a 2324 Byte Sector size, then -a startup delay of 8 sectors will work just fine. - -What does the above parameter mean? - -Normally, the Decoding/Presentation Time Stamp of the first access -unit is set to the clock value that will happen exactly after the last -packet containig data from this first unit arrives into the system -target decoder. This works fine if the video/audio streams are of -*very perfectly constant* or the packet size are *very* small -(ideally: the size of one access unit, that would mean variable -packet length). -Anyway: this parameter allows you to say that the System Target -Decoder should start decoding the first access unit after he -gets (startup_packet_delay + size_of_first_access_units[av]) -packets of data. -This guarantees that the buffers are conveniently filled up. -Note that both the video stream offset and audio stream offset (ms) -add up even more bytes to this startup delay, but you can -tell conveniently that audio should start so many ms after video, -for example. - -Sorry for no further doc, enjoy multiplexing A/V :) - -Christoph. - -moar@heaven.zfe.siemens.de -+---------------------------------------+--------------------------------+ -| http://www.informatik.tu-muenchen.de/ | Christoph Moar | -| cgi-bin/nph-gateway/hphalle6/~moar/ | Kaulbachstr.29a | -| index.html | 80539 Munich | -| email:moar@informatik.tu-muenchen.de | voice: ++49 - 89 - 23862874 | -+---------------------------------------+--------------------------------+ - diff --git a/ext/mplex/README b/ext/mplex/README deleted file mode 100644 index c060c1f..0000000 --- a/ext/mplex/README +++ /dev/null @@ -1,58 +0,0 @@ - -* mplex-2 - MPEG1/2 SYSTEMS/PROGRAM stream multiplexer -* -* Orginally based on mplex -* Copyright (C) 1994 1995 Christoph Moar -* Reengineered version in C++ -* Copyright (C) 2000,2001, 2002 Andrew Stevens -* -* as@comlab.ox.ac.uk - (Andrew Stevens) -* 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 in the file COPYING 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. - - - -MODIFICATIONS TO ORIGINAL - -July 2000 Andrew Stevens - Trivial modifications to support catenated audio stremas and - non-intractive use. -August 2000 Andrew Stevens - Modifed to support multiplexing of variable bit-rate - video streams. Seems to work well. -August 2000 Andrew Stevens - Removed use of temporary files for storing stream data. - Increased performance through the use of a more efficient bitstream - library. - Eliminated arithmetic overflow errors for large streams. - Initial support for multiplexing variable bit-rate streams. - -Novermber 2000 Andrew Stevens - Clean up code to suit modern compilers with 64-bit int support. - Cleaned up packet size calculations to make the code more flexible. - Initial MPEG-2 support - Support for splitting output streams (not yet completely implemented) - Support for multiplexing for VCD. - -Jan 2001- - - Reengineered in C++ - Support for SVCD. - Support for basic DVD - VBR Audio as well as video. - Clean stream splitting support. - Class structure to simplify adding new stream types - - Encapsulation and modularistion diff --git a/ext/mplex/TODO b/ext/mplex/TODO deleted file mode 100644 index 8b39301..0000000 --- a/ext/mplex/TODO +++ /dev/null @@ -1,41 +0,0 @@ -TODO - -- Check if video and MPEG audio streams have the same eof bug as I found -in AC3 audio. - -- Need to add general facility for enforcing max STD buffer delay for audio - and for warning if constraints for particular formats are exceeded. - -- Make VBR more efficient (a skip for long periods where no sector is emitted). - - -- Complete tidying up the systems.cc structure. Non-duplication of the - header generation stuff would be neat if it can be managed... - - -- Add checking for changed sequence parameters in mid-sequence sequence headers. - - -- Currently the VCD HR Stills muxing stuff assumes *all* HR stills - are the same size which is given in the initial vbv_buffer_size... - This will work with mpeg2enc (which does this) but will fail fail fail - with other streams. - -- Rebuild initial delay / sequence splitting DTS adjustment stuff so - different streams can have different starting delays based on - *stream* parameters. I.e. delay should be delegated to the elementary - streams with only a sector_prefix offset set centrally. - -- Tidy code so Elementary streams handle their mux parameter initialisation - from cmd-line parameters *not* the output stream. - - - - -Eventually: - -- Full SVCD (MPEG audio extension) support. - -- DVD muxing and generation of info for .IFO's etc. - - diff --git a/ext/mplex/ac3strm_in.cc b/ext/mplex/ac3strm_in.cc deleted file mode 100644 index 806cffa..0000000 --- a/ext/mplex/ac3strm_in.cc +++ /dev/null @@ -1,383 +0,0 @@ -/* - * ac3strm_in.c: AC3 Audio strem class members handling scanning and - * buffering raw input stream. - * - * Copyright (C) 2001 Andrew Stevens - * Copyright (C) 2000,2001 Brent Byeler for original header-structure - * parsing code. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include - -#include "audiostrm.hh" -#include "outputstream.hh" -#include - - - -#define AC3_SYNCWORD 0x0b77 -#define AC3_PACKET_SAMPLES 1536 - -/// table for the available AC3 bitrates -static const unsigned int ac3_bitrate_index[32] = -{ - 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, - 224, 256, 320, 384, 448, 512, 576, 640, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const unsigned int ac3_frame_size[3][32] = -{ - {64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, - 448, 512, 640, 768, 896, 1024, 1152, 1280, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {69, 87, 104, 121, 139, 174, 208, 243, 278, 348, 417, - 487, 557, 696, 835, 975, 1114, 1253, 1393, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, - 672, 768, 960, 1152, 1344, 1536, 1728, 1920, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -}; - -/// table for the available AC3 frequencies -static const unsigned int ac3_frequency[4] = { 48000, 44100, 32000, 0 }; - - -AC3Stream::AC3Stream (IBitStream & ibs, OutputStream & into): -AudioStream (ibs, into) -{ -} - -bool -AC3Stream::Probe (IBitStream & bs) -{ - return bs.getbits (16) == AC3_SYNCWORD; -} - - -/************************************************************************* - * - * Reads initial stream parameters and displays feedback banner to users - * @param stream_num AC3 substream ID - *************************************************************************/ - - -void -AC3Stream::Init (const int stream_num) -{ - unsigned int framesize_code; - - this->stream_num = stream_num; - - MuxStream::Init (PRIVATE_STR_1, 1, // Buffer scale - default_buffer_size, - muxinto.vcd_zero_stuffing, - muxinto.buffers_in_audio, muxinto.always_buffers_in_audio); - mjpeg_info ("Scanning for header info: AC3 Audio stream %02x", stream_num); - - InitAUbuffer (); - AU_start = bs.bitcount (); - if (bs.getbits (16) == AC3_SYNCWORD) { - num_syncword++; - bs.getbits (16); // CRC field - frequency = bs.getbits (2); // Sample rate code - framesize_code = bs.getbits (6); // Frame size code - framesize = ac3_frame_size[frequency][framesize_code >> 1]; - framesize = (framesize_code & 1) && frequency == 1 ? (framesize + 1) << 1 : (framesize << 1); - - - size_frames[0] = framesize; - size_frames[1] = framesize; - num_frames[0]++; - access_unit.start = AU_start; - access_unit.length = framesize; - bit_rate = ac3_bitrate_index[framesize_code >> 1]; - samples_per_second = ac3_frequency[frequency]; - - - /* Presentation time-stamping */ - access_unit.PTS = static_cast < clockticks > (decoding_order) * - static_cast < clockticks > (AC3_PACKET_SAMPLES) * - static_cast < clockticks > (CLOCKS) / samples_per_second; - access_unit.DTS = access_unit.PTS; - access_unit.dorder = decoding_order; - ++decoding_order; - aunits.append (access_unit); - - } else { - mjpeg_error ("Invalid AC3 Audio stream header."); - exit (1); - } - - OutputHdrInfo (); -} - -/// @returns the current bitrate -unsigned int -AC3Stream::NominalBitRate () -{ - return bit_rate; -} - -/// Prefills the internal buffer for output multiplexing. -/// @param frames_to_buffer the number of audio frames to read ahead -void -AC3Stream::FillAUbuffer (unsigned int frames_to_buffer) -{ - unsigned int framesize_code; - - last_buffered_AU += frames_to_buffer; - mjpeg_debug ("Scanning %d MPEG audio frames to frame %d", frames_to_buffer, last_buffered_AU); - - static int header_skip = 5; // Initially skipped past 5 bytes of header - int skip; - bool bad_last_frame = false; - - while (!bs.eos () && - decoding_order < last_buffered_AU) { - skip = access_unit.length - header_skip; - if (skip & 0x1) - bs.getbits (8); - if (skip & 0x2) - bs.getbits (16); - skip = skip >> 2; - - for (int i = 0; i < skip; i++) { - bs.getbits (32); - } - - prev_offset = AU_start; - AU_start = bs.bitcount (); - if (AU_start - prev_offset != access_unit.length * 8) { - bad_last_frame = true; - break; - } - - /* Check we have reached the end of have another catenated - stream to process before finishing ... */ - if ((syncword = bs.getbits (16)) != AC3_SYNCWORD) { - if (!bs.eos ()) { - mjpeg_error_exit1 ("Can't find next AC3 frame - broken bit-stream?"); - } - break; - } - - bs.getbits (16); // CRC field - bs.getbits (2); // Sample rate code TOOD: check for change! - framesize_code = bs.getbits (6); - framesize = ac3_frame_size[frequency][framesize_code >> 1]; - framesize = (framesize_code & 1) && frequency == 1 ? (framesize + 1) << 1 : (framesize << 1); - - access_unit.start = AU_start; - access_unit.length = framesize; - access_unit.PTS = static_cast < clockticks > (decoding_order) * - static_cast < clockticks > (AC3_PACKET_SAMPLES) * - static_cast < clockticks > (CLOCKS) / samples_per_second;; - access_unit.DTS = access_unit.PTS; - access_unit.dorder = decoding_order; - decoding_order++; - aunits.append (access_unit); - num_frames[0]++; - - num_syncword++; - - -#ifdef DEBUG_AC3_HEADERS - /* Some stuff to generate frame-header information */ - printf ("bsid = %d\n", bs.getbits (5)); - printf ("bsmode = 0x%1x\n", bs.getbits (3)); - int acmode = bs.getbits (3); - - printf ("acmode = 0x%1x\n", acmode); - if ((acmode & 0x1) && (acmode != 1)) - printf ("cmixlev = %d\n", bs.getbits (2)); - if ((acmode & 0x4)) - printf ("smixlev = %d\n", bs.getbits (2)); - if (acmode == 2) - printf ("dsurr = %d\n", bs.getbits (2)); - printf ("lfeon = %d\n", bs.getbits (1)); - printf ("dialnorm = %02d\n", bs.getbits (5)); - int compre = bs.getbits (1); - - printf ("compre = %d\n", compre); - if (compre) - printf ("compr = %02d\n", bs.getbits (8)); - int langcode = bs.getbits (1); - - printf ("langcode = %d\n", langcode); - if (langcode) - printf ("langcod = 0x%02x\n", bs.getbits (8)); - - while (bs.bitcount () % 8 != 0) - bs.getbits (1); - header_skip = (bs.bitcount () - AU_start) / 8; -#endif - if (num_syncword >= old_frames + 10) { - mjpeg_debug ("Got %d frame headers.", num_syncword); - old_frames = num_syncword; - } - - - } - if (bad_last_frame) { - mjpeg_error_exit1 ("Last AC3 frame ended prematurely!\n"); - } - last_buffered_AU = decoding_order; - eoscan = bs.eos (); - -} - - -/// Closes the AC3 stream and prints some statistics. -void -AC3Stream::Close () -{ - stream_length = AU_start >> 3; - mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); - mjpeg_info ("Audio stream length %d bytes.", (int)stream_length); - mjpeg_info ("Syncwords : %8u", num_syncword); - mjpeg_info ("Frames : %8u padded", num_frames[0]); - mjpeg_info ("Frames : %8u unpadded", num_frames[1]); - - bs.close (); -} - -/************************************************************************* - OutputAudioInfo - gibt gesammelte Informationen zu den Audio Access Units aus. - - Prints information on audio access units -*************************************************************************/ - -void -AC3Stream::OutputHdrInfo () -{ - mjpeg_info ("AC3 AUDIO STREAM:"); - - mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)", bit_rate * 128, bit_rate); - - if (frequency == 3) - mjpeg_info ("Frequency : reserved"); - else - mjpeg_info ("Frequency : %d Hz", ac3_frequency[frequency]); - -} - -/** -Reads the bytes neccessary to complete the current packet payload. -@param to_read number of bytes to read -@param dst byte buffer pointer to read to -@returns the number of bytes read - */ -unsigned int -AC3Stream::ReadPacketPayload (uint8_t * dst, unsigned int to_read) -{ - static unsigned int aus = 0; - static unsigned int rd = 0; - - unsigned int bytes_read = bs.read_buffered_bytes (dst + 4, to_read - 4); - - rd += bytes_read; - clockticks decode_time; - - unsigned int first_header = (new_au_next_sec || au_unsent > bytes_read) - ? 0 : au_unsent; - - // BUG BUG BUG: how do we set the 1st header pointer if we have - // the *middle* part of a large frame? - assert (first_header <= to_read - 2); - - - unsigned int syncwords = 0; - unsigned int bytes_muxed = bytes_read; - - if (bytes_muxed == 0 || MuxCompleted ()) { - goto completion; - } - - - /* Work through what's left of the current AU and the following AU's - updating the info until we reach a point where an AU had to be - split between packets. - NOTE: It *is* possible for this loop to iterate. - - The DTS/PTS field for the packet in this case would have been - given the that for the first AU to start in the packet. - - */ - - decode_time = RequiredDTS (); - while (au_unsent < bytes_muxed) { - // BUG BUG BUG: if we ever had odd payload / packet size we might - // split an AC3 frame in the middle of the syncword! - assert (bytes_muxed > 1); - bufmodel.Queued (au_unsent, decode_time); - bytes_muxed -= au_unsent; - if (new_au_next_sec) - ++syncwords; - aus += au->length; - if (!NextAU ()) { - goto completion; - } - new_au_next_sec = true; - decode_time = RequiredDTS (); - }; - - // We've now reached a point where the current AU overran or - // fitted exactly. We need to distinguish the latter case - // so we can record whether the next packet starts with an - // existing AU or not - info we need to decide what PTS/DTS - // info to write at the start of the next packet. - - if (au_unsent > bytes_muxed) { - if (new_au_next_sec) - ++syncwords; - bufmodel.Queued (bytes_muxed, decode_time); - au_unsent -= bytes_muxed; - new_au_next_sec = false; - } else // if (au_unsent == bytes_muxed) - { - bufmodel.Queued (bytes_muxed, decode_time); - if (new_au_next_sec) - ++syncwords; - aus += au->length; - new_au_next_sec = NextAU (); - } -completion: - // Generate the AC3 header... - // Note the index counts from the low byte of the offset so - // the smallest value is 1! - - dst[0] = AC3_SUB_STR_0 + stream_num; - dst[1] = syncwords; - dst[2] = (first_header + 1) >> 8; - dst[3] = (first_header + 1) & 0xff; - - return bytes_read + 4; -} - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/audiostrm.hh b/ext/mplex/audiostrm.hh deleted file mode 100644 index bc0167a..0000000 --- a/ext/mplex/audiostrm.hh +++ /dev/null @@ -1,163 +0,0 @@ - -/* - * inptstrm.hh: Input stream classes for MPEG multiplexing - * TODO: Split into the base classes and the different types of - * actual input stream. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __AUDIOSTRM_H__ -#define __AUDIOSTRM_H__ - -#include "inputstrm.hh" - -class AudioStream:public ElementaryStream -{ -public: - AudioStream (IBitStream & ibs, OutputStream & into); - virtual void Init (const int stream_num) = 0; - virtual void Close () = 0; - - void OutputSector (); - bool RunOutComplete (); - virtual unsigned int NominalBitRate () = 0; - - unsigned int num_syncword; - unsigned int num_frames[2]; - unsigned int size_frames[2]; - unsigned int version_id; - unsigned int layer; - unsigned int protection; - unsigned int bit_rate_code; - unsigned int frequency; - unsigned int mode; - unsigned int mode_extension; - unsigned int copyright; - unsigned int original_copy; - unsigned int emphasis; - -protected: - virtual bool AUBufferNeedsRefill (); - virtual void FillAUbuffer (unsigned int frames_to_buffer) = 0; - void InitAUbuffer (); - - /* State variables for scanning source bit-stream */ - unsigned int framesize; - unsigned int skip; - unsigned int samples_per_second; - unsigned long long int length_sum; - AAunit access_unit; -}; - -class MPAStream:public AudioStream -{ -public: - MPAStream (IBitStream & ibs, OutputStream & into); - virtual void Init (const int stream_num); - static bool Probe (IBitStream & bs); - virtual void Close (); - virtual unsigned int NominalBitRate (); - - -private: - void OutputHdrInfo (); - unsigned int SizeFrame (int bit_rate, int padding_bit); - virtual void FillAUbuffer (unsigned int frames_to_buffer); - - - /* State variables for scanning source bit-stream */ - unsigned int framesize; - unsigned int skip; - unsigned int samples_per_second; -}; - - - -class AC3Stream:public AudioStream -{ -public: - AC3Stream (IBitStream & ibs, OutputStream & into); - virtual void Init (const int stream_num); - static bool Probe (IBitStream & bs); - virtual void Close (); - virtual unsigned int NominalBitRate (); - - virtual unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read); - virtual unsigned int StreamHeaderSize () - { - return 4; - } - - -private: - void OutputHdrInfo (); - virtual void FillAUbuffer (unsigned int frames_to_buffer); - - static const unsigned int default_buffer_size = 16 * 1024; - - /* State variables for scanning source bit-stream */ - unsigned int framesize; - unsigned int samples_per_second; - unsigned int bit_rate; - unsigned int stream_num; -}; - -class LPCMStream:public AudioStream -{ -public: - LPCMStream (IBitStream & ibs, OutputStream & into); - virtual void Init (const int stream_num); - static bool Probe (IBitStream & bs); - virtual void Close (); - virtual unsigned int NominalBitRate (); - - virtual unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read); - virtual unsigned int StreamHeaderSize () - { - return 7; - } - - -private: - void OutputHdrInfo (); - virtual void FillAUbuffer (unsigned int frames_to_buffer); - - static const unsigned int default_buffer_size = 232 * 1024; - static const unsigned int ticks_per_frame_90kHz = 150; - - /* State variables for scanning source bit-stream */ - unsigned int stream_num; - unsigned int samples_per_second; - unsigned int channels; - unsigned int bits_per_sample; - unsigned int bytes_per_frame; - unsigned int frame_index; - unsigned int dynamic_range_code; -}; - - -#endif // __AUDIOSTRM_H__ - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/audiostrm_out.cc b/ext/mplex/audiostrm_out.cc deleted file mode 100644 index 5ef358a..0000000 --- a/ext/mplex/audiostrm_out.cc +++ /dev/null @@ -1,144 +0,0 @@ - -/* - * inptstrm.c: Members of audi stream classes related to muxing out into - * the output stream. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - - -#include -#include -#include "fastintfns.h" -#include "audiostrm.hh" -#include "outputstream.hh" - - - -AudioStream::AudioStream (IBitStream & ibs, OutputStream & into): -ElementaryStream (ibs, into, ElementaryStream::audio), num_syncword (0) -{ - FRAME_CHUNK = 24; - for (int i = 0; i < 2; ++i) - num_frames[i] = size_frames[i] = 0; -} - -void -AudioStream::InitAUbuffer () -{ - unsigned int i; - - for (i = 0; i < aunits.BUF_SIZE; ++i) - aunits.init (new AAunit); -} - - - -/********************************* - * Signals when audio stream has completed mux run-out specified - * in associated mux stream. - *********************************/ - -bool -AudioStream::RunOutComplete () -{ - return (au_unsent == 0 || (muxinto.running_out && RequiredPTS () >= muxinto.runout_PTS)); -} - -bool -AudioStream::AUBufferNeedsRefill () -{ - return - !eoscan - && (aunits.current () + FRAME_CHUNK > last_buffered_AU - || bs.buffered_bytes () < muxinto.sector_size); -} - -/****************************************************************** - Output_Audio - generates Pack/Sys Header/Packet information from the - audio stream and saves them into the sector -******************************************************************/ - -void -AudioStream::OutputSector () -{ - clockticks PTS; - unsigned int max_packet_data; - unsigned int actual_payload; - unsigned int old_au_then_new_payload; - - PTS = RequiredDTS (); - old_au_then_new_payload = muxinto.PacketPayload (*this, buffers_in_header, false, false); - - max_packet_data = 0; - if (muxinto.running_out && NextRequiredPTS () > muxinto.runout_PTS) { - /* We're now in the last AU of a segment. So we don't want to - go beyond it's end when writing sectors. Hence we limit - packet payload size to (remaining) AU length. - */ - max_packet_data = au_unsent; - } - - /* CASE: packet starts with new access unit */ - - if (new_au_next_sec) { - actual_payload = - muxinto.WritePacket (max_packet_data, *this, buffers_in_header, PTS, 0, TIMESTAMPBITS_PTS); - - } - - - /* CASE: packet starts with old access unit, no new one */ - /* starts in this very same packet */ - else if (!(new_au_next_sec) && (au_unsent >= old_au_then_new_payload)) { - actual_payload = - muxinto.WritePacket (max_packet_data, *this, buffers_in_header, 0, 0, TIMESTAMPBITS_NO); - } - - - /* CASE: packet starts with old access unit, a new one */ - /* starts in this very same packet */ - else { /* !(new_au_next_sec) && (au_unsent < old_au_then_new_payload)) */ - - /* is there another access unit anyway ? */ - if (Lookahead () != 0) { - PTS = NextRequiredDTS (); - actual_payload = - muxinto.WritePacket (max_packet_data, *this, buffers_in_header, PTS, 0, TIMESTAMPBITS_PTS); - - } else { - actual_payload = muxinto.WritePacket (0, *this, buffers_in_header, 0, 0, TIMESTAMPBITS_NO); - }; - - } - - ++nsec; - - buffers_in_header = always_buffers_in_header; - -} - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/aunit.hh b/ext/mplex/aunit.hh deleted file mode 100644 index 0876887..0000000 --- a/ext/mplex/aunit.hh +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __AUNIT_H__ -#define __AUNIT_H__ - -#include -#include "mjpeg_types.h" -#include "bits.hh" - -typedef int64_t clockticks; // This value *must* be signed - - // because we frequently compute *offsets* - -class Aunit -{ -public: - Aunit ():length (0), PTS (0), DTS (0) - { - } - void markempty () - { - length = 0; - } - bitcount_t start; - unsigned int length; - clockticks PTS; - int dorder; - - // Used only for video AU's but otherwise - // you have to go crazy on templates. - clockticks DTS; - int porder; - unsigned int type; - bool seq_header; - bool end_seq; - -}; - -typedef Aunit VAunit; - -typedef Aunit AAunit; - -#endif // __AUNIT_H__ diff --git a/ext/mplex/bits.cc b/ext/mplex/bits.cc deleted file mode 100644 index 84d0591..0000000 --- a/ext/mplex/bits.cc +++ /dev/null @@ -1,358 +0,0 @@ -/** @file bits.cc, bit-level output */ - -/* Copyright (C) 2001, Andrew Stevens * - - * - * Disclaimer of Warranty - * - * These software programs are available to the user without any license fee or - * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims - * any and all warranties, whether express, implied, or statuary, including any - * implied warranties or merchantability or of fitness for a particular - * purpose. In no event shall the copyright-holder be liable for any - * incidental, punitive, or consequential damages of any kind whatsoever - * arising from the use of these programs. - * - * This disclaimer of warranty extends to the user of these programs and user's - * customers, employees, agents, transferees, successors, and assigns. - * - * The MPEG Software Simulation Group does not represent or warrant that the - * programs furnished hereunder are free of infringement of any third-party - * patents. - * - * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, - * are subject to royalty fees to patent holders. Many of these patents are - * general enough such that they are unavoidable regardless of implementation - * design. - * - */ - -#include -#include -#include -#include -#include -#include -#include "mjpeg_logging.h" -#include "bits.hh" - - -/// Initializes the bitstream, sets internal variables. -// TODO: The buffer size should be set dynamically to sensible sizes. -// -BitStream::BitStream (): -user_data (NULL) -{ - totbits = 0LL; - buffer_start = 0LL; - eobs = true; - readpos = 0LL; - bfr = 0; - bfr_size = 0; -} - -/// Deconstructor. Deletes the internal buffer. -BitStream::~BitStream () -{ - delete bfr; -} - -/** - Refills an IBitStream's input buffer based on the internal variables bufcount and bfr_size. - */ -bool -IBitStream::refill_buffer () -{ - size_t i; - - if (bufcount >= bfr_size) { - SetBufSize (bfr_size + 4096); - } - - i = read_callback (this, bfr + bufcount, static_cast < size_t > (bfr_size - bufcount), user_data); - bufcount += i; - - if (i == 0) { - eobs = true; - return false; - } - return true; -} - -/** - Flushes all read input up-to *but not including* bit - unbuffer_upto. -@param flush_to the number of bits to flush -*/ - -void -IBitStream::flush (bitcount_t flush_upto) -{ - if (flush_upto > buffer_start + bufcount) - mjpeg_error_exit1 ("INTERNAL ERROR: attempt to flush input beyond buffered amount"); - - if (flush_upto < buffer_start) - mjpeg_error_exit1 - ("INTERNAL ERROR: attempt to flush input stream before first buffered byte %d last is %d", - (int) flush_upto, (int) buffer_start); - unsigned int bytes_to_flush = static_cast < unsigned int >(flush_upto - buffer_start); - - // - // Don't bother actually flushing until a good fraction of a buffer - // will be cleared. - // - - if (bytes_to_flush < bfr_size * 3 / 4) - return; - - bufcount -= bytes_to_flush; - buffer_start = flush_upto; - byteidx -= bytes_to_flush; - memmove (bfr, bfr + bytes_to_flush, static_cast < size_t > (bufcount)); -} - - -/** - Undo scanning / reading - N.b buffer *must not* be flushed between prepareundo and undochanges. - @param undo handle to store the undo information -*/ -void -IBitStream::prepareundo (BitStreamUndo & undo) -{ - undo = *(static_cast < BitStreamUndo * >(this)); -} - -/** -Undoes changes committed to an IBitStream. -@param undo handle to retrieve the undo information - */ -void -IBitStream::undochanges (BitStreamUndo & undo) -{ - *(static_cast < BitStreamUndo * >(this)) = undo; -} - -/** - Read a number bytes over an IBitStream, using the buffer. - @param dst buffer to read to - @param length the number of bytes to read - */ -unsigned int -IBitStream::read_buffered_bytes (uint8_t * dst, unsigned int length) -{ - unsigned int to_read = length; - - if (readpos < buffer_start) - mjpeg_error_exit1 - ("INTERNAL ERROR: access to input stream buffer @ %d: before first buffered byte (%d)", - (int) readpos, (int) buffer_start); - - if (readpos + length > buffer_start + bufcount) { - /* - if (!feof (fileh)) { - mjpeg_error - ("INTERNAL ERROR: access to input stream buffer beyond last buffered byte @POS=%lld END=%d REQ=%lld + %d bytes", - readpos, bufcount, readpos - (bitcount_t) buffer_start, length); - abort (); - } - */ - to_read = static_cast < unsigned int >((buffer_start + bufcount) - readpos); - } - memcpy (dst, bfr + (static_cast < unsigned int >(readpos - buffer_start)), to_read); - // We only ever flush up to the start of a read as we - // have only scanned up to a header *beginning* a block that is then - // read - flush (readpos); - readpos += to_read; - return to_read; -} - -/** open the device to read the bit stream from it -@param bs_filename filename to open -@param buf_size size of the internal buffer -*/ -void -IBitStream::open (ReadCallback read_callback, void *user_data, unsigned int buf_size) -{ - this->read_callback = read_callback; - this->user_data = user_data; - - bfr_size = buf_size; - if (bfr == NULL) - bfr = new uint8_t[buf_size]; - else { - delete bfr; - - bfr = new uint8_t[buf_size]; - } - - byteidx = 0; - bitidx = 8; - totbits = 0LL; - bufcount = 0; - eobs = false; - if (!refill_buffer ()) { - if (bufcount == 0) { - mjpeg_error_exit1 ("Unable to read."); - } - } -} - - -/** sets the internal buffer size. - @param new_buf_size the new internal buffer size -*/ -void -IBitStream::SetBufSize (unsigned int new_buf_size) -{ - assert (bfr != NULL); // Must be open first! - assert (new_buf_size >= bfr_size); // Can only be increased in size... - - if (bfr_size != new_buf_size) { - uint8_t *new_buf = new uint8_t[new_buf_size]; - - memcpy (new_buf, bfr, static_cast < size_t > (bfr_size)); - delete bfr; - - bfr_size = new_buf_size; - bfr = new_buf; - } - -} - -/** - close the device containing the bit stream after a read process -*/ -void -IBitStream::close () -{ -} - - -// TODO replace with shift ops! - -uint8_t - IBitStream::masks[8] = { - 0x1, - 0x2, - 0x4, - 0x8, - 0x10, - 0x20, - 0x40, -0x80 }; - -/*read 1 bit from the bit stream -@returns the read bit, 0 on EOF */ -uint32_t -IBitStream::get1bit () -{ - unsigned int bit; - - if (eobs) - return 0; - - bit = (bfr[byteidx] & masks[bitidx - 1]) >> (bitidx - 1); - totbits++; - bitidx--; - if (!bitidx) { - bitidx = 8; - byteidx++; - if (byteidx == bufcount) { - refill_buffer (); - } - } - - return bit; -} - -/*read N bits from the bit stream -@returns the read bits, 0 on EOF */ -uint32_t -IBitStream::getbits (int N) -{ - uint32_t val = 0; - int i = N; - unsigned int j; - - // Optimize: we are on byte boundary and want to read multiple of bytes! - if ((bitidx == 8) && ((N & 7) == 0)) { - i = N >> 3; - while (i > 0) { - if (eobs) - return 0; - val = (val << 8) | bfr[byteidx]; - byteidx++; - totbits += 8; - if (byteidx == bufcount) { - refill_buffer (); - } - i--; - } - } else { - while (i > 0) { - if (eobs) - return 0; - - j = (bfr[byteidx] & masks[bitidx - 1]) >> (bitidx - 1); - totbits++; - bitidx--; - if (!bitidx) { - bitidx = 8; - byteidx++; - if (byteidx == bufcount) { - refill_buffer (); - } - } - val = (val << 1) | j; - i--; - } - } - return val; -} - - -/** This function seeks for a byte aligned sync word (max 32 bits) in the bit stream and - places the bit stream pointer right after the sync. - This function returns 1 if the sync was found otherwise it returns 0 -@param sync the sync word to search for -@param N the number of bits to retrieve -@param lim number of bytes to search through -@returns false on error */ - -bool -IBitStream::seek_sync (uint32_t sync, int N, int lim) -{ - uint32_t val, val1; - uint32_t maxi = ((1U << N) - 1); /* pow(2.0, (double)N) - 1 */ ; - if (maxi == 0) { - maxi = 0xffffffff; - } - while (bitidx != 8) { - get1bit (); - } - - val = getbits (N); - if (eobs) - return false; - while ((val & maxi) != sync && --lim) { - val <<= 8; - val1 = getbits (8); - val |= val1; - if (eobs) - return false; - } - - return (!!lim); -} - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/bits.hh b/ext/mplex/bits.hh deleted file mode 100644 index 275b8c0..0000000 --- a/ext/mplex/bits.hh +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __BITS_H__ -#define __BITS_H__ - -#include -#include - -typedef uint64_t bitcount_t; - - -class BitStreamUndo -{ -//protected: -public: - uint8_t outbyte; - unsigned int byteidx; - int bitidx; - unsigned int bufcount; - fpos_t actpos; - bitcount_t totbits; - bitcount_t buffer_start; - bitcount_t readpos; - uint8_t *bfr; - unsigned int bfr_size; -public: - bool eobs; -}; - -typedef class BitStream _BitStream; - -typedef size_t (*ReadCallback) (_BitStream *bs, uint8_t *dest, size_t size, void *user_data); - -class BitStream : public BitStreamUndo -{ -public: - void *user_data; - static const unsigned int BUFFER_SIZE = 4 * 1024; -public: - BitStream (); - ~BitStream (); - inline bitcount_t bitcount () - { - return totbits; - } - inline bool eos () - { - return eobs; - } -}; - - -// -// Input bit stream class. Supports the "scanning" of a stream -// into a large buffer which is flushed once it has been read. -// N.b. if you scan ahead a long way and don't read its your -// responsibility to flush manually... -// - -class IBitStream:public BitStream -{ -public: - void open (ReadCallback read_callback, void *user_data, unsigned int buf_size = BUFFER_SIZE); - void SetBufSize (unsigned int buf_size); - void close (); - uint32_t get1bit (); - uint32_t getbits (int N); - void prepareundo (BitStreamUndo & undobuf); - void undochanges (BitStreamUndo & undobuf); - bool seek_sync (unsigned int sync, int N, int lim); - void flush (bitcount_t bitposition); - inline unsigned int buffered_bytes () - { - return (buffer_start + bufcount - readpos); - } - unsigned int read_buffered_bytes (uint8_t * dst, unsigned int length_bytes); - -private: - bool refill_buffer (); - static uint8_t masks[8]; - ReadCallback read_callback; -}; - -#endif // __BITS_H__ diff --git a/ext/mplex/buffer.cc b/ext/mplex/buffer.cc deleted file mode 100644 index 2b29180..0000000 --- a/ext/mplex/buffer.cc +++ /dev/null @@ -1,118 +0,0 @@ -#include "buffer.hh" -#include - -/****************************************************************** - * Remove entries from FIFO buffer list, if their DTS is less than - * actual SCR. These packet data have been already decoded and have - * been removed from the system target decoder's elementary stream - * buffer. - *****************************************************************/ - -void -BufferModel::Cleaned (clockticks SCR) -{ - BufferQueue *pointer; - - while ((first != NULL) && first->DTS < SCR) { - pointer = first; - first = first->next; - delete pointer; - } -} - -/****************************************************************** - * Return the SCR when there will next be some change in the - * buffer. - * If the buffer is empty return a zero timestamp. - *****************************************************************/ - -clockticks -BufferModel::NextChange () -{ - if (first == NULL) - return static_cast < clockticks > (0); - else - return first->DTS; -} - - -/****************************************************************** - * - * Remove all entries from FIFO buffer list, if their DTS is less - * than actual SCR. These packet data have been already decoded and - * have been removed from the system target decoder's elementary - * stream buffer. - *****************************************************************/ - -void -BufferModel::Flushed () -{ - BufferQueue *pointer; - - while (first != NULL) { - pointer = first; - first = first->next; - delete pointer; - } -} - -/****************************************************************** - BufferModel::Space - - returns free space in the buffer -******************************************************************/ - -unsigned int -BufferModel::Space () -{ - unsigned int used_bytes; - BufferQueue *pointer; - - pointer = first; - used_bytes = 0; - - while (pointer != NULL) { - used_bytes += pointer->size; - pointer = pointer->next; - } - - return (max_size - used_bytes); - -} - -/****************************************************************** - Queue_Buffer - - adds entry into the buffer FIFO queue -******************************************************************/ - -void -BufferModel::Queued (unsigned int bytes, clockticks TS) -{ - BufferQueue *pointer; - - pointer = first; - if (pointer == NULL) { - first = new BufferQueue; - first->size = bytes; - first->next = NULL; - first->DTS = TS; - } else { - while ((pointer->next) != NULL) { - pointer = pointer->next; - } - - pointer->next = (BufferQueue *) malloc (sizeof (BufferQueue)); - pointer->next->size = bytes; - pointer->next->next = NULL; - pointer->next->DTS = TS; - } -} - - -void -BufferModel::Init (unsigned int size) -{ - max_size = size; - first = 0; -} diff --git a/ext/mplex/buffer.hh b/ext/mplex/buffer.hh deleted file mode 100644 index a7bdba9..0000000 --- a/ext/mplex/buffer.hh +++ /dev/null @@ -1,73 +0,0 @@ - -/* - * buffer.hh: Classes for decoder buffer models for mux despatch - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __BUFFER_H__ -#define __BUFFER_H__ - -#include -#include "aunit.hh" - -class BufferQueue -{ -#include -# -public: - unsigned int size; /* als verkettete Liste implementiert */ - clockticks DTS; - BufferQueue *next; -}; - - -class BufferModel -{ -public: - BufferModel ():max_size (0), first (0) - { - } - void Init (unsigned int size); - - void Cleaned (clockticks timenow); - clockticks NextChange (); - void Flushed (); - unsigned int Space (); - void Queued (unsigned int bytes, clockticks removaltime); - inline unsigned int Size () - { - return max_size; - } -private: - unsigned int max_size; - BufferQueue *first; -}; - - - -#endif // __BUFFER_H__ - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/fastintfns.h b/ext/mplex/fastintfns.h deleted file mode 100644 index 7c1ec13..0000000 --- a/ext/mplex/fastintfns.h +++ /dev/null @@ -1,35 +0,0 @@ -/* fast int primitives. min,max,abs,samesign - * - * WARNING: Assumes 2's complement arithmetic. - * - */ - -#ifndef __inline__ -#define __inline__ inline -#endif - -static __inline__ int intmax( register int x, register int y ) -{ - return x < y ? y : x; -} - -static __inline__ int intmin( register int x, register int y ) -{ - return x < y ? x : y; -} - -static __inline__ int intabs( register int x ) -{ - return x < 0 ? -x : x; -} - -#define fabsshift ((8*sizeof(unsigned int))-1) - -#define signmask(x) (((int)x)>>fabsshift) -static __inline__ int intsamesign(int x, int y) -{ - return (y+(signmask(x) & -(y<<1))); -} -#undef signmask -#undef fabsshift - diff --git a/ext/mplex/format_codes.h b/ext/mplex/format_codes.h deleted file mode 100644 index 32f668f..0000000 --- a/ext/mplex/format_codes.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - $Id$ - - Copyright (C) 2001 Andrew Stevens - - 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 __FORMAT_CODES_H__ -#define __FORMAT_CODES_H__ - -#define MPEG_FORMAT_MPEG1 0 -#define MPEG_FORMAT_VCD 1 -#define MPEG_FORMAT_VCD_NSR 2 -#define MPEG_FORMAT_MPEG2 3 -#define MPEG_FORMAT_SVCD 4 -#define MPEG_FORMAT_SVCD_NSR 5 -#define MPEG_FORMAT_VCD_STILL 6 -#define MPEG_FORMAT_SVCD_STILL 7 -#define MPEG_FORMAT_DVD 8 - -#define MPEG_FORMAT_FIRST 0 -#define MPEG_FORMAT_LAST 8 - -#define MPEG_STILLS_FORMAT(x) (x==MPEG_FORMAT_VCD_STILL||x==MPEG_FORMAT_SVCD_STILL) -#endif /* __FORMAT_CODES_H__ */ diff --git a/ext/mplex/inputstrm.cc b/ext/mplex/inputstrm.cc deleted file mode 100644 index 4a19724..0000000 --- a/ext/mplex/inputstrm.cc +++ /dev/null @@ -1,249 +0,0 @@ - -/* - * inputstrm.c: Base classes related to muxing out input streams into - * the output stream. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - - -#include -#include -#include "fastintfns.h" -#include "inputstrm.hh" -#include "outputstream.hh" - -MuxStream::MuxStream ():init (false) -{ -} - - -void -MuxStream::Init (const int strm_id, - const unsigned int _buf_scale, - const unsigned int buf_size, - const unsigned int _zero_stuffing, bool bufs_in_first, bool always_bufs) -{ - stream_id = strm_id; - nsec = 0; - zero_stuffing = _zero_stuffing; - buffer_scale = _buf_scale; - buffer_size = buf_size; - bufmodel.Init (buf_size); - buffers_in_header = bufs_in_first; - always_buffers_in_header = always_bufs; - new_au_next_sec = true; - init = true; -} - - - -unsigned int -MuxStream::BufferSizeCode () -{ - if (buffer_scale == 1) - return buffer_size / 1024; - else if (buffer_scale == 0) - return buffer_size / 128; - else - assert (false); -} - - - -ElementaryStream::ElementaryStream (IBitStream & ibs, OutputStream & into, stream_kind _kind): -InputStream (ibs), muxinto (into), kind (_kind), buffer_min (INT_MAX), buffer_max (1) -{ -} - - -bool ElementaryStream::NextAU () -{ - Aunit * - p_au = - next (); - - if (p_au != NULL) { - au = p_au; - au_unsent = p_au->length; - return true; - } else { - au_unsent = 0; - return false; - } -} - - -Aunit * -ElementaryStream::Lookahead () -{ - return aunits.lookahead (); -} - -unsigned int -ElementaryStream::BytesToMuxAUEnd (unsigned int sector_transport_size) -{ - return (au_unsent / min_packet_data) * sector_transport_size + - (au_unsent % min_packet_data) + (sector_transport_size - min_packet_data); -} - - -/****************************************************************** - * ElementaryStream::ReadPacketPayload - * - * Reads the stream data from actual input stream, updates decode - * buffer model and current access unit information from the - * look-ahead scanning buffer to account for bytes_muxed bytes being - * muxed out. Particular important is the maintenance of "au_unsent" - * the count of how much data in the current AU remains umuxed. It - * not only allows us to keep track of AU's but is also used for - * generating substream headers - * - * Unless we need to over-ride it to handle sub-stream headers - * The packet payload for an elementary stream is simply the parsed and - * spliced buffered stream data.. - * - ******************************************************************/ - - - -unsigned int -ElementaryStream::ReadPacketPayload (uint8_t * dst, unsigned int to_read) -{ - unsigned int actually_read = bs.read_buffered_bytes (dst, to_read); - - Muxed (actually_read); - return actually_read; -} - - - - -void -ElementaryStream::Muxed (unsigned int bytes_muxed) -{ - clockticks decode_time; - - if (bytes_muxed == 0 || MuxCompleted ()) - return; - - - /* Work through what's left of the current AU and the following AU's - updating the info until we reach a point where an AU had to be - split between packets. - NOTE: It *is* possible for this loop to iterate. - - The DTS/PTS field for the packet in this case would have been - given the that for the first AU to start in the packet. - Whether Joe-Blow's hardware VCD player handles this properly is - another matter of course! - */ - - decode_time = RequiredDTS (); - while (au_unsent < bytes_muxed) { - - bufmodel.Queued (au_unsent, decode_time); - bytes_muxed -= au_unsent; - if (!NextAU ()) - return; - new_au_next_sec = true; - decode_time = RequiredDTS (); - }; - - // We've now reached a point where the current AU overran or - // fitted exactly. We need to distinguish the latter case - // so we can record whether the next packet starts with an - // existing AU or not - info we need to decide what PTS/DTS - // info to write at the start of the next packet. - - if (au_unsent > bytes_muxed) { - - bufmodel.Queued (bytes_muxed, decode_time); - au_unsent -= bytes_muxed; - new_au_next_sec = false; - } else // if (au_unsent == bytes_muxed) - { - bufmodel.Queued (bytes_muxed, decode_time); - if (!NextAU ()) - return; - new_au_next_sec = true; - } - -} - -bool -ElementaryStream::MuxPossible (clockticks currentSCR) -{ - return (!RunOutComplete () && bufmodel.Space () > max_packet_data); -} - - -void -ElementaryStream::UpdateBufferMinMax () -{ - buffer_min = buffer_min < (int) bufmodel.Space ()? buffer_min : bufmodel.Space (); - buffer_max = buffer_max > (int) bufmodel.Space ()? buffer_max : bufmodel.Space (); -} - - - -void -ElementaryStream::AllDemuxed () -{ - bufmodel.Flushed (); -} - -void -ElementaryStream::DemuxedTo (clockticks SCR) -{ - bufmodel.Cleaned (SCR); -} - -bool -ElementaryStream::MuxCompleted () -{ - return au_unsent == 0; -} - -void -ElementaryStream::SetSyncOffset (clockticks sync_offset) -{ - timestamp_delay = sync_offset; -} - -Aunit * -ElementaryStream::next () -{ - Aunit *res; - - while (AUBufferNeedsRefill ()) { - FillAUbuffer (FRAME_CHUNK); - } - res = aunits.next (); - return res; -} - - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/inputstrm.hh b/ext/mplex/inputstrm.hh deleted file mode 100644 index a424749..0000000 --- a/ext/mplex/inputstrm.hh +++ /dev/null @@ -1,278 +0,0 @@ - -/* - * inptstrm.hh: Input stream classes for MPEG multiplexing - * TODO: Split into the base classes and the different types of - * actual input stream. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __INPUTSTRM_H__ -#define __INPUTSTRM_H__ - -#include -#include -#include -#include - -#include "mjpeg_types.h" -#include "mpegconsts.h" -#include "format_codes.h" -#include "mjpeg_logging.h" - -#include "mplexconsts.hh" -#include "bits.hh" -#include "aunit.hh" -#include "vector.hh" -#include "buffer.hh" - - -class InputStream -{ -public: - InputStream (IBitStream & istream):bs (istream), - eoscan (false), stream_length (0), last_buffered_AU (0), decoding_order (0), old_frames (0) - { - } - - void SetBufSize (unsigned int buf_size) - { - bs.SetBufSize (buf_size); - } - -protected: - IBitStream & bs; - bool eoscan; - bitcount_t stream_length; - off_t file_length; - - unsigned int last_buffered_AU; // decode seq num of last buffered frame + 1 - bitcount_t AU_start; - uint32_t syncword; - bitcount_t prev_offset; - unsigned int decoding_order; - unsigned int old_frames; - -}; - -// -// Abstract forward reference... -// - -class OutputStream; - - -class MuxStream -{ -public: - MuxStream (); - - void Init (const int strm_id, - const unsigned int _buf_scale, - const unsigned int buf_size, - const unsigned int _zero_stuffing, const bool bufs_in_first, const bool always_bufs); - - unsigned int BufferSizeCode (); - inline unsigned int BufferSize () - { - return buffer_size; - } - inline unsigned int BufferScale () - { - return buffer_scale; - } - - - inline void SetMaxPacketData (unsigned int max) - { - max_packet_data = max; - } - inline void SetMinPacketData (unsigned int min) - { - min_packet_data = min; - } - inline unsigned int MaxPacketData () - { - return max_packet_data; - } - inline unsigned int MinPacketData () - { - return min_packet_data; - } - inline bool NewAUNextSector () - { - return new_au_next_sec; - } - - // - // Read the next packet payload (sub-stream headers plus - // parsed and spliced stream data) for a packet with the - // specified payload capacity. Update the AU info. - // - - virtual unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read) = 0; - - // - // Return the size of the substream headers... - // - virtual unsigned int StreamHeaderSize () - { - return 0; - } - -public: // TODO should go protected once encapsulation complete - int stream_id; - unsigned int buffer_scale; - unsigned int buffer_size; - BufferModel bufmodel; - unsigned int max_packet_data; - unsigned int min_packet_data; - unsigned int zero_stuffing; - unsigned int nsec; - bool buffers_in_header; - bool always_buffers_in_header; - bool new_au_next_sec; - bool init; -}; - -class DummyMuxStream:public MuxStream -{ -public: - DummyMuxStream (const int strm_id, const unsigned int buf_scale, unsigned int buf_size) - { - stream_id = strm_id; - buffer_scale = buf_scale; - buffer_size = buf_size; - } - - unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read) - { - abort (); - return 0; - } -}; - - -class ElementaryStream:public InputStream, public MuxStream -{ -public: - enum stream_kind - { audio, video, dummy }; - ElementaryStream (IBitStream & ibs, OutputStream & into, stream_kind kind); - virtual void Close () = 0; - - bool NextAU (); - Aunit *Lookahead (); - unsigned int BytesToMuxAUEnd (unsigned int sector_transport_size); - bool MuxCompleted (); - virtual bool MuxPossible (clockticks currentSCR); - void DemuxedTo (clockticks SCR); - void SetTSOffset (clockticks baseTS); - void AllDemuxed (); - inline stream_kind Kind () - { - return kind; - } - inline int BufferMin () - { - return buffer_min; - } - inline int BufferMax () - { - return buffer_max; - } - inline clockticks RequiredDTS () - { - return au->DTS + timestamp_delay; - }; - inline clockticks RequiredPTS () - { - return au->PTS + timestamp_delay; - }; - inline clockticks NextRequiredDTS () - { - Aunit *next = Lookahead (); - - if (next != 0) - return next->DTS + timestamp_delay; - else - return 0; - }; - inline clockticks NextRequiredPTS () - { - Aunit *next = Lookahead (); - - if (next != 0) - return next->PTS + timestamp_delay; - else - return 0; - }; - - void UpdateBufferMinMax (); - - void SetSyncOffset (clockticks timestamp_delay); - - - inline bool BuffersInHeader () - { - return buffers_in_header; - } - virtual unsigned int NominalBitRate () = 0; - virtual bool RunOutComplete () = 0; - virtual void OutputSector () = 0; - - virtual unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read); - - -protected: - virtual void FillAUbuffer (unsigned int frames_to_buffer) = 0; - virtual void InitAUbuffer () = 0; - virtual bool AUBufferNeedsRefill () = 0; - AUStream aunits; - void Muxed (unsigned int bytes_muxed); - -public: // TODO should go protected once encapsulation complete - // N.b. currently length=0 is used to indicate an ended - // stream. - // au itself should simply disappear - Aunit * au; - clockticks timestamp_delay; - -protected: - unsigned int au_unsent; - Aunit *next (); - - OutputStream & muxinto; - stream_kind kind; - int buffer_min; - int buffer_max; - int FRAME_CHUNK; - -}; - - - -#endif // __INPUTSTRM_H__ - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/lpcmstrm_in.cc b/ext/mplex/lpcmstrm_in.cc deleted file mode 100644 index a7e0c32..0000000 --- a/ext/mplex/lpcmstrm_in.cc +++ /dev/null @@ -1,304 +0,0 @@ -/* - * lpcmstrm_in.c: LPCM Audio strem class members handling scanning and - * buffering raw input stream. - * - * Copyright (C) 2001 Andrew Stevens - * Copyright (C) 2000,2001 Brent Byeler for original header-structure - * parsing code. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include -#include - -#include "audiostrm.hh" -#include "outputstream.hh" -#include - - - - -LPCMStream::LPCMStream (IBitStream & ibs, OutputStream & into): -AudioStream (ibs, into) -{ -} - -bool LPCMStream::Probe (IBitStream & bs) -{ - return true; -} - - -/************************************************************************* - * - * Reads initial stream parameters and displays feedback banner to users - * - *************************************************************************/ - - -void -LPCMStream::Init (const int stream_num) -{ - - MuxStream::Init (PRIVATE_STR_1, 1, // Buffer scale - default_buffer_size, - muxinto.vcd_zero_stuffing, - muxinto.buffers_in_audio, muxinto.always_buffers_in_audio); - mjpeg_info ("Scanning for header info: LPCM Audio stream %02x", stream_num); - - InitAUbuffer (); - - AU_start = bs.bitcount (); - - // This is a dummy debug version that simply assumes 48kHz - // two channel 16 bit sample LPCM - samples_per_second = 48000; - channels = 2; - bits_per_sample = 16; - bytes_per_frame = - samples_per_second * channels * bits_per_sample / 8 * ticks_per_frame_90kHz / 90000; - frame_index = 0; - dynamic_range_code = 0x80; - - /* Presentation/decoding time-stamping */ - access_unit.start = AU_start; - access_unit.length = bytes_per_frame; - access_unit.PTS = static_cast < clockticks > (decoding_order) * - (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz); - access_unit.DTS = access_unit.PTS; - access_unit.dorder = decoding_order; - decoding_order++; - aunits.append (access_unit); - - OutputHdrInfo (); -} - -unsigned int -LPCMStream::NominalBitRate () -{ - return samples_per_second * channels * bits_per_sample; -} - - - -void -LPCMStream::FillAUbuffer (unsigned int frames_to_buffer) -{ - last_buffered_AU += frames_to_buffer; - mjpeg_debug ("Scanning %d MPEG LPCM audio frames to frame %d", - frames_to_buffer, last_buffered_AU); - - static int header_skip = 0; // Initially skipped past 5 bytes of header - int skip; - bool bad_last_frame = false; - - while (!bs.eos () && - decoding_order < last_buffered_AU) { - skip = access_unit.length - header_skip; - mjpeg_debug ("Buffering frame %d (%d bytes)\n", decoding_order - 1, skip); - if (skip & 0x1) - bs.getbits (8); - if (skip & 0x2) - bs.getbits (16); - skip = skip >> 2; - - for (int i = 0; i < skip; i++) { - bs.getbits (32); - } - - prev_offset = AU_start; - AU_start = bs.bitcount (); - if (AU_start - prev_offset != access_unit.length * 8) { - bad_last_frame = true; - break; - } - // Here we would check for header data but LPCM has no headers... - if (bs.eos ()) - break; - - access_unit.start = AU_start; - access_unit.length = bytes_per_frame; - access_unit.PTS = static_cast < clockticks > (decoding_order) * - (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz); - access_unit.DTS = access_unit.PTS; - access_unit.dorder = decoding_order; - decoding_order++; - aunits.append (access_unit); - num_frames[0]++; - - num_syncword++; - - if (num_syncword >= old_frames + 10) { - mjpeg_debug ("Got %d frame headers.", num_syncword); - old_frames = num_syncword; - } - mjpeg_debug ("Got frame %d\n", decoding_order); - - } - if (bad_last_frame) { - mjpeg_error_exit1 ("Last LPCM frame ended prematurely!\n"); - } - last_buffered_AU = decoding_order; - eoscan = bs.eos (); - -} - - - -void -LPCMStream::Close () -{ - stream_length = AU_start / 8; - mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); - mjpeg_info ("Audio stream length %d bytes.", (int)stream_length); - mjpeg_info ("Frames : %8u ", num_frames[0]); - bs.close (); -} - -/************************************************************************* - OutputAudioInfo - gibt gesammelte Informationen zu den Audio Access Units aus. - - Prints information on audio access units -*************************************************************************/ - -void -LPCMStream::OutputHdrInfo () -{ - mjpeg_info ("LPCM AUDIO STREAM:"); - - mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)", - NominalBitRate () / 8, NominalBitRate ()); - mjpeg_info ("Channels : %d\n", channels); - mjpeg_info ("Bits per sample: %d\n", bits_per_sample); - mjpeg_info ("Frequency : %d Hz", samples_per_second); - -} - - -unsigned int -LPCMStream::ReadPacketPayload (uint8_t * dst, unsigned int to_read) -{ - unsigned int header_size = LPCMStream::StreamHeaderSize (); - unsigned int bytes_read = bs.read_buffered_bytes (dst + header_size, - to_read - header_size); - clockticks decode_time; - bool starting_frame_found = false; - uint8_t starting_frame_index = 0; - - int starting_frame_offset = (new_au_next_sec || au_unsent > bytes_read) - ? 0 : au_unsent; - - unsigned int frames = 0; - unsigned int bytes_muxed = bytes_read; - - if (bytes_muxed == 0 || MuxCompleted ()) { - goto completion; - } - - - /* Work through what's left of the current frames and the - following frames's updating the info until we reach a point where - an frame had to be split between packets. - - The DTS/PTS field for the packet in this case would have been - given the that for the first AU to start in the packet. - - */ - - decode_time = RequiredDTS (); - while (au_unsent < bytes_muxed) { - assert (bytes_muxed > 1); - bufmodel.Queued (au_unsent, decode_time); - bytes_muxed -= au_unsent; - if (new_au_next_sec) { - ++frames; - if (!starting_frame_found) { - starting_frame_index = static_cast < uint8_t > (au->dorder % 20); - starting_frame_found = true; - } - } - if (!NextAU ()) { - goto completion; - } - new_au_next_sec = true; - decode_time = RequiredDTS (); - }; - - // We've now reached a point where the current AU overran or - // fitted exactly. We need to distinguish the latter case so we - // can record whether the next packet starts with the tail end of - // // an already started frame or a new one. We need this info to - // decide what PTS/DTS info to write at the start of the next - // packet. - - if (au_unsent > bytes_muxed) { - if (new_au_next_sec) - ++frames; - bufmodel.Queued (bytes_muxed, decode_time); - au_unsent -= bytes_muxed; - new_au_next_sec = false; - } else // if (au_unsent == bytes_muxed) - { - bufmodel.Queued (bytes_muxed, decode_time); - if (new_au_next_sec) - ++frames; - new_au_next_sec = NextAU (); - } -completion: - // Generate the LPCM header... - // Note the index counts from the low byte of the offset so - // the smallest value is 1! - dst[0] = LPCM_SUB_STR_0 + stream_num; - dst[1] = frames; - dst[2] = (starting_frame_offset + 1) >> 8; - dst[3] = (starting_frame_offset + 1) & 0xff; - unsigned int bps_code; - - switch (bits_per_sample) { - case 16: - bps_code = 0; - break; - case 20: - bps_code = 1; - break; - case 24: - bps_code = 2; - break; - default: - bps_code = 3; - break; - } - dst[4] = starting_frame_index; - unsigned int bsf_code = (samples_per_second == 48000) ? 0 : 1; - unsigned int channels_code = channels - 1; - - dst[5] = (bps_code << 6) | (bsf_code << 4) | channels_code; - dst[6] = dynamic_range_code; - return bytes_read + header_size; -} - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/mjpeg_logging.cc b/ext/mplex/mjpeg_logging.cc deleted file mode 100644 index db4b0c0..0000000 --- a/ext/mplex/mjpeg_logging.cc +++ /dev/null @@ -1,239 +0,0 @@ -/* - $Id$ - - Copyright (C) 2000 Herbert Valerio Riedel - - 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 -*/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include - -extern int fred; - -#include "mjpeg_logging.h" - -static const char _rcsid[] = "$Id: "; - -#define MAX_DEFAULT_ID_SIZE 16 -#define DEFAULT_DEFAULT_ID "???" - -#ifdef HAVE___PROGNAME -extern const char *__progname; -#endif - -static log_level_t mjpeg_log_verbosity = (log_level_t) 0; -static char default_handler_id[MAX_DEFAULT_ID_SIZE]; -static char default_handler_id_is_set = 0; - -static int -default_mjpeg_log_filter (log_level_t level) -{ - int verb_from_env; - - if (mjpeg_log_verbosity == 0) { - char *mjpeg_verb_env = getenv ("MJPEG_VERBOSITY"); - - if (mjpeg_verb_env != NULL) { - verb_from_env = LOG_WARN - atoi (mjpeg_verb_env); - if (verb_from_env >= LOG_DEBUG && verb_from_env <= LOG_ERROR) - mjpeg_log_verbosity = (log_level_t) verb_from_env; - } - } - return (level < LOG_WARN && level < mjpeg_log_verbosity); -} - -static mjpeg_log_filter_t _filter = default_mjpeg_log_filter; - -static void -default_mjpeg_log_handler (log_level_t level, const char message[]) -{ - const char *ids; - - if ((*_filter) (level)) - return; - if (default_handler_id_is_set) { - ids = default_handler_id; - } else { -#ifdef HAVE___PROGNAME - ids = __progname; -#else - ids = DEFAULT_DEFAULT_ID; -#endif - } - switch (level) { - case LOG_ERROR: - fprintf (stderr, "**ERROR: [%s] %s\n", ids, message); - break; - case LOG_DEBUG: - fprintf (stderr, "--DEBUG: [%s] %s\n", ids, message); - break; - case LOG_WARN: - fprintf (stderr, "++ WARN: [%s] %s\n", ids, message); - break; - case LOG_INFO: - fprintf (stderr, " INFO: [%s] %s\n", ids, message); - break; - default: - assert (0); - } -} - -static mjpeg_log_handler_t _handler = default_mjpeg_log_handler; - - -mjpeg_log_handler_t -mjpeg_log_set_handler (mjpeg_log_handler_t new_handler) -{ - mjpeg_log_handler_t old_handler = _handler; - - _handler = new_handler; - - return old_handler; -} - -/*************** - * - * Set default log handlers degree of verboseity. - * 0 = quiet, 1 = info, 2 = debug - * - *************/ - -int -mjpeg_default_handler_verbosity (int verbosity) -{ - int prev_verb = mjpeg_log_verbosity; - - mjpeg_log_verbosity = (log_level_t) (LOG_WARN - (log_level_t) verbosity); - return prev_verb; -} - -/* - * Set identifier string used by default handler - * - */ -int -mjpeg_default_handler_identifier (const char *new_id) -{ - const char *s; - - if (new_id == NULL) { - default_handler_id_is_set = 0; - return 0; - } - /* find basename of new_id (remove any directory prefix) */ - if ((s = strrchr (new_id, '/')) == NULL) - s = new_id; - else - s = s + 1; - strncpy (default_handler_id, s, MAX_DEFAULT_ID_SIZE); - default_handler_id[MAX_DEFAULT_ID_SIZE - 1] = '\0'; - default_handler_id_is_set = 1; - return 0; -} - - -static void -mjpeg_logv (log_level_t level, const char format[], va_list args) -{ - char buf[1024] = { 0, }; - - /* TODO: Original had a re-entrancy error trap to assist bug - finding. To make this work with multi-threaded applications a - lock is needed hence delete. - */ - - - vsnprintf (buf, sizeof (buf) - 1, format, args); - - _handler (level, buf); -} - -void -mjpeg_log (log_level_t level, const char format[], ...) -{ - va_list args; - - va_start (args, format); - mjpeg_logv (level, format, args); - va_end (args); -} - -void -mjpeg_debug (const char format[], ...) -{ - va_list args; - - va_start (args, format); - mjpeg_logv (LOG_DEBUG, format, args); - va_end (args); -} - -void -mjpeg_info (const char format[], ...) -{ - va_list args; - - va_start (args, format); - mjpeg_logv (LOG_INFO, format, args); - va_end (args); -} - -void -mjpeg_warn (const char format[], ...) -{ - va_list args; - - va_start (args, format); - mjpeg_logv (LOG_WARN, format, args); - va_end (args); -} - -void -mjpeg_error (const char format[], ...) -{ - va_list args; - - va_start (args, format); - mjpeg_logv (LOG_ERROR, format, args); - va_end (args); -} - -void -mjpeg_error_exit1 (const char format[], ...) -{ - va_list args; - - va_start (args, format); - mjpeg_logv (LOG_ERROR, format, args); - va_end (args); - exit (EXIT_FAILURE); -} - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/mjpeg_logging.h b/ext/mplex/mjpeg_logging.h deleted file mode 100644 index 3028f89..0000000 --- a/ext/mplex/mjpeg_logging.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - $Id$ - - Copyright (C) 2000 Herbert Valerio Riedel - - 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 __MJPEG_LOGGING_H__ -#define __MJPEG_LOGGING_H__ - -#include "mjpeg_types.h" - -typedef enum { - LOG_DEBUG = 1, - LOG_INFO, - LOG_WARN, - LOG_ERROR -} log_level_t; - -#ifdef __cplusplus -extern "C" { -#endif -void -mjpeg_log(log_level_t level, const char format[], ...) GNUC_PRINTF(2, 3); - -typedef int(*mjpeg_log_filter_t)(log_level_t level); - -typedef void(*mjpeg_log_handler_t)(log_level_t level, const char message[]); - -mjpeg_log_handler_t -mjpeg_log_set_handler(mjpeg_log_handler_t new_handler); - -int -mjpeg_default_handler_identifier(const char *new_id); - -int -mjpeg_default_handler_verbosity(int verbosity); - -void -mjpeg_debug(const char format[], ...) GNUC_PRINTF(1,2); - -void -mjpeg_info(const char format[], ...) GNUC_PRINTF(1,2); - -void -mjpeg_warn(const char format[], ...) GNUC_PRINTF(1,2); - -void -mjpeg_error(const char format[], ...) GNUC_PRINTF(1,2); - -void -mjpeg_error_exit1(const char format[], ...) GNUC_PRINTF(1,2); - -#ifdef __cplusplus -} -#endif -#endif /* __MJPEG_LOGGING_H__ */ - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/mjpeg_types.h b/ext/mplex/mjpeg_types.h deleted file mode 100644 index 21edb9a..0000000 --- a/ext/mplex/mjpeg_types.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - $Id$ - - Copyright (C) 2000 Herbert Valerio Riedel - - 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 __MJPEG_TYPES_H__ -#define __MJPEG_TYPES_H__ -//#include - -#if defined(HAVE_STDINT_H) -# include -#elif defined(HAVE_INTTYPES_H) -# include -#elif defined(__CYGWIN__) -# include -typedef u_int8_t uint8_t; -typedef u_int16_t uint16_t; -typedef u_int32_t uint32_t; -typedef u_int64_t uint64_t; -# define INT8_C(c) c -# define INT16_C(c) c -# define INT32_C(c) c -# define INT64_C(c) c ## LL -# define UINT8_C(c) c ## U -# define UINT16_C(c) c ## U -# define UINT32_C(c) c ## U -# define UINT64_C(c) c ## ULL -#else -/* warning ISO/IEC 9899:1999 was missing and even */ -/* fixme */ -/* (Ronald) we'll just give an error now...Better solutions might come later */ -#error You don't seem to have sys/types.h, inttypes.h or stdint.h! \ -This might mean two things: \ -Either you really don't have them, in which case you should \ -install the system headers and/or C-library headers. \ -You might also have forgotten to define whether you have them. \ -You can do this by either defining their presence before including \ -mjpegtools' header files (e.g. "#define HAVE_STDINT_H"), or you can check \ -for their presence in a configure script. mjpegtools' configure \ -script is a good example of how to do this. You need to check for \ -PRId64, stdbool.h, inttypes.h, stdint.h and sys/types.h -#endif /* HAVE_STDINT_H */ - -#if defined(__FreeBSD__) -#include /* FreeBSD - ssize_t */ -#endif - -#if defined(HAVE_STDBOOL_H) && !defined(__cplusplus) -#include -#else -/* ISO/IEC 9899:1999 missing -- enabling workaround */ - -# ifndef __cplusplus -typedef enum - { - false = 0, - true = 1 - } locBool; - -# define false false -# define true true -# define bool locBool -# endif -#endif - -#ifndef PRId64 -#define PRId64 PRID64_STRING_FORMAT -#endif - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) -#define GNUC_PRINTF( format_idx, arg_idx ) \ - __attribute__((format (printf, format_idx, arg_idx))) -#define GNUC_SCANF( format_idx, arg_idx ) \ - __attribute__((format (scanf, format_idx, arg_idx))) -#define GNUC_FORMAT( arg_idx ) \ - __attribute__((format_arg (arg_idx))) -#define GNUC_NORETURN \ - __attribute__((noreturn)) -#define GNUC_CONST \ - __attribute__((const)) -#define GNUC_UNUSED \ - __attribute__((unused)) -#define GNUC_PACKED \ - __attribute__((packed)) -#else /* !__GNUC__ */ -#define GNUC_PRINTF( format_idx, arg_idx ) -#define GNUC_SCANF( format_idx, arg_idx ) -#define GNUC_FORMAT( arg_idx ) -#define GNUC_NORETURN -#define GNUC_CONST -#define GNUC_UNUSED -#define GNUC_PACKED -#endif /* !__GNUC__ */ - - -#endif /* __MJPEG_TYPES_H__ */ - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/mpastrm_in.cc b/ext/mplex/mpastrm_in.cc deleted file mode 100644 index 0d085b8..0000000 --- a/ext/mplex/mpastrm_in.cc +++ /dev/null @@ -1,329 +0,0 @@ -/* - * audiostrm_in.c: MPEG Audio strem class members handling scanning - * and buffering raw input stream. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include - -#include "audiostrm.hh" -#include "outputstream.hh" - - -static const char *mpa_audio_version[4] = { - "2.5", - "2.0", - "reserved", - "1.0" -}; - -static const unsigned int mpa_bitrates_kbps[4][3][16] = { - { /* MPEG audio V2.5 */ - {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0} - }, - { /*RESERVED*/ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - }, - { /* MPEG audio V2 */ - {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0} - }, - { /* MPEG audio V1 */ - {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0}, - {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, - {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0} - } - -}; - - -static const int mpa_freq_table[4][4] = { - /* MPEG audio V2.5 */ - {11025, 12000, 8000, 0}, - /* RESERVED */ - {0, 0, 0, 0}, - /* MPEG audio V2 */ - {22050, 24000, 16000, 0}, - /* MPEG audio V1 */ - {44100, 48000, 32000, 0} -}; - -static const char mpa_stereo_mode[4][15] = - { "stereo", "joint stereo", "dual channel", "single channel" }; -static const char mpa_copyright_status[2][20] = { "no copyright", "copyright protected" }; -static const char mpa_original_bit[2][10] = { "copy", "original" }; -static const char mpa_emphasis_mode[4][20] = - { "none", "50/15 microseconds", "reserved", "CCITT J.17" }; -static const unsigned int mpa_slots[4] = { 12, 144, 144, 0 }; -static const unsigned int mpa_samples[4] = { 384, 1152, 1152, 0 }; - - - -MPAStream::MPAStream (IBitStream & ibs, OutputStream & into): -AudioStream (ibs, into) -{ -} - -bool -MPAStream::Probe (IBitStream & bs) -{ - return bs.getbits (11) == AUDIO_SYNCWORD; -} - - -/************************************************************************* - * - * Reads initial stream parameters and displays feedback banner to users - * - *************************************************************************/ - - -void -MPAStream::Init (const int stream_num) -{ - int padding_bit; - - MuxStream::Init (AUDIO_STR_0 + stream_num, 0, // Buffer scale - muxinto.audio_buffer_size, - muxinto.vcd_zero_stuffing, - muxinto.buffers_in_audio, muxinto.always_buffers_in_audio); - mjpeg_info ("Scanning for header info: Audio stream %02x", AUDIO_STR_0 + stream_num); - - InitAUbuffer (); - - /* A.Stevens 2000 - update to be compatible up to MPEG2.5 - */ - AU_start = bs.bitcount (); - if (bs.getbits (11) == AUDIO_SYNCWORD) { - num_syncword++; - version_id = bs.getbits (2); - layer = 3 - bs.getbits (2); /* 0..2 not 1..3!! */ - protection = bs.get1bit (); - bit_rate_code = bs.getbits (4); - frequency = bs.getbits (2); - padding_bit = bs.get1bit (); - bs.get1bit (); - mode = bs.getbits (2); - mode_extension = bs.getbits (2); - copyright = bs.get1bit (); - original_copy = bs.get1bit (); - emphasis = bs.getbits (2); - - framesize = - mpa_bitrates_kbps[version_id][layer][bit_rate_code] * - mpa_slots[layer] * 1000 / mpa_freq_table[version_id][frequency]; - - size_frames[0] = framesize; - size_frames[1] = framesize + (layer == 0 ? 4 : 1); - num_frames[padding_bit]++; - access_unit.start = AU_start; - access_unit.length = size_frames[padding_bit]; - - samples_per_second = mpa_freq_table[version_id][frequency]; - - /* Presentation time-stamping */ - access_unit.PTS = static_cast < clockticks > (decoding_order) * - static_cast < clockticks > (mpa_samples[layer]) * - static_cast < clockticks > (CLOCKS) / samples_per_second; - access_unit.DTS = access_unit.PTS; - access_unit.dorder = decoding_order; - ++decoding_order; - aunits.append (access_unit); - - } else { - mjpeg_error ("Invalid MPEG Audio stream header."); - exit (1); - } - - - OutputHdrInfo (); -} - -unsigned int -MPAStream::NominalBitRate () -{ - return mpa_bitrates_kbps[version_id][layer][bit_rate_code] * 128; -} - - -unsigned int -MPAStream::SizeFrame (int rate_code, int padding) -{ - return mpa_bitrates_kbps[version_id][layer][rate_code] * - mpa_slots[layer] * 1000 / mpa_freq_table[version_id][frequency] + padding; -} - -void -MPAStream::FillAUbuffer (unsigned int frames_to_buffer) -{ - unsigned int i; - unsigned int padding_bit; - - last_buffered_AU += frames_to_buffer; - - mjpeg_debug ("Scanning %d MPEG audio frames to frame %d", frames_to_buffer, last_buffered_AU); - - while (!bs.eos () && - decoding_order < last_buffered_AU) { - - skip = access_unit.length - 4; - if (skip & 0x1) - bs.getbits (8); - if (skip & 0x2) - bs.getbits (16); - skip = skip >> 2; - - for (i = 0; i < skip; i++) { - bs.getbits (32); - } - prev_offset = AU_start; - AU_start = bs.bitcount (); - - /* Check we have reached the end of have another catenated - stream to process before finishing ... */ - if ((syncword = bs.getbits (11)) != AUDIO_SYNCWORD) { - if (!bs.eobs) { - /* There appears to be another catenated stream... */ - int next; - - mjpeg_warn ("End of component bit-stream ... seeking next"); - /* Catenated stream must start on byte boundary */ - syncword = (syncword << (8 - AU_start % 8)); - next = bs.getbits (8 - (AU_start % 8)); - AU_start = bs.bitcount () - 11; - syncword = syncword | next; - if (syncword != AUDIO_SYNCWORD) { - mjpeg_warn ("Failed to find start of next stream at %d prev %d !", (int) AU_start / 8, - (int)prev_offset / 8); - break; - } - } else - /* No catenated stream... finished! */ - break; - } - // Skip version_id:2, layer:2, protection:1 - (void) bs.getbits (5); - int rate_code = bs.getbits (4); - - // Skip frequency - (void) bs.getbits (2); - - padding_bit = bs.get1bit (); - access_unit.start = AU_start; - access_unit.length = SizeFrame (rate_code, padding_bit); - access_unit.PTS = - static_cast < clockticks > (decoding_order) * static_cast < clockticks > - (mpa_samples[layer]) * static_cast < clockticks > (CLOCKS) - / samples_per_second; - access_unit.DTS = access_unit.PTS; - access_unit.dorder = decoding_order; - decoding_order++; - aunits.append (access_unit); - num_frames[padding_bit]++; - - bs.getbits (9); - - num_syncword++; - - if (num_syncword >= old_frames + 10) { - mjpeg_debug ("Got %d frame headers.", num_syncword); - old_frames = num_syncword; - - } - - - - } - last_buffered_AU = decoding_order; - eoscan = bs.eos (); - -} - - - -void -MPAStream::Close () -{ - stream_length = AU_start >> 3; - mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); - mjpeg_info ("Audio stream length %d bytes.", (int)stream_length); - mjpeg_info ("Syncwords : %8u", num_syncword); - mjpeg_info ("Frames : %8u padded", num_frames[0]); - mjpeg_info ("Frames : %8u unpadded", num_frames[1]); - - bs.close (); -} - -/************************************************************************* - OutputAudioInfo - gibt gesammelte Informationen zu den Audio Access Units aus. - - Prints information on audio access units -*************************************************************************/ - -void -MPAStream::OutputHdrInfo () -{ - unsigned int bitrate; - - bitrate = mpa_bitrates_kbps[version_id][layer][bit_rate_code]; - - - mjpeg_info ("AUDIO STREAM:"); - mjpeg_info ("Audio version : %s", mpa_audio_version[version_id]); - mjpeg_info ("Layer : %8u", layer + 1); - - if (protection == 0) - mjpeg_info ("CRC checksums : yes"); - else - mjpeg_info ("CRC checksums : no"); - - if (bit_rate_code == 0) - mjpeg_info ("Bit rate : free"); - else if (bit_rate_code == 0xf) - mjpeg_info ("Bit rate : reserved"); - else - mjpeg_info ("Bit rate : %8u bytes/sec (%3u kbit/sec)", bitrate * 128, bitrate); - - if (frequency == 3) - mjpeg_info ("Frequency : reserved"); - else - mjpeg_info ("Frequency : %d Hz", mpa_freq_table[version_id][frequency]); - - mjpeg_info ("Mode : %8u %s", mode, mpa_stereo_mode[mode]); - mjpeg_info ("Mode extension : %8u", mode_extension); - mjpeg_info ("Copyright bit : %8u %s", copyright, mpa_copyright_status[copyright]); - mjpeg_info ("Original/Copy : %8u %s", original_copy, mpa_original_bit[original_copy]); - mjpeg_info ("Emphasis : %8u %s", emphasis, mpa_emphasis_mode[emphasis]); -} - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/mpegconsts.cc b/ext/mplex/mpegconsts.cc deleted file mode 100644 index 2265da3..0000000 --- a/ext/mplex/mpegconsts.cc +++ /dev/null @@ -1,427 +0,0 @@ - -/* - * mpegconsts.c: Video format constants for MPEG and utilities for display - * and conversion to format used for yuv4mpeg - * - * Copyright (C) 2001 Andrew Stevens - * Copyright (C) 2001 Matthew Marjanovic - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - -#include -#include "mpegconsts.h" -#include "yuv4mpeg.h" -#include "yuv4mpeg_intern.h" - -static y4m_ratio_t mpeg_framerates[] = { - Y4M_FPS_UNKNOWN, - Y4M_FPS_NTSC_FILM, - Y4M_FPS_FILM, - Y4M_FPS_PAL, - Y4M_FPS_NTSC, - Y4M_FPS_30, - Y4M_FPS_PAL_FIELD, - Y4M_FPS_NTSC_FIELD, - Y4M_FPS_60 -}; - - -#define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0])) -const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES; - -static const char *framerate_definitions[MPEG_NUM_RATES] = { - "illegal", - "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)", - "24.0 (NATIVE FILM)", - "25.0 (PAL/SECAM VIDEO / converted FILM)", - "30000.0/1001.0 (NTSC VIDEO)", - "30.0", - "50.0 (PAL FIELD RATE)", - "60000.0/1001.0 (NTSC FIELD RATE)", - "60.0" -}; - - -static const char *mpeg1_aspect_ratio_definitions[] = { - "1:1 (square pixels)", - "1:0.6735", - "1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)", - "1:0.7615", - "1:0.8055", - "1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)", - "1:0.8935", - "1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)", - "1:0.9815", - "1:1.0255", - "1:1:0695", - "1:1.1250 (4:3 NTSC for 720x480/352x240 images)", - "1:1.1575", - "1:1.2015" -}; - -static const y4m_ratio_t mpeg1_aspect_ratios[] = { - Y4M_SAR_MPEG1_1, - Y4M_SAR_MPEG1_2, - Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */ - Y4M_SAR_MPEG1_4, - Y4M_SAR_MPEG1_5, - Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */ - Y4M_SAR_MPEG1_7, - Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */ - Y4M_SAR_MPEG1_9, - Y4M_SAR_MPEG1_10, - Y4M_SAR_MPEG1_11, - Y4M_SAR_MPEG1_12, /* NTSC 4:3 */ - Y4M_SAR_MPEG1_13, - Y4M_SAR_MPEG1_14, -}; - -static const char *mpeg2_aspect_ratio_definitions[] = { - "1:1 pixels", - "4:3 display", - "16:9 display", - "2.21:1 display" -}; - - -static const y4m_ratio_t mpeg2_aspect_ratios[] = { - Y4M_DAR_MPEG2_1, - Y4M_DAR_MPEG2_2, - Y4M_DAR_MPEG2_3, - Y4M_DAR_MPEG2_4 -}; - -static const char **aspect_ratio_definitions[2] = { - mpeg1_aspect_ratio_definitions, - mpeg2_aspect_ratio_definitions -}; - -static const y4m_ratio_t *mpeg_aspect_ratios[2] = { - mpeg1_aspect_ratios, - mpeg2_aspect_ratios -}; - -const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] = { - sizeof (mpeg1_aspect_ratios) / sizeof (mpeg1_aspect_ratios[0]), - sizeof (mpeg2_aspect_ratios) / sizeof (mpeg2_aspect_ratios[0]) -}; - -/* - * Convert MPEG frame-rate code to corresponding frame-rate - */ - -y4m_ratio_t -mpeg_framerate (mpeg_framerate_code_t code) -{ - if (code == 0 || code > mpeg_num_framerates) - return y4m_fps_UNKNOWN; - else - return mpeg_framerates[code]; -} - -/* - * Look-up MPEG frame rate code for a (exact) frame rate. - */ - - -mpeg_framerate_code_t -mpeg_framerate_code (y4m_ratio_t framerate) -{ - mpeg_framerate_code_t i; - - y4m_ratio_reduce (&framerate); - for (i = 1; i < mpeg_num_framerates; ++i) { - if (Y4M_RATIO_EQL (framerate, mpeg_framerates[i])) - return i; - } - return 0; -} - - -/* small enough to distinguish 1/1000 from 1/1001 */ -#define MPEG_FPS_TOLERANCE 0.0001 - - -y4m_ratio_t -mpeg_conform_framerate (double fps) -{ - mpeg_framerate_code_t i; - y4m_ratio_t result; - - /* try to match it to a standard frame rate */ - for (i = 1; i < mpeg_num_framerates; i++) { - double deviation = 1.0 - (Y4M_RATIO_DBL (mpeg_framerates[i]) / fps); - - if ((deviation > -MPEG_FPS_TOLERANCE) && (deviation < +MPEG_FPS_TOLERANCE)) - return mpeg_framerates[i]; - } - /* no luck? just turn it into a ratio (6 decimal place accuracy) */ - result.n = (int) ((fps * 1000000.0) + 0.5); - result.d = 1000000; - y4m_ratio_reduce (&result); - return result; -} - - - -/* - * Convert MPEG aspect-ratio code to corresponding aspect-ratio - */ - -y4m_ratio_t -mpeg_aspect_ratio (int mpeg_version, mpeg_aspect_code_t code) -{ - y4m_ratio_t ratio; - - if (mpeg_version < 1 || mpeg_version > 2) - return y4m_sar_UNKNOWN; - if (code == 0 || code > mpeg_num_aspect_ratios[mpeg_version - 1]) - return y4m_sar_UNKNOWN; - else { - ratio = mpeg_aspect_ratios[mpeg_version - 1][code - 1]; - y4m_ratio_reduce (&ratio); - return ratio; - } -} - -/* - * Look-up corresponding MPEG aspect ratio code given an exact aspect ratio. - * - * WARNING: The semantics of aspect ratio coding *changed* between - * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In - * MPEG2 it is the (far more sensible) aspect ratio of the eventual - * display. - * - */ - -mpeg_aspect_code_t -mpeg_frame_aspect_code (int mpeg_version, y4m_ratio_t aspect_ratio) -{ - mpeg_aspect_code_t i; - y4m_ratio_t red_ratio = aspect_ratio; - - y4m_ratio_reduce (&red_ratio); - if (mpeg_version < 1 || mpeg_version > 2) - return 0; - for (i = 1; i < mpeg_num_aspect_ratios[mpeg_version - 1]; ++i) { - y4m_ratio_t red_entry = mpeg_aspect_ratios[mpeg_version - 1][i - 1]; - - y4m_ratio_reduce (&red_entry); - if (Y4M_RATIO_EQL (red_entry, red_ratio)) - return i; - } - - return 0; - -} - - - -/* - * Guess the correct MPEG aspect ratio code, - * given the true sample aspect ratio and frame size of a video stream - * (and the MPEG version, 1 or 2). - * - * Returns 0 if it has no good guess. - * - */ - - -/* this is big enough to accommodate the difference between 720 and 704 */ -#define GUESS_ASPECT_TOLERANCE 0.03 - -mpeg_aspect_code_t -mpeg_guess_mpeg_aspect_code (int mpeg_version, y4m_ratio_t sampleaspect, - int frame_width, int frame_height) -{ - if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_UNKNOWN)) { - return 0; - } - switch (mpeg_version) { - case 1: - if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_SQUARE)) { - return 1; - } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_NTSC_CCIR601)) { - return 12; - } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_NTSC_16_9)) { - return 6; - } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_PAL_CCIR601)) { - return 8; - } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_PAL_16_9)) { - return 3; - } - return 0; - break; - case 2: - if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_SQUARE)) { - return 1; /* '1' means square *pixels* in MPEG-2; go figure. */ - } else { - unsigned int i; - double true_far; /* true frame aspect ratio */ - - true_far = - (double) (sampleaspect.n * frame_width) / (double) (sampleaspect.d * frame_height); - /* start at '2'... */ - for (i = 2; i < mpeg_num_aspect_ratios[mpeg_version - 1]; i++) { - double ratio = true_far / Y4M_RATIO_DBL (mpeg_aspect_ratios[mpeg_version - 1][i - 1]); - - if ((ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && (ratio < (1.0 + GUESS_ASPECT_TOLERANCE))) - return i; - } - return 0; - } - break; - default: - return 0; - break; - } -} - - - - -/* - * Guess the true sample aspect ratio of a video stream, - * given the MPEG aspect ratio code and the actual frame size - * (and the MPEG version, 1 or 2). - * - * Returns y4m_sar_UNKNOWN if it has no good guess. - * - */ -y4m_ratio_t -mpeg_guess_sample_aspect_ratio (int mpeg_version, - mpeg_aspect_code_t code, int frame_width, int frame_height) -{ - switch (mpeg_version) { - case 1: - /* MPEG-1 codes turn into SAR's, just not quite the right ones. - For the common/known values, we provide the ratio used in practice, - otherwise say we don't know. */ - switch (code) { - case 1: - return y4m_sar_SQUARE; - break; - case 3: - return y4m_sar_PAL_16_9; - break; - case 6: - return y4m_sar_NTSC_16_9; - break; - case 8: - return y4m_sar_PAL_CCIR601; - break; - case 12: - return y4m_sar_NTSC_CCIR601; - break; - default: - return y4m_sar_UNKNOWN; - break; - } - break; - case 2: - /* MPEG-2 codes turn into Frame Aspect Ratios, though not exactly the - FAR's used in practice. For common/standard frame sizes, we provide - the original SAR; otherwise, we say we don't know. */ - if (code == 1) { - return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */ - } else if ((code >= 2) && (code <= 4)) { - return y4m_guess_sar (frame_width, frame_height, mpeg2_aspect_ratios[code - 1]); - } else { - return y4m_sar_UNKNOWN; - } - break; - default: - return y4m_sar_UNKNOWN; - break; - } -} - - - - - -/* - * Look-up MPEG explanatory definition string for frame rate code - * - */ - - -const char * -mpeg_framerate_code_definition (mpeg_framerate_code_t code) -{ - if (code == 0 || code >= mpeg_num_framerates) - return "UNDEFINED: illegal/reserved frame-rate ratio code"; - - return framerate_definitions[code]; -} - -/* - * Look-up MPEG explanatory definition string aspect ratio code for an - * aspect ratio code - * - */ - -const char * -mpeg_aspect_code_definition (int mpeg_version, mpeg_aspect_code_t code) -{ - if (mpeg_version < 1 || mpeg_version > 2) - return "UNDEFINED: illegal MPEG version"; - - if (code < 1 || code > mpeg_num_aspect_ratios[mpeg_version - 1]) - return "UNDEFINED: illegal aspect ratio code"; - - return aspect_ratio_definitions[mpeg_version - 1][code - 1]; -} - - -/* - * Look-up explanatory definition of interlace field order code - * - */ - -const char * -mpeg_interlace_code_definition (int yuv4m_interlace_code) -{ - const char *def; - - switch (yuv4m_interlace_code) { - case Y4M_UNKNOWN: - def = "unknown"; - break; - case Y4M_ILACE_NONE: - def = "none/progressive"; - break; - case Y4M_ILACE_TOP_FIRST: - def = "top-field-first"; - break; - case Y4M_ILACE_BOTTOM_FIRST: - def = "bottom-field-first"; - break; - default: - def = "UNDEFINED: illegal video interlacing type-code!"; - break; - } - return def; -} - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/mpegconsts.h b/ext/mplex/mpegconsts.h deleted file mode 100644 index 461fd2d..0000000 --- a/ext/mplex/mpegconsts.h +++ /dev/null @@ -1,149 +0,0 @@ - -/* - * mpegconsts.c: Video format constants for MPEG and utilities for display - * and conversion to format used for yuv4mpeg - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __MPEGCONSTS_H__ -#define __MPEGCONSTS_H__ - - -#include "yuv4mpeg.h" - - -typedef unsigned int mpeg_framerate_code_t; -typedef unsigned int mpeg_aspect_code_t; - -extern const mpeg_framerate_code_t mpeg_num_framerates; -extern const mpeg_aspect_code_t mpeg_num_aspect_ratios[2]; - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Convert MPEG frame-rate code to corresponding frame-rate - * y4m_fps_UNKNOWN = { 0, 0 } = Undefined/resrerved code. - */ - -y4m_ratio_t -mpeg_framerate( mpeg_framerate_code_t code ); - - -/* - * Look-up MPEG frame rate code for a (exact) frame rate. - * 0 = No MPEG code defined for frame-rate - */ - -mpeg_framerate_code_t -mpeg_framerate_code( y4m_ratio_t framerate ); - - -/* - * Convert floating-point framerate to an exact ratio. - * Uses a standard MPEG rate, if it finds one within MPEG_FPS_TOLERANCE - * (see mpegconsts.c), otherwise uses "fps:1000000" as the ratio. - */ - -y4m_ratio_t -mpeg_conform_framerate( double fps ); - - -/* - * Convert MPEG aspect ratio code to corresponding aspect ratio - * - * WARNING: The semantics of aspect ratio coding *changed* between - * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In - * MPEG2 it is the (far more sensible) aspect ratio of the eventual - * display. - * - */ - -y4m_ratio_t -mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ); - -/* - * Look-up MPEG aspect ratio code for an aspect ratio - tolerance - * is Y4M_ASPECT_MULT used by YUV4MPEG (see yuv4mpeg_intern.h) - * - * WARNING: The semantics of aspect ratio coding *changed* between - * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In - * MPEG2 it is the (far more sensible) aspect ratio of the eventual - * display. - * - */ - -mpeg_aspect_code_t -mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ); - -/* - * Look-up MPEG explanatory definition string aspect ratio code for an - * aspect ratio code - * - */ - -const char * -mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ); - -/* - * Look-up MPEG explanatory definition string aspect ratio code for an - * frame rate code - * - */ - -const char * -mpeg_framerate_code_definition( mpeg_framerate_code_t code ); - -const char * -mpeg_interlace_code_definition( int yuv4m_interlace_code ); - - -/* - * Guess the correct MPEG aspect ratio code, - * given the true sample aspect ratio and frame size of a video stream - * (and the MPEG version, 1 or 2). - * - * Returns 0 if it has no good answer. - * - */ -mpeg_aspect_code_t -mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, - int frame_width, int frame_height); - -/* - * Guess the true sample aspect ratio of a video stream, - * given the MPEG aspect ratio code and the actual frame size - * (and the MPEG version, 1 or 2). - * - * Returns y4m_sar_UNKNOWN if it has no good answer. - * - */ -y4m_ratio_t -mpeg_guess_sample_aspect_ratio(int mpeg_version, - mpeg_aspect_code_t code, - int frame_width, int frame_height); - - -#ifdef __cplusplus -}; -#endif - - - -#endif /* __MPEGCONSTS_H__ */ diff --git a/ext/mplex/mplexconsts.hh b/ext/mplex/mplexconsts.hh deleted file mode 100644 index c3fe6ce..0000000 --- a/ext/mplex/mplexconsts.hh +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __MPLEXCONSTS_H__ -#define __MPLEXCONSTS_H__ - - -#define SEQUENCE_HEADER 0x000001b3 -#define SEQUENCE_END 0x000001b7 -#define PICTURE_START 0x00000100 -#define EXT_START_CODE 0x000001b5 -#define GROUP_START 0x000001b8 -#define SYNCWORD_START 0x000001 - -#define IFRAME 1 -#define PFRAME 2 -#define BFRAME 3 -#define DFRAME 4 -#define NOFRAME 5 - -#define PIC_TOP_FIELD 1 -#define PIC_BOT_FIELD 2 -#define PIC_FRAME 3 - -#define CODING_EXT_ID 8 -#define AUDIO_SYNCWORD 0x7ff - - -#define PACK_START 0x000001ba -#define SYS_HEADER_START 0x000001bb -#define ISO11172_END 0x000001b9 -#define PACKET_START 0x000001 - -#define MAX_FFFFFFFF 4294967295.0 /* = 0xffffffff in dec. */ - -#define CLOCKS_per_90Kth_sec 300 - -#define CLOCKS (CLOCKS_per_90Kth_sec*90000) -/* MPEG-2 System Clock Hertz - we divide down by 300.0 for MPEG-1*/ - -/* Range of sizes of the fields following the packet length field in packet header: - used to calculate if recieve buffers will have enough space... */ - -#define MPEG2_BUFFERINFO_LENGTH 3 -#define MPEG1_BUFFERINFO_LENGTH 2 -#define DTS_PTS_TIMESTAMP_LENGTH 5 -#define MPEG2_AFTER_PACKET_LENGTH_MIN 3 -#define MPEG1_AFTER_PACKET_LENGTH_MIN (0+1) - - /* Sector under-size below which header stuffing rather than padding packets - or post-packet zero stuffing is used. *Must* be less than 20 for VCD - multiplexing to work correctly! - */ - -#define MINIMUM_PADDING_PACKET_SIZE 10 - -#define PACKET_HEADER_SIZE 6 - -#define AUDIO_STREAMS 0xb8 /* Marker Audio Streams */ -#define VIDEO_STREAMS 0xb9 /* Marker Video Streams */ -#define AUDIO_STR_0 0xc0 /* Marker Audio Stream0 */ -#define VIDEO_STR_0 0xe0 /* Marker Video Stream0 */ -#define PADDING_STR 0xbe /* Marker Padding Stream */ -#define PRIVATE_STR_1 0xbd /* private stream 1 */ -#define PRIVATE_STR_2 0xbf /* private stream 2 */ -#define AC3_SUB_STR_0 0x80 /* AC3 substream id 0 */ - -#define LPCM_SUB_STR_0 0xa0 /* LPCM substream id 0 */ - -#define ZERO_STUFFING_BYTE 0 -#define STUFFING_BYTE 0xff -#define RESERVED_BYTE 0xff -#define TIMESTAMPBITS_NO 0 /* Flag NO timestamps */ -#define TIMESTAMPBITS_PTS 2 /* Flag PTS timestamp */ -#define TIMESTAMPBITS_DTS 1 /* Flag PTS timestamp */ -#define TIMESTAMPBITS_PTS_DTS (TIMESTAMPBITS_DTS|TIMESTAMPBITS_PTS) /* Flag BOTH timestamps */ - -#define MARKER_MPEG1_SCR 2 /* Marker SCR */ -#define MARKER_MPEG2_SCR 1 /* These don't need to be distinct! */ -#define MARKER_JUST_PTS 2 /* Marker only PTS */ -#define MARKER_PTS 3 /* Marker PTS */ -#define MARKER_DTS 1 /* Marker DTS */ -#define MARKER_NO_TIMESTAMPS 0x0f /* Marker NO timestamps */ - - -#endif // __MPLEXCONSTS_H__ diff --git a/ext/mplex/multplex.cc b/ext/mplex/multplex.cc deleted file mode 100644 index 10a49af..0000000 --- a/ext/mplex/multplex.cc +++ /dev/null @@ -1,1126 +0,0 @@ - -#include -#include -#include -#include - -#include -#include -#include - -#include "videostrm.hh" -#include "outputstream.hh" -#include -#include "glib.h" - - -/******************************************************************* - Find the timecode corresponding to given position in the system stream - (assuming the SCR starts at 0 at the beginning of the stream -@param bytepos byte position in the stream -@param ts returns the number of clockticks the bytepos is from the file start -****************************************************************** */ - -void -OutputStream::ByteposTimecode (bitcount_t bytepos, clockticks & ts) -{ - ts = (bytepos * CLOCKS) / static_cast < bitcount_t > (dmux_rate); -} - - -/********** - * - * UpdateSectorHeaders - Update the sector headers after a change in stream - * position / SCR - ********** - - ********** - * - * NextPosAndSCR - Update nominal (may be >= actual) byte count - * and SCR to next output sector. - * - ********/ - -void -OutputStream::NextPosAndSCR () -{ - bytes_output += sector_transport_size; - ByteposTimecode (bytes_output, current_SCR); - if (start_of_new_pack) { - psstrm->CreatePack (&pack_header, current_SCR, mux_rate); - pack_header_ptr = &pack_header; - if (include_sys_header) - sys_header_ptr = &sys_header; - else - sys_header_ptr = NULL; - - } else - pack_header_ptr = NULL; -} - - -/********** - * - * NextPosAndSCR - Update nominal (may be >= actual) byte count - * and SCR to next output sector. - * @param bytepos byte position in the stream - ********/ - -void -OutputStream::SetPosAndSCR (bitcount_t bytepos) -{ - bytes_output = bytepos; - ByteposTimecode (bytes_output, current_SCR); - if (start_of_new_pack) { - psstrm->CreatePack (&pack_header, current_SCR, mux_rate); - pack_header_ptr = &pack_header; - if (include_sys_header) - sys_header_ptr = &sys_header; - else - sys_header_ptr = NULL; - - } else - pack_header_ptr = NULL; -} - -/* - Stream syntax parameters. -*/ - - -/****************************************************************** - - Initialisation of stream syntax paramters based on selected - user options. -******************************************************************/ - - -// TODO: this mixes class member parameters with opt_ globals... - -void -OutputStream::InitSyntaxParameters () -{ - video_buffer_size = 0; - seg_starts_with_video = false; - audio_buffer_size = 4 * 1024; - - switch (opt_mux_format) { - case MPEG_FORMAT_VCD: - opt_data_rate = 75 * 2352; /* 75 raw CD sectors/sec */ - video_buffer_size = 46 * 1024; - opt_VBR = 0; - - case MPEG_FORMAT_VCD_NSR: /* VCD format, non-standard rate */ - mjpeg_info ("Selecting VCD output profile"); - if (video_buffer_size == 0) - video_buffer_size = opt_buffer_size * 1024; - vbr = opt_VBR; - opt_mpeg = 1; - packets_per_pack = 1; - sys_header_in_pack1 = 0; - always_sys_header_in_pack = 0; - sector_transport_size = 2352; /* Each 2352 bytes with 2324 bytes payload */ - transport_prefix_sectors = 30; - sector_size = 2324; - buffers_in_video = 1; - always_buffers_in_video = 0; - buffers_in_audio = 1; // This is needed as otherwise we have - always_buffers_in_audio = 1; // to stuff the packer header which - // must be 13 bytes for VCD audio - vcd_zero_stuffing = 20; // The famous 20 zero bytes for VCD - // audio sectors. - dtspts_for_all_vau = false; - sector_align_iframeAUs = false; - timestamp_iframe_only = false; - seg_starts_with_video = true; - break; - - case MPEG_FORMAT_MPEG2: - mjpeg_info ("Selecting generic MPEG2 output profile"); - opt_mpeg = 2; - packets_per_pack = 1; - sys_header_in_pack1 = 1; - always_sys_header_in_pack = 0; - sector_transport_size = 2048; /* Each 2352 bytes with 2324 bytes payload */ - transport_prefix_sectors = 0; - sector_size = 2048; - video_buffer_size = 234 * 1024; - buffers_in_video = 1; - always_buffers_in_video = 0; - buffers_in_audio = 1; - always_buffers_in_audio = 1; - vcd_zero_stuffing = 0; - dtspts_for_all_vau = 0; - sector_align_iframeAUs = false; - timestamp_iframe_only = false; - video_buffers_iframe_only = false; - vbr = opt_VBR; - break; - - case MPEG_FORMAT_SVCD: - opt_data_rate = 150 * 2324; - video_buffer_size = 230 * 1024; - - case MPEG_FORMAT_SVCD_NSR: /* Non-standard data-rate */ - mjpeg_info ("Selecting SVCD output profile"); - if (video_buffer_size == 0) - video_buffer_size = opt_buffer_size * 1024; - opt_mpeg = 2; - packets_per_pack = 1; - sys_header_in_pack1 = 0; - always_sys_header_in_pack = 0; - sector_transport_size = 2324; - transport_prefix_sectors = 0; - sector_size = 2324; - vbr = true; - buffers_in_video = 1; - always_buffers_in_video = 0; - buffers_in_audio = 1; - always_buffers_in_audio = 0; - vcd_zero_stuffing = 0; - dtspts_for_all_vau = 0; - sector_align_iframeAUs = true; - seg_starts_with_video = true; - timestamp_iframe_only = false; - video_buffers_iframe_only = false; - break; - - case MPEG_FORMAT_VCD_STILL: - opt_data_rate = 75 * 2352; /* 75 raw CD sectors/sec */ - vbr = false; - opt_mpeg = 1; - packets_per_pack = 1; - sys_header_in_pack1 = 0; - always_sys_header_in_pack = 0; - sector_transport_size = 2352; /* Each 2352 bytes with 2324 bytes payload */ - transport_prefix_sectors = 0; - sector_size = 2324; - buffers_in_video = 1; - always_buffers_in_video = 0; - buffers_in_audio = 1; - always_buffers_in_audio = 0; - vcd_zero_stuffing = 20; - dtspts_for_all_vau = 1; - sector_align_iframeAUs = true; - timestamp_iframe_only = false; - video_buffers_iframe_only = false; - if (opt_buffer_size == 0) - opt_buffer_size = 46; - else if (opt_buffer_size > 220) { - mjpeg_error_exit1 ("VCD stills has max. permissible video buffer size of 220KB"); - } else { - /* Add a margin for sequence header overheads for HR stills */ - /* So the user simply specifies the nominal size... */ - opt_buffer_size += 4; - } - video_buffer_size = opt_buffer_size * 1024; - break; - - case MPEG_FORMAT_SVCD_STILL: - mjpeg_info ("Selecting SVCD output profile"); - if (opt_data_rate == 0) - opt_data_rate = 150 * 2324; - video_buffer_size = 230 * 1024; - opt_mpeg = 2; - packets_per_pack = 1; - sys_header_in_pack1 = 0; - always_sys_header_in_pack = 0; - sector_transport_size = 2324; - transport_prefix_sectors = 0; - sector_size = 2324; - vbr = true; - buffers_in_video = 1; - always_buffers_in_video = 0; - buffers_in_audio = 1; - always_buffers_in_audio = 0; - vcd_zero_stuffing = 0; - dtspts_for_all_vau = 0; - sector_align_iframeAUs = true; - timestamp_iframe_only = false; - video_buffers_iframe_only = false; - break; - - case MPEG_FORMAT_DVD: - mjpeg_info ("Selecting DVD output profile (INCOMPLETE!!!!)"); - opt_data_rate = 1260000; - opt_mpeg = 2; - packets_per_pack = 1; - sys_header_in_pack1 = false; // Handle by control packets - always_sys_header_in_pack = false; - sector_transport_size = 2048; - transport_prefix_sectors = 0; - sector_size = 2048; - video_buffer_size = 232 * 1024; - buffers_in_video = true; - always_buffers_in_video = false; - buffers_in_audio = true; - always_buffers_in_audio = false; - vcd_zero_stuffing = 0; - dtspts_for_all_vau = 0; - sector_align_iframeAUs = true; - timestamp_iframe_only = true; - video_buffers_iframe_only = true; - vbr = true; - if (opt_max_segment_size == 0) - opt_max_segment_size = 2000 * 1024 * 1024; - break; - - default: /* MPEG_FORMAT_MPEG1 - auto format MPEG1 */ - mjpeg_info ("Selecting generic MPEG1 output profile"); - opt_mpeg = 1; - vbr = opt_VBR; - packets_per_pack = opt_packets_per_pack; - always_sys_header_in_pack = opt_always_system_headers; - sys_header_in_pack1 = 1; - sector_transport_size = opt_sector_size; - transport_prefix_sectors = 0; - sector_size = opt_sector_size; - if (opt_buffer_size == 0) { - opt_buffer_size = 46; - } - video_buffer_size = opt_buffer_size * 1024; - buffers_in_video = 1; - always_buffers_in_video = 1; - buffers_in_audio = 0; - always_buffers_in_audio = 1; - vcd_zero_stuffing = 0; - dtspts_for_all_vau = 0; - sector_align_iframeAUs = false; - timestamp_iframe_only = false; - video_buffers_iframe_only = false; - break; - } - -} - -/** - * Compute the number of run-in sectors needed to fill up the buffers to - * suit the type of stream being muxed. - * - * For stills we have to ensure an entire buffer is loaded as we only - * ever process one frame at a time. - * @returns the number of run-in sectors needed to fill up the buffers to suit the type of stream being muxed. - */ - -unsigned int -OutputStream::RunInSectors () -{ - vector < ElementaryStream * >::iterator str; - unsigned int sectors_delay = 1; - - for (str = vstreams.begin (); str < vstreams.end (); ++str) { - - if (MPEG_STILLS_FORMAT (opt_mux_format)) { - sectors_delay += (unsigned int) (1.02 * (*str)->BufferSize ()) / sector_size + 2; - } else if (vbr) - sectors_delay += 3 * (*str)->BufferSize () / (4 * sector_size); - else - sectors_delay += 5 * (*str)->BufferSize () / (6 * sector_size); - } - sectors_delay += astreams.size (); - return sectors_delay; -} - -/** - Initializes the output stream. Traverses the input files and calculates their payloads. - Estimates the multiplex rate. Estimates the neccessary stream delay for the different substreams. - */ - - -void -OutputStream::Init (vector < ElementaryStream * >*strms, PS_Stream *strm) -{ - vector < ElementaryStream * >::iterator str; - clockticks delay; - unsigned int sectors_delay; - - Pack_struc dummy_pack; - Sys_header_struc dummy_sys_header; - Sys_header_struc *sys_hdr; - unsigned int nominal_rate_sum; - - packets_left_in_pack = 0; /* Suppress warning */ - video_first = false; - - estreams = strms; - - for (str = estreams->begin (); str < estreams->end (); ++str) { - switch ((*str)->Kind ()) { - case ElementaryStream::audio: - astreams.push_back (*str); - break; - case ElementaryStream::video: - vstreams.push_back (*str); - break; - default: - break; - } - - completed.push_back (false); - } - - mjpeg_info ("SYSTEMS/PROGRAM stream:"); - this->psstrm = strm; - - psstrm->Init (opt_mpeg, sector_size, opt_max_segment_size); - - /* These are used to make (conservative) decisions - about whether a packet should fit into the recieve buffers... - Audio packets always have PTS fields, video packets needn'. - TODO: Really this should be encapsulated in Elementary stream...? - */ - psstrm->CreatePack (&dummy_pack, 0, mux_rate); - if (always_sys_header_in_pack) { - vector < MuxStream * >muxstreams; - AppendMuxStreamsOf (*estreams, muxstreams); - psstrm->CreateSysHeader (&dummy_sys_header, mux_rate, !vbr, 1, true, true, muxstreams); - sys_hdr = &dummy_sys_header; - } else - sys_hdr = NULL; - - nominal_rate_sum = 0; - for (str = estreams->begin (); str < estreams->end (); ++str) { - switch ((*str)->Kind ()) { - case ElementaryStream::audio: - (*str)->SetMaxPacketData (psstrm->PacketPayload (**str, NULL, NULL, - false, true, false)); - (*str)->SetMinPacketData (psstrm->PacketPayload (**str, sys_hdr, &dummy_pack, - always_buffers_in_audio, true, false)); - - break; - case ElementaryStream::video: - (*str)->SetMaxPacketData (psstrm->PacketPayload (**str, NULL, NULL, - false, false, false)); - (*str)->SetMinPacketData (psstrm->PacketPayload (**str, sys_hdr, &dummy_pack, - always_buffers_in_video, true, true)); - break; - default: - mjpeg_error_exit1 ("INTERNAL: Only audio and video payload calculations implemented!"); - - } - - if ((*str)->NominalBitRate () == 0 && opt_data_rate == 0) - mjpeg_error_exit1 - ("Variable bit-rate stream present: output stream (max) data-rate *must* be specified!"); - nominal_rate_sum += (*str)->NominalBitRate (); - - } - - /* Attempt to guess a sensible mux rate for the given video and * - audio estreams-> This is a rough and ready guess for MPEG-1 like - formats. */ - - - dmux_rate = static_cast < int >(1.015 * nominal_rate_sum); - - dmux_rate = (dmux_rate / 50 + 25) * 50; - - mjpeg_info ("rough-guess multiplexed stream data rate : %07d", dmux_rate * 8); - if (opt_data_rate != 0) - mjpeg_info ("target data-rate specified : %7d", opt_data_rate * 8); - - if (opt_data_rate == 0) { - mjpeg_info ("Setting best-guess data rate."); - } else if (opt_data_rate >= dmux_rate) { - mjpeg_info ("Setting specified specified data rate: %7d", opt_data_rate * 8); - dmux_rate = opt_data_rate; - } else if (opt_data_rate < dmux_rate) { - mjpeg_warn ("Target data rate lower than computed requirement!"); - mjpeg_warn ("N.b. a 20%% or so discrepancy in variable bit-rate"); - mjpeg_warn ("streams is common and harmless provided no time-outs will occur"); - dmux_rate = opt_data_rate; - } - - mux_rate = dmux_rate / 50; - - /* To avoid Buffer underflow, the DTS of the first video and audio AU's - must be offset sufficiently forward of the SCR to allow the buffer - time to fill before decoding starts. Calculate the necessary delays... - */ - - sectors_delay = RunInSectors (); - - ByteposTimecode (static_cast < bitcount_t > (sectors_delay * sector_transport_size), delay); - - - video_delay = delay + static_cast < clockticks > (opt_video_offset * CLOCKS / 1000); - audio_delay = delay + static_cast < clockticks > (opt_audio_offset * CLOCKS / 1000); - mjpeg_info ("Sectors = %d Video delay = %d Audio delay = %d", - sectors_delay, (int)video_delay / 300, (int)audio_delay / 300); - - - // - // Now that all mux parameters are set we can trigger parsing - // of actual input stream data and calculation of associated - // PTS/DTS by causing the read of the first AU's... - // - for (str = estreams->begin (); str < estreams->end (); ++str) { - (*str)->NextAU (); - } - - - // - // Now that we have both output and input streams initialised and - // data-rates set we can make a decent job of setting the maximum - // STD buffer delay in video streams. - // - - for (str = vstreams.begin (); str < vstreams.end (); ++str) { - static_cast < VideoStream * >(*str)->SetMaxStdBufferDelay (dmux_rate); - } - - - - /* Let's try to read in unit after unit and to write it out into - the outputstream. The only difficulty herein lies into the - buffer management, and into the fact the the actual access - unit *has* to arrive in time, that means the whole unit - (better yet, packet data), has to arrive before arrival of - DTS. If both buffers are full we'll generate a padding packet - - Of course, when we start we're starting a new segment with no - bytes output... - */ - - ByteposTimecode (sector_transport_size, ticks_per_sector); - seg_state = start_segment; - running_out = false; -} - -/** - Prints the current status of the substreams. - @param level the desired log level - */ -void -OutputStream::MuxStatus (log_level_t level) -{ - vector < ElementaryStream * >::iterator str; - for (str = estreams->begin (); str < estreams->end (); ++str) { - switch ((*str)->Kind ()) { - case ElementaryStream::video: - mjpeg_log (level, - "Video %02x: buf=%7d frame=%06d sector=%08d", - (*str)->stream_id, (*str)->bufmodel.Space (), (*str)->au->dorder, (*str)->nsec); - break; - case ElementaryStream::audio: - mjpeg_log (level, - "Audio %02x: buf=%7d frame=%06d sector=%08d", - (*str)->stream_id, (*str)->bufmodel.Space (), (*str)->au->dorder, (*str)->nsec); - break; - default: - mjpeg_log (level, - "Other %02x: buf=%7d sector=%08d", - (*str)->stream_id, (*str)->bufmodel.Space (), (*str)->nsec); - break; - } - } - if (!vbr) - mjpeg_log (level, "Padding : sector=%08d", pstrm.nsec); - - -} - - -/** - Append input substreams to the output multiplex stream. - */ -void -OutputStream::AppendMuxStreamsOf (vector < ElementaryStream * >&elem, vector < MuxStream * >&mux) -{ - vector < ElementaryStream * >::iterator str; - for (str = elem.begin (); str < elem.end (); ++str) { - mux.push_back (static_cast < MuxStream * >(*str)); - } -} - -/****************************************************************** - Program start-up packets. Generate any irregular packets -needed at the start of the stream... - Note: *must* leave a sensible in-stream system header in - sys_header. - TODO: get rid of this grotty sys_header global. -******************************************************************/ -void -OutputStream::OutputPrefix () -{ - vector < MuxStream * >vmux, amux, emux; - AppendMuxStreamsOf (vstreams, vmux); - AppendMuxStreamsOf (astreams, amux); - AppendMuxStreamsOf (*estreams, emux); - - /* Deal with transport padding */ - SetPosAndSCR (bytes_output + transport_prefix_sectors * sector_transport_size); - - /* VCD: Two padding packets with video and audio system headers */ - split_at_seq_end = !opt_multifile_segment; - - switch (opt_mux_format) { - case MPEG_FORMAT_VCD: - case MPEG_FORMAT_VCD_NSR: - - /* Annoyingly VCD generates seperate system headers for - audio and video ... DOH... */ - if (astreams.size () > 1 || vstreams.size () > 1 || - astreams.size () + vstreams.size () != estreams->size ()) { - mjpeg_error_exit1 ("VCD man only have max. 1 audio and 1 video stream"); - } - /* First packet carries video-info-only sys_header */ - psstrm->CreateSysHeader (&sys_header, mux_rate, false, true, true, true, vmux); - sys_header_ptr = &sys_header; - pack_header_ptr = &pack_header; - OutputPadding (false); - - /* Second packet carries audio-info-only sys_header */ - psstrm->CreateSysHeader (&sys_header, mux_rate, false, true, true, true, amux); - sys_header_ptr = &sys_header; - pack_header_ptr = &pack_header; - OutputPadding (true); - break; - - case MPEG_FORMAT_SVCD: - case MPEG_FORMAT_SVCD_NSR: - /* First packet carries sys_header */ - psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, true, true, true, emux); - sys_header_ptr = &sys_header; - pack_header_ptr = &pack_header; - OutputPadding (false); - break; - - case MPEG_FORMAT_VCD_STILL: - split_at_seq_end = false; - /* First packet carries small-still sys_header */ - /* TODO No support mixed-mode stills sequences... */ - psstrm->CreateSysHeader (&sys_header, mux_rate, false, false, true, true, emux); - sys_header_ptr = &sys_header; - pack_header_ptr = &pack_header; - OutputPadding (false); - break; - - case MPEG_FORMAT_SVCD_STILL: - /* TODO: Video only at present */ - /* First packet carries video-info-only sys_header */ - psstrm->CreateSysHeader (&sys_header, mux_rate, false, true, true, true, vmux); - sys_header_ptr = &sys_header; - pack_header_ptr = &pack_header; - OutputPadding (false); - break; - - case MPEG_FORMAT_DVD: - /* A DVD System header is a weird thing. We seem to need to - include buffer info about streams 0xb8, 0xb9, 0xbf even if - they're not physically present but the buffers for the actual - video streams aren't included. - - TODO: I have no idead about MPEG audio streams if present... - */ - { - DummyMuxStream dvd_0xb9_strm_dummy (0xb9, 1, video_buffer_size); - DummyMuxStream dvd_0xb8_strm_dummy (0xb8, 0, 4096); - DummyMuxStream dvd_0xbf_strm_dummy (0xbf, 1, 2048); - - vector < MuxStream * >dvdmux; - vector < MuxStream * >::iterator muxstr; - dvdmux.push_back (&dvd_0xb9_strm_dummy); - dvdmux.push_back (&dvd_0xb8_strm_dummy); - unsigned int max_priv1_buffer = 0; - - for (muxstr = amux.begin (); muxstr < amux.end (); ++muxstr) { - // We mux *many* substreams on PRIVATE_STR_1 - // we set the system header buffer size to the maximum - // of all those we find - if ((*muxstr)->stream_id == PRIVATE_STR_1 && (*muxstr)->BufferSize () > max_priv1_buffer) { - max_priv1_buffer = (*muxstr)->BufferSize (); - } else - dvdmux.push_back (*muxstr); - } - - DummyMuxStream dvd_priv1_strm_dummy (PRIVATE_STR_1, 1, max_priv1_buffer); - - if (max_priv1_buffer > 0) - dvdmux.push_back (&dvd_priv1_strm_dummy); - - dvdmux.push_back (&dvd_0xbf_strm_dummy); - psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, false, true, true, dvdmux); - sys_header_ptr = &sys_header; - pack_header_ptr = &pack_header; - /* It is then followed up by a pair of PRIVATE_STR_2 packets which - we keep empty 'cos we don't know what goes there... - */ - } - break; - - default: - /* Create the in-stream header in case it is needed */ - psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, false, true, true, emux); - } -} - -/****************************************************************** - Program shutdown packets. Generate any irregular packets - needed at the end of the stream... - -******************************************************************/ - -void -OutputStream::OutputSuffix () -{ - psstrm->CreatePack (&pack_header, current_SCR, mux_rate); - psstrm->CreateSector (&pack_header, NULL, 0, pstrm, false, true, 0, 0, TIMESTAMPBITS_NO); -} - -/****************************************************************** - - Main multiplex iteration. - Opens and closes all needed files and manages the correct - call od the respective Video- and Audio- packet routines. - The basic multiplexing is done here. Buffer capacity and - Timestamp checking is also done here, decision is taken - wether we should genereate a Video-, Audio- or Padding- - packet. -******************************************************************/ - - - -bool -OutputStream::OutputMultiplex () -{ - for (;;) { - bool completion = true; - - for (str = estreams->begin (); str < estreams->end (); ++str) - completion &= (*str)->MuxCompleted (); - if (completion) - break; - - /* A little state-machine for handling the transition from one - segment to the next - */ - bool runout_incomplete; - VideoStream *master; - - switch (seg_state) { - - /* Audio and slave video access units at end of segment. - If there are any audio AU's whose PTS implies they - should be played *before* the video AU starting the - next segement is presented we mux them out. Once - they're gone we've finished this segment so we write - the suffix switch file, and start muxing a new segment. - */ - case runout_segment: - runout_incomplete = false; - for (str = estreams->begin (); str < estreams->end (); ++str) { - runout_incomplete |= !(*str)->RunOutComplete (); - } - - if (runout_incomplete) - break; - - /* Otherwise we write the stream suffix and start a new - stream file */ - OutputSuffix (); - psstrm->NextFile (); - - running_out = false; - seg_state = start_segment; - - /* Starting a new segment. - We send the segment prefix, video and audio reciever - buffers are assumed to start empty. We reset the segment - length count and hence the SCR. - - */ - - case start_segment: - mjpeg_info ("New sequence commences..."); - SetPosAndSCR (0); - MuxStatus (LOG_INFO); - - for (str = estreams->begin (); str < estreams->end (); ++str) { - (*str)->AllDemuxed (); - } - - packets_left_in_pack = packets_per_pack; - start_of_new_pack = true; - include_sys_header = sys_header_in_pack1; - buffers_in_video = always_buffers_in_video; - video_first = seg_starts_with_video & (vstreams.size () > 0); - OutputPrefix (); - - /* Set the offset applied to the raw PTS/DTS of AU's to - make the DTS of the first AU in the master (video) stream - precisely the video delay plus whatever time we wasted in - the sequence pre-amble. - - The DTS of the remaining streams are set so that - (modulo the relevant delay offset) they maintain the - same relative timing to the master stream. - - */ - - clockticks ZeroSCR; - - if (vstreams.size () != 0) - ZeroSCR = vstreams[0]->au->DTS; - else - ZeroSCR = (*estreams)[0]->au->DTS; - - for (str = vstreams.begin (); str < vstreams.end (); ++str) - (*str)->SetSyncOffset (video_delay + current_SCR - ZeroSCR); - for (str = astreams.begin (); str < astreams.end (); ++str) - (*str)->SetSyncOffset (audio_delay + current_SCR - ZeroSCR); - pstrm.nsec = 0; - for (str = estreams->begin (); str < estreams->end (); ++str) - (*str)->nsec = 0; - seg_state = mid_segment; - //for( str = estreams->begin(); str < estreams->end(); ++str ) - //{ - //mjpeg_info("STREAM %02x: SCR=%lld mux=%d reqDTS=%lld", - //(*str)->stream_id, - //current_SCR /300, - //(*str)->MuxPossible(current_SCR), - //(*str)->RequiredDTS()/300 - //); - //} - break; - - case mid_segment: - /* Once we exceed our file size limit, we need to - start a new file soon. If we want a single stream we - simply switch. - - Otherwise we're in the last gop of the current segment - (and need to start running streams out ready for a - clean continuation in the next segment). - TODO: runout_PTS really needs to be expressed in - sync delay adjusted units... - */ - - master = vstreams.size () > 0 ? static_cast < VideoStream * >(vstreams[0]) : 0; - if (psstrm->FileLimReached ()) { - if (opt_multifile_segment || master == 0) - psstrm->NextFile (); - else { - if (master->NextAUType () == IFRAME) { - seg_state = runout_segment; - runout_PTS = master->NextRequiredPTS (); - mjpeg_debug ("Running out to (raw) PTS %d SCR=%d", - (int)runout_PTS / 300, (int)current_SCR / 300); - running_out = true; - seg_state = runout_segment; - } - } - } else if (master != 0 && master->EndSeq ()) { - if (split_at_seq_end && master->Lookahead () != 0) { - if (!master->SeqHdrNext () || master->NextAUType () != IFRAME) { - mjpeg_error_exit1 ("Sequence split detected %d but no following sequence found...", - master->NextAUType ()); - } - - runout_PTS = master->NextRequiredPTS (); - mjpeg_debug ("Running out to %d SCR=%d", (int)runout_PTS / 300, (int)current_SCR / 300); - MuxStatus (LOG_INFO); - running_out = true; - seg_state = runout_segment; - } - } - break; - - } - - padding_packet = false; - start_of_new_pack = (packets_left_in_pack == packets_per_pack); - - for (str = estreams->begin (); str < estreams->end (); ++str) { - (*str)->DemuxedTo (current_SCR); - } - - - - // - // Find the ready-to-mux stream with the most urgent DTS - // - ElementaryStream *despatch = 0; - clockticks earliest = 0; - - for (str = estreams->begin (); str < estreams->end (); ++str) { - /* DEBUG - mjpeg_info("STREAM %02x: SCR=%lld mux=%d reqDTS=%lld", - (*str)->stream_id, - current_SCR /300, - (*str)->MuxPossible(current_SCR), - (*str)->RequiredDTS()/300 - ); - */ - if ((*str)->MuxPossible (current_SCR) && - (!video_first || (*str)->Kind () == ElementaryStream::video) - ) { - if (despatch == 0 || earliest > (*str)->RequiredDTS ()) { - despatch = *str; - earliest = (*str)->RequiredDTS (); - } - } - } - - if (underrun_ignore > 0) - --underrun_ignore; - - if (despatch) { - despatch->OutputSector (); - video_first = false; - if (current_SCR >= earliest && underrun_ignore == 0) { - mjpeg_warn ("Stream %02x: data will arrive too late sent(SCR)=%d required(DTS)=%d", - despatch->stream_id, (int) current_SCR / 300, (int) earliest / 300); - MuxStatus (LOG_WARN); - // Give the stream a chance to recover - underrun_ignore = 300; - ++underruns; - if (underruns > 10 && !opt_ignore_underrun) { - mjpeg_error_exit1 ("Too many frame drops -exiting"); - } - } - if (despatch->nsec > 50 && despatch->Lookahead () != 0 && !running_out) - despatch->UpdateBufferMinMax (); - padding_packet = false; - - } else { - // - // If we got here no stream could be muxed out. - // We therefore generate padding packets if necessary - // usually this is because reciever buffers are likely to be - // full. - // - if (vbr) { - // - // VBR: For efficiency we bump SCR up to five times or - // until it looks like buffer status will change - NextPosAndSCR (); - clockticks next_change = static_cast < clockticks > (0); - - for (str = estreams->begin (); str < estreams->end (); ++str) { - clockticks change_time = (*str)->bufmodel.NextChange (); - - if (next_change == 0 || change_time < next_change) - next_change = change_time; - } - unsigned int bumps = 5; - - while (bumps > 0 && next_change > current_SCR + ticks_per_sector) { - NextPosAndSCR (); - --bumps; - } - } else { - // Just output a padding packet - OutputPadding (false); - } - padding_packet = true; - } - - /* Update the counter for pack packets. VBR is a tricky - case as here padding packets are "virtual" */ - - if (!(vbr && padding_packet)) { - --packets_left_in_pack; - if (packets_left_in_pack == 0) - packets_left_in_pack = packets_per_pack; - } - - MuxStatus (LOG_DEBUG); - /* Unless sys headers are always required we turn them off after the first - packet has been generated */ - include_sys_header = always_sys_header_in_pack; - - pcomp = completed.begin (); - str = estreams->begin (); - while (str < estreams->end ()) { - if (!(*pcomp) && (*str)->MuxCompleted ()) { - mjpeg_info ("STREAM %02x completed @ %d.", (*str)->stream_id, (*str)->au->dorder); - MuxStatus (LOG_DEBUG); - (*pcomp) = true; - } - ++str; - ++pcomp; - } - - return true; - } - - return false; -} - - -void -OutputStream::Close () -{ - // Tidy up - OutputSuffix (); - psstrm->Close (); - mjpeg_info ("Multiplex completion at SCR=%d.", (int) current_SCR / 300); - MuxStatus (LOG_INFO); - for (str = estreams->begin (); str < estreams->end (); ++str) { - (*str)->Close (); - if ((*str)->nsec <= 50) - mjpeg_info ("BUFFERING stream too short for useful statistics"); - else - mjpeg_info ("BUFFERING min %d Buf max %d", (*str)->BufferMin (), (*str)->BufferMax ()); - } - - if (underruns > 0) { - mjpeg_error ("foo"); - mjpeg_error_exit1 ("MUX STATUS: Frame data under-runs detected!"); - } else { - mjpeg_info ("foo"); - mjpeg_info ("MUX STATUS: no under-runs detected."); - } -} - -/** - Calculate the packet payload of the output stream at a certain timestamp. -@param strm the output stream -@param buffers the number of buffers -@param PTSstamp presentation time stamp -@param DTSstamp decoding time stamp - */ -unsigned int -OutputStream::PacketPayload (MuxStream & strm, bool buffers, bool PTSstamp, bool DTSstamp) -{ - return psstrm->PacketPayload (strm, sys_header_ptr, pack_header_ptr, buffers, PTSstamp, DTSstamp) - - strm.StreamHeaderSize (); -} - -/*************************************************** - - WritePacket - Write out a normal packet carrying data from one of - the elementary stream being muxed. -@param max_packet_data_size the maximum packet data size allowed -@param strm output mux stream -@param buffers ? -@param PTSstamp presentation time stamp of the packet -@param DTSstamp decoding time stamp of the packet -@param timestamps ? -@param returns the written bytes/packets (?) -***************************************************/ - -unsigned int -OutputStream::WritePacket (unsigned int max_packet_data_size, - MuxStream & strm, - bool buffers, clockticks PTS, clockticks DTS, uint8_t timestamps) -{ - unsigned int written = psstrm->CreateSector (pack_header_ptr, - sys_header_ptr, - max_packet_data_size, - strm, - buffers, - false, - PTS, - DTS, - timestamps); - - NextPosAndSCR (); - return written; -} - -/*************************************************** - * - * WriteRawSector - Write out a packet carrying data for - * a control packet with irregular content. -@param rawsector data for the raw sector -@param length length of the raw sector - ***************************************************/ - -void -OutputStream::WriteRawSector (uint8_t * rawsector, unsigned int length) -{ - // - // Writing raw sectors when packs stretch over multiple sectors - // is a recipe for disaster! - // - assert (packets_per_pack == 1); - psstrm->RawWrite (rawsector, length); - NextPosAndSCR (); - -} - - - -/****************************************************************** - OutputPadding - - generates Pack/Sys Header/Packet information for a - padding stream and saves the sector - - We have to pass in a special flag to cope with appalling mess VCD - makes of audio packets (the last 20 bytes being dropped thing) 0 = - Fill the packet completetely. This include "audio packets" that - include no actual audio, only a system header and padding. -@param vcd_audio_pad flag for VCD audio padding -******************************************************************/ - - -void -OutputStream::OutputPadding (bool vcd_audio_pad) -{ - if (vcd_audio_pad) - psstrm->CreateSector (pack_header_ptr, sys_header_ptr, - 0, vcdapstrm, false, false, 0, 0, TIMESTAMPBITS_NO); - else - psstrm->CreateSector (pack_header_ptr, sys_header_ptr, - 0, pstrm, false, false, 0, 0, TIMESTAMPBITS_NO); - ++pstrm.nsec; - NextPosAndSCR (); - -} - - /****************************************************************** - * OutputGOPControlSector - * DVD System headers are carried in peculiar sectors carrying 2 - * PrivateStream2 packets. We're sticking 0's in the packets - * as we have no idea what's supposed to be in there. - * - * Thanks to Brent Byeler who worked out this work-around. - * - ******************************************************************/ - -void -OutputStream::OutputDVDPriv2 () -{ - uint8_t *packet_size_field; - uint8_t *index; - uint8_t *sector_buf; - unsigned int tozero; - - sector_buf = g_new0(uint8_t, sector_size); - - assert (sector_size == 2048); - PS_Stream::BufferSectorHeader (sector_buf, pack_header_ptr, &sys_header, index); - PS_Stream::BufferPacketHeader (index, PRIVATE_STR_2, 2, // MPEG 2 - false, // No buffers - 0, 0, 0, // No timestamps - 0, TIMESTAMPBITS_NO, packet_size_field, index); - tozero = sector_buf + 1024 - index; - memset (index, 0, tozero); - index += tozero; - PS_Stream::BufferPacketSize (packet_size_field, index); - - PS_Stream::BufferPacketHeader (index, PRIVATE_STR_2, 2, // MPEG 2 - false, // No buffers - 0, 0, 0, // No timestamps - 0, TIMESTAMPBITS_NO, packet_size_field, index); - tozero = sector_buf + 2048 - index; - memset (index, 0, tozero); - index += tozero; - PS_Stream::BufferPacketSize (packet_size_field, index); - - WriteRawSector (sector_buf, sector_size); - - g_free(sector_buf); -} - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/outputstream.hh b/ext/mplex/outputstream.hh deleted file mode 100644 index 3b62561..0000000 --- a/ext/mplex/outputstream.hh +++ /dev/null @@ -1,198 +0,0 @@ - -#ifndef __OUTPUTSTREAM_H__ -#define __OUTPUTSTREAM_H__ - -#include -#include -#include "mjpeg_types.h" - -#include "inputstrm.hh" -#include "padstrm.hh" -#include "systems.hh" - -typedef enum -{ start_segment, mid_segment, - runout_segment -} -segment_state; - -class OutputStream -{ -public: - OutputStream () - { - underrun_ignore = 0; - underruns = 0; - - opt_verbosity = 1; - opt_buffer_size = 46; - opt_data_rate = 0; /* 3486 = 174300B/sec would be right for VCD */ - opt_video_offset = 0; - opt_audio_offset = 0; - opt_sector_size = 2324; - opt_VBR = 0; - opt_mpeg = 1; - opt_mux_format = 0; /* Generic MPEG-1 stream as default */ - opt_multifile_segment = 0; - opt_always_system_headers = 0; - opt_packets_per_pack = 20; - opt_ignore_underrun = false; - opt_max_segment_size = 0; - } - bool OutputMultiplex (); - void Init (vector < ElementaryStream * >*strms, PS_Stream *stream); - void Close (); - - void InitSyntaxParameters (); - void ByteposTimecode (bitcount_t bytepos, clockticks & ts); - - inline Sys_header_struc *SystemHeader () - { - return &sys_header; - } - - unsigned int PacketPayload (MuxStream & strm, bool buffers, bool PTSstamp, bool DTSstamp); - unsigned int WritePacket (unsigned int max_packet_data_size, - MuxStream & strm, - bool buffers, clockticks PTS, clockticks DTS, uint8_t timestamps); - - /* Special "unusual" sector types needed for particular formats - */ - - void OutputDVDPriv2 (); - - /* Syntax control parameters, public becaus they're partly referenced - by the input stream objects. - */ - - bool always_sys_header_in_pack; - bool dtspts_for_all_vau; - bool sys_header_in_pack1; - bool buffers_in_video; - bool always_buffers_in_video; - bool buffers_in_audio; - bool always_buffers_in_audio; - bool sector_align_iframeAUs; - bool split_at_seq_end; - bool seg_starts_with_video; - bool timestamp_iframe_only; - bool video_buffers_iframe_only; - unsigned int audio_buffer_size; - unsigned int video_buffer_size; - - /* more profile options */ - int opt_verbosity; - int opt_quiet_mode; - int opt_buffer_size; - int opt_data_rate; - int opt_video_offset; - int opt_audio_offset; - int opt_sector_size; - int opt_VBR; - int opt_mpeg; - int opt_mux_format; - int opt_multifile_segment; - int opt_always_system_headers; - int opt_packets_per_pack; - bool opt_stills; - bool opt_ignore_underrun; - int verbose; - off_t opt_max_segment_size; - - /* Sequence run-out control */ - bool running_out; - clockticks runout_PTS; - - -/* In some situations the system/PES packets are embedded with - external transport data which has to be taken into account for SCR - calculations to be correct. E.g. VCD streams. Where each 2324 byte - system packet is embedded in a 2352 byte CD sector and the actual - MPEG data is preceded by 30 empty sectors. -*/ - - unsigned int sector_transport_size; - unsigned int transport_prefix_sectors; - unsigned int sector_size; - unsigned int vcd_zero_stuffing; /* VCD audio sectors have 20 0 bytes :-( */ - - int dmux_rate; /* Actual data mux-rate for calculations always a multiple of 50 */ - int mux_rate; /* MPEG mux rate (50 byte/sec units */ - unsigned int packets_per_pack; - -private: - - /* Stream packet component buffers */ - - Sys_header_struc sys_header; - Pack_struc pack_header; - Pack_struc *pack_header_ptr; - Sys_header_struc *sys_header_ptr; - bool start_of_new_pack; - bool include_sys_header; - - /* Under-run error messages */ - unsigned int underruns; - unsigned int underrun_ignore; - - /* Output data stream... */ - PS_Stream *psstrm; - bitcount_t bytes_output; - clockticks ticks_per_sector; - -public: - clockticks current_SCR; -private: - clockticks audio_delay; - clockticks video_delay; - bool vbr; - - /* Source data streams */ - /* Note: 1st video stream is regarded as the "master" stream for - the purpose of splitting sequences etc... - */ - vector < ElementaryStream * >*estreams; // Complete set - vector < ElementaryStream * >vstreams; // Video streams in estreams - vector < ElementaryStream * >astreams; // Audio streams in estreams - - PaddingStream pstrm; - VCDAPadStream vcdapstrm; - DVDPriv2Stream dvdpriv2strm; - -private: - unsigned int RunInSectors (); - - void NextPosAndSCR (); - void SetPosAndSCR (bitcount_t bytepos); - - void OutputPrefix (); - - void OutputSuffix (); - void OutputPadding (bool vcd_audio_pad); - void MuxStatus (log_level_t level); - - void WriteRawSector (uint8_t * rawpackets, unsigned int length); - void AppendMuxStreamsOf (vector < ElementaryStream * >&elem, vector < MuxStream * >&mux); - - /* state var for muxing */ - segment_state seg_state; - - vector < bool > completed; - vector < bool >::iterator pcomp; - vector < ElementaryStream * >::iterator str; - - unsigned int packets_left_in_pack; /* Suppress warning */ - bool padding_packet; - bool video_first; - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ -}; - - -#endif //__OUTPUTSTREAM_H__ diff --git a/ext/mplex/padstrm.cc b/ext/mplex/padstrm.cc deleted file mode 100644 index 95e32db..0000000 --- a/ext/mplex/padstrm.cc +++ /dev/null @@ -1,59 +0,0 @@ - -/* - * padstrm.cc: Padding stream pseudo-input streams - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - - -#include "padstrm.hh" - - - -// -// Generator for padding packets in a padding stream... -// - - -unsigned int -PaddingStream::ReadPacketPayload (uint8_t * dst, unsigned int to_read) -{ - memset (dst, STUFFING_BYTE, to_read); - return to_read; -} - -unsigned int -VCDAPadStream::ReadPacketPayload (uint8_t * dst, unsigned int to_read) -{ - memset (dst, STUFFING_BYTE, to_read); - return to_read; -} - -unsigned int -DVDPriv2Stream::ReadPacketPayload (uint8_t * dst, unsigned int to_read) -{ - memset (dst, 0, to_read); - return to_read; -} - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/padstrm.hh b/ext/mplex/padstrm.hh deleted file mode 100644 index 3300e5b..0000000 --- a/ext/mplex/padstrm.hh +++ /dev/null @@ -1,73 +0,0 @@ - -/* - * padstrm.hh: Padding stream pseudo input-streamsin - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __PADSTRM_H__ -#define __PADSTRM_H__ - -#include "inputstrm.hh" - - -class PaddingStream:public MuxStream -{ -public: - PaddingStream () - { - MuxStream::Init (PADDING_STR, 0, 0, 0, false, false); - } - - unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read); -}; - -class VCDAPadStream:public MuxStream -{ -public: - VCDAPadStream () - { - Init (PADDING_STR, 0, 0, 20, false, false); - - } - - unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read); -}; - -class DVDPriv2Stream:public MuxStream -{ -public: - DVDPriv2Stream () - { - Init (PRIVATE_STR_2, 0, 0, 0, false, false); - - } - - unsigned int ReadPacketPayload (uint8_t * dst, unsigned int to_read); -}; - - -#endif // __PADSTRM_H__ - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/stillsstream.cc b/ext/mplex/stillsstream.cc deleted file mode 100644 index 1b6d10b..0000000 --- a/ext/mplex/stillsstream.cc +++ /dev/null @@ -1,194 +0,0 @@ - -/* - * stillsstreams.c: Class for elemenary still video streams - * Most functionality is inherited from VideoStream - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - - -#include - -#include "stillsstream.hh" -#include "outputstream.hh" -#include - -void -StillsStream::Init () -{ - int stream_id = 0; - int buffer_size = 0; - - SetBufSize (4 * 1024 * 1024); - InitAUbuffer (); - ScanFirstSeqHeader (); - - mjpeg_debug ("SETTING video buffer to %d", muxinto.video_buffer_size); - switch (opt_mux_format) { - case MPEG_FORMAT_VCD_STILL: - if (horizontal_size > 352) { - stream_id = VIDEO_STR_0 + 2; - buffer_size = vbv_buffer_size * 2048; - mjpeg_info ("Stills Stream %02x: high-resolution VCD stills %d KB each", - stream_id, buffer_size); - if (buffer_size < 46 * 1024) - mjpeg_error_exit1 - ("I Can't multiplex high-res stills smaller than normal res stills - sorry!"); - - } else { - stream_id = VIDEO_STR_0 + 1; - buffer_size = 46 * 1024; - mjpeg_info ("Stills Stream %02x: normal VCD stills", stream_id); - } - break; - case MPEG_FORMAT_SVCD_STILL: - if (horizontal_size > 480) { - stream_id = VIDEO_STR_0 + 1; - buffer_size = 230 * 1024; - mjpeg_info ("Stills Stream %02x: high-resolution SVCD stills.", stream_id); - } else { - stream_id = VIDEO_STR_0 + 1; - buffer_size = 230 * 1024; - mjpeg_info ("Stills Stream %02x: normal-resolution SVCD stills.", stream_id); - } - break; - } - - - MuxStream::Init (stream_id, 1, // Buffer scale - buffer_size, 0, // Zero stuffing - muxinto.buffers_in_video, muxinto.always_buffers_in_video); - - /* Skip to the end of the 1st AU (*2nd* Picture start!) - */ - AU_hdr = SEQUENCE_HEADER; - AU_pict_data = 0; - AU_start = 0LL; - - OutputSeqhdrInfo (); - -} - - - - -/* - * Compute DTS / PTS for a VCD/SVCD Stills sequence - * TODO: Very crude. Simply assumes each still stays for the specified - * frame interval and that enough run-in delay is present for the first - * frame to be loaded. - * - */ - -void -StillsStream::NextDTSPTS (clockticks & DTS, clockticks & PTS) -{ - clockticks interval = static_cast < clockticks > - (intervals->NextFrameInterval () * CLOCKS / frame_rate); - clockticks time_for_xfer; - - muxinto.ByteposTimecode (BufferSize (), time_for_xfer); - - DTS = current_PTS + time_for_xfer; // This frame decoded just after - // Predecessor completed. - PTS = current_PTS + time_for_xfer + interval; - current_PTS = PTS; - current_DTS = DTS; -} - -/* - * VCD mixed stills segment items have the constraint that both stills - * streams must end together. To do this each stream has to know - * about its "sibling". - * - */ - -void -VCDStillsStream::SetSibling (VCDStillsStream * _sibling) -{ - assert (_sibling != 0); - sibling = _sibling; - if (sibling->stream_id == stream_id) { - mjpeg_error_exit1 ("VCD mixed stills stream cannot contain two streams of the same type!"); - } - -} - -/* - * Check if we've reached the last sector of the last AU. Note: that - * we know no PTS/DTS time-stamps will be needed because no new AU - * will appear in the last sector. WARNING: We assume a still won't - * fit into a single secotr. - * - */ - -bool -VCDStillsStream::LastSectorLastAU () -{ - return (Lookahead () == 0 && - au_unsent <= muxinto.PacketPayload (*this, buffers_in_header, false, false) - ); -} - - -/* - * The requirement that VCD mixed stills segment items constituent streams - * end together means we can't mux the last sector of the last AU of - * such streams until its sibling has already completed muxing or is - * also ready to mux the last sector of its last AU. - * - * NOTE: Will not work right if sector_align_iframe_AUs not set as this - * will allow multiple AU's in a sector. - * - */ - - -bool -VCDStillsStream::MuxPossible () -{ - if (bufmodel.Size () < au_unsent) { - mjpeg_error_exit1 - ("Illegal VCD still: larger than maximum permitted by its buffering parameters!"); - } - if (RunOutComplete () || bufmodel.Space () < au_unsent) { - return false; - } - - if (LastSectorLastAU ()) { - if (sibling != 0) { - if (!stream_mismatch_warned && sibling->NextAUType () != NOFRAME) { - mjpeg_warn ("One VCD stills stream runs significantly longer than the other!"); - mjpeg_warn ("Simultaneous stream ending recommended by standard not possible"); - return true; - } - return sibling->MuxCompleted () || sibling->LastSectorLastAU (); - } else - return true; - } else - return true; -} - - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/stillsstream.hh b/ext/mplex/stillsstream.hh deleted file mode 100644 index bfd2aca..0000000 --- a/ext/mplex/stillsstream.hh +++ /dev/null @@ -1,107 +0,0 @@ - -/* - * stillsstreams.c: Class for elemenary still video streams - * Most functionality is inherited from VideoStream - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - - -#include "videostrm.hh" - -class FrameIntervals -{ -public: - virtual int NextFrameInterval () = 0; -}; - -// -// Class of sequence of frame intervals. -// - -class ConstantFrameIntervals:public FrameIntervals -{ -public: - ConstantFrameIntervals (int _frame_interval):frame_interval (_frame_interval) - { - } - int NextFrameInterval () - { - return frame_interval; - }; -private: - int frame_interval; -}; - - -// -// Class for video stills sequence for (S)VCD non-mixed stills segment -// item -// - -class StillsStream:public VideoStream -{ -public: - StillsStream (IBitStream & ibs, - OutputStream & into, FrameIntervals * frame_ints):VideoStream (ibs, into), - current_PTS (0LL), current_DTS (0LL), intervals (frame_ints) - { - } - void Init (); - -private: - virtual void NextDTSPTS (clockticks & DTS, clockticks & PTS); - clockticks current_PTS; - clockticks current_DTS; - FrameIntervals *intervals; - - int opt_mux_format; -}; - -// -// Class for video stills sequence for VCD mixed stills Segment item. -// - -class VCDStillsStream:public StillsStream -{ -public: - VCDStillsStream (IBitStream & ibs, - OutputStream & into, FrameIntervals * frame_ints):StillsStream (ibs, into, - frame_ints), - sibling (0), stream_mismatch_warned (false) - { - } - - void SetSibling (VCDStillsStream *); - virtual bool MuxPossible (); - -private: - bool LastSectorLastAU (); - VCDStillsStream *sibling; - bool stream_mismatch_warned; -}; - - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/systems.cc b/ext/mplex/systems.cc deleted file mode 100644 index fd5b908..0000000 --- a/ext/mplex/systems.cc +++ /dev/null @@ -1,762 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "systems.hh" -#include "mplexconsts.hh" -#include - -uint8_t dummy_buf[8000]; -void -PS_Stream::Init (unsigned _mpeg, unsigned int _sector_size, off_t max_seg_size) -{ - max_segment_size = max_seg_size; - mpeg_version = _mpeg; - sector_size = _sector_size; - segment_num = 1; - written = 0; - - sector_buf = new uint8_t[_sector_size]; -} - -bool PS_Stream::FileLimReached () -{ - return max_segment_size != 0 && written > max_segment_size; -} - -void -PS_Stream::NextFile () -{ -/* - char prev_filename[strlen (cur_filename) + 1]; - - //fclose (strm); - ++segment_num; - strcpy (prev_filename, cur_filename); - snprintf (cur_filename, MAXPATHLEN, filename_pat, segment_num); - if (strcmp (prev_filename, cur_filename) == 0) { - mjpeg_error_exit1 - ("Need to split output but there appears to be no %%d in the filename pattern %s", - filename_pat); - } - strm = fopen (cur_filename, "wb"); - if (strm == NULL) { - mjpeg_error_exit1 ("Could not open for writing: %s", cur_filename); - } - */ -} - -/************************************************************** - - Packet payload compute how much payload a sector-sized packet with the - specified headers can carry... - TODO: Should really be called "Sector Payload" -**************************************************************/ - - -unsigned int -PS_Stream::PacketPayload (MuxStream & strm, - Sys_header_struc * sys_header, - Pack_struc * pack_header, int buffers, int PTSstamp, int DTSstamp) -{ - int payload = sector_size - (PACKET_HEADER_SIZE + strm.zero_stuffing); - - if (sys_header != NULL) - payload -= sys_header->length; - if (mpeg_version == 2) { - if (buffers) - payload -= MPEG2_BUFFERINFO_LENGTH; - - payload -= MPEG2_AFTER_PACKET_LENGTH_MIN; - if (pack_header != NULL) - payload -= pack_header->length; - if (DTSstamp) - payload -= DTS_PTS_TIMESTAMP_LENGTH; - if (PTSstamp) - payload -= DTS_PTS_TIMESTAMP_LENGTH; - - } else { - if (buffers) - payload -= MPEG1_BUFFERINFO_LENGTH; - - payload -= MPEG1_AFTER_PACKET_LENGTH_MIN; - if (pack_header != NULL) - payload -= pack_header->length; - if (DTSstamp) - payload -= DTS_PTS_TIMESTAMP_LENGTH; - if (PTSstamp) - payload -= DTS_PTS_TIMESTAMP_LENGTH; - if (DTSstamp || PTSstamp) - payload += 1; /* No need for nostamp marker ... */ - - } - - return payload; -} - - - -/************************************************************************* - Kopiert einen TimeCode in einen Bytebuffer. Dabei wird er nach - MPEG-Verfahren in bits aufgesplittet. - - Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields - for MPEG-1/2 DTS/PTS fields and MPEG-1 pack scr fields -*************************************************************************/ - -void -PS_Stream::BufferDtsPtsMpeg1ScrTimecode (clockticks timecode, uint8_t marker, uint8_t ** buffer) -{ - clockticks thetime_base; - uint8_t temp; - unsigned int msb, lsb; - - /* MPEG-1 uses a 90KHz clock, extended to 300*90KHz = 27Mhz in MPEG-2 */ - /* For these fields we only encode to MPEG-1 90Khz resolution... */ - - thetime_base = timecode / 300; - msb = (thetime_base >> 32) & 1; - lsb = (thetime_base & 0xFFFFFFFFLL); - - temp = (marker << 4) | (msb << 3) | ((lsb >> 29) & 0x6) | 1; - *((*buffer)++) = temp; - temp = (lsb & 0x3fc00000) >> 22; - *((*buffer)++) = temp; - temp = ((lsb & 0x003f8000) >> 14) | 1; - *((*buffer)++) = temp; - temp = (lsb & 0x7f80) >> 7; - *((*buffer)++) = temp; - temp = ((lsb & 0x007f) << 1) | 1; - *((*buffer)++) = temp; - -} - -/************************************************************************* - Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields - for MPEG-2 pack scr fields which use the full 27Mhz resolution - - Did they *really* need to put a 27Mhz - clock source into the system stream. Does anyone really need it - for their decoders? Get real... I guess they thought it might allow - someone somewhere to save on a proper clock circuit. -*************************************************************************/ - - -void -PS_Stream::BufferMpeg2ScrTimecode (clockticks timecode, uint8_t ** buffer) -{ - clockticks thetime_base; - unsigned int thetime_ext; - uint8_t temp; - unsigned int msb, lsb; - - thetime_base = timecode / 300; - thetime_ext = timecode % 300; - msb = (thetime_base >> 32) & 1; - lsb = thetime_base & 0xFFFFFFFFLL; - - - temp = (MARKER_MPEG2_SCR << 6) | (msb << 5) | ((lsb >> 27) & 0x18) | 0x4 | ((lsb >> 28) & 0x3); - *((*buffer)++) = temp; - temp = (lsb & 0x0ff00000) >> 20; - *((*buffer)++) = temp; - temp = ((lsb & 0x000f8000) >> 12) | 0x4 | ((lsb & 0x00006000) >> 13); - *((*buffer)++) = temp; - temp = (lsb & 0x00001fe0) >> 5; - *((*buffer)++) = temp; - temp = ((lsb & 0x0000001f) << 3) | 0x4 | ((thetime_ext & 0x00000180) >> 7); - *((*buffer)++) = temp; - temp = ((thetime_ext & 0x0000007F) << 1) | 1; - *((*buffer)++) = temp; -} - -/************************************************************************* - -BufferPaddingPacket - Insert a padding packet of the desired length - into the specified Program/System stream buffer - -**************************************************************************/ - -void -PS_Stream::BufferPaddingPacket (int padding, uint8_t * &buffer) -{ - uint8_t *index = buffer; - int i; - - assert ((mpeg_version == 2 && padding >= 6) || (mpeg_version == 1 && padding >= 7)); - - *(index++) = static_cast < uint8_t > (PACKET_START) >> 16; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x00ffff) >> 8; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x0000ff); - *(index++) = PADDING_STR; - *(index++) = static_cast < uint8_t > ((padding - 6) >> 8); - *(index++) = static_cast < uint8_t > ((padding - 6) & 0xff); - if (mpeg_version == 2) { - for (i = 0; i < padding - 6; i++) - *(index++) = static_cast < uint8_t > (STUFFING_BYTE); - } else { - *(index++) = 0x0F; - for (i = 0; i < padding - 7; i++) - *(index++) = static_cast < uint8_t > (STUFFING_BYTE); - } - - buffer = index; -} - - -void -PS_Stream::BufferSectorHeader (uint8_t * index, - Pack_struc * pack, - Sys_header_struc * sys_header, uint8_t * &header_end) -{ - /* Pack header if present */ - - if (pack != NULL) { - memcpy (index, pack->buf, pack->length); - index += pack->length; - } - - /* System header if present */ - - if (sys_header != NULL) { - memcpy (index, sys_header->buf, sys_header->length); - index += sys_header->length; - } - header_end = index; -} - -/****************************************** - * - * BufferPacketHeader - * Construct and MPEG-1/2 header for a packet in the specified - * buffer (which *MUST* be long enough) and set points to the start of - * the payload and packet length fields. - * - ******************************************/ - - -void -PS_Stream::BufferPacketHeader (uint8_t * buf, - uint8_t type, - unsigned int mpeg_version, - bool buffers, - unsigned int buffer_size, - uint8_t buffer_scale, - clockticks PTS, - clockticks DTS, - uint8_t timestamps, uint8_t * &size_field, uint8_t * &header_end) -{ - - uint8_t *index = buf; - uint8_t *pes_header_len_field = 0; - - - /* konstante Packet Headerwerte eintragen */ - /* write constant packet header data */ - - *(index++) = static_cast < uint8_t > (PACKET_START) >> 16; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x00ffff) >> 8; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x0000ff); - *(index++) = type; - - - /* we remember this offset so we can fill in the packet size field once - we know the actual size... */ - size_field = index; - index += 2; - - if (mpeg_version == 1) { - /* MPEG-1: buffer information */ - if (buffers) { - *(index++) = static_cast < uint8_t > (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); - *(index++) = static_cast < uint8_t > (buffer_size & 0xff); - } - - /* MPEG-1: PTS, PTS & DTS, oder gar nichts? */ - /* should we write PTS, PTS & DTS or nothing at all ? */ - - switch (timestamps) { - case TIMESTAMPBITS_NO: - *(index++) = MARKER_NO_TIMESTAMPS; - break; - case TIMESTAMPBITS_PTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_JUST_PTS, &index); - break; - case TIMESTAMPBITS_PTS_DTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_PTS, &index); - BufferDtsPtsMpeg1ScrTimecode (DTS, MARKER_DTS, &index); - break; - } - } else if (type != PADDING_STR) { - /* MPEG-2 packet syntax header flags. */ - /* These *DO NOT* appear in padding packets */ - /* TODO: They don't appear in several others either! */ - /* First byte: - <1,0> - */ - *(index++) = 0x81; - /* Second byte: PTS PTS_DTS or neither? Buffer info? - - - */ - *(index++) = (timestamps << 6) | (!!buffers); - /* Third byte: - */ - pes_header_len_field = index; /* To fill in later! */ - index++; - /* MPEG-2: the timecodes if required */ - switch (timestamps) { - case TIMESTAMPBITS_PTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_JUST_PTS, &index); - break; - - case TIMESTAMPBITS_PTS_DTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_PTS, &index); - BufferDtsPtsMpeg1ScrTimecode (DTS, MARKER_DTS, &index); - break; - } - - /* MPEG-2 The buffer information in a PES_extension */ - if (buffers) { - /* MPEG-2 PES extension header - - - <{PES_extension_flag_2=0> */ - *(index++) = static_cast < uint8_t > (0x1e); - *(index++) = static_cast < uint8_t > (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); - *(index++) = static_cast < uint8_t > (buffer_size & 0xff); - } - } - - if (mpeg_version == 2 && type != PADDING_STR) { - *pes_header_len_field = static_cast < uint8_t > (index - (pes_header_len_field + 1)); - } - - header_end = index; -} - -/************************************************************************* - * CreateSector - * - * Creates a complete sector to carry a padding packet or a packet - * from one of the elementary streams. Pack and System headers are - * prepended if required. - * - * We allow for situations where want to - * deliberately reduce the payload carried by stuffing. - * This allows us to deal with tricky situations where the - * header overhead of adding in additional information - * would exceed the remaining payload capacity. - * - * Header stuffing and/or a padding packet is appended if the sector is - * unfilled. Zero stuffing after the end of a packet is also supported - * to allow thos wretched audio packets from VCD's to be handled. - * - * TODO: Should really be called "WriteSector" - * TODO: We need to add a mechanism for sub-headers of private streams - * to be generated... - * - *************************************************************************/ - - -unsigned int -PS_Stream::CreateSector (Pack_struc * pack, - Sys_header_struc * sys_header, - unsigned int max_packet_data_size, - MuxStream & strm, - bool buffers, - bool end_marker, clockticks PTS, clockticks DTS, uint8_t timestamps) -{ - unsigned int i; - unsigned int j; - uint8_t *index; - uint8_t *size_offset; - uint8_t *fixed_packet_header_end; - uint8_t *pes_header_len_offset = 0; - unsigned int target_packet_data_size; - unsigned int actual_packet_data_size; - int packet_data_to_read; - unsigned int bytes_short; - uint8_t type = strm.stream_id; - uint8_t buffer_scale = strm.BufferScale (); - unsigned int buffer_size = strm.BufferSizeCode (); - unsigned int sector_pack_area; - - index = sector_buf; - - sector_pack_area = sector_size - strm.zero_stuffing; - if (end_marker) - sector_pack_area -= 4; - - BufferSectorHeader (index, pack, sys_header, index); - - /* konstante Packet Headerwerte eintragen */ - /* write constant packet header data */ - - *(index++) = static_cast < uint8_t > (PACKET_START) >> 16; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x00ffff) >> 8; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x0000ff); - *(index++) = type; - - - /* we remember this offset so we can fill in the packet size field once - we know the actual size... */ - size_offset = index; - index += 2; - fixed_packet_header_end = index; - - if (mpeg_version == 1) { - /* MPEG-1: buffer information */ - if (buffers) { - *(index++) = static_cast < uint8_t > (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); - *(index++) = static_cast < uint8_t > (buffer_size & 0xff); - } - - /* MPEG-1: PTS, PTS & DTS, oder gar nichts? */ - /* should we write PTS, PTS & DTS or nothing at all ? */ - - switch (timestamps) { - case TIMESTAMPBITS_NO: - *(index++) = MARKER_NO_TIMESTAMPS; - break; - case TIMESTAMPBITS_PTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_JUST_PTS, &index); - break; - case TIMESTAMPBITS_PTS_DTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_PTS, &index); - BufferDtsPtsMpeg1ScrTimecode (DTS, MARKER_DTS, &index); - break; - } - } else if (type != PADDING_STR) { - /* MPEG-2 packet syntax header flags. */ - /* These *DO NOT* appear in padding packets */ - /* TODO: They don't appear in several others either! */ - /* First byte: - <1,0> - */ - *(index++) = 0x81; - /* Second byte: PTS PTS_DTS or neither? Buffer info? - - - */ - *(index++) = (timestamps << 6) | (!!buffers); - /* Third byte: - */ - pes_header_len_offset = index; /* To fill in later! */ - index++; - /* MPEG-2: the timecodes if required */ - switch (timestamps) { - case TIMESTAMPBITS_PTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_JUST_PTS, &index); - break; - - case TIMESTAMPBITS_PTS_DTS: - BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_PTS, &index); - BufferDtsPtsMpeg1ScrTimecode (DTS, MARKER_DTS, &index); - break; - } - - /* MPEG-2 The buffer information in a PES_extension */ - if (buffers) { - /* MPEG-2 PES extension header - - - <{PES_extension_flag_2=0> */ - *(index++) = static_cast < uint8_t > (0x1e); - *(index++) = static_cast < uint8_t > (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); - *(index++) = static_cast < uint8_t > (buffer_size & 0xff); - } - } -#ifdef MUX_DEBUG - // DVD MPEG2: AC3 in PRIVATE_STR_1 - if (type == PRIVATE_STR_1) { - ac3_header = index; - // TODO: should allow multiple AC3 streams... - //ac3_header[0] = AC3_SUB_STR_1; // byte: Audio stream number - // byte: num of AC3 syncwords - // byte: Offset first AC3 syncword (hi) - // byte: Offset 2nd AC2 syncword (lo) - //index += 4; - //subheader_size = 4; - subheader_size = 0; - } else -#endif - - - /* MPEG-1, MPEG-2: data available to be filled is packet_size less - * header and MPEG-1 trailer... */ - - target_packet_data_size = sector_pack_area - (index - sector_buf); - - - /* DEBUG: A handy consistency check when we're messing around */ -#ifdef MUX_DEBUG - if (type != PADDING_STR && (end_marker ? target_packet_data_size + 4 : target_packet_data_size) - != - PacketPayload (strm, sys_header, pack, buffers, - timestamps & TIMESTAMPBITS_PTS, timestamps & TIMESTAMPBITS_DTS)) - { - printf ("\nPacket size calculation error %d S%d P%d B%d %d %d!\n ", - timestamps, - sys_header != 0, pack != 0, buffers, - target_packet_data_size, - PacketPayload (strm, sys_header, pack, buffers, - timestamps & TIMESTAMPBITS_PTS, timestamps & TIMESTAMPBITS_DTS)); - exit (1); - } -#endif - - /* If a maximum payload data size is specified (!=0) and is - smaller than the space available thats all we read (the - remaining space is stuffed) */ - if (max_packet_data_size != 0 && max_packet_data_size < target_packet_data_size) { - packet_data_to_read = max_packet_data_size; - } else - packet_data_to_read = target_packet_data_size; - - - /* MPEG-1, MPEG-2: read in available packet data ... */ - - actual_packet_data_size = strm.ReadPacketPayload (index, packet_data_to_read); - - // DVD MPEG2: AC3 in PRIVATE_STR_1: fill in syncword count and offset -#ifdef MUX_DEBUG - if (type == PRIVATE_STR_1) { - unsigned int syncwords_found; - - for (i = 0; i < actual_packet_data_size; ++i) { - if (index[i + 4] == 0x0b && i + 5 < actual_packet_data_size && index[i + 5] == 0x77) { - if (syncwords_found == 0) { - if (ac3_header[2] != static_cast < uint8_t > ((i + 1) >> 8) || - ac3_header[3] != static_cast < uint8_t > ((i + 1) & 0xff)) - printf ("BROKEN HEADER %2x %2x (%2x %2x)\n", - ac3_header[2], - ac3_header[3], - static_cast < uint8_t > ((i + 1) >> 8), - static_cast < uint8_t > ((i + 1) & 0xff)); - } - ++syncwords_found; - } - } - } -#endif - bytes_short = target_packet_data_size - actual_packet_data_size; - - /* Handle the situations where we don't have enough data to fill - the packet size fully ... - Small shortfalls are dealt with by stuffing, big ones by inserting - padding packets. - */ - - - if (bytes_short < MINIMUM_PADDING_PACKET_SIZE && bytes_short > 0) { - if (mpeg_version == 1) { - /* MPEG-1 stuffing happens *before* header data fields. */ - memmove (fixed_packet_header_end + bytes_short, - fixed_packet_header_end, actual_packet_data_size + (index - fixed_packet_header_end) - ); - for (j = 0; j < bytes_short; ++j) - fixed_packet_header_end[j] = static_cast < uint8_t > (STUFFING_BYTE); - } else { - memmove (index + bytes_short, index, actual_packet_data_size); - for (j = 0; j < bytes_short; ++j) - *(index + j) = static_cast < uint8_t > (STUFFING_BYTE); - } - index += bytes_short; - bytes_short = 0; - } - - - /* MPEG-2: we now know the header length... but we mustn't forget - to take into account any non-MPEG headers we've included. - Currently this only happens for AC3 audio, but who knows... - */ - if (mpeg_version == 2 && type != PADDING_STR) { - unsigned int pes_header_len = index - (pes_header_len_offset + 1); - - *pes_header_len_offset = static_cast < uint8_t > (pes_header_len); - } - index += actual_packet_data_size; - /* MPEG-1, MPEG-2: Now we know that actual packet size */ - size_offset[0] = static_cast < uint8_t > ((index - size_offset - 2) >> 8); - size_offset[1] = static_cast < uint8_t > ((index - size_offset - 2) & 0xff); - - /* The case where we have fallen short enough to allow it to be - dealt with by inserting a stuffing packet... */ - if (bytes_short != 0) { - *(index++) = static_cast < uint8_t > (PACKET_START) >> 16; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x00ffff) >> 8; - *(index++) = static_cast < uint8_t > (PACKET_START & 0x0000ff); - *(index++) = PADDING_STR; - *(index++) = static_cast < uint8_t > ((bytes_short - 6) >> 8); - *(index++) = static_cast < uint8_t > ((bytes_short - 6) & 0xff); - if (mpeg_version == 2) { - for (i = 0; i < bytes_short - 6; i++) - *(index++) = static_cast < uint8_t > (STUFFING_BYTE); - } else { - *(index++) = 0x0F; /* TODO: A.Stevens 2000 Why is this here? */ - for (i = 0; i < bytes_short - 7; i++) - *(index++) = static_cast < uint8_t > (STUFFING_BYTE); - } - - bytes_short = 0; - } - - if (end_marker) { - *(index++) = static_cast < uint8_t > ((ISO11172_END) >> 24); - *(index++) = static_cast < uint8_t > ((ISO11172_END & 0x00ff0000) >> 16); - *(index++) = static_cast < uint8_t > ((ISO11172_END & 0x0000ff00) >> 8); - *(index++) = static_cast < uint8_t > (ISO11172_END & 0x000000ff); - } - - for (i = 0; i < strm.zero_stuffing; i++) - *(index++) = static_cast < uint8_t > (0); - - - /* At this point padding or stuffing will have ensured the packet - is filled to target_packet_data_size - */ - RawWrite (sector_buf, sector_size); - return actual_packet_data_size; -} - - - - -/************************************************************************* - Create_Pack - erstellt in einem Buffer die spezifischen Pack-Informationen. - Diese werden dann spaeter von der Sector-Routine nochmals - in dem Sektor kopiert. - - writes specifical pack header information into a buffer - later this will be copied from the sector routine into - the sector buffer -*************************************************************************/ - -void -PS_Stream::CreatePack (Pack_struc * pack, clockticks SCR, unsigned int mux_rate) -{ - uint8_t *index; - - index = pack->buf; - - *(index++) = static_cast < uint8_t > ((PACK_START) >> 24); - *(index++) = static_cast < uint8_t > ((PACK_START & 0x00ff0000) >> 16); - *(index++) = static_cast < uint8_t > ((PACK_START & 0x0000ff00) >> 8); - *(index++) = static_cast < uint8_t > (PACK_START & 0x000000ff); - - if (mpeg_version == 2) { - /* Annoying: MPEG-2's SCR pack header time is different from - all the rest... */ - BufferMpeg2ScrTimecode (SCR, &index); - *(index++) = static_cast < uint8_t > (mux_rate >> 14); - *(index++) = static_cast < uint8_t > (0xff & (mux_rate >> 6)); - *(index++) = static_cast < uint8_t > (0x03 | ((mux_rate & 0x3f) << 2)); - *(index++) = static_cast < uint8_t > (RESERVED_BYTE << 3 | 0); /* No pack stuffing */ - } else { - BufferDtsPtsMpeg1ScrTimecode (SCR, MARKER_MPEG1_SCR, &index); - *(index++) = static_cast < uint8_t > (0x80 | (mux_rate >> 15)); - *(index++) = static_cast < uint8_t > (0xff & (mux_rate >> 7)); - *(index++) = static_cast < uint8_t > (0x01 | ((mux_rate & 0x7f) << 1)); - } - pack->SCR = SCR; - pack->length = index - pack->buf; -} - - -/************************************************************************* - Create_Sys_Header - erstelle in einem Buffer die spezifischen Sys_Header - Informationen. Diese werden spaeter von der Sector-Routine - nochmals zum Sectorbuffer kopiert. - - writes specifical system header information into a buffer - later this will be copied from the sector routine into - the sector buffer - RETURN: Length of header created... -*************************************************************************/ - -void -PS_Stream::CreateSysHeader (Sys_header_struc * sys_header, - unsigned int rate_bound, - bool fixed, - int CSPS, - bool audio_lock, bool video_lock, vector < MuxStream * >&streams) -{ - uint8_t *index; - uint8_t *len_index; - int system_header_size; - - index = sys_header->buf; - int video_bound = 0; - int audio_bound = 0; - - vector < MuxStream * >::iterator str; - for (str = streams.begin (); str < streams.end (); ++str) { - switch (((*str)->stream_id & 0xe0)) { - case 0xe0: // MPEG Video - ++video_bound; - break; - case 0xb9: // DVD seems to use this stream id in - ++video_bound; // system headers for video buffer size - break; - case 0xc0: - ++audio_bound; // MPEG Audio - break; - default: - break; - } - } - - /* if we are not using both streams, we should clear some - options here */ - - *(index++) = static_cast < uint8_t > ((SYS_HEADER_START) >> 24); - *(index++) = static_cast < uint8_t > ((SYS_HEADER_START & 0x00ff0000) >> 16); - *(index++) = static_cast < uint8_t > ((SYS_HEADER_START & 0x0000ff00) >> 8); - *(index++) = static_cast < uint8_t > (SYS_HEADER_START & 0x000000ff); - - len_index = index; /* Skip length field for now... */ - index += 2; - - *(index++) = static_cast < uint8_t > (0x80 | (rate_bound >> 15)); - *(index++) = static_cast < uint8_t > (0xff & (rate_bound >> 7)); - *(index++) = static_cast < uint8_t > (0x01 | ((rate_bound & 0x7f) << 1)); - *(index++) = static_cast < uint8_t > ((audio_bound << 2) | (fixed << 1) | CSPS); - *(index++) = static_cast < uint8_t > ((audio_lock << 7) | (video_lock << 6) | 0x20 | video_bound); - - *(index++) = static_cast < uint8_t > (RESERVED_BYTE); - for (str = streams.begin (); str < streams.end (); ++str) { - *(index++) = (*str)->stream_id; - *(index++) = static_cast < uint8_t > - (0xc0 | ((*str)->BufferScale () << 5) | ((*str)->BufferSizeCode () >> 8)); - *(index++) = static_cast < uint8_t > ((*str)->BufferSizeCode () & 0xff); - } - - - system_header_size = (index - sys_header->buf); - len_index[0] = static_cast < uint8_t > ((system_header_size - 6) >> 8); - len_index[1] = static_cast < uint8_t > ((system_header_size - 6) & 0xff); - sys_header->length = system_header_size; -} - - -void -PS_Stream::RawWrite (uint8_t * buf, unsigned int len) -{ - if (callback (this, buf, len, user_data) != len) { - mjpeg_error_exit1 ("Failed write"); - } - written += len; -} - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/systems.hh b/ext/mplex/systems.hh deleted file mode 100644 index bbad92f..0000000 --- a/ext/mplex/systems.hh +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef __SYSTEMS_HH__ -#define __SYSTEMS_HH__ - -#include "inputstrm.hh" - -#include - -using std::vector; - -/* Buffer size parameters */ - -#define MAX_SECTOR_SIZE 16384 -#define MAX_PACK_HEADER_SIZE 255 -#define MAX_SYS_HEADER_SIZE 255 - - -typedef class PS_Stream _PS_Stream; - -typedef size_t (*WriteCallback) (_PS_Stream *str, uint8_t *data, size_t size, void *user_data); - - -typedef struct sector_struc /* Ein Sektor, kann Pack, Sys Header */ -/* und Packet enthalten. */ -{ - unsigned char buf[MAX_SECTOR_SIZE]; - unsigned int length_of_packet_data; - //clockticks TS ; -} -Sector_struc; - -typedef struct pack_struc /* Pack Info */ -{ - unsigned char buf[MAX_PACK_HEADER_SIZE]; - int length; - clockticks SCR; -} -Pack_struc; - -typedef struct sys_header_struc /* System Header Info */ -{ - unsigned char buf[MAX_SYS_HEADER_SIZE]; - int length; -} -Sys_header_struc; - - -class PS_Stream { -public: - PS_Stream (WriteCallback _callback, void *_user_data): - callback (_callback), - user_data (_user_data) - { - } - - void Init (unsigned _mpeg, unsigned int _sector_sizen, off_t max_segment_size); // 0 = No Limit - - bool FileLimReached (); - void NextFile (); - unsigned int PacketPayload (MuxStream & strm, - Sys_header_struc * sys_header, - Pack_struc * pack_header, int buffers, int PTSstamp, int DTSstamp); - - unsigned int CreateSector (Pack_struc * pack, - Sys_header_struc * sys_header, - unsigned int max_packet_data_size, - MuxStream & strm, - bool buffers, bool end_marker, clockticks PTS, clockticks DTS, uint8_t timestamps); - void RawWrite (uint8_t * data, unsigned int len); - static void BufferSectorHeader (uint8_t * buf, - Pack_struc * pack, Sys_header_struc * sys_header, uint8_t * &header_end); - static void BufferPacketHeader (uint8_t * buf, - uint8_t type, - unsigned int mpeg_version, - bool buffers, - unsigned int buffer_size, - uint8_t buffer_scale, - clockticks PTS, - clockticks DTS, - uint8_t timestamps, uint8_t * &size_field, uint8_t * &header_end); - - static inline void BufferPacketSize (uint8_t * size_field, uint8_t * packet_end) - { - unsigned int - packet_size = - packet_end - - size_field - - 2; - - size_field[0] = static_cast < uint8_t > (packet_size >> 8); - size_field[1] = static_cast < uint8_t > (packet_size & 0xff); - - } - - void CreatePack (Pack_struc * pack, clockticks SCR, unsigned int mux_rate); - void CreateSysHeader (Sys_header_struc * sys_header, - unsigned int rate_bound, - bool fixed, - int CSPS, bool audio_lock, bool video_lock, vector < MuxStream * >&streams); - - void Close () - { - } - -private: - - /* TODO: Replace **'s with *&'s */ - static void BufferDtsPtsMpeg1ScrTimecode (clockticks timecode, uint8_t marker, uint8_t ** buffer); - static void BufferMpeg2ScrTimecode (clockticks timecode, uint8_t ** buffer); - void BufferPaddingPacket (int padding, uint8_t * &buffer); - -private: - unsigned int mpeg_version; - unsigned int sector_size; - int segment_num; - - off_t max_segment_size; - uint8_t * sector_buf; - WriteCallback callback; - void *user_data; - off_t written; -}; -#endif // __SYSTEMS_HH__ - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/vector.cc b/ext/mplex/vector.cc deleted file mode 100644 index 343b628..0000000 --- a/ext/mplex/vector.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include -#include "mjpeg_types.h" -#include "vector.hh" - - -AUStream::AUStream (): -cur_rd (0), cur_wr (0), totalctr (0), size (0), buf (0) -{ - buf = new (Aunit *)[AUStream::BUF_SIZE]; -} - - -void -AUStream::init (Aunit * rec) -{ - buf[cur_wr] = rec; - ++cur_wr; - cur_wr = cur_wr >= AUStream::BUF_SIZE ? 0 : cur_wr; - cur_rd = cur_wr; -} diff --git a/ext/mplex/vector.hh b/ext/mplex/vector.hh deleted file mode 100644 index 9a4f041..0000000 --- a/ext/mplex/vector.hh +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __AUSTREAM_H__ -#define __AUSTREAM_H__ - -#include -#include -#include "mjpeg_logging.h" -#include "aunit.hh" - -class AUStream -{ -public: - AUStream (); - - void init (Aunit * rec); - - void append (Aunit & rec) - { - if (size == BUF_SIZE) - mjpeg_error_exit1 ("INTERNAL ERROR: AU buffer overflow"); - *buf[cur_wr] = rec; - ++size; - ++cur_wr; - cur_wr = cur_wr >= BUF_SIZE ? 0 : cur_wr; - } - - inline Aunit *next () - { - if (size == 0) { - return 0; - } else { - Aunit *ret; - - ret = buf[cur_rd]; - ++cur_rd; - ++totalctr; - --size; - cur_rd = cur_rd >= BUF_SIZE ? 0 : cur_rd; - return ret; - } - } - - inline Aunit *lookahead () - { - return size == 0 ? 0 : buf[cur_rd]; - } - - inline Aunit *last () - { - int i = cur_wr - 1 < 0 ? BUF_SIZE - 1 : cur_wr - 1; - - return buf[i]; - } - - static const unsigned int BUF_SIZE = 128; - - inline unsigned int current () - { - return totalctr; - } -//private: - unsigned int cur_rd; - unsigned int cur_wr; - unsigned int totalctr; - unsigned int size; - Aunit **buf; -}; - - - - -#endif // __AUSTREAM_H__ diff --git a/ext/mplex/videostrm.hh b/ext/mplex/videostrm.hh deleted file mode 100644 index 6eeac47..0000000 --- a/ext/mplex/videostrm.hh +++ /dev/null @@ -1,155 +0,0 @@ - -/* - * videostrm.hh: Video stream elementary input stream - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __VIDEOSTRM_H__ -#define __VIDEOSTRM_H__ - -#include "inputstrm.hh" - -class VideoStream:public ElementaryStream -{ -public: - VideoStream (IBitStream & ibs, OutputStream & into); - void Init (const int stream_num); - static bool Probe (IBitStream & bs); - - void Close (); - - inline int AUType () - { - return au->type; - } - - inline bool EndSeq () - { - return au->end_seq; - } - - inline int NextAUType () - { - VAunit *p_au = Lookahead (); - - if (p_au != NULL) - return p_au->type; - else - return NOFRAME; - } - - inline bool SeqHdrNext () - { - VAunit *p_au = Lookahead (); - - return p_au != NULL && p_au->seq_header; - } - - virtual unsigned int NominalBitRate () - { - return bit_rate * 50; - } - - virtual void OutputGOPControlSector (); - bool RunOutComplete (); - virtual bool MuxPossible (clockticks currentSCR); - void SetMaxStdBufferDelay (unsigned int demux_rate); - void OutputSector (); - -protected: - void OutputSeqhdrInfo (); - virtual bool AUBufferNeedsRefill (); - virtual void FillAUbuffer (unsigned int frames_to_buffer); - virtual void InitAUbuffer (); - virtual void NextDTSPTS (clockticks & DTS, clockticks & PTS); - void ScanFirstSeqHeader (); - uint8_t NewAUTimestamps (int AUtype); - bool NewAUBuffers (int AUtype); - -public: - unsigned int num_sequence; - unsigned int num_seq_end; - unsigned int num_pictures; - unsigned int num_groups; - unsigned int num_frames[4]; - unsigned int avg_frames[4]; - - unsigned int horizontal_size; - unsigned int vertical_size; - unsigned int aspect_ratio; - unsigned int picture_rate; - unsigned int bit_rate; - unsigned int comp_bit_rate; - unsigned int peak_bit_rate; - unsigned int vbv_buffer_size; - unsigned int CSPF; - double secs_per_frame; - - - bool dtspts_for_all_au; - bool gop_control_packet; - -protected: - - /* State variables for scanning source bit-stream */ - VAunit access_unit; - unsigned int fields_presented; - unsigned int group_order; - unsigned int group_start_pic; - unsigned int group_start_field; - int temporal_reference; - unsigned int pict_rate; - unsigned int pict_struct; - int pulldown_32; - int repeat_first_field; - int prev_temp_ref; - double frame_rate; - unsigned int max_bits_persec; - int AU_pict_data; - int AU_hdr; - clockticks max_PTS; - clockticks max_STD_buffer_delay; - - int opt_mpeg; - int opt_multifile_segment; -}; - -// -// DVD's generate control sectors for each GOP... -// - -class DVDVideoStream:public VideoStream -{ -public: - DVDVideoStream (IBitStream & ibs, OutputStream & into):VideoStream (ibs, into) - { - gop_control_packet = true; - } - void OutputGOPControlSector (); -}; - -#endif // __INPUTSTRM_H__ - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/videostrm_in.cc b/ext/mplex/videostrm_in.cc deleted file mode 100644 index df9578a..0000000 --- a/ext/mplex/videostrm_in.cc +++ /dev/null @@ -1,429 +0,0 @@ -/* - * inptstrm.c: Members of video stream class related to raw stream - * scanning and buffering. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include - -#include "videostrm.hh" -#include "outputstream.hh" - - - -static void -marker_bit (IBitStream & bs, unsigned int what) -{ - if (what != bs.get1bit ()) { - mjpeg_error ("Illegal MPEG stream at offset (bits) %d: supposed marker bit not found.", - (int)bs.bitcount ()); - exit (1); - } -} - - -void -VideoStream::ScanFirstSeqHeader () -{ - if (bs.getbits (32) == SEQUENCE_HEADER) { - num_sequence++; - horizontal_size = bs.getbits (12); - vertical_size = bs.getbits (12); - aspect_ratio = bs.getbits (4); - pict_rate = bs.getbits (4); - picture_rate = pict_rate; - bit_rate = bs.getbits (18); - marker_bit (bs, 1); - vbv_buffer_size = bs.getbits (10); - CSPF = bs.get1bit (); - - } else { - mjpeg_error ("Invalid MPEG Video stream header."); - exit (1); - } - - if (pict_rate > 0 && pict_rate <= mpeg_num_framerates) { - frame_rate = Y4M_RATIO_DBL (mpeg_framerate (pict_rate)); - } else { - frame_rate = 25.0; - } - -} - - - - -void -VideoStream::Init (const int stream_num) -{ - mjpeg_debug ("SETTING video buffer to %d", muxinto.video_buffer_size); - MuxStream::Init (VIDEO_STR_0 + stream_num, 1, // Buffer scale - muxinto.video_buffer_size, 0, // Zero stuffing - muxinto.buffers_in_video, muxinto.always_buffers_in_video); - mjpeg_info ("Scanning for header info: Video stream %02x ", VIDEO_STR_0 + stream_num); - InitAUbuffer (); - - ScanFirstSeqHeader (); - - /* Skip to the end of the 1st AU (*2nd* Picture start!) - */ - AU_hdr = SEQUENCE_HEADER; - AU_pict_data = 0; - AU_start = 0LL; - - OutputSeqhdrInfo (); -} - -// -// Set the Maximum STD buffer delay for this video stream. -// By default we set 1 second but if we have specified a video -// buffer that can hold more than 1.0 seconds demuxed data we -// set the delay to the time to fill the buffer. -// - -void -VideoStream::SetMaxStdBufferDelay (unsigned int dmux_rate) -{ - double max_delay = CLOCKS; - - if (static_cast < double >(BufferSize ()) / dmux_rate > 1.0) - max_delay *= static_cast < double >(BufferSize ()) / dmux_rate; - - // - // To enforce a maximum STD buffer residency the - // calculation is a bit tricky as when we decide to mux we may - // (but not always) have some of the *previous* picture left to - // mux in which case it is the timestamp of the next picture that counts. - // For simplicity we simply reduce the limit by 1.5 frame intervals - // and use the timestamp for the current picture. - // - if (frame_rate > 10.0) - max_STD_buffer_delay = static_cast < clockticks > (max_delay * (frame_rate - 1.5) / frame_rate); - else - max_STD_buffer_delay = static_cast < clockticks > (10.0 * max_delay / frame_rate); - -} - -// -// Return whether AU buffer needs refilling. There are two cases: -// 1. We have less than our look-ahead "FRAME_CHUNK" buffer AU's -// buffered 2. AU's are very small and we could have less than 1 -// sector's worth of data buffered. -// - -bool -VideoStream::AUBufferNeedsRefill () -{ - return - !eoscan - && (aunits.current () + FRAME_CHUNK > last_buffered_AU - || bs.buffered_bytes () < muxinto.sector_size); -} - -// -// Refill the AU unit buffer setting AU PTS DTS from the scanned -// header information... -// - -void -VideoStream::FillAUbuffer (unsigned int frames_to_buffer) -{ - if (eoscan) - return; - - last_buffered_AU += frames_to_buffer; - mjpeg_debug ("Scanning %d video frames to frame %d", frames_to_buffer, last_buffered_AU); - - // We set a limit of 2M to seek before we give up. - // This is intentionally very high because some heavily - // padded still frames may have a loooong gap before - // a following sequence end marker. - while (!bs.eos () && - bs.seek_sync (SYNCWORD_START, 24, 2 * 1024 * 1024) && - decoding_order < last_buffered_AU) - { - syncword = (SYNCWORD_START << 8) + bs.getbits (8); - if (AU_pict_data) { - - /* Handle the header *ending* an AU... - If we have the AU picture data an AU and have now - reached a header marking the end of an AU fill in the - the AU length and append it to the list of AU's and - start a new AU. I.e. sequence and gop headers count as - part of the AU of the corresponding picture - */ - stream_length = bs.bitcount () - 32LL; - switch (syncword) { - case SEQUENCE_HEADER: - case GROUP_START: - case PICTURE_START: - access_unit.start = AU_start; - access_unit.length = (int) (stream_length - AU_start) >> 3; - access_unit.end_seq = 0; - avg_frames[access_unit.type - 1] += access_unit.length; - aunits.append (access_unit); - mjpeg_debug ("Found AU %d: DTS=%d", access_unit.dorder, (int) access_unit.DTS / 300); - AU_hdr = syncword; - AU_start = stream_length; - AU_pict_data = 0; - break; - case SEQUENCE_END: - access_unit.length = ((stream_length - AU_start) >> 3) + 4; - access_unit.end_seq = 1; - aunits.append (access_unit); - mjpeg_info ("Scanned to end AU %d", access_unit.dorder); - avg_frames[access_unit.type - 1] += access_unit.length; - - /* Do we have a sequence split in the video stream? */ - if (!bs.eos () && bs.getbits (32) == SEQUENCE_HEADER) { - stream_length = bs.bitcount () - 32LL; - AU_start = stream_length; - syncword = AU_hdr = SEQUENCE_HEADER; - AU_pict_data = 0; - if (opt_multifile_segment) - mjpeg_warn - ("Sequence end marker found in video stream but single-segment splitting specified!"); - } else { - if (!bs.eos () && !opt_multifile_segment) - mjpeg_warn ("No seq. header starting new sequence after seq. end!"); - } - - num_seq_end++; - break; - } - } - - /* Handle the headers starting an AU... */ - switch (syncword) { - case SEQUENCE_HEADER: - /* TODO: Really we should update the info here so we can handle - streams where parameters change on-the-fly... */ - num_sequence++; - break; - - case GROUP_START: - num_groups++; - group_order = 0; - break; - - case PICTURE_START: - /* We have reached AU's picture data... */ - AU_pict_data = 1; - - prev_temp_ref = temporal_reference; - temporal_reference = bs.getbits (10); - access_unit.type = bs.getbits (3); - - /* Now scan forward a little for an MPEG-2 picture coding extension - so we can get pulldown info (if present) */ - if (bs.seek_sync (EXT_START_CODE, 32, 64) && bs.getbits (4) == CODING_EXT_ID) { - /* Skip: 4 F-codes (4)... */ - (void) bs.getbits (16); - /* Skip: DC Precision(2) */ - (void) bs.getbits (2); - pict_struct = bs.getbits (2); - /* Skip: topfirst (1) frame pred dct (1), - concealment_mv(1), q_scale_type (1), */ - (void) bs.getbits (4); - /* Skip: intra_vlc_format(1), alternate_scan (1) */ - (void) bs.getbits (2); - repeat_first_field = bs.getbits (1); - pulldown_32 |= repeat_first_field; - - } else { - repeat_first_field = 0; - pict_struct = PIC_FRAME; - } - - if (access_unit.type == IFRAME) { - unsigned int bits_persec = - (unsigned int) (((double) (stream_length - prev_offset)) * - 2 * frame_rate / ((double) (2 + fields_presented - group_start_field))); - - if (bits_persec > max_bits_persec) { - max_bits_persec = bits_persec; - } - prev_offset = stream_length; - group_start_pic = decoding_order; - group_start_field = fields_presented; - } - - NextDTSPTS (access_unit.DTS, access_unit.PTS); - - access_unit.dorder = decoding_order; - access_unit.porder = temporal_reference + group_start_pic; - access_unit.seq_header = (AU_hdr == SEQUENCE_HEADER); - - decoding_order++; - group_order++; - - if ((access_unit.type > 0) && (access_unit.type < 5)) { - num_frames[access_unit.type - 1]++; - } - - - if (decoding_order >= old_frames + 1000) { - mjpeg_debug ("Got %d picture headers.", decoding_order); - old_frames = decoding_order; - } - - break; - - - - } - } - last_buffered_AU = decoding_order; - num_pictures = decoding_order; - eoscan = bs.eos (); -} - -void -VideoStream::Close () -{ - - bs.close (); - stream_length = (unsigned int) (AU_start / 8); - for (int i = 0; i < 4; i++) { - avg_frames[i] /= num_frames[i] == 0 ? 1 : num_frames[i]; - } - - comp_bit_rate = (unsigned int) - ((((double) stream_length) / ((double) fields_presented)) * 2.0 - * ((double) frame_rate) + 25.0) / 50; - - /* Peak bit rate in 50B/sec units... */ - peak_bit_rate = ((max_bits_persec / 8) / 50); - mjpeg_info ("VIDEO_STATISTICS: %02x", stream_id); - mjpeg_info ("Video Stream length: %11u bytes", (int)stream_length / 8); - mjpeg_info ("Sequence headers: %8u", num_sequence); - mjpeg_info ("Sequence ends : %8u", num_seq_end); - mjpeg_info ("No. Pictures : %8u", num_pictures); - mjpeg_info ("No. Groups : %8u", num_groups); - mjpeg_info ("No. I Frames : %8u avg. size%6u bytes", num_frames[0], avg_frames[0]); - mjpeg_info ("No. P Frames : %8u avg. size%6u bytes", num_frames[1], avg_frames[1]); - mjpeg_info ("No. B Frames : %8u avg. size%6u bytes", num_frames[2], avg_frames[2]); - mjpeg_info ("No. D Frames : %8u avg. size%6u bytes", num_frames[3], avg_frames[3]); - mjpeg_info ("Average bit-rate : %8u bits/sec", comp_bit_rate * 400); - mjpeg_info ("Peak bit-rate : %8u bits/sec", peak_bit_rate * 400); - -} - - - - -/************************************************************************* - OutputSeqHdrInfo - Display sequence header parameters -*************************************************************************/ - -void -VideoStream::OutputSeqhdrInfo () -{ - const char *str; - - mjpeg_info ("VIDEO STREAM: %02x", stream_id); - - mjpeg_info ("Frame width : %u", horizontal_size); - mjpeg_info ("Frame height : %u", vertical_size); - if (aspect_ratio <= mpeg_num_aspect_ratios[opt_mpeg - 1]) - str = mpeg_aspect_code_definition (opt_mpeg, aspect_ratio); - else - str = "forbidden"; - mjpeg_info ("Aspect ratio : %s", str); - - - if (picture_rate == 0) - mjpeg_info ("Picture rate : forbidden"); - else if (picture_rate <= mpeg_num_framerates) - mjpeg_info ("Picture rate : %2.3f frames/sec", - Y4M_RATIO_DBL (mpeg_framerate (picture_rate))); - else - mjpeg_info ("Picture rate : %x reserved", picture_rate); - - if (bit_rate == 0x3ffff) { - bit_rate = 0; - mjpeg_info ("Bit rate : variable"); - } else if (bit_rate == 0) - mjpeg_info ("Bit rate : forbidden"); - else - mjpeg_info ("Bit rate : %u bits/sec", bit_rate * 400); - - mjpeg_info ("Vbv buffer size : %u bytes", vbv_buffer_size * 2048); - mjpeg_info ("CSPF : %u", CSPF); -} - -// -// Compute PTS DTS of current AU in the video sequence being -// scanned. This is is the PTS/DTS calculation for normal video only. -// It is virtual and over-ridden for non-standard streams (Stills -// etc!). -// - -void -VideoStream::NextDTSPTS (clockticks & DTS, clockticks & PTS) -{ - if (pict_struct != PIC_FRAME) { - DTS = static_cast < clockticks > (fields_presented * (double) (CLOCKS / 2) / frame_rate); - int dts_fields = temporal_reference * 2 + group_start_field + 1; - - if (temporal_reference == prev_temp_ref) - dts_fields += 1; - PTS = static_cast < clockticks > (dts_fields * (double) (CLOCKS / 2) / frame_rate); - access_unit.porder = temporal_reference + group_start_pic; - fields_presented += 1; - } else if (pulldown_32) { - int frames2field; - int frames3field; - - DTS = static_cast < clockticks > (fields_presented * (double) (CLOCKS / 2) / frame_rate); - if (repeat_first_field) { - frames2field = (temporal_reference + 1) / 2; - frames3field = temporal_reference / 2; - fields_presented += 3; - } else { - frames2field = (temporal_reference) / 2; - frames3field = (temporal_reference + 1) / 2; - fields_presented += 2; - } - PTS = static_cast < clockticks > - ((frames2field * 2 + frames3field * 3 + group_start_field + - 1) * (double) (CLOCKS / 2) / frame_rate); - access_unit.porder = temporal_reference + group_start_pic; - } else { - DTS = static_cast < clockticks > (decoding_order * (double) CLOCKS / frame_rate); - PTS = static_cast < clockticks > - ((temporal_reference + group_start_pic + 1) * (double) CLOCKS / frame_rate); - fields_presented += 2; - } - -} - - - - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/videostrm_out.cc b/ext/mplex/videostrm_out.cc deleted file mode 100644 index a70bd07..0000000 --- a/ext/mplex/videostrm_out.cc +++ /dev/null @@ -1,276 +0,0 @@ - -/* - * inptstrm.c: Members of input stream classes related to muxing out into - * the output stream. - * - * Copyright (C) 2001 Andrew Stevens - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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. - */ - - -#include -#include -#include "fastintfns.h" -#include "videostrm.hh" -#include "outputstream.hh" - - -VideoStream::VideoStream (IBitStream & ibs, OutputStream & into): -ElementaryStream (ibs, into, ElementaryStream::video), -num_sequence (0), -num_seq_end (0), -num_pictures (0), -num_groups (0), dtspts_for_all_au (into.dtspts_for_all_vau), gop_control_packet (false) -{ - prev_offset = 0; - decoding_order = 0; - fields_presented = 0; - group_order = 0; - group_start_pic = 0; - group_start_field = 0; - temporal_reference = 0; - pulldown_32 = 0; - temporal_reference = -1; // Needed to recognise 2nd field of 1st - // frame in a field pic sequence - last_buffered_AU = 0; - max_bits_persec = 0; - AU_hdr = SEQUENCE_HEADER; /* GOP or SEQ Header starting AU? */ - for (int i = 0; i < 4; ++i) - num_frames[i] = avg_frames[i] = 0; - FRAME_CHUNK = 6; - - this->opt_mpeg = into.opt_mpeg; - this->opt_multifile_segment = into.opt_multifile_segment; -} - -bool -VideoStream::Probe (IBitStream & bs) -{ - return bs.getbits (32) == 0x1b3; -} - -void -VideoStream::InitAUbuffer () -{ - unsigned int i; - - for (i = 0; i < aunits.BUF_SIZE; ++i) - aunits.init (new VAunit); -} - - -/********************************* - * Signals when video stream has completed mux run-out specified - * in associated mux stream. Run-out is always to complete GOP's. - *********************************/ - -bool -VideoStream::RunOutComplete () -{ - - return (au_unsent == 0 || - (muxinto.running_out && au->type == IFRAME && RequiredPTS () >= muxinto.runout_PTS)); -} - -/********************************* - * Signals if it is permissible/possible to Mux out a sector from the Stream. - * The universal constraints that muxing should not be complete and that - * that the reciever buffer should have sufficient it also insists that - * the muxed data won't hang around in the receiver buffer for more than - * one second. This is mainly for the benefit of (S)VCD and DVD applications - * where long delays mess up random access. - *******************************/ - - -bool -VideoStream::MuxPossible (clockticks currentSCR) -{ - - return (ElementaryStream::MuxPossible (currentSCR) && - RequiredDTS () < currentSCR + max_STD_buffer_delay); -} - -/********************************* - * Work out the timestamps to be set in the header of sectors starting - * new AU's. - *********************************/ - -uint8_t -VideoStream::NewAUTimestamps (int AUtype) -{ - uint8_t timestamps; - - if (AUtype == BFRAME) - timestamps = TIMESTAMPBITS_PTS; - else - timestamps = TIMESTAMPBITS_PTS_DTS; - - if (muxinto.timestamp_iframe_only && AUtype != IFRAME) - timestamps = TIMESTAMPBITS_NO; - return timestamps; -} - -/********************************* - * Work out the buffer records to be set in the header of sectors - * starting new AU's. - *********************************/ - -bool -VideoStream::NewAUBuffers (int AUtype) -{ - return buffers_in_header & !(muxinto.video_buffers_iframe_only && AUtype != IFRAME); -} - -/****************************************************************** - Output_Video - generiert Pack/Sys_Header/Packet Informationen aus dem - Video Stream und speichert den so erhaltenen Sektor ab. - - generates Pack/Sys_Header/Packet information from the - video stream and writes out the new sector -******************************************************************/ - -void -VideoStream::OutputSector () -{ - - unsigned int max_packet_payload; - unsigned int actual_payload; - unsigned int old_au_then_new_payload; - clockticks DTS, PTS; - int autype; - - max_packet_payload = 0; /* 0 = Fill sector */ - /* - We're now in the last AU of a segment. - So we don't want to go beyond it's end when filling - sectors. Hence we limit packet payload size to (remaining) AU length. - The same applies when we wish to ensure sequence headers starting - ACCESS-POINT AU's in (S)VCD's etc are sector-aligned. - */ - int nextAU = NextAUType (); - - if ((muxinto.running_out && nextAU == IFRAME && - NextRequiredPTS () > muxinto.runout_PTS) || - (muxinto.sector_align_iframeAUs && nextAU == IFRAME) - ) { - max_packet_payload = au_unsent; - } - - /* Figure out the threshold payload size below which we can fit more - than one AU into a packet N.b. because fitting more than one in - imposses an overhead of additional header fields so there is a - dead spot where we *have* to stuff the packet rather than start - fitting in an extra AU. Slightly over-conservative in the case - of the last packet... */ - - old_au_then_new_payload = muxinto.PacketPayload (*this, buffers_in_header, true, true); - - /* CASE: Packet starts with new access unit */ - if (new_au_next_sec) { - autype = AUType (); - // - // Some types of output format (e.g. DVD) require special - // control sectors before the sector starting a new GOP - // N.b. this implies muxinto.sector_align_iframeAUs - // - if (gop_control_packet && autype == IFRAME) { - OutputGOPControlSector (); - } - - if (dtspts_for_all_au && max_packet_payload == 0) - max_packet_payload = au_unsent; - - PTS = RequiredPTS (); - DTS = RequiredDTS (); - actual_payload = - muxinto.WritePacket (max_packet_payload, - *this, NewAUBuffers (autype), PTS, DTS, NewAUTimestamps (autype)); - - } - - /* CASE: Packet begins with old access unit, no new one */ - /* can begin in the very same packet */ - - else if (au_unsent >= old_au_then_new_payload || - (max_packet_payload != 0 && au_unsent >= max_packet_payload)) { - actual_payload = muxinto.WritePacket (au_unsent, *this, false, 0, 0, TIMESTAMPBITS_NO); - } - - /* CASE: Packet begins with old access unit, a new one */ - /* could begin in the very same packet */ - else { /* if ( !new_au_next_sec && - (au_unsent < old_au_then_new_payload)) */ - /* Is there a new access unit ? */ - if (Lookahead () != 0) { - autype = NextAUType (); - if (dtspts_for_all_au && max_packet_payload == 0) - max_packet_payload = au_unsent + Lookahead ()->length; - - PTS = NextRequiredPTS (); - DTS = NextRequiredDTS (); - - actual_payload = - muxinto.WritePacket (max_packet_payload, - *this, NewAUBuffers (autype), PTS, DTS, NewAUTimestamps (autype)); - } else { - actual_payload = muxinto.WritePacket (0, *this, false, 0, 0, TIMESTAMPBITS_NO); - } - - } - ++nsec; - buffers_in_header = always_buffers_in_header; -} - - -/*********************************************** - OutputControlSector - Write control sectors prefixing a GOP - For "normal" video streams this doesn't happen and so represents - a bug and triggers an abort. - - In DVD's these sectors carry a system header and what is - presumably indexing and/or sub-title information in - private_stream_2 packets. I have no idea what to put in here so we - simply pad the sector out. -***********************************************/ - -void -VideoStream::OutputGOPControlSector () -{ - abort (); -} - - /****************************************************************** - * OutputGOPControlSector - * DVD System headers are carried in peculiar sectors carrying 2 - * PrivateStream2 packets. We're sticking 0's in the packets - * as we have no idea what's supposed to be in there. - ******************************************************************/ - -void -DVDVideoStream::OutputGOPControlSector () -{ - muxinto.OutputDVDPriv2 (); -} - - -/* - * Local variables: - * c-file-style: "stroustrup" - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/mplex/yuv4mpeg.cc b/ext/mplex/yuv4mpeg.cc deleted file mode 100644 index a9e1aeb..0000000 --- a/ext/mplex/yuv4mpeg.cc +++ /dev/null @@ -1,880 +0,0 @@ -/* - * yuv4mpeg.c: Functions for reading and writing "new" YUV4MPEG streams - * - * Copyright (C) 2001 Matthew J. Marjanovic - * - * - * 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. - * - */ - -#include - -#include -#include -#include -#include -#include "yuv4mpeg.h" -#include "yuv4mpeg_intern.h" -#include "mjpeg_logging.h" - - -static int _y4mparam_allow_unknown_tags = 1; /* default is forgiveness */ - -static void *(*_y4m_alloc) (size_t bytes) = malloc; -static void (*_y4m_free) (void *ptr) = free; - - - -int -y4m_allow_unknown_tags (int yn) -{ - int old = _y4mparam_allow_unknown_tags; - - if (yn >= 0) - _y4mparam_allow_unknown_tags = (yn) ? 1 : 0; - return old; -} - - - -/************************************************************************* - * - * Convenience functions for fd read/write - * - * - guaranteed to transfer entire payload (or fail) - * - returns: - * 0 on complete success - * +(# of remaining bytes) on eof (for y4m_read) - * -(# of rem. bytes) on error (and ERRNO should be set) - * - *************************************************************************/ - - -ssize_t -y4m_read (int fd, void *buf, size_t len) -{ - ssize_t n; - uint8_t *ptr = (uint8_t *) buf; - - while (len > 0) { - n = read (fd, ptr, len); - if (n <= 0) { - /* return amount left to read */ - if (n == 0) - return len; /* n == 0 --> eof */ - else - return -len; /* n < 0 --> error */ - } - ptr += n; - len -= n; - } - return 0; -} - - -ssize_t -y4m_write (int fd, const void *buf, size_t len) -{ - ssize_t n; - const uint8_t *ptr = (const uint8_t *) buf; - - while (len > 0) { - n = write (fd, ptr, len); - if (n <= 0) - return -len; /* return amount left to write */ - ptr += n; - len -= n; - } - return 0; -} - - - -/************************************************************************* - * - * "Extra tags" handling - * - *************************************************************************/ - - -static char * -y4m_new_xtag (void) -{ - return (char *) _y4m_alloc (Y4M_MAX_XTAG_SIZE * sizeof (char)); -} - - -void -y4m_init_xtag_list (y4m_xtag_list_t * xtags) -{ - int i; - - xtags->count = 0; - for (i = 0; i < Y4M_MAX_XTAGS; i++) { - xtags->tags[i] = NULL; - } -} - - -void -y4m_fini_xtag_list (y4m_xtag_list_t * xtags) -{ - int i; - - for (i = 0; i < Y4M_MAX_XTAGS; i++) { - if (xtags->tags[i] != NULL) { - _y4m_free (xtags->tags[i]); - xtags->tags[i] = NULL; - } - } - xtags->count = 0; -} - - -void -y4m_copy_xtag_list (y4m_xtag_list_t * dest, const y4m_xtag_list_t * src) -{ - int i; - - for (i = 0; i < src->count; i++) { - if (dest->tags[i] == NULL) - dest->tags[i] = y4m_new_xtag (); - strncpy (dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); - } - dest->count = src->count; -} - - - -static int -y4m_snprint_xtags (char *s, int maxn, const y4m_xtag_list_t * xtags) -{ - int i, room; - - for (i = 0, room = maxn - 1; i < xtags->count; i++) { - int n = snprintf (s, room + 1, " %s", xtags->tags[i]); - - if ((n < 0) || (n > room)) - return Y4M_ERR_HEADER; - s += n; - room -= n; - } - s[0] = '\n'; /* finish off header with newline */ - s[1] = '\0'; /* ...and end-of-string */ - return Y4M_OK; -} - - -int -y4m_xtag_count (const y4m_xtag_list_t * xtags) -{ - return xtags->count; -} - - -const char * -y4m_xtag_get (const y4m_xtag_list_t * xtags, int n) -{ - if (n >= xtags->count) - return NULL; - else - return xtags->tags[n]; -} - - -int -y4m_xtag_add (y4m_xtag_list_t * xtags, const char *tag) -{ - if (xtags->count >= Y4M_MAX_XTAGS) - return Y4M_ERR_XXTAGS; - if (xtags->tags[xtags->count] == NULL) - xtags->tags[xtags->count] = y4m_new_xtag (); - strncpy (xtags->tags[xtags->count], tag, Y4M_MAX_XTAG_SIZE); - (xtags->count)++; - return Y4M_OK; -} - - -int -y4m_xtag_remove (y4m_xtag_list_t * xtags, int n) -{ - int i; - char *q; - - if ((n < 0) || (n >= xtags->count)) - return Y4M_ERR_RANGE; - q = xtags->tags[n]; - for (i = n; i < (xtags->count - 1); i++) - xtags->tags[i] = xtags->tags[i + 1]; - xtags->tags[i] = q; - (xtags->count)--; - return Y4M_OK; -} - - -int -y4m_xtag_clearlist (y4m_xtag_list_t * xtags) -{ - xtags->count = 0; - return Y4M_OK; -} - - -int -y4m_xtag_addlist (y4m_xtag_list_t * dest, const y4m_xtag_list_t * src) -{ - int i, j; - - if ((dest->count + src->count) > Y4M_MAX_XTAGS) - return Y4M_ERR_XXTAGS; - for (i = dest->count, j = 0; j < src->count; i++, j++) { - if (dest->tags[i] == NULL) - dest->tags[i] = y4m_new_xtag (); - strncpy (dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); - } - dest->count += src->count; - return Y4M_OK; -} - - -/************************************************************************* - * - * Creators/destructors for y4m_*_info_t structures - * - *************************************************************************/ - - -void -y4m_init_stream_info (y4m_stream_info_t * info) -{ - if (info == NULL) - return; - /* initialize info */ - info->width = Y4M_UNKNOWN; - info->height = Y4M_UNKNOWN; - info->interlace = Y4M_UNKNOWN; - info->framerate = y4m_fps_UNKNOWN; - info->sampleaspect = y4m_sar_UNKNOWN; - y4m_init_xtag_list (&(info->x_tags)); -} - - -void -y4m_copy_stream_info (y4m_stream_info_t * dest, const y4m_stream_info_t * src) -{ - if ((dest == NULL) || (src == NULL)) - return; - /* copy info */ - dest->width = src->width; - dest->height = src->height; - dest->interlace = src->interlace; - dest->framerate = src->framerate; - dest->sampleaspect = src->sampleaspect; - dest->framelength = src->framelength; - y4m_copy_xtag_list (&(dest->x_tags), &(src->x_tags)); -} - - -void -y4m_fini_stream_info (y4m_stream_info_t * info) -{ - if (info == NULL) - return; - y4m_fini_xtag_list (&(info->x_tags)); -} - - -void -y4m_si_set_width (y4m_stream_info_t * si, int width) -{ - si->width = width; - si->framelength = (si->height * si->width) * 3 / 2; -} - -int -y4m_si_get_width (const y4m_stream_info_t * si) -{ - return si->width; -} - -void -y4m_si_set_height (y4m_stream_info_t * si, int height) -{ - si->height = height; - si->framelength = (si->height * si->width) * 3 / 2; -} - -int -y4m_si_get_height (const y4m_stream_info_t * si) -{ - return si->height; -} - -void -y4m_si_set_interlace (y4m_stream_info_t * si, int interlace) -{ - si->interlace = interlace; -} - -int -y4m_si_get_interlace (const y4m_stream_info_t * si) -{ - return si->interlace; -} - -void -y4m_si_set_framerate (y4m_stream_info_t * si, y4m_ratio_t framerate) -{ - si->framerate = framerate; -} - -y4m_ratio_t -y4m_si_get_framerate (const y4m_stream_info_t * si) -{ - return si->framerate; -} - -void -y4m_si_set_sampleaspect (y4m_stream_info_t * si, y4m_ratio_t sar) -{ - si->sampleaspect = sar; -} - -y4m_ratio_t -y4m_si_get_sampleaspect (const y4m_stream_info_t * si) -{ - return si->sampleaspect; -} - -int -y4m_si_get_framelength (const y4m_stream_info_t * si) -{ - return si->framelength; -} - -y4m_xtag_list_t * -y4m_si_xtags (y4m_stream_info_t * si) -{ - return &(si->x_tags); -} - - - -void -y4m_init_frame_info (y4m_frame_info_t * info) -{ - if (info == NULL) - return; - /* initialize info */ - y4m_init_xtag_list (&(info->x_tags)); -} - - -void -y4m_copy_frame_info (y4m_frame_info_t * dest, const y4m_frame_info_t * src) -{ - if ((dest == NULL) || (src == NULL)) - return; - /* copy info */ - y4m_copy_xtag_list (&(dest->x_tags), &(src->x_tags)); -} - - -void -y4m_fini_frame_info (y4m_frame_info_t * info) -{ - if (info == NULL) - return; - y4m_fini_xtag_list (&(info->x_tags)); -} - - - -/************************************************************************* - * - * Tag parsing - * - *************************************************************************/ - -int -y4m_parse_stream_tags (char *s, y4m_stream_info_t * i) -{ - char *token, *value; - char tag; - int err; - - /* parse fields */ - for (token = strtok (s, Y4M_DELIM); token != NULL; token = strtok (NULL, Y4M_DELIM)) { - if (token[0] == '\0') - continue; /* skip empty strings */ - tag = token[0]; - value = token + 1; - switch (tag) { - case 'W': /* width */ - i->width = atoi (value); - if (i->width <= 0) - return Y4M_ERR_RANGE; - break; - case 'H': /* height */ - i->height = atoi (value); - if (i->height <= 0) - return Y4M_ERR_RANGE; - break; - case 'F': /* frame rate (fps) */ - if ((err = y4m_parse_ratio (&(i->framerate), value)) != Y4M_OK) - return err; - if (i->framerate.n < 0) - return Y4M_ERR_RANGE; - break; - case 'I': /* interlacing */ - switch (value[0]) { - case 'p': - i->interlace = Y4M_ILACE_NONE; - break; - case 't': - i->interlace = Y4M_ILACE_TOP_FIRST; - break; - case 'b': - i->interlace = Y4M_ILACE_BOTTOM_FIRST; - break; - case '?': - default: - i->interlace = Y4M_UNKNOWN; - break; - } - break; - case 'A': /* sample (pixel) aspect ratio */ - if ((err = y4m_parse_ratio (&(i->sampleaspect), value)) != Y4M_OK) - return err; - if (i->sampleaspect.n < 0) - return Y4M_ERR_RANGE; - break; - case 'X': /* 'X' meta-tag */ - if ((err = y4m_xtag_add (&(i->x_tags), token)) != Y4M_OK) - return err; - break; - default: - /* possible error on unknown options */ - if (_y4mparam_allow_unknown_tags) { - /* unknown tags ok: store in xtag list and warn... */ - if ((err = y4m_xtag_add (&(i->x_tags), token)) != Y4M_OK) - return err; - mjpeg_warn ("Unknown stream tag encountered: '%s'", token); - } else { - /* unknown tags are *not* ok */ - return Y4M_ERR_BADTAG; - } - break; - } - } - /* Error checking... width and height must be known since we can't - * parse without them - */ - if (i->width == Y4M_UNKNOWN || i->height == Y4M_UNKNOWN) - return Y4M_ERR_HEADER; - /* ta da! done. */ - return Y4M_OK; -} - - - -static int -y4m_parse_frame_tags (char *s, y4m_frame_info_t * i) -{ - char *token, *value; - char tag; - int err; - - /* parse fields */ - for (token = strtok (s, Y4M_DELIM); token != NULL; token = strtok (NULL, Y4M_DELIM)) { - if (token[0] == '\0') - continue; /* skip empty strings */ - tag = token[0]; - value = token + 1; - switch (tag) { - case 'X': /* 'X' meta-tag */ - if ((err = y4m_xtag_add (&(i->x_tags), token)) != Y4M_OK) - return err; - break; - default: - /* possible error on unknown options */ - if (_y4mparam_allow_unknown_tags) { - /* unknown tags ok: store in xtag list and warn... */ - if ((err = y4m_xtag_add (&(i->x_tags), token)) != Y4M_OK) - return err; - mjpeg_warn ("Unknown frame tag encountered: '%s'", token); - } else { - /* unknown tags are *not* ok */ - return Y4M_ERR_BADTAG; - } - break; - } - } - /* ta da! done. */ - return Y4M_OK; -} - - - - - -/************************************************************************* - * - * Read/Write stream header - * - *************************************************************************/ - - -int -y4m_read_stream_header (int fd, y4m_stream_info_t * i) -{ - char line[Y4M_LINE_MAX]; - char *p; - int n; - int err; - - /* read the header line */ - for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { - if (read (fd, p, 1) < 1) - return Y4M_ERR_SYSTEM; - if (*p == '\n') { - *p = '\0'; /* Replace linefeed by end of string */ - break; - } - } - if (n >= Y4M_LINE_MAX) - return Y4M_ERR_HEADER; - /* look for keyword in header */ - if (strncmp (line, Y4M_MAGIC, strlen (Y4M_MAGIC))) - return Y4M_ERR_MAGIC; - if ((err = y4m_parse_stream_tags (line + strlen (Y4M_MAGIC), i)) != Y4M_OK) - return err; - - i->framelength = (i->height * i->width) * 3 / 2; - return Y4M_OK; -} - - - -int -y4m_write_stream_header (int fd, const y4m_stream_info_t * i) -{ - char s[Y4M_LINE_MAX + 1]; - int n; - int err; - y4m_ratio_t rate = i->framerate; - y4m_ratio_t aspect = i->sampleaspect; - - y4m_ratio_reduce (&rate); - y4m_ratio_reduce (&aspect); - n = snprintf (s, sizeof (s), "%s W%d H%d F%d:%d I%s A%d:%d", - Y4M_MAGIC, - i->width, - i->height, - rate.n, rate.d, - (i->interlace == Y4M_ILACE_NONE) ? "p" : - (i->interlace == Y4M_ILACE_TOP_FIRST) ? "t" : - (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "b" : "?", aspect.n, aspect.d); - if ((n < 0) || (n > Y4M_LINE_MAX)) - return Y4M_ERR_HEADER; - if ((err = y4m_snprint_xtags (s + n, sizeof (s) - n - 1, &(i->x_tags))) - != Y4M_OK) - return err; - /* non-zero on error */ - return (y4m_write (fd, s, strlen (s)) ? Y4M_ERR_SYSTEM : Y4M_OK); -} - - - - - -/************************************************************************* - * - * Read/Write frame header - * - *************************************************************************/ - -int -y4m_read_frame_header (int fd, y4m_frame_info_t * i) -{ - char line[Y4M_LINE_MAX]; - char *p; - int n; - ssize_t remain; - - /* This is more clever than read_stream_header... - Try to read "FRAME\n" all at once, and don't try to parse - if nothing else is there... - */ - remain = y4m_read (fd, line, sizeof (Y4M_FRAME_MAGIC) - 1 + 1); /* -'\0', +'\n' */ - if (remain < 0) - return Y4M_ERR_SYSTEM; - if (remain > 0) { - /* A clean EOF should end exactly at a frame-boundary */ - if (remain == sizeof (Y4M_FRAME_MAGIC)) - return Y4M_ERR_EOF; - else - return Y4M_ERR_BADEOF; - } - if (strncmp (line, Y4M_FRAME_MAGIC, sizeof (Y4M_FRAME_MAGIC) - 1)) - return Y4M_ERR_MAGIC; - if (line[sizeof (Y4M_FRAME_MAGIC) - 1] == '\n') - return Y4M_OK; /* done -- no tags: that was the end-of-line. */ - - if (line[sizeof (Y4M_FRAME_MAGIC) - 1] != Y4M_DELIM[0]) { - return Y4M_ERR_MAGIC; /* wasn't a space -- what was it? */ - } - - /* proceed to get the tags... (overwrite the magic) */ - for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { - if (y4m_read (fd, p, 1)) - return Y4M_ERR_SYSTEM; - if (*p == '\n') { - *p = '\0'; /* Replace linefeed by end of string */ - break; - } - } - if (n >= Y4M_LINE_MAX) - return Y4M_ERR_HEADER; - /* non-zero on error */ - return y4m_parse_frame_tags (line, i); -} - - -int -y4m_write_frame_header (int fd, const y4m_frame_info_t * i) -{ - char s[Y4M_LINE_MAX + 1]; - int n; - int err; - - n = snprintf (s, sizeof (s), "%s", Y4M_FRAME_MAGIC); - if ((n < 0) || (n > Y4M_LINE_MAX)) - return Y4M_ERR_HEADER; - if ((err = y4m_snprint_xtags (s + n, sizeof (s) - n - 1, &(i->x_tags))) - != Y4M_OK) - return err; - /* non-zero on error */ - return (y4m_write (fd, s, strlen (s)) ? Y4M_ERR_SYSTEM : Y4M_OK); -} - - - -/************************************************************************* - * - * Read/Write entire frame - * - *************************************************************************/ - -int -y4m_read_frame (int fd, const y4m_stream_info_t * si, y4m_frame_info_t * fi, uint8_t * const yuv[3]) -{ - int err; - int w = si->width; - int h = si->height; - - /* Read frame header */ - if ((err = y4m_read_frame_header (fd, fi)) != Y4M_OK) - return err; - /* Read luminance scanlines */ - if (y4m_read (fd, yuv[0], w * h)) - return Y4M_ERR_SYSTEM; - /* Read chrominance scanlines */ - if (y4m_read (fd, yuv[1], w * h / 4)) - return Y4M_ERR_SYSTEM; - if (y4m_read (fd, yuv[2], w * h / 4)) - return Y4M_ERR_SYSTEM; - - return Y4M_OK; -} - - - - -int -y4m_write_frame (int fd, const y4m_stream_info_t * si, - const y4m_frame_info_t * fi, uint8_t * const yuv[3]) -{ - int err; - int w = si->width; - int h = si->height; - - /* Write frame header */ - if ((err = y4m_write_frame_header (fd, fi)) != Y4M_OK) - return err; - /* Write luminance,chrominance scanlines */ - if (y4m_write (fd, yuv[0], w * h) || - y4m_write (fd, yuv[1], w * h / 4) || y4m_write (fd, yuv[2], w * h / 4)) - return Y4M_ERR_SYSTEM; - return Y4M_OK; -} - - - -/************************************************************************* - * - * Read/Write entire frame, (de)interleaved (to)from two separate fields - * - *************************************************************************/ - - -int -y4m_read_fields (int fd, const y4m_stream_info_t * si, y4m_frame_info_t * fi, - uint8_t * const upper_field[3], uint8_t * const lower_field[3]) -{ - int i, y, err; - int width = si->width; - int height = si->height; - - /* Read frame header */ - if ((err = y4m_read_frame_header (fd, fi)) != Y4M_OK) - return err; - /* Read Y', Cb, and Cr planes */ - for (i = 0; i < 3; i++) { - uint8_t *srctop = upper_field[i]; - uint8_t *srcbot = lower_field[i]; - - /* alternately write one line from each */ - for (y = 0; y < height; y += 2) { - if (y4m_read (fd, srctop, width)) - return Y4M_ERR_SYSTEM; - srctop += width; - if (y4m_read (fd, srcbot, width)) - return Y4M_ERR_SYSTEM; - srcbot += width; - } - /* for chroma, width/height are half as big */ - if (i == 0) { - width /= 2; - height /= 2; - } - } - return Y4M_OK; -} - - - -int -y4m_write_fields (int fd, const y4m_stream_info_t * si, - const y4m_frame_info_t * fi, - uint8_t * const upper_field[3], uint8_t * const lower_field[3]) -{ - int i, y, err; - int width = si->width; - int height = si->height; - - /* Write frame header */ - if ((err = y4m_write_frame_header (fd, fi)) != Y4M_OK) - return err; - /* Write Y', Cb, and Cr planes */ - for (i = 0; i < 3; i++) { - uint8_t *srctop = upper_field[i]; - uint8_t *srcbot = lower_field[i]; - - /* alternately write one line from each */ - for (y = 0; y < height; y += 2) { - if (y4m_write (fd, srctop, width)) - return Y4M_ERR_SYSTEM; - srctop += width; - if (y4m_write (fd, srcbot, width)) - return Y4M_ERR_SYSTEM; - srcbot += width; - } - /* for chroma, width/height are half as big */ - if (i == 0) { - width /= 2; - height /= 2; - } - } - return Y4M_OK; -} - - - -/************************************************************************* - * - * Handy logging of stream info - * - *************************************************************************/ - -void -y4m_log_stream_info (log_level_t level, const char *prefix, const y4m_stream_info_t * i) -{ - char s[256]; - - snprintf (s, sizeof (s), " frame size: "); - if (i->width == Y4M_UNKNOWN) - snprintf (s + strlen (s), sizeof (s) - strlen (s), "(?)x"); - else - snprintf (s + strlen (s), sizeof (s) - strlen (s), "%dx", i->width); - if (i->height == Y4M_UNKNOWN) - snprintf (s + strlen (s), sizeof (s) - strlen (s), "(?) pixels "); - else - snprintf (s + strlen (s), sizeof (s) - strlen (s), "%d pixels ", i->height); - if (i->framelength == Y4M_UNKNOWN) - snprintf (s + strlen (s), sizeof (s) - strlen (s), "(? bytes)"); - else - snprintf (s + strlen (s), sizeof (s) - strlen (s), "(%d bytes)", i->framelength); - mjpeg_log (level, "%s%s", prefix, s); - if ((i->framerate.n == 0) && (i->framerate.d == 0)) - mjpeg_log (level, "%s frame rate: ??? fps", prefix); - else - mjpeg_log (level, "%s frame rate: %d/%d fps (~%f)", prefix, - i->framerate.n, i->framerate.d, (double) i->framerate.n / (double) i->framerate.d); - mjpeg_log (level, "%s interlace: %s", prefix, - (i->interlace == Y4M_ILACE_NONE) ? "none/progressive" : - (i->interlace == Y4M_ILACE_TOP_FIRST) ? "top-field-first" : - (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom-field-first" : "anyone's guess"); - if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0)) - mjpeg_log (level, "%ssample aspect ratio: ?:?", prefix); - else - mjpeg_log (level, "%ssample aspect ratio: %d:%d", prefix, - i->sampleaspect.n, i->sampleaspect.d); -} - - -/************************************************************************* - * - * Convert error code to string - * - *************************************************************************/ - -const char * -y4m_strerr (int err) -{ - switch (err) { - case Y4M_OK: - return "no error"; - case Y4M_ERR_RANGE: - return "parameter out of range"; - case Y4M_ERR_SYSTEM: - return "system error (failed read/write)"; - case Y4M_ERR_HEADER: - return "bad stream or frame header"; - case Y4M_ERR_BADTAG: - return "unknown header tag"; - case Y4M_ERR_MAGIC: - return "bad header magic"; - case Y4M_ERR_XXTAGS: - return "too many xtags"; - case Y4M_ERR_EOF: - return "end-of-file"; - case Y4M_ERR_BADEOF: - return "stream ended unexpectedly (EOF)"; - default: - return "unknown error code"; - } -} diff --git a/ext/mplex/yuv4mpeg.h b/ext/mplex/yuv4mpeg.h deleted file mode 100644 index 6028ea8..0000000 --- a/ext/mplex/yuv4mpeg.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - * yuv4mpeg.h: Functions for reading and writing "new" YUV4MPEG2 streams. - * - * Stream format is described at the end of this file. - * - * - * Copyright (C) 2001 Matthew J. Marjanovic - * - * - * 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 __YUV4MPEG_H__ -#define __YUV4MPEG_H__ - -#include -#include -#include -#include - - -/************************************************************************ - * error codes returned by y4m_* functions - ************************************************************************/ -#define Y4M_OK 0 -#define Y4M_ERR_RANGE 1 /* argument or tag value out of range */ -#define Y4M_ERR_SYSTEM 2 /* failed system call, check errno */ -#define Y4M_ERR_HEADER 3 /* illegal/malformed header */ -#define Y4M_ERR_BADTAG 4 /* illegal tag character */ -#define Y4M_ERR_MAGIC 5 /* bad header magic */ -#define Y4M_ERR_EOF 6 /* end-of-file (clean) */ -#define Y4M_ERR_XXTAGS 7 /* too many xtags */ -#define Y4M_ERR_BADEOF 8 /* unexpected end-of-file */ - - -/* generic 'unknown' value for integer parameters (e.g. interlace, height) */ -#define Y4M_UNKNOWN -1 - - - -/************************************************************************ - * 'ratio' datatype, for rational numbers - * (see 'ratio' functions down below) - ************************************************************************/ -typedef struct _y4m_ratio { - int n; /* numerator */ - int d; /* denominator */ -} y4m_ratio_t; - - -/************************************************************************ - * useful standard framerates (as ratios) - ************************************************************************/ -extern const y4m_ratio_t y4m_fps_UNKNOWN; -extern const y4m_ratio_t y4m_fps_NTSC_FILM; /* 24000/1001 film (in NTSC) */ -extern const y4m_ratio_t y4m_fps_FILM; /* 24fps film */ -extern const y4m_ratio_t y4m_fps_PAL; /* 25fps PAL */ -extern const y4m_ratio_t y4m_fps_NTSC; /* 30000/1001 NTSC */ -extern const y4m_ratio_t y4m_fps_30; /* 30fps */ -extern const y4m_ratio_t y4m_fps_PAL_FIELD; /* 50fps PAL field rate */ -extern const y4m_ratio_t y4m_fps_NTSC_FIELD; /* 60000/1001 NTSC field rate */ -extern const y4m_ratio_t y4m_fps_60; /* 60fps */ - -/************************************************************************ - * useful standard sample (pixel) aspect ratios (W:H) - ************************************************************************/ -extern const y4m_ratio_t y4m_sar_UNKNOWN; -extern const y4m_ratio_t y4m_sar_SQUARE; /* square pixels */ -extern const y4m_ratio_t y4m_sar_NTSC_CCIR601; /* 525-line (NTSC) Rec.601 */ -extern const y4m_ratio_t y4m_sar_NTSC_16_9; /* 16:9 NTSC/Rec.601 */ -extern const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3; /* NTSC SVCD 4:3 */ -extern const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9;/* NTSC SVCD 16:9 */ -extern const y4m_ratio_t y4m_sar_PAL_CCIR601; /* 625-line (PAL) Rec.601 */ -extern const y4m_ratio_t y4m_sar_PAL_16_9; /* 16:9 PAL/Rec.601 */ -extern const y4m_ratio_t y4m_sar_PAL_SVCD_4_3; /* PAL SVCD 4:3 */ -extern const y4m_ratio_t y4m_sar_PAL_SVCD_16_9; /* PAL SVCD 16:9 */ -extern const y4m_ratio_t y4m_sar_SQR_ANA16_9; /* anamorphic 16:9 sampled */ - /* from 4:3 with square pixels */ - -/************************************************************************ - * useful standard display aspect ratios (W:H) - ************************************************************************/ -extern const y4m_ratio_t y4m_dar_UNKNOWN; -extern const y4m_ratio_t y4m_dar_4_3; /* standard TV */ -extern const y4m_ratio_t y4m_dar_16_9; /* widescreen TV */ -extern const y4m_ratio_t y4m_dar_221_100; /* word-to-your-mother TV */ - - -/************************************************************************ - * 'xtag_list' --- list of unparsed and/or meta/X header tags - * - * Do not touch this structure directly! - * - * Use the y4m_xtag_*() functions (see below). - * You must initialize/finalize this structure before/after use. - ************************************************************************/ -#define Y4M_MAX_XTAGS 32 /* maximum number of xtags in list */ -#define Y4M_MAX_XTAG_SIZE 32 /* max length of an xtag (including 'X') */ -typedef struct _y4m_xtag_list { - int count; - char *tags[Y4M_MAX_XTAGS]; -} y4m_xtag_list_t; - - - -/************************************************************************ - * 'stream_info' --- stream header information - * - * Do not touch this structure directly! - * - * Use the y4m_si_*() functions (see below). - * You must initialize/finalize this structure before/after use. - ************************************************************************/ -typedef struct _y4m_stream_info { - /* values from header */ - int width; - int height; - int interlace; /* see Y4M_ILACE_* definitions below */ - y4m_ratio_t framerate; /* frames-per-second; 0:0 == unknown */ - y4m_ratio_t sampleaspect; /* pixel width/height; 0:0 == unknown */ - /* computed/derivative values */ - int framelength; /* bytes of data per frame (not including header) */ - /* mystical X tags */ - y4m_xtag_list_t x_tags; -} y4m_stream_info_t; - -/* possible options for the interlace parameter */ -#define Y4M_ILACE_NONE 0 /* non-interlaced, progressive frame */ -#define Y4M_ILACE_TOP_FIRST 1 /* interlaced, top-field first */ -#define Y4M_ILACE_BOTTOM_FIRST 2 /* interlaced, bottom-field first */ - - -/************************************************************************ - * 'frame_info' --- frame header information - * - * Do not touch this structure directly! - * - * Use the y4m_fi_*() functions (see below). - * You must initialize/finalize this structure before/after use. - ************************************************************************/ -typedef struct _y4m_frame_info { - /* mystical X tags */ - y4m_xtag_list_t x_tags; -} y4m_frame_info_t; - - - -#ifdef __cplusplus -extern "C" { -#else -#endif - - -/************************************************************************ - * 'ratio' functions - ************************************************************************/ - -/* 'normalize' a ratio (remove common factors) */ -void y4m_ratio_reduce(y4m_ratio_t *r); - -/* parse "nnn:ddd" into a ratio (returns Y4M_OK or Y4M_ERR_RANGE) */ -int y4m_parse_ratio(y4m_ratio_t *r, const char *s); - -/* quick test of two ratios for equality (i.e. identical components) */ -#define Y4M_RATIO_EQL(a,b) ( ((a).n == (b).n) && ((a).d == (b).d) ) - -/* quick conversion of a ratio to a double (no divide-by-zero check!) */ -#define Y4M_RATIO_DBL(r) ((double)(r).n / (double)(r).d) - -/************************************************************************* - * - * Guess the true SAR (sample aspect ratio) from a list of commonly - * encountered values, given the "suggested" display aspect ratio (DAR), - * and the true frame width and height. - * - * Returns y4m_sar_UNKNOWN if no match is found. - * - *************************************************************************/ -y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar); - - - -/************************************************************************ - * 'xtag' functions - * - * o Before using an xtag_list (but after the structure/memory has been - * allocated), you must initialize it via y4m_init_xtag_list(). - * o After using an xtag_list (but before the structure is released), - * call y4m_fini_xtag_list() to free internal memory. - * - ************************************************************************/ - -/* initialize an xtag_list structure */ -void y4m_init_xtag_list(y4m_xtag_list_t *xtags); - -/* finalize an xtag_list structure */ -void y4m_fini_xtag_list(y4m_xtag_list_t *xtags); - -/* make one xtag_list into a copy of another */ -void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); - -/* return number of tags in an xtag_list */ -int y4m_xtag_count(const y4m_xtag_list_t *xtags); - -/* access n'th tag in an xtag_list */ -const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n); - -/* append a new tag to an xtag_list - returns: Y4M_OK - success - Y4M_ERR_XXTAGS - list is already full */ -int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag); - -/* remove a tag from an xtag_list - returns: Y4M_OK - success - Y4M_ERR_RANGE - n is out of range */ -int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n); - -/* remove all tags from an xtag_list - returns: Y4M_OK - success */ -int y4m_xtag_clearlist(y4m_xtag_list_t *xtags); - -/* append copies of tags from src list to dest list - returns: Y4M_OK - success - Y4M_ERR_XXTAGS - operation would overfill dest list */ -int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); - - - -/************************************************************************ - * '*_info' functions - * - * o Before using a *_info structure (but after the structure/memory has - * been allocated), you must initialize it via y4m_init_*_info(). - * o After using a *_info structure (but before the structure is released), - * call y4m_fini_*_info() to free internal memory. - * o Use the 'set' and 'get' accessors to modify or access the fields in - * the structures; don't touch the structure directly. (Ok, so there - * is no really convenient C syntax to prevent you from doing this, - * but we are all responsible programmers here, so just don't do it!) - * - ************************************************************************/ - -/* initialize a stream_info structure */ -void y4m_init_stream_info(y4m_stream_info_t *i); - -/* finalize a stream_info structure */ -void y4m_fini_stream_info(y4m_stream_info_t *i); - -/* make one stream_info into a copy of another */ -void y4m_copy_stream_info(y4m_stream_info_t *dest, - const y4m_stream_info_t *src); - -/* access or set stream_info fields */ -void y4m_si_set_width(y4m_stream_info_t *si, int width); -int y4m_si_get_width(const y4m_stream_info_t *si); -void y4m_si_set_height(y4m_stream_info_t *si, int height); -int y4m_si_get_height(const y4m_stream_info_t *si); -void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace); -int y4m_si_get_interlace(const y4m_stream_info_t *si); -void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate); -y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si); -void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar); -y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si); -int y4m_si_get_framelength(const y4m_stream_info_t *si); - -/* access stream_info xtag_list */ -y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si); - - -/* initialize a frame_info structure */ -void y4m_init_frame_info(y4m_frame_info_t *i); - -/* finalize a frame_info structure */ -void y4m_fini_frame_info(y4m_frame_info_t *i); - -/* make one frame_info into a copy of another */ -void y4m_copy_frame_info(y4m_frame_info_t *dest, - const y4m_frame_info_t *src); - -/* access frame_info xtag_list */ -y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi); - - - -/************************************************************************ - * blocking read and write functions - * - * o guaranteed to transfer entire payload (or fail) - * o return values: - * 0 (zero) complete success - * -(# of remaining bytes) error (and errno left set) - * +(# of remaining bytes) EOF (for y4m_read only) - * - ************************************************************************/ - -/* read len bytes from fd into buf */ -ssize_t y4m_read(int fd, void *buf, size_t len); - -/* write len bytes from fd into buf */ -ssize_t y4m_write(int fd, const void *buf, size_t len); - - - -/************************************************************************ - * stream header processing functions - * - * o return values: - * Y4M_OK - success - * Y4M_ERR_* - error (see y4m_strerr() for descriptions) - * - ************************************************************************/ - -/* parse a string of stream header tags */ -int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i); - -/* read a stream header from file descriptor fd */ -int y4m_read_stream_header(int fd, y4m_stream_info_t *i); - -/* write a stream header to file descriptor fd */ -int y4m_write_stream_header(int fd, const y4m_stream_info_t *i); - - - -/************************************************************************ - * frame processing functions - * - * o return values: - * Y4M_OK - success - * Y4M_ERR_* - error (see y4m_strerr() for descriptions) - * - ************************************************************************/ - -/* read a frame header from file descriptor fd */ -int y4m_read_frame_header(int fd, y4m_frame_info_t *i); - -/* write a frame header to file descriptor fd */ -int y4m_write_frame_header(int fd, const y4m_frame_info_t *i); - -/* read a complete frame (header + data) - o yuv[3] points to three buffers, one each for Y, U, V planes */ -int y4m_read_frame(int fd, const y4m_stream_info_t *si, - y4m_frame_info_t *fi, uint8_t * const yuv[3]); - -/* write a complete frame (header + data) - o yuv[3] points to three buffers, one each for Y, U, V planes */ -int y4m_write_frame(int fd, const y4m_stream_info_t *si, - const y4m_frame_info_t *fi, uint8_t * const yuv[3]); - - -/* read a complete frame (header + data), but de-interleave fields - into two separate buffers - o upper_field[3] same as yuv[3] above, but for upper field - o lower_field[3] same as yuv[3] above, but for lower field -*/ -int y4m_read_fields(int fd, const y4m_stream_info_t *si, - y4m_frame_info_t *fi, - uint8_t * const upper_field[3], - uint8_t * const lower_field[3]); - -/* write a complete frame (header + data), but interleave fields - from two separate buffers - o upper_field[3] same as yuv[3] above, but for upper field - o lower_field[3] same as yuv[3] above, but for lower field -*/ -int y4m_write_fields(int fd, const y4m_stream_info_t *si, - const y4m_frame_info_t *fi, - uint8_t * const upper_field[3], - uint8_t * const lower_field[3]); - - - -/************************************************************************ - * miscellaneous functions - ************************************************************************/ - -/* convenient dump of stream header info via mjpeg_log facility - * - each logged/printed line is prefixed by 'prefix' - */ -void y4m_log_stream_info(log_level_t level, const char *prefix, - const y4m_stream_info_t *i); - -/* convert a Y4M_ERR_* error code into mildly explanatory string */ -const char *y4m_strerr(int err); - -/* set 'allow_unknown_tag' flag for library... - o yn = 0 : unknown header tags will produce a parsing error - o yn = 1 : unknown header tags/values will produce a warning, but - are otherwise passed along via the xtags list - o yn = -1: don't change, just return current setting - - return value: previous setting of flag -*/ -int y4m_allow_unknown_tags(int yn); - - -#ifdef __cplusplus -} -#endif - -/************************************************************************ - ************************************************************************ - - Description of the (new!, forever?) YUV4MPEG2 stream format: - - STREAM consists of - o one '\n' terminated STREAM-HEADER - o unlimited number of FRAMEs - - FRAME consists of - o one '\n' terminated FRAME-HEADER - o "length" octets of planar YCrCb 4:2:0 image data - (if frame is interlaced, then the two fields are interleaved) - - - STREAM-HEADER consists of - o string "YUV4MPEG2 " (note the space after the '2') - o unlimited number of ' ' separated TAGGED-FIELDs - o '\n' line terminator - - FRAME-HEADER consists of - o string "FRAME " (note the space after the 'E') - o unlimited number of ' ' separated TAGGED-FIELDs - o '\n' line terminator - - - TAGGED-FIELD consists of - o single ascii character tag - o VALUE (which does not contain whitespace) - - VALUE consists of - o integer (base 10 ascii representation) - or o RATIO - or o single ascii character - or o generic ascii string - - RATIO consists of - o numerator (integer) - o ':' (a colon) - o denominator (integer) - - - The currently supported tags for the STREAM-HEADER: - W - [integer] frame width, pixels, should be > 0 - H - [integer] frame height, pixels, should be > 0 - I - [char] interlacing: p - progressive (none) - t - top-field-first - b - bottom-field-first - ? - unknown - F - [ratio] frame-rate, 0:0 == unknown - A - [ratio] sample (pixel) aspect ratio, 0:0 == unknown - X - [character string] 'metadata' (unparsed, but passed around) - - The currently supported tags for the FRAME-HEADER: - X - character string 'metadata' (unparsed, but passed around) - - ************************************************************************ - ************************************************************************/ - -#endif /* __YUV4MPEG_H__ */ - - diff --git a/ext/mplex/yuv4mpeg_intern.h b/ext/mplex/yuv4mpeg_intern.h deleted file mode 100644 index 140f9d6..0000000 --- a/ext/mplex/yuv4mpeg_intern.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * yuv4mpeg_intern.h: Internal constants for "new" YUV4MPEG streams - * - * Copyright (C) 2001 Andrew Stevens - * Copyright (C) 2001 Matthew J. Marjanovic - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * 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 __YUV4MPEG_INTERN_H__ -#define __YUV4MPEG_INTERN_H__ - - -#define Y4M_MAGIC "YUV4MPEG2" -#define Y4M_FRAME_MAGIC "FRAME" - -#define Y4M_DELIM " " /* single-character(space) separating tagged fields */ - -#define Y4M_LINE_MAX 256 /* max number of characters in a header line - (including the '\n', but not the '\0') */ - - -/* standard framerate ratios */ -#define Y4M_FPS_UNKNOWN { 0, 0 } -#define Y4M_FPS_NTSC_FILM { 24000, 1001 } -#define Y4M_FPS_FILM { 24, 1 } -#define Y4M_FPS_PAL { 25, 1 } -#define Y4M_FPS_NTSC { 30000, 1001 } -#define Y4M_FPS_30 { 30, 1 } -#define Y4M_FPS_PAL_FIELD { 50, 1 } -#define Y4M_FPS_NTSC_FIELD { 60000, 1001 } -#define Y4M_FPS_60 { 60, 1 } - -/* standard sample/pixel aspect ratios */ -#define Y4M_SAR_UNKNOWN { 0, 0 } -#define Y4M_SAR_SQUARE { 1, 1 } -#define Y4M_SAR_SQR_ANA_16_9 { 4, 3 } -#define Y4M_SAR_NTSC_CCIR601 { 10, 11 } -#define Y4M_SAR_NTSC_16_9 { 40, 33 } -#define Y4M_SAR_NTSC_SVCD_4_3 { 15, 11 } -#define Y4M_SAR_NTSC_SVCD_16_9 { 20, 11 } -#define Y4M_SAR_PAL_CCIR601 { 59, 54 } -#define Y4M_SAR_PAL_16_9 { 118, 81 } -#define Y4M_SAR_PAL_SVCD_4_3 { 59, 36 } -#define Y4M_SAR_PAL_SVCD_16_9 { 59, 27 } - -#define Y4M_SAR_MPEG1_1 Y4M_SAR_SQUARE -#define Y4M_SAR_MPEG1_2 { 10000, 6735 } -#define Y4M_SAR_MPEG1_3 { 10000, 7031 } /* Anamorphic 16:9 PAL */ -#define Y4M_SAR_MPEG1_4 { 10000, 7615 } -#define Y4M_SAR_MPEG1_5 { 10000, 8055 } -#define Y4M_SAR_MPEG1_6 { 10000, 8437 } /* Anamorphic 16:9 NTSC */ -#define Y4M_SAR_MPEG1_7 { 10000, 8935 } -#define Y4M_SAR_MPEG1_8 { 10000, 9375 } /* PAL/SECAM 4:3 */ -#define Y4M_SAR_MPEG1_9 { 10000, 9815 } -#define Y4M_SAR_MPEG1_10 { 10000, 10255 } -#define Y4M_SAR_MPEG1_11 { 10000, 10695 } -#define Y4M_SAR_MPEG1_12 { 10000, 11250 } /* NTSC 4:3 */ -#define Y4M_SAR_MPEG1_13 { 10000, 11575 } -#define Y4M_SAR_MPEG1_14 { 10000, 12015 } - -#define Y4M_DAR_UNKNOWN { 0, 0 } -#define Y4M_DAR_4_3 { 4, 3 } -#define Y4M_DAR_16_9 { 16, 9 } -#define Y4M_DAR_221_100 { 221, 100 } - -#define Y4M_DAR_MPEG2_1 { 1, 1 } -#define Y4M_DAR_MPEG2_2 { 4, 3 } -#define Y4M_DAR_MPEG2_3 { 16, 9 } -#define Y4M_DAR_MPEG2_4 { 221, 100 } - -#endif /* __YUV4MPEG_INTERN_H__ */ - diff --git a/ext/mplex/yuv4mpeg_ratio.cc b/ext/mplex/yuv4mpeg_ratio.cc deleted file mode 100644 index 262df6f..0000000 --- a/ext/mplex/yuv4mpeg_ratio.cc +++ /dev/null @@ -1,167 +0,0 @@ -/* - * yuv4mpeg_ratio.c: Functions for dealing with y4m_ratio_t datatype. - * - * Copyright (C) 2001 Matthew J. Marjanovic - * - * - * 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. - * - */ - -#include - -#include -#include "yuv4mpeg.h" -#include "yuv4mpeg_intern.h" - - -/* useful list of standard framerates */ -const y4m_ratio_t y4m_fps_UNKNOWN = Y4M_FPS_UNKNOWN; -const y4m_ratio_t y4m_fps_NTSC_FILM = Y4M_FPS_NTSC_FILM; -const y4m_ratio_t y4m_fps_FILM = Y4M_FPS_FILM; -const y4m_ratio_t y4m_fps_PAL = Y4M_FPS_PAL; -const y4m_ratio_t y4m_fps_NTSC = Y4M_FPS_NTSC; -const y4m_ratio_t y4m_fps_30 = Y4M_FPS_30; -const y4m_ratio_t y4m_fps_PAL_FIELD = Y4M_FPS_PAL_FIELD; -const y4m_ratio_t y4m_fps_NTSC_FIELD = Y4M_FPS_NTSC_FIELD; -const y4m_ratio_t y4m_fps_60 = Y4M_FPS_60; - -/* useful list of standard sample aspect ratios */ -const y4m_ratio_t y4m_sar_UNKNOWN = Y4M_SAR_UNKNOWN; -const y4m_ratio_t y4m_sar_SQUARE = Y4M_SAR_SQUARE; -const y4m_ratio_t y4m_sar_SQR_ANA_16_9 = Y4M_SAR_SQR_ANA_16_9; -const y4m_ratio_t y4m_sar_NTSC_CCIR601 = Y4M_SAR_NTSC_CCIR601; -const y4m_ratio_t y4m_sar_NTSC_16_9 = Y4M_SAR_NTSC_16_9; -const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3 = Y4M_SAR_NTSC_SVCD_4_3; -const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9 = Y4M_SAR_NTSC_SVCD_16_9; -const y4m_ratio_t y4m_sar_PAL_CCIR601 = Y4M_SAR_PAL_CCIR601; -const y4m_ratio_t y4m_sar_PAL_16_9 = Y4M_SAR_PAL_16_9; -const y4m_ratio_t y4m_sar_PAL_SVCD_4_3 = Y4M_SAR_PAL_SVCD_4_3; -const y4m_ratio_t y4m_sar_PAL_SVCD_16_9 = Y4M_SAR_PAL_SVCD_16_9; - -/* useful list of standard display aspect ratios */ -const y4m_ratio_t y4m_dar_4_3 = Y4M_DAR_4_3; -const y4m_ratio_t y4m_dar_16_9 = Y4M_DAR_16_9; -const y4m_ratio_t y4m_dar_221_100 = Y4M_DAR_221_100; - -/* - * Euler's algorithm for greatest common divisor - */ - -static int -gcd (int a, int b) -{ - a = (a >= 0) ? a : -a; - b = (b >= 0) ? b : -b; - - while (b > 0) { - int x = b; - - b = a % b; - a = x; - } - return a; -} - - -/************************************************************************* - * - * Remove common factors from a ratio - * - *************************************************************************/ - - -void -y4m_ratio_reduce (y4m_ratio_t * r) -{ - int d; - - if ((r->n == 0) && (r->d == 0)) - return; /* "unknown" */ - d = gcd (r->n, r->d); - r->n /= d; - r->d /= d; -} - - - -/************************************************************************* - * - * Parse "nnn:ddd" into a ratio - * - * returns: Y4M_OK - success - * Y4M_ERR_RANGE - range error - * - *************************************************************************/ - -int -y4m_parse_ratio (y4m_ratio_t * r, const char *s) -{ - char *t = (char *) strchr (s, ':'); - - if (t == NULL) - return Y4M_ERR_RANGE; - r->n = atoi (s); - r->d = atoi (t + 1); - if (r->d < 0) - return Y4M_ERR_RANGE; - /* 0:0 == unknown, so that is ok, otherwise zero denominator is bad */ - if ((r->d == 0) && (r->n != 0)) - return Y4M_ERR_RANGE; - y4m_ratio_reduce (r); - return Y4M_OK; -} - - - -/************************************************************************* - * - * Guess the true SAR (sample aspect ratio) from a list of commonly - * encountered values, given the "suggested" display aspect ratio, and - * the true frame width and height. - * - * Returns y4m_sar_UNKNOWN if no match is found. - * - *************************************************************************/ - -/* this is big enough to accommodate the difference between 720 and 704 */ -#define GUESS_ASPECT_TOLERANCE 0.03 - -y4m_ratio_t -y4m_guess_sar (int width, int height, y4m_ratio_t dar) -{ - int i; - double implicit_sar = (double) (dar.n * height) / (double) (dar.d * width); - y4m_ratio_t sarray[] = { - y4m_sar_SQUARE, - y4m_sar_NTSC_CCIR601, - y4m_sar_NTSC_16_9, - y4m_sar_NTSC_SVCD_4_3, - y4m_sar_NTSC_SVCD_16_9, - y4m_sar_PAL_CCIR601, - y4m_sar_PAL_16_9, - y4m_sar_PAL_SVCD_4_3, - y4m_sar_PAL_SVCD_16_9, - y4m_sar_UNKNOWN - }; - - for (i = 0; !(Y4M_RATIO_EQL (sarray[i], y4m_sar_UNKNOWN)); i++) { - double ratio = implicit_sar / Y4M_RATIO_DBL (sarray[i]); - - if ((ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && (ratio < (1.0 + GUESS_ASPECT_TOLERANCE))) - return sarray[i]; - } - return y4m_sar_UNKNOWN; -}