diff --git a/COPYING b/COPYING deleted file mode 100644 index e77696ae8d..0000000000 --- a/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 - - 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/Makefile b/Makefile deleted file mode 100644 index 590784966b..0000000000 --- a/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -CFLAGS= -O2 -Wall -g -I./libav -LDFLAGS= -g -L./libav - -PROG= ffmpeg ffserver - -all: lib $(PROG) - -lib: - make -C libav all - -ffmpeg: rmenc.o mpegmux.o asfenc.o jpegenc.o swfenc.o udp.o formats.o grab.o ffmpeg.o libav/libav.a - gcc $(LDFLAGS) -o $@ $^ -lav -lm - -ffserver: rmenc.o mpegmux.o asfenc.o jpegenc.o swfenc.o formats.o grab.o ffserver.o libav/libav.a - gcc $(LDFLAGS) -o $@ $^ -lav -lpthread -lm - -%.o: %.c - gcc $(CFLAGS) -c -o $@ $< - -clean: - make -C libav clean - rm -f *.o *~ gmon.out TAGS $(PROG) - -etags: - etags *.[ch] libav/*.[ch] - -tar: - (cd .. ; tar zcvf ffmpeg-0.3.tgz ffmpeg --exclude CVS --exclude TAGS ) diff --git a/README b/README deleted file mode 100644 index 45029dbfad..0000000000 --- a/README +++ /dev/null @@ -1,60 +0,0 @@ -FFmpeg version 0.9 - (c) 2000 Gerard Lantau. - -1) Introduction ---------------- - -ffmpeg is a hyper fast realtime audio/video encoder and streaming -server. It can grab from a standard Video4Linux video source and -convert it into several file formats based on DCT/motion compensation -encoding. Sound is compressed in MPEG audio layer 2 or using an AC3 -compatible stream. - -What makes ffmpeg interesting ? - -- Innovative streaming technology : multiformat, real time encoding, - simple configuration. - -- Simple and efficient video encoder: outputs MPEG1, H263 and Real - Video(tm) compatible bitstreams using the same encoder core. - -- Real time encoding (25 fps in 352x288 on a K6 500) using the video4linux API. - -- Generates I and P frames, which means it is far better than a MJPEG - encoder. - -- Hyper fast MPEG audio layer 2 compression (50 times faster than - realtime on a K6 500). - -- Hyper fast AC3 compatible encoder. - -- simple and very small portable C source code, easy to understand and - to modify. It be may the smallest decent MPEG encoder :-) - -ffmpeg is made of two programs: - -* ffmpeg: soft VCR which encodes in real time to several formats. - -* ffserver: live broadcast streaming server based on the ffmpeg core -encoders. - -2) Documentation ----------------- - -read doc/ffmpeg.txt and doc/ffserver.txt to learn the basic features. - -read ffmpeg - -3) Licensing: ------------- - -* See the file COPYING. ffmpeg is licensed under the GNU General - Public License. - -* Source code from third parties: The DCT code comes from the Berkeley - MPEG decoder and the JPEG encoder. - -* This code should be patent free since it is very simple. I took care - to use the same video encoder core for all formats to show that they - really ARE THE SAME except for the encoding huffman codes. - -Gerard Lantau (glantau@users.sourceforge.net). diff --git a/asfenc.c b/asfenc.c deleted file mode 100644 index 5b2892309f..0000000000 --- a/asfenc.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * ASF compatible encoder - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include "mpegenc.h" - -#define PACKET_SIZE 3200 -#define PACKET_HEADER_SIZE 12 -#define FRAME_HEADER_SIZE 17 - -typedef struct { - AVEncodeContext *enc; - int num; - int seq; -} ASFStream; - -typedef struct { - int is_streamed; /* true if streamed */ - int seqno; - int packet_size; - - ASFStream streams[2]; - ASFStream *audio_stream, *video_stream; - int nb_streams; - /* non streamed additonnal info */ - int file_size_offset; - int data_offset; - /* packet filling */ - int packet_size_left; - int packet_timestamp_start; - int packet_timestamp_end; - int packet_nb_frames; - UINT8 packet_buf[PACKET_SIZE]; - PutByteContext pb; -} ASFContext; - -typedef struct { - UINT32 v1; - UINT16 v2; - UINT16 v3; - UINT8 v4[8]; -} GUID; - -static const GUID asf_header = { - 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C }, -}; - -static const GUID file_header = { - 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, -}; - -static const GUID stream_header = { - 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 }, -}; - -static const GUID audio_stream = { - 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }, -}; - -static const GUID audio_conceal_none = { - 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 }, -}; - -static const GUID video_stream = { - 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }, -}; - -static const GUID video_conceal_none = { - 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }, -}; - -static const GUID comment_header = { - 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 }, -}; - -static const GUID data_header = { - 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c }, -}; - -static const GUID packet_guid = { - 0xF656CCE1, 0x03B3, 0x11D4, { 0xBE, 0xA2, 0x00, 0xA0, 0xCC, 0x3D, 0x72, 0x74 }, -}; - -/* I am not a number !!! This GUID is the one found on the PC used to - generate the stream */ -static const GUID my_guid = { - 0x12345678, 0xA947, 0x11CF, { 0x31, 0x41, 0x59, 0x26, 0x20, 0x20, 0x20, 0x20 }, -}; - -static void put_guid(PutByteContext *s, const GUID *g) -{ - int i; - - put_le32(s, g->v1); - put_le16(s, g->v2); - put_le16(s, g->v3); - for(i=0;i<8;i++) - put_byte(s, g->v4[i]); -} - -#if 0 -static void put_str16(PutByteContext *s, const char *tag) -{ - put_le16(s,strlen(tag)); - while (*tag) { - put_le16(s, *tag++); - } -} -#endif - -/* write an asf chunk (only used in streaming case) */ -static void put_chunk(AVFormatContext *s, int type, int payload_length) -{ - ASFContext *asf = s->priv_data; - PutByteContext *pb = &s->pb; - int length; - - length = payload_length + 8; - put_le16(pb, type); - put_le16(pb, length); - put_le32(pb, asf->seqno); - put_le16(pb, 0); /* unknown bytes */ - put_le16(pb, length); - asf->seqno++; -} - - -static int asf_write_header(AVFormatContext *s) -{ - PutByteContext *pb = &s->pb; - ASFContext *asf; - int header_size, n, extra_size, extra_size2, i, wav_extra_size; - AVEncodeContext *enc; - long long header_offset, cur_pos; - - asf = malloc(sizeof(ASFContext)); - if (!asf) - return -1; - memset(asf, 0, sizeof(ASFContext)); - s->priv_data = asf; - - asf->packet_size = PACKET_SIZE; - - if (!s->is_streamed) { - put_guid(pb, &asf_header); - put_le64(pb, 0); /* header length, will be patched after */ - put_le32(pb, 6); /* ??? */ - put_byte(pb, 1); /* ??? */ - put_byte(pb, 2); /* ??? */ - } else { - put_chunk(s, 0x4824, 0); /* start of stream (length will be patched later) */ - } - - /* file header */ - header_offset = put_pos(pb); - put_guid(pb, &file_header); - put_le64(pb, 24 + 80); - put_guid(pb, &my_guid); - asf->file_size_offset = put_pos(pb); - put_le64(pb, 0); /* file size (patched after if not streamed) */ - put_le64(pb, 0); /* file time : 1601 :-) */ - put_le64(pb, 0x283); /* ??? */ - put_le64(pb, 0); /* stream 0 length in us */ - put_le64(pb, 0); /* stream 1 length in us */ - put_le32(pb, 0x0c1c); /* ??? */ - put_le32(pb, 0); /* ??? */ - put_le32(pb, 2); /* ??? */ - put_le32(pb, asf->packet_size); /* packet size */ - put_le32(pb, asf->packet_size); /* ??? */ - put_le32(pb, 0x03e800); /* ??? */ - - /* stream headers */ - n = 0; - for(i=0;i<2;i++) { - if (i == 0) - enc = s->audio_enc; - else - enc = s->video_enc; - - if (!enc) - continue; - asf->streams[n].num = i; - asf->streams[n].seq = 0; - asf->streams[n].enc = enc; - - switch(enc->codec->type) { - case CODEC_TYPE_AUDIO: - asf->audio_stream = &asf->streams[n]; - wav_extra_size = 0; - extra_size = 18 + wav_extra_size; - extra_size2 = 0; - break; - default: - case CODEC_TYPE_VIDEO: - asf->video_stream = &asf->streams[n]; - wav_extra_size = 0; - extra_size = 0x33; - extra_size2 = 0; - break; - } - - put_guid(pb, &stream_header); - put_le64(pb, 24 + 16 * 2 + 22 + extra_size + extra_size2); - if (enc->codec->type == CODEC_TYPE_AUDIO) { - put_guid(pb, &audio_stream); - put_guid(pb, &audio_conceal_none); - } else { - put_guid(pb, &video_stream); - put_guid(pb, &video_conceal_none); - } - put_le64(pb, 0); /* ??? */ - put_le32(pb, extra_size); /* wav header len */ - put_le32(pb, extra_size2); /* additional data len */ - put_le16(pb, n + 1); /* stream number */ - put_le32(pb, 0); /* ??? */ - - if (enc->codec->type == CODEC_TYPE_AUDIO) { - /* WAVEFORMATEX header */ - - put_le16(pb, 0x55); /* MP3 format */ - put_le16(pb, s->audio_enc->channels); - put_le32(pb, s->audio_enc->rate); - put_le32(pb, s->audio_enc->bit_rate / 8); - put_le16(pb, 1); /* block align */ - put_le16(pb, 16); /* bits per sample */ - put_le16(pb, wav_extra_size); - - /* no addtionnal adata */ - } else { - put_le32(pb, enc->width); - put_le32(pb, enc->height); - put_byte(pb, 2); /* ??? */ - put_le16(pb, 40); /* size */ - - /* BITMAPINFOHEADER header */ - put_le32(pb, 40); /* size */ - put_le32(pb, enc->width); - put_le32(pb, enc->height); - put_le16(pb, 1); /* planes */ - put_le16(pb, 24); /* depth */ - /* compression type */ - switch(enc->codec->id) { - case CODEC_ID_H263: - put_tag(pb, "I263"); - break; - case CODEC_ID_MJPEG: - put_tag(pb, "MJPG"); - break; - default: - put_tag(pb, "XXXX"); - break; - } - put_le32(pb, enc->width * enc->height * 3); - put_le32(pb, 0); - put_le32(pb, 0); - put_le32(pb, 0); - put_le32(pb, 0); - } - n++; - } - asf->nb_streams = n; - - /* XXX: should media comments */ -#if 0 - put_guid(pb, &comment_header); - put_le64(pb, 0); -#endif - /* patch the header size fields */ - cur_pos = put_pos(pb); - header_size = cur_pos - header_offset; - if (!s->is_streamed) { - header_size += 24 + 6; - put_seek(pb, header_offset - 14, SEEK_SET); - put_le64(pb, header_size); - } else { - header_size += 8 + 50; - put_seek(pb, header_offset - 10, SEEK_SET); - put_le16(pb, header_size); - put_seek(pb, header_offset - 2, SEEK_SET); - put_le16(pb, header_size); - } - put_seek(pb, cur_pos, SEEK_SET); - - /* movie chunk, followed by packets of packet_size */ - asf->data_offset = cur_pos; - put_guid(pb, &data_header); - put_le64(pb, 24); /* will be patched after */ - put_guid(pb, &packet_guid); - put_le64(pb, 0x283); /* ??? */ - put_byte(pb, 1); /* ??? */ - put_byte(pb, 1); /* ??? */ - - put_flush_packet(&s->pb); - - asf->packet_nb_frames = 0; - asf->packet_timestamp_start = -1; - asf->packet_timestamp_end = -1; - asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE; - init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, - NULL, NULL, NULL); - - return 0; -} - -/* write a fixed size packet */ -static void put_packet(AVFormatContext *s, - unsigned int timestamp, unsigned int duration, - int nb_frames, int padsize) -{ - ASFContext *asf = s->priv_data; - PutByteContext *pb = &s->pb; - int flags; - - if (s->is_streamed) { - put_chunk(s, 0x4424, asf->packet_size); - } - - put_byte(pb, 0x82); - put_le16(pb, 0); - - flags = 0x01; /* nb segments present */ - if (padsize > 0) { - if (padsize < 256) - flags |= 0x08; - else - flags |= 0x10; - } - put_byte(pb, flags); /* flags */ - put_byte(pb, 0x5d); - if (flags & 0x10) - put_le16(pb, padsize); - if (flags & 0x08) - put_byte(pb, padsize); - put_le32(pb, timestamp); - put_le16(pb, duration); - put_byte(pb, nb_frames | 0x80); -} - -static void flush_packet(AVFormatContext *s) -{ - ASFContext *asf = s->priv_data; - int hdr_size, ptr; - - put_packet(s, asf->packet_timestamp_start, - asf->packet_timestamp_end - asf->packet_timestamp_start, - asf->packet_nb_frames, asf->packet_size_left); - - /* compute padding */ - hdr_size = PACKET_HEADER_SIZE; - if (asf->packet_size_left > 0) { - /* if padding needed, don't forget to count the - padding byte in the header size */ - hdr_size++; - asf->packet_size_left--; - /* XXX: I do not test again exact limit to avoid boundary problems */ - if (asf->packet_size_left > 200) { - hdr_size++; - asf->packet_size_left--; - } - } - ptr = asf->packet_size - PACKET_HEADER_SIZE - asf->packet_size_left; - memset(asf->packet_buf + ptr, 0, asf->packet_size_left); - - put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size); - - put_flush_packet(&s->pb); - asf->packet_nb_frames = 0; - asf->packet_timestamp_start = -1; - asf->packet_timestamp_end = -1; - asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE; - init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, - NULL, NULL, NULL); -} - -static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp, - int payload_size, int frag_offset, int frag_len) -{ - ASFContext *asf = s->priv_data; - PutByteContext *pb = &asf->pb; - int val; - - val = stream->num; - if (stream->enc->key_frame) - val |= 0x80; - put_byte(pb, val); - put_byte(pb, stream->seq); - put_le32(pb, frag_offset); /* fragment offset */ - put_byte(pb, 0x08); /* flags */ - put_le32(pb, payload_size); - put_le32(pb, timestamp); - put_le16(pb, frag_len); -} - - -/* Output a frame. We suppose that payload_size <= PACKET_SIZE. - - It is there that you understand that the ASF format is really - crap. They have misread the MPEG Systems spec ! - */ -static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp, - UINT8 *buf, int payload_size) -{ - ASFContext *asf = s->priv_data; - int frag_pos, frag_len, frag_len1; - - frag_pos = 0; - while (frag_pos < payload_size) { - frag_len = payload_size - frag_pos; - frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE; - if (frag_len1 > 0) { - if (frag_len > frag_len1) - frag_len = frag_len1; - put_frame_header(s, stream, timestamp, payload_size, frag_pos, frag_len); - put_buffer(&asf->pb, buf, frag_len); - asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE); - asf->packet_timestamp_end = timestamp; - if (asf->packet_timestamp_start == -1) - asf->packet_timestamp_start = timestamp; - asf->packet_nb_frames++; - } else { - frag_len = 0; - } - frag_pos += frag_len; - buf += frag_len; - /* output the frame if filled */ - if (asf->packet_size_left <= FRAME_HEADER_SIZE) - flush_packet(s); - } - stream->seq++; -} - - -static int asf_write_audio(AVFormatContext *s, UINT8 *buf, int size) -{ - ASFContext *asf = s->priv_data; - int timestamp; - - timestamp = (int)((float)s->audio_enc->frame_number * s->audio_enc->frame_size * 1000.0 / - s->audio_enc->rate); - put_frame(s, asf->audio_stream, timestamp, buf, size); - return 0; -} - -static int asf_write_video(AVFormatContext *s, UINT8 *buf, int size) -{ - ASFContext *asf = s->priv_data; - int timestamp; - - timestamp = (int)((float)s->video_enc->frame_number * 1000.0 / - s->video_enc->rate); - put_frame(s, asf->audio_stream, timestamp, buf, size); - return 0; -} - -static int asf_write_trailer(AVFormatContext *s) -{ - ASFContext *asf = s->priv_data; - long long file_size; - - /* flush the current packet */ - if (asf->pb.buf_ptr > asf->pb.buffer) - flush_packet(s); - - if (s->is_streamed) { - put_chunk(s, 0x4524, 0); /* end of stream */ - } else { - /* patch the various place which depends on the file size */ - file_size = put_pos(&s->pb); - put_seek(&s->pb, asf->file_size_offset, SEEK_SET); - put_le64(&s->pb, file_size); - put_seek(&s->pb, asf->data_offset + 16, SEEK_SET); - put_le64(&s->pb, file_size - asf->data_offset); - } - - put_flush_packet(&s->pb); - - free(asf); - return 0; -} - -AVFormat asf_format = { - "asf", - "asf format", - "application/octet-stream", - "asf", - CODEC_ID_MP2, - CODEC_ID_MJPEG, - asf_write_header, - asf_write_audio, - asf_write_video, - asf_write_trailer, -}; diff --git a/doc/BUGS b/doc/BUGS deleted file mode 100644 index 0c9ef63267..0000000000 --- a/doc/BUGS +++ /dev/null @@ -1,14 +0,0 @@ -- Sound is only handled in mono. The fixed psycho acoustic model is - very bad, although the quality is surpringly good for such a model ! - -- the bit rate control is really not correct. - -- Only frame size multiple of 16 are handled. - -- If you want a specific format to be added (I am thinking about - MJPEG, H261) please tell me. Of course, the format you choose should - be based on MPEG to be easily integrated - -- ffmpeg can be used to generate streaming audio/video on a - server. Please tell me if you are interested. - diff --git a/doc/README.tech b/doc/README.tech deleted file mode 100644 index 8ba259d27a..0000000000 --- a/doc/README.tech +++ /dev/null @@ -1,25 +0,0 @@ -Technical notes: ---------------- - -- To increase speed, only motion vectors (0,0) are tested - -- The decision intra/predicted macroblock is the algorithm suggested - by the mpeg 1 specification. - -- only Huffman based H263 is supported, mainly because of patent - issues. - -- Many options can be modified only in the source code. - -- I rewrote the mpeg audio layer 2 compatible encoder from scratch. It - is one of the simplest encoder you can imagine (800 lines of C code - !). It is also one of the fastest because of its simplicity. They - are still some problems of overflow. A minimal psycho acoustic model - could be added. Only mono stream can be generated. I may add stereo - if needed. - -- I rewrote the AC3 audio encoder from scratch. It is fairly naive, - but the result are quiet interesting at 64 kbit/s. It includes - extensions for low sampling rates used in some Internet - formats. Differential and coupled stereo is not handled. Stereo - channels are simply handled as two mono channels. diff --git a/doc/TODO b/doc/TODO deleted file mode 100644 index c57a4876d6..0000000000 --- a/doc/TODO +++ /dev/null @@ -1,19 +0,0 @@ -ffmpeg TODO list: - -- Add ASF format. - -- add MJPEG codec. - -- fix skip frame bug in mpeg video - -- fix G2 audio problem (bad volume in AC3 ?) - -- use non zero motion vectors. - -- test fifo & master handling - -- deny & allow + password. - -- Improve psycho acoustic model for AC3 & mpeg audio. - -- Improve the bit rate control for video codecs. diff --git a/doc/ffmpeg.txt b/doc/ffmpeg.txt deleted file mode 100644 index b7fffcdd29..0000000000 --- a/doc/ffmpeg.txt +++ /dev/null @@ -1,62 +0,0 @@ -* ffmpeg can use YUV files as input : - - ffmpeg /tmp/out.mpg /tmp/test - -If will use the files: -/tmp/test0.Y, /tmp/test0.U, /tmp/test0.V, -/tmp/test1.Y, /tmp/test1.U, /tmp/test1.V, etc... - -The Y files use twice the resolution of the U and V files. They are -raw files, without header. They can be generated by all decent video -decoders. - -* ffmpeg can use a video4linux compatible video source : - - ffmpeg /tmp/out.mpg - - Note that you must activate the right video source and channel - before launching ffmpeg. You can use any TV viewer such as xawtv by - Gerd Knorr which I find very good. - -* There are some importants options to know: - --s size set frame size [160x128] --f format set encoding format [mpeg1] --r fps set frame rate [25] --b bitrate set the bitrate in kbit/s [100] --t time set recording time in seconds [10.0] - -The frame size can also be: cif, qcif, sqcif and 4cif. -The encoding format can be mpeg1, h263 or rv10. - -Advanced options are: - --d device set video4linux device name --g gop_size set the group of picture size. - An 'intra' frame is generated every gop_size frames. --i use only intra images (speed up compression, but lower quality). --c comment set the comment string. - -Comment strings are only used for Real Video(tm) encoding. Tags are -used in the comment string. A typical comment string is: - -"+title=Test Video +author=FFMpeg +copyright=Free +comment=Generated by FFMpeg 1.0" - -The output file can be "-" to output to a pipe. This is only possible -with mpeg1 and h263 formats. - -* Tips: - -- For low bit rate application, use a low frame rate and a small gop - size. This is especially true for real video where the Linux player - does not seem to be very fast, so it can miss frames. An example is: - - ffmpeg -g 3 -r 3 -t 10 -b 50 -s qcif -f rv10 /tmp/b.rm - -- The parameter 'q' which is displayed while encoding is the current - quantizer. The value of 1 indicates that a very good quality could - be achieved. The value of 31 indicates the worst quality. If q=31 - too often, it means that the encoder cannot compress enough to meet - your bit rate. You must either increase the bit rate, decrease the - frame rate or decrease the frame size. - diff --git a/doc/ffserver.conf b/doc/ffserver.conf deleted file mode 100644 index 8b5d926a12..0000000000 --- a/doc/ffserver.conf +++ /dev/null @@ -1,214 +0,0 @@ -# Port on which the server is listening. You must select a different -# port from your standard http web server if it is running on the same -# computer. - -Port 8080 - -# Address on which the server is bound. Only useful if you have -# several network interfaces. - -BindAddress 0.0.0.0 - -# Host and port of the master server if you which that this server -# duplicates another existing server. Otherwise, the server does the -# audio/video grab itself. See the following options for the grab parameters - -#MasterServer http://localhost:80/index.html - -# Grab parameters - -#AudioDevice /dev/dsp -#VideoDevice /dev/video - -# Number of simultaneous requests that can be handled. Since FFServer -# is very fast, this limit is determined mainly by your Internet -# connection speed. - -MaxClients 1000 - -# Access Log file (uses standard Apache log file format) -# '-' is the standard output - -CustomLog - - -################################################################## -# Now you can define each stream which will be generated from the -# original audio and video stream. Each format has a filename (here -# 'test128.mpg'). FFServer will send this stream when answering a -# request containing this filename. - - - -# Format of the stream : you can choose among: -# mpeg1 : MPEG1 multiplexed video and audio -# mpeg1video : only MPEG1 video -# mp2 : MPEG audio layer 2 -# mp3 : MPEG audio layer 3 (currently sent as layer 2) -# rm : Real Networks compatible stream. Multiplexed audio and video. -# ra : Real Networks compatible stream. Audio only. -# mpjpeg : Multipart JPEG (works with Netscape without any plugin) -# jpeg : Generate a single JPEG image. -# asf : ASF compatible stream (Windows Media Player format) -# swf : Macromedia flash(tm) compatible stream -# master : special ffmpeg stream used to duplicate a server - -Format mpeg1 - -# Bitrate for the audio stream. Codecs usually support only a few different bitrates. - -AudioBitRate 32 - -# Number of audio channels : 1 = mono, 2 = stereo - -AudioChannels 1 - -# Sampling frequency for audio. When using low bitrates, you should -# lower this frequency to 22050 or 11025. The supported frequencies -# depend on the selected audio codec. - -AudioSampleRate 44100 - -# Bitrate for the video stream. -VideoBitRate 64 - -# Number of frames per second -VideoFrameRate 3 - -# Size of the video frame : WxH -# W : width, H : height -# The following abbreviation are defined : sqcif, qcif, cif, 4cif -#VideoSize 352x240 - -# transmit only intra frames (useful for low bitrates) -VideoIntraOnly - -# If non intra only, an intra frame is transmitted every VideoGopSize -# frames Video synchronization can only begin at an I frames. -#VideoGopSize 12 - - - -# second mpeg stream with high frame rate - - -Format mpeg1video -VideoBitRate 128 -VideoFrameRate 25 -#VideoSize 352x240 -VideoGopSize 25 - - -################################################################## -# Another stream : used to download data to another server which -# duplicates this one - - - -Format master - - - -################################################################## -# Another stream : Real with audio only at 32 kbits - - - -Format ra -AudioBitRate 32 - - - -################################################################## -# Another stream : Real with audio and video at 64 kbits - - - -Format rm - -AudioBitRate 32 -VideoBitRate 20 -VideoFrameRate 2 -VideoIntraOnly - - - -################################################################## -# Another stream : Mpeg audio layer 2 at 64 kbits. - - - -Format mp2 -AudioBitRate 64 -AudioSampleRate 44100 - - - - - -Format mp2 -AudioBitRate 32 -AudioSampleRate 16000 - - - -################################################################## -# Another stream : Multipart JPEG - - - -Format mpjpeg - -VideoFrameRate 2 -VideoIntraOnly - - - -################################################################## -# Another stream : Multipart JPEG - - - -Format jpeg - -# the parameters are choose here to take the same output as the -# Multipart JPEG one. -VideoFrameRate 2 -VideoIntraOnly - - - -################################################################## -# Another stream : Flash - - - -Format swf - -VideoFrameRate 2 -VideoIntraOnly - - - - -################################################################## -# Another stream : ASF compatible - - - -Format asf - -AudioBitRate 64 -AudioSampleRate 44100 -VideoFrameRate 2 -VideoIntraOnly - - - -################################################################## -# Another stream : server status - - - -Format status - - diff --git a/ffmpeg.c b/ffmpeg.c deleted file mode 100644 index 57cdd07348..0000000000 --- a/ffmpeg.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Basic user interface for ffmpeg system - * Copyright (c) 2000 Gerard Lantau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpegenc.h" -#include "mpegvideo.h" - -static AVFormat *file_format; -static int frame_width = 160; -static int frame_height = 128; -static int frame_rate = 25; -static int bit_rate = 200000; -static int video_disable = 0; - -static const char *video_filename, *audio_filename; -static float recording_time = 10.0; -static int nb_frames; -static int gop_size = 12; -static int intra_only = 0; -static int audio_freq = 44100; -static int audio_bit_rate = 64000; -static int audio_disable = 0; -static int audio_channels = 1; - -static long long time_start; - - -static int file_read_picture(AVEncodeContext *s, - UINT8 *picture[3], - int width, int height, - int picture_number) -{ - FILE *f; - char buf[1024]; - static int init = 0; - static UINT8 *pict[3]; - if (!init) { - pict[0] = malloc(width * height); - pict[1] = malloc(width * height / 4); - pict[2] = malloc(width * height / 4); - init = 1; - } - - picture[0] = pict[0]; - picture[1] = pict[1]; - picture[2] = pict[2]; - - sprintf(buf, "%s%d.Y", video_filename, picture_number); - f=fopen(buf, "r"); - if (!f) { - return -1; - } - - fread(picture[0], 1, width * height, f); - fclose(f); - - sprintf(buf, "%s%d.U", video_filename, picture_number); - f=fopen(buf, "r"); - if (!f) { - perror(buf); - exit(1); - } - fread(picture[1], 1, width * height / 4, f); - fclose(f); - - sprintf(buf, "%s%d.V", video_filename, picture_number); - f=fopen(buf, "r"); - if (!f) { - perror(buf); - exit(1); - } - fread(picture[2], 1, width * height / 4, f); - fclose(f); - return 0; -} - -static void display_stats(AVEncodeContext *video_ctx, - AVEncodeContext *audio_ctx, - int batch_mode, int the_end) -{ - if (video_ctx && - ((video_ctx->frame_number % video_ctx->rate) == 0 || - the_end)) { - float ti; - - if (batch_mode) { - ti = (float)video_ctx->frame_number / video_ctx->rate; - } else { - ti = (gettime() - time_start) / 1000000.0; - if (ti < 0.1) - ti = 0.1; - } - - fprintf(stderr, - "frame=%5d size=%8dkB time=%0.1f fps=%4.1f bitrate=%6.1fkbits/s q=%2d\r", - video_ctx->frame_number, - data_out_size / 1024, - ti, - video_ctx->frame_number / ti, - (data_out_size * 8 / ti / 1000), - ((MpegEncContext *)video_ctx->priv_data)->qscale); - if (the_end) { - fprintf(stderr,"\n"); - } - fflush(stderr); - } -#if 0 - if (the_end && batch_mode && audio_ctx) { - duration = (gettime() - ti) / 1000000.0; - factor = 0; - if (ti > 0) { - factor = (float)nb_samples / s->sample_rate / duration; - } - fprintf(stderr, "%0.1f seconds compressed in %0.1f seconds (speed factor: %0.1f)\n", - (float)nb_samples / s->sample_rate, - duration, - factor); - } -#endif -} - -void raw_write_data(void *opaque, - unsigned char *buf, int size) -{ - FILE *outfile = opaque; - fwrite(buf, 1, size, outfile); - data_out_size += size; -} - -int raw_seek(void *opaque, long long offset, int whence) -{ - FILE *outfile = opaque; - fseek(outfile, offset, whence); - return 0; -} - -static void av_encode(AVFormatContext *ctx, - const char *video_filename, - const char *audio_filename) -{ - UINT8 audio_buffer[4096]; - UINT8 video_buffer[128*1024]; - char buf[256]; - short *samples; - int ret; - int audio_fd; - FILE *infile; - int sample_count; - int batch_mode; - AVEncodeContext *audio_enc, *video_enc; - int frame_size, frame_bytes; - AVEncoder *audio_encoder, *video_encoder; - UINT8 *picture[3]; - - /* audio */ - audio_enc = ctx->audio_enc; - sample_count = 0; - infile = NULL; - frame_size = 0; - samples = NULL; - audio_fd = -1; - frame_bytes = 0; - batch_mode = 0; - if (audio_filename || - video_filename) - batch_mode = 1; - - if (audio_enc) { - if (batch_mode) { - if (!audio_filename) { - fprintf(stderr, "Must give audio input file\n"); - exit(1); - } - infile = fopen(audio_filename, "r"); - if (!infile) { - fprintf(stderr, "Could not open '%s'\n", audio_filename); - exit(1); - } - audio_fd = -1; - } else { - audio_fd = audio_open(audio_enc->rate, audio_enc->channels); - if (audio_fd < 0) { - fprintf(stderr, "Could not open audio device\n"); - exit(1); - } - } - - audio_encoder = avencoder_find(ctx->format->audio_codec); - if (avencoder_open(audio_enc, audio_encoder) < 0) { - fprintf(stderr, "Audio encoder: incorrect audio frequency or bitrate\n"); - exit(1); - } - avencoder_string(buf, sizeof(buf), audio_enc); - fprintf(stderr, " %s\n", buf); - - frame_size = audio_enc->frame_size; - - frame_bytes = frame_size * 2 * audio_enc->channels; - samples = malloc(frame_bytes); - } - - /* video */ - video_enc = ctx->video_enc; - if (video_enc) { - if (batch_mode) { - if (!video_filename) { - fprintf(stderr, "Must give video input file\n"); - exit(1); - } - } else { - ret = v4l_init(video_enc->rate, video_enc->width, video_enc->height); - if (ret < 0) { - fprintf(stderr,"Could not init video 4 linux capture\n"); - exit(1); - } - } - - video_encoder = avencoder_find(ctx->format->video_codec); - if (avencoder_open(video_enc, video_encoder) < 0) { - fprintf(stderr, "Error while initializing video codec\n"); - exit(1); - } - - avencoder_string(buf, sizeof(buf), video_enc); - fprintf(stderr, " %s\n", buf); - } - - ctx->format->write_header(ctx); - time_start = gettime(); - - for(;;) { - /* read & compression audio frames */ - if (audio_enc) { - if (!batch_mode) { - for(;;) { - ret = read(audio_fd, samples, frame_bytes); - if (ret != frame_bytes) - break; - ret = avencoder_encode(audio_enc, - audio_buffer, sizeof(audio_buffer), samples); - ctx->format->write_audio_frame(ctx, audio_buffer, ret); - } - } else { - if (video_enc) - sample_count += audio_enc->rate / video_enc->rate; - else - sample_count += frame_size; - while (sample_count > frame_size) { - if (fread(samples, 1, frame_bytes, infile) == 0) - goto the_end; - - ret = avencoder_encode(audio_enc, - audio_buffer, sizeof(audio_buffer), samples); - ctx->format->write_audio_frame(ctx, audio_buffer, ret); - - sample_count -= frame_size; - } - } - } - - if (video_enc) { - /* read video image */ - if (batch_mode) { - ret = file_read_picture (video_enc, picture, - video_enc->width, video_enc->height, - video_enc->frame_number); - } else { - ret = v4l_read_picture (picture, - video_enc->width, video_enc->height, - video_enc->frame_number); - } - if (ret < 0) - break; - ret = avencoder_encode(video_enc, video_buffer, sizeof(video_buffer), picture); - ctx->format->write_video_picture(ctx, video_buffer, ret); - } - - display_stats(video_enc, NULL, batch_mode, 0); - if (video_enc && video_enc->frame_number >= nb_frames) - break; - } - the_end: - display_stats(video_enc, NULL, batch_mode, 1); - - if (video_enc) - avencoder_close(video_enc); - - if (audio_enc) - avencoder_close(audio_enc); - - ctx->format->write_trailer(ctx); - - if (!infile) { - close(audio_fd); - } else { - fclose(infile); - } -} - -typedef struct { - const char *str; - int width, height; -} SizeEntry; - -SizeEntry sizes[] = { - { "sqcif", 128, 96 }, - { "qcif", 176, 144 }, - { "cif", 352, 288 }, - { "4cif", 704, 576 }, -}; - -enum { - OPT_AR=256, - OPT_AB, - OPT_AN, - OPT_AC, - OPT_VN, -}; - -struct option long_options[] = -{ - { "ar", required_argument, NULL, OPT_AR }, - { "ab", required_argument, NULL, OPT_AB }, - { "an", no_argument, NULL, OPT_AN }, - { "ac", required_argument, NULL, OPT_AC }, - { "vn", no_argument, NULL, OPT_VN }, -}; - -enum { - OUT_FILE, - OUT_PIPE, - OUT_UDP, -}; - - -void help(void) -{ - AVFormat *f; - - printf("ffmpeg version 1.0, Copyright (c) 2000 Gerard Lantau\n" - "usage: ffmpeg [options] outfile [video_infile] [audio_infile]\n" - "Hyper fast MPEG1 video/H263/RV and AC3/MPEG audio layer 2 encoder\n" - "\n" - "Main options are:\n" - "\n" - "-L print the LICENSE\n" - "-s size set frame size [%dx%d]\n" - "-f format set encoding format [%s]\n" - "-r fps set frame rate [%d]\n" - "-b bitrate set the total bitrate in kbit/s [%d]\n" - "-t time set recording time in seconds [%0.1f]\n" - "-ar freq set the audio sampling freq [%d]\n" - "-ab bitrate set the audio bitrate in kbit/s [%d]\n" - "-ac channels set the number of audio channels [%d]\n" - "-an disable audio recording [%s]\n" - "-vn disable video recording [%s]\n" - "\n" - "Frame sizes abbreviations: sqcif qcif cif 4cif\n", - frame_width, frame_height, - file_format->name, - frame_rate, - bit_rate / 1000, - recording_time, - audio_freq, - audio_bit_rate / 1000, - audio_channels, - audio_disable ? "yes" : "no", - video_disable ? "yes" : "no"); - - printf("Encoding video formats:"); - for(f = first_format; f != NULL; f = f->next) - printf(" %s", f->name); - printf("\n"); - - printf("outfile can be a file name, - (pipe) or 'udp:host:port'\n" - "\n" - "Advanced options are:\n" - "-d device set video4linux device name\n" - "-g gop_size set the group of picture size [%d]\n" - "-i use only intra frames [%s]\n" - "-c comment set the comment string\n" - "\n", - gop_size, - intra_only ? "yes" : "no"); -} - -void licence(void) -{ - printf( - "ffmpeg version 1.0\n" - "Copyright (c) 2000 Gerard Lantau\n" - "This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" - ); -} - -static unsigned char output_buffer[32768]; - -int main(int argc, char **argv) -{ - AVEncodeContext video_enc1, *video_enc = &video_enc1; - AVEncodeContext audio_enc1, *audio_enc = &audio_enc1; - UDPContext udp_ctx1, *udp_ctx = &udp_ctx1; - AVFormatContext av_ctx1, *av_ctx = &av_ctx1; - FILE *outfile; - int i, c; - char *filename; - int output_type; - int use_video, use_audio; - - register_avencoder(&ac3_encoder); - register_avencoder(&mp2_encoder); - register_avencoder(&mpeg1video_encoder); - register_avencoder(&h263_encoder); - register_avencoder(&rv10_encoder); - register_avencoder(&mjpeg_encoder); - - register_avformat(&mp2_format); - register_avformat(&ac3_format); - register_avformat(&mpeg1video_format); - register_avformat(&h263_format); - register_avformat(&mpeg_mux_format); - register_avformat(&ra_format); - register_avformat(&rm_format); - register_avformat(&asf_format); - register_avformat(&mpjpeg_format); - register_avformat(&swf_format); - - file_format = NULL; - - for(;;) { - c = getopt_long_only(argc, argv, "s:f:r:b:t:hd:g:ic:L", - long_options, NULL); - if (c == -1) - break; - switch(c) { - case 'L': - licence(); - exit(1); - case 'h': - help(); - exit(1); - case 's': - { - int n = sizeof(sizes) / sizeof(SizeEntry); - const char *p; - - for(i=0;iname, optarg) != 0) f = f->next; - if (f == NULL) { - fprintf(stderr, "Invalid format: %s\n", optarg); - exit(1); - } - file_format = f; - } - break; - case 'r': - { - frame_rate = atoi(optarg); - } - break; - case 'b': - { - bit_rate = atoi(optarg) * 1000; - } - break; - case 't': - { - recording_time = atof(optarg); - break; - } - /* audio specific */ - case OPT_AR: - { - audio_freq = atoi(optarg); - break; - } - case OPT_AB: - { - audio_bit_rate = atoi(optarg) * 1000; - break; - } - case OPT_AN: - audio_disable = 1; - break; - case OPT_VN: - video_disable = 1; - break; - case OPT_AC: - { - audio_channels = atoi(optarg); - if (audio_channels != 1 && - audio_channels != 2) { - fprintf(stderr, "Incorrect number of channels: %d\n", audio_channels); - exit(1); - } - } - break; - /* advanced options */ - case 'd': - v4l_device = optarg; - break; - case 'g': - gop_size = atoi(optarg); - break; - case 'i': - intra_only = 1; - break; - case 'c': - comment_string = optarg; - break; - default: - exit(2); - } - } - - if (optind >= argc) { - help(); - exit(1); - } - - filename = argv[optind++]; - video_filename = NULL; - audio_filename = NULL; - - /* auto detect format */ - if (file_format == NULL) - file_format = guess_format(NULL, filename, NULL); - - if (file_format == NULL) - file_format = &mpeg_mux_format; - - /* check parameters */ - if (frame_width <= 0 || frame_height <= 0) { - fprintf(stderr, "Incorrect frame size\n"); - exit(1); - } - if ((frame_width % 16) != 0 || (frame_height % 16) != 0) { - fprintf(stderr, "Frame size must be a multiple of 16\n"); - exit(1); - } - - if (bit_rate < 5000 || bit_rate >= 10000000) { - fprintf(stderr, "Invalid bit rate\n"); - exit(1); - } - - if (frame_rate < 1 || frame_rate >= 60) { - fprintf(stderr, "Invalid frame rate\n"); - exit(1); - } - - nb_frames = (int)(recording_time * frame_rate); - if (nb_frames < 1) { - fprintf(stderr, "Invalid recording time\n"); - exit(1); - } - - use_video = file_format->video_codec != CODEC_ID_NONE; - use_audio = file_format->audio_codec != CODEC_ID_NONE; - if (audio_disable) { - use_audio = 0; - } - if (video_disable) { - use_video = 0; - } - - if (use_video == 0 && use_audio == 0) { - fprintf(stderr, "No audio or video selected\n"); - exit(1); - } - - fprintf(stderr, "Recording: %s, %0.1f seconds\n", - file_format->name, - recording_time); - - /* open output media */ - - if (strstart(filename, "udp:", NULL)) { - output_type = OUT_UDP; - outfile = NULL; - memset(udp_ctx, 0, sizeof(*udp_ctx)); - if (udp_tx_open(udp_ctx, filename, 0) < 0) { - fprintf(stderr, "Could not open UDP socket\n"); - exit(1); - } - } else if (!strcmp(filename, "-")) { - output_type = OUT_PIPE; - outfile = stdout; - } else { - output_type = OUT_FILE; - outfile = fopen(filename, "w"); - if (!outfile) { - perror(filename); - exit(1); - } - } - - av_ctx->video_enc = NULL; - av_ctx->audio_enc = NULL; - - if (output_type == OUT_UDP) { - init_put_byte(&av_ctx->pb, output_buffer, sizeof(output_buffer), - udp_ctx, udp_write_data, NULL); - } else { - init_put_byte(&av_ctx->pb, output_buffer, sizeof(output_buffer), - outfile, raw_write_data, raw_seek); - } - - if (use_video) { - if (optind < argc) { - video_filename = argv[optind++]; - } - /* init mpeg video encoding context */ - memset(video_enc, 0, sizeof(*video_enc)); - video_enc->bit_rate = bit_rate; - video_enc->rate = frame_rate; - - video_enc->width = frame_width; - video_enc->height = frame_height; - if (!intra_only) - video_enc->gop_size = gop_size; - else - video_enc->gop_size = 0; - - av_ctx->video_enc = video_enc; - av_ctx->format = file_format; - } - - if (use_audio) { - if (optind < argc) { - audio_filename = argv[optind++]; - } - audio_enc->bit_rate = audio_bit_rate; - audio_enc->rate = audio_freq; - audio_enc->channels = audio_channels; - av_ctx->audio_enc = audio_enc; - } - av_ctx->format = file_format; - av_ctx->is_streamed = 0; - - av_encode(av_ctx, video_filename, audio_filename); - - /* close output media */ - - switch(output_type) { - case OUT_FILE: - fclose(outfile); - break; - case OUT_PIPE: - break; - case OUT_UDP: - udp_tx_close(udp_ctx); - break; - } - fprintf(stderr, "\n"); - - return 0; -} - diff --git a/ffserver.c b/ffserver.c deleted file mode 100644 index 4bece8c455..0000000000 --- a/ffserver.c +++ /dev/null @@ -1,1642 +0,0 @@ -/* - * Multiple format streaming server - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpegenc.h" - -/* maximum number of simultaneous HTTP connections */ -#define HTTP_MAX_CONNECTIONS 2000 - -enum HTTPState { - HTTPSTATE_WAIT_REQUEST, - HTTPSTATE_SEND_HEADER, - HTTPSTATE_SEND_DATA_HEADER, - HTTPSTATE_SEND_DATA, - HTTPSTATE_SEND_DATA_TRAILER, -}; - -enum MasterState { - MASTERSTATE_RECEIVE_HEADER, - MASTERSTATE_RECEIVE_DATA, -}; - -#define IOBUFFER_MAX_SIZE 16384 -#define FIFO_MAX_SIZE (1024*1024) - -/* coef for exponential mean for bitrate estimation in statistics */ -#define AVG_COEF 0.9 - -/* timeouts are in ms */ -#define REQUEST_TIMEOUT (15 * 1000) -#define SYNC_TIMEOUT (10 * 1000) -#define MASTER_CONNECT_TIMEOUT (10 * 1000) - -typedef struct HTTPContext { - enum HTTPState state; - int fd; /* socket file descriptor */ - struct sockaddr_in from_addr; /* origin */ - struct pollfd *poll_entry; /* used when polling */ - long timeout; - UINT8 buffer[IOBUFFER_MAX_SIZE]; - UINT8 *buffer_ptr, *buffer_end; - int http_error; - struct HTTPContext *next; - UINT8 *rptr; /* read pointer in the fifo */ - int got_key_frame[2]; /* for each type */ - long long data_count; - long long last_http_fifo_write_count; /* used to monitor overflow in the fifo */ - /* format handling */ - struct FFStream *stream; - AVFormatContext fmt_ctx; - int last_packet_sent; /* true if last data packet was sent */ -} HTTPContext; - -/* each generated stream is described here */ -enum StreamType { - STREAM_TYPE_LIVE, - STREAM_TYPE_MASTER, - STREAM_TYPE_STATUS, -}; - -typedef struct FFStream { - enum StreamType stream_type; - char filename[1024]; - AVFormat *fmt; - AVEncodeContext *audio_enc; - AVEncodeContext *video_enc; - struct FFStream *next; -} FFStream; - -typedef struct FifoBuffer { - UINT8 *buffer; - UINT8 *rptr, *wptr, *end; -} FifoBuffer; - -/* each codec is here */ -typedef struct FFCodec { - struct FFCodec *next; - FifoBuffer fifo; /* for compression: one audio fifo per codec */ - ReSampleContext resample; /* for audio resampling */ - long long data_count; - float avg_frame_size; /* frame size averraged over last frames with exponential mean */ - AVEncodeContext enc; -} FFCodec; - -/* packet header */ -typedef struct { - UINT8 codec_type; - UINT8 codec_id; - UINT8 data[4]; - UINT16 bit_rate; - UINT16 payload_size; -} PacketHeader; - -struct sockaddr_in my_addr; -char logfilename[1024]; -HTTPContext *first_http_ctx; -FFStream *first_stream; -FFCodec *first_codec; - -/* master state */ -char master_url[1024]; -enum MasterState master_state; -UINT8 *master_wptr; -int master_count; - -long long http_fifo_write_count; -static FifoBuffer http_fifo; - -static int handle_http(HTTPContext *c, long cur_time); -static int http_parse_request(HTTPContext *c); -static int http_send_data(HTTPContext *c); -static int master_receive(int fd); -static void compute_stats(HTTPContext *c); - -int nb_max_connections; -int nb_connections; - -/* fifo handling */ -int fifo_init(FifoBuffer *f, int size) -{ - f->buffer = malloc(size); - if (!f->buffer) - return -1; - f->end = f->buffer + size; - f->wptr = f->rptr = f->buffer; - return 0; -} - -static int fifo_size(FifoBuffer *f, UINT8 *rptr) -{ - int size; - - if (f->wptr >= rptr) { - size = f->wptr - rptr; - } else { - size = (f->end - rptr) + (f->wptr - f->buffer); - } - return size; -} - -/* get data from the fifo (return -1 if not enough data) */ -static int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr) -{ - UINT8 *rptr = *rptr_ptr; - int size, len; - - if (f->wptr >= rptr) { - size = f->wptr - rptr; - } else { - size = (f->end - rptr) + (f->wptr - f->buffer); - } - - if (size < buf_size) - return -1; - while (buf_size > 0) { - len = f->end - rptr; - if (len > buf_size) - len = buf_size; - memcpy(buf, rptr, len); - buf += len; - rptr += len; - if (rptr >= f->end) - rptr = f->buffer; - buf_size -= len; - } - *rptr_ptr = rptr; - return 0; -} - -static void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr) -{ - int len; - UINT8 *wptr; - wptr = *wptr_ptr; - while (size > 0) { - len = f->end - wptr; - if (len > size) - len = size; - memcpy(wptr, buf, len); - wptr += len; - if (wptr >= f->end) - wptr = f->buffer; - buf += len; - size -= len; - } - *wptr_ptr = wptr; -} - -static long gettime_ms(void) -{ - struct timeval tv; - - gettimeofday(&tv,NULL); - return (long long)tv.tv_sec * 1000 + (tv.tv_usec / 1000); -} - -static FILE *logfile = NULL; - -static void http_log(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - if (logfile) - vfprintf(logfile, fmt, ap); - va_end(ap); -} - - -/* connect to url 'url' and return the connected socket ready to read data */ -static int url_get(const char *url) -{ - struct sockaddr_in dest_addr; - struct hostent *h; - int s, port, size, line_size, len; - char hostname[1024], *q; - const char *p, *path; - char req[1024]; - unsigned char ch; - - if (!strstart(url, "http://", &p)) - return -1; - q = hostname; - while (*p != ':' && *p != '\0' && *p != '/') { - if ((q - hostname) < (sizeof(hostname) - 1)) - *q++ = *p; - p++; - } - port = 80; - if (*p == ':') { - p++; - port = strtol(p, (char **)&p, 10); - } - path = p; - - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); - - if (!inet_aton(hostname, &dest_addr.sin_addr)) { - if ((h = gethostbyname(hostname)) == NULL) - return -1; - memcpy(&dest_addr.sin_addr, h->h_addr, sizeof(dest_addr.sin_addr)); - } - - s=socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) - return -1; - - if (connect(s, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) { - fail: - close(s); - return -1; - } - - /* send http request */ - snprintf(req, sizeof(req), "GET %s HTTP/1.0\r\n\r\n", path); - p = req; - size = strlen(req); - while (size > 0) { - len = write(s, p, size); - if (len == -1) { - if (errno != EAGAIN && errno != EINTR) - goto fail; - } else { - size -= len; - p += len; - } - } - - /* receive answer */ - line_size = 0; - for(;;) { - len = read(s, &ch, 1); - if (len == -1) { - if (errno != EAGAIN && errno != EINTR) - goto fail; - } else if (len == 0) { - goto fail; - } else { - if (ch == '\n') { - if (line_size == 0) - break; - line_size = 0; - } else if (ch != '\r') { - line_size++; - } - } - } - - return s; -} - -/* Each request is served by reading the input FIFO and by adding the - right format headers */ -static int http_server(struct sockaddr_in my_addr) -{ - int server_fd, tmp, ret; - struct sockaddr_in from_addr; - struct pollfd poll_table[HTTP_MAX_CONNECTIONS + 1], *poll_entry; - HTTPContext *c, **cp; - long cur_time; - int master_fd, master_timeout; - - /* will try to connect to master as soon as possible */ - master_fd = -1; - master_timeout = gettime_ms(); - - server_fd = socket(AF_INET,SOCK_STREAM,0); - if (server_fd < 0) { - perror ("socket"); - return -1; - } - - tmp = 1; - setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)); - - if (bind (server_fd, (struct sockaddr *) &my_addr, sizeof (my_addr)) < 0) { - perror ("bind"); - close(server_fd); - return -1; - } - - if (listen (server_fd, 5) < 0) { - perror ("listen"); - close(server_fd); - return -1; - } - - http_log("ffserver started.\n"); - - fcntl(server_fd, F_SETFL, O_NONBLOCK); - first_http_ctx = NULL; - nb_connections = 0; - first_http_ctx = NULL; - for(;;) { - poll_entry = poll_table; - poll_entry->fd = server_fd; - poll_entry->events = POLLIN; - poll_entry++; - - if (master_fd >= 0) { - poll_entry->fd = master_fd; - poll_entry->events = POLLIN; - poll_entry++; - } - - /* wait for events on each HTTP handle */ - c = first_http_ctx; - while (c != NULL) { - int fd; - fd = c->fd; - switch(c->state) { - case HTTPSTATE_WAIT_REQUEST: - c->poll_entry = poll_entry; - poll_entry->fd = fd; - poll_entry->events = POLLIN; - poll_entry++; - break; - case HTTPSTATE_SEND_HEADER: - case HTTPSTATE_SEND_DATA_HEADER: - case HTTPSTATE_SEND_DATA: - case HTTPSTATE_SEND_DATA_TRAILER: - c->poll_entry = poll_entry; - poll_entry->fd = fd; - poll_entry->events = POLLOUT; - poll_entry++; - break; - default: - c->poll_entry = NULL; - break; - } - c = c->next; - } - - /* wait for an event on one connection. We poll at least every - second to handle timeouts */ - do { - ret = poll(poll_table, poll_entry - poll_table, 1000); - } while (ret == -1); - - cur_time = gettime_ms(); - - /* now handle the events */ - - cp = &first_http_ctx; - while ((*cp) != NULL) { - c = *cp; - if (handle_http (c, cur_time) < 0) { - /* close and free the connection */ - close(c->fd); - *cp = c->next; - free(c); - nb_connections--; - } else { - cp = &c->next; - } - } - - /* new connection request ? */ - poll_entry = poll_table; - if (poll_entry->revents & POLLIN) { - int fd, len; - - len = sizeof(from_addr); - fd = accept(server_fd, &from_addr, &len); - if (fd >= 0) { - fcntl(fd, F_SETFL, O_NONBLOCK); - /* XXX: should output a warning page when comming - close to the connection limit */ - if (nb_connections >= nb_max_connections) { - close(fd); - } else { - /* add a new connection */ - c = malloc(sizeof(HTTPContext)); - memset(c, 0, sizeof(*c)); - c->next = first_http_ctx; - first_http_ctx = c; - c->fd = fd; - c->poll_entry = NULL; - c->from_addr = from_addr; - c->state = HTTPSTATE_WAIT_REQUEST; - c->buffer_ptr = c->buffer; - c->buffer_end = c->buffer + IOBUFFER_MAX_SIZE; - c->timeout = cur_time + REQUEST_TIMEOUT; - nb_connections++; - } - } - } - poll_entry++; - - /* master events */ - if (poll_entry->revents & POLLIN) { - if (master_receive(master_fd) < 0) { - close(master_fd); - master_fd = -1; - } - } - - /* master (re)connection handling */ - if (master_url[0] != '\0' && - master_fd < 0 && (master_timeout - cur_time) <= 0) { - master_fd = url_get(master_url); - if (master_fd < 0) { - master_timeout = gettime_ms() + MASTER_CONNECT_TIMEOUT; - http_log("Connection to master: '%s' failed\n", master_url); - } else { - fcntl(master_fd, F_SETFL, O_NONBLOCK); - master_state = MASTERSTATE_RECEIVE_HEADER; - master_count = sizeof(PacketHeader); - master_wptr = http_fifo.wptr; - } - } - } -} - -static int handle_http(HTTPContext *c, long cur_time) -{ - int len; - - switch(c->state) { - case HTTPSTATE_WAIT_REQUEST: - /* timeout ? */ - if ((c->timeout - cur_time) < 0) - return -1; - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - - /* no need to read if no events */ - if (!(c->poll_entry->revents & POLLIN)) - return 0; - /* read the data */ - len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); - if (len < 0) { - if (errno != EAGAIN && errno != EINTR) - return -1; - } else if (len == 0) { - return -1; - } else { - /* search for end of request. XXX: not fully correct since garbage could come after the end */ - UINT8 *ptr; - c->buffer_ptr += len; - ptr = c->buffer_ptr; - if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) || - (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) { - /* request found : parse it and reply */ - if (http_parse_request(c) < 0) - return -1; - } else if (ptr >= c->buffer_end) { - /* request too long: cannot do anything */ - return -1; - } - } - break; - - case HTTPSTATE_SEND_HEADER: - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - - /* no need to read if no events */ - if (!(c->poll_entry->revents & POLLOUT)) - return 0; - len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); - if (len < 0) { - if (errno != EAGAIN && errno != EINTR) { - /* error : close connection */ - return -1; - } - } else { - c->buffer_ptr += len; - if (c->buffer_ptr >= c->buffer_end) { - /* if error, exit */ - if (c->http_error) - return -1; - /* all the buffer was send : synchronize to the incoming stream */ - c->state = HTTPSTATE_SEND_DATA_HEADER; - c->buffer_ptr = c->buffer_end = c->buffer; - } - } - break; - - case HTTPSTATE_SEND_DATA: - case HTTPSTATE_SEND_DATA_HEADER: - case HTTPSTATE_SEND_DATA_TRAILER: - /* no need to read if no events */ - if (c->poll_entry->revents & (POLLERR | POLLHUP)) - return -1; - - if (!(c->poll_entry->revents & POLLOUT)) - return 0; - if (http_send_data(c) < 0) - return -1; - break; - default: - return -1; - } - return 0; -} - -/* parse http request and prepare header */ -static int http_parse_request(HTTPContext *c) -{ - const char *p; - char cmd[32]; - char url[1024], *q; - char protocol[32]; - char msg[1024]; - char *mime_type; - FFStream *stream; - - p = c->buffer; - q = cmd; - while (!isspace(*p) && *p != '\0') { - if ((q - cmd) < sizeof(cmd) - 1) - *q++ = *p; - p++; - } - *q = '\0'; - if (strcmp(cmd, "GET")) - return -1; - - while (isspace(*p)) p++; - q = url; - while (!isspace(*p) && *p != '\0') { - if ((q - url) < sizeof(url) - 1) - *q++ = *p; - p++; - } - *q = '\0'; - - while (isspace(*p)) p++; - q = protocol; - while (!isspace(*p) && *p != '\0') { - if ((q - protocol) < sizeof(protocol) - 1) - *q++ = *p; - p++; - } - *q = '\0'; - if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1")) - return -1; - - /* find the filename in the request */ - p = url; - if (*p == '/') - p++; - - stream = first_stream; - while (stream != NULL) { - if (!strcmp(stream->filename, p)) - break; - stream = stream->next; - } - if (stream == NULL) { - sprintf(msg, "File '%s' not found", url); - goto send_error; - } - c->stream = stream; - - /* should do it after so that the size can be computed */ - { - char buf1[32], buf2[32], *p; - time_t ti; - /* XXX: reentrant function ? */ - p = inet_ntoa(c->from_addr.sin_addr); - strcpy(buf1, p); - ti = time(NULL); - p = ctime(&ti); - strcpy(buf2, p); - p = buf2 + strlen(p) - 1; - if (*p == '\n') - *p = '\0'; - http_log("%s - - [%s] \"%s %s %s\" %d %d\n", - buf1, buf2, cmd, url, protocol, 200, 1024); - } - - if (c->stream->stream_type == STREAM_TYPE_STATUS) - goto send_stats; - - /* prepare http header */ - q = c->buffer; - q += sprintf(q, "HTTP/1.0 200 OK\r\n"); - mime_type = c->stream->fmt->mime_type; - if (!mime_type) - mime_type = "application/x-octet_stream"; - q += sprintf(q, "Content-type: %s\r\n", mime_type); - q += sprintf(q, "Pragma: no-cache\r\n"); - /* for asf, we need extra headers */ - if (!strcmp(c->stream->fmt->name,"asf")) { - q += sprintf(q, "Pragma: features=broadcast\r\n"); - } - q += sprintf(q, "\r\n"); - - /* prepare output buffer */ - c->http_error = 0; - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - return 0; - send_error: - c->http_error = 404; - q = c->buffer; - q += sprintf(q, "HTTP/1.0 404 Not Found\r\n"); - q += sprintf(q, "Content-type: %s\r\n", "text/html"); - q += sprintf(q, "\r\n"); - q += sprintf(q, "\n"); - q += sprintf(q, "404 Not Found\n"); - q += sprintf(q, "%s\n", msg); - q += sprintf(q, "\n"); - - /* prepare output buffer */ - c->buffer_ptr = c->buffer; - c->buffer_end = q; - c->state = HTTPSTATE_SEND_HEADER; - return 0; - send_stats: - compute_stats(c); - c->http_error = 200; /* horrible : we use this value to avoid - going to the send data state */ - c->state = HTTPSTATE_SEND_HEADER; - return 0; -} - -static void compute_stats(HTTPContext *c) -{ - AVEncodeContext *enc; - HTTPContext *c1; - FFCodec *ffenc; - FFStream *stream; - float avg; - char buf[1024], *q, *p; - time_t ti; - int i; - - q = c->buffer; - q += sprintf(q, "HTTP/1.0 200 OK\r\n"); - q += sprintf(q, "Content-type: %s\r\n", "text/html"); - q += sprintf(q, "Pragma: no-cache\r\n"); - q += sprintf(q, "\r\n"); - - q += sprintf(q, "FFServer Status\n"); - q += sprintf(q, "

FFServer Status

\n"); - /* format status */ - q += sprintf(q, "

Available Streams

\n"); - q += sprintf(q, "\n"); - q += sprintf(q, "
PathFormatBit rate (kbits/s)VideoAudio\n"); - stream = first_stream; - while (stream != NULL) { - q += sprintf(q, "
%s ", - stream->filename, stream->filename); - switch(stream->stream_type) { - case STREAM_TYPE_LIVE: - { - int audio_bit_rate = 0; - int video_bit_rate = 0; - if (stream->audio_enc) - audio_bit_rate = stream->audio_enc->bit_rate; - if (stream->video_enc) - video_bit_rate = stream->video_enc->bit_rate; - - q += sprintf(q, " %s %d %d %d\n", - stream->fmt->name, - (audio_bit_rate + video_bit_rate) / 1000, - video_bit_rate / 1000, audio_bit_rate / 1000); - } - break; - case STREAM_TYPE_MASTER: - q += sprintf(q, " %s - - -\n", - "master"); - break; - default: - q += sprintf(q, " - - - -\n"); - break; - } - stream = stream->next; - } - q += sprintf(q, "
\n"); - - /* codec status */ - q += sprintf(q, "

Codec Status

\n"); - q += sprintf(q, "\n"); - q += sprintf(q, "
ParametersFrame countSizeAvg bitrate (kbits/s)\n"); - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - avencoder_string(buf, sizeof(buf), enc); - avg = ffenc->avg_frame_size * (float)enc->rate * 8.0; - if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0) - avg /= enc->frame_size; - q += sprintf(q, "
%s %d %Ld %0.1f\n", - buf, enc->frame_number, ffenc->data_count, avg / 1000.0); - ffenc = ffenc->next; - } - q += sprintf(q, "
\n"); - - /* exclude the stat connection */ - q += sprintf(q, "Number of connections: %d / %d
\n", - nb_connections, nb_max_connections); - - /* connection status */ - q += sprintf(q, "

Connection Status

\n"); - q += sprintf(q, "\n"); - q += sprintf(q, "
#FileIPSize\n"); - c1 = first_http_ctx; - i = 0; - while (c1 != NULL) { - i++; - p = inet_ntoa(c1->from_addr.sin_addr); - q += sprintf(q, "
%d%s %s %Ld\n", - i, c1->stream->filename, p, c1->data_count); - c1 = c1->next; - } - q += sprintf(q, "
\n"); - - /* date */ - ti = time(NULL); - p = ctime(&ti); - q += sprintf(q, "
Generated at %s", p); - q += sprintf(q, "\n\n"); - - c->buffer_ptr = c->buffer; - c->buffer_end = q; -} - - -static void http_write_packet(void *opaque, - unsigned char *buf, int size) -{ - HTTPContext *c = opaque; - if (size > IOBUFFER_MAX_SIZE) - abort(); - memcpy(c->buffer, buf, size); - c->buffer_ptr = c->buffer; - c->buffer_end = c->buffer + size; -} - -/* this headers are used to identify a packet for a given codec */ -void mk_header(PacketHeader *h, AVEncodeContext *c, int payload_size) -{ - h->codec_type = c->codec->type; - h->codec_id = c->codec->id; - h->bit_rate = htons(c->bit_rate / 1000); - switch(c->codec->type) { - case CODEC_TYPE_VIDEO: - h->data[0] = c->rate; - h->data[1] = c->width / 16; - h->data[2] = c->height / 16; - break; - case CODEC_TYPE_AUDIO: - h->data[0] = c->rate / 1000; - h->data[1] = c->channels; - h->data[2] = 0; - break; - } - h->data[3] = c->key_frame; - h->payload_size = htons(payload_size); -} - -int test_header(PacketHeader *h, AVEncodeContext *c) -{ - if (!c) - return 0; - - if (h->codec_type == c->codec->type && - h->codec_id == c->codec->id && - h->bit_rate == htons(c->bit_rate / 1000)) { - - switch(c->codec->type) { - case CODEC_TYPE_VIDEO: - if (h->data[0] == c->rate && - h->data[1] == (c->width / 16) && - h->data[2] == (c->height / 16)) - goto found; - break; - case CODEC_TYPE_AUDIO: - if (h->data[0] == (c->rate / 1000) && - (h->data[1] == c->channels)) - goto found; - break; - } - } - return 0; - found: - c->frame_number++; - c->key_frame = h->data[3]; - return 1; -} - -static int http_prepare_data(HTTPContext *c) -{ - PacketHeader hdr; - UINT8 *start_rptr, *payload; - int payload_size, ret; - long long fifo_total_size; - - switch(c->state) { - case HTTPSTATE_SEND_DATA_HEADER: - if (c->stream->stream_type != STREAM_TYPE_MASTER) { - memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx)); - c->fmt_ctx.format = c->stream->fmt; - if (c->fmt_ctx.format->audio_codec != CODEC_ID_NONE) { - /* create a fake new codec instance */ - c->fmt_ctx.audio_enc = malloc(sizeof(AVEncodeContext)); - memcpy(c->fmt_ctx.audio_enc, c->stream->audio_enc, - sizeof(AVEncodeContext)); - c->fmt_ctx.audio_enc->frame_number = 0; - } - if (c->fmt_ctx.format->video_codec != CODEC_ID_NONE) { - c->fmt_ctx.video_enc = malloc(sizeof(AVEncodeContext)); - memcpy(c->fmt_ctx.video_enc, c->stream->video_enc, - sizeof(AVEncodeContext)); - c->fmt_ctx.video_enc->frame_number = 0; - } - init_put_byte(&c->fmt_ctx.pb, c->buffer, IOBUFFER_MAX_SIZE, - c, http_write_packet, NULL); - c->fmt_ctx.is_streamed = 1; - c->got_key_frame[0] = 0; - c->got_key_frame[1] = 0; - /* prepare header */ - c->fmt_ctx.format->write_header(&c->fmt_ctx); - } - c->state = HTTPSTATE_SEND_DATA; - c->last_packet_sent = 0; - c->rptr = http_fifo.wptr; - c->last_http_fifo_write_count = http_fifo_write_count; - break; - case HTTPSTATE_SEND_DATA: - /* find a new packet */ - fifo_total_size = http_fifo_write_count - c->last_http_fifo_write_count; - if (fifo_total_size >= ((3 * FIFO_MAX_SIZE) / 4)) { - /* overflow : resync. We suppose that wptr is at this - point a pointer to a valid packet */ - c->rptr = http_fifo.wptr; - c->got_key_frame[0] = 0; - c->got_key_frame[1] = 0; - } - - start_rptr = c->rptr; - if (fifo_read(&http_fifo, (UINT8 *)&hdr, sizeof(hdr), &c->rptr) < 0) - return 0; - payload_size = ntohs(hdr.payload_size); - payload = malloc(payload_size); - if (fifo_read(&http_fifo, payload, payload_size, &c->rptr) < 0) { - /* cannot read all the payload */ - free(payload); - c->rptr = start_rptr; - return 0; - } - - c->last_http_fifo_write_count = http_fifo_write_count - - fifo_size(&http_fifo, c->rptr); - - if (c->stream->stream_type != STREAM_TYPE_MASTER) { - /* test if the packet can be handled by this format */ - ret = 0; - if (test_header(&hdr, c->fmt_ctx.audio_enc)) { - /* only begin sending when got a key frame */ - if (c->fmt_ctx.audio_enc->key_frame) - c->got_key_frame[1] = 1; - if (c->got_key_frame[1]) { - ret = c->fmt_ctx.format->write_audio_frame(&c->fmt_ctx, - payload, payload_size); - } - } else if (test_header(&hdr, c->fmt_ctx.video_enc)) { - if (c->fmt_ctx.video_enc->key_frame) - c->got_key_frame[0] = 1; - if (c->got_key_frame[0]) { - ret = c->fmt_ctx.format->write_video_picture(&c->fmt_ctx, - payload, payload_size); - } - } - if (ret) { - /* must send trailer now */ - c->state = HTTPSTATE_SEND_DATA_TRAILER; - } - } else { - /* master case : send everything */ - char *q; - q = c->buffer; - memcpy(q, &hdr, sizeof(hdr)); - q += sizeof(hdr); - memcpy(q, payload, payload_size); - q += payload_size; - c->buffer_ptr = c->buffer; - c->buffer_end = q; - } - free(payload); - break; - default: - case HTTPSTATE_SEND_DATA_TRAILER: - /* last packet test ? */ - if (c->last_packet_sent) - return -1; - /* prepare header */ - c->fmt_ctx.format->write_trailer(&c->fmt_ctx); - c->last_packet_sent = 1; - break; - } - return 0; -} - - -/* should convert the format at the same time */ -static int http_send_data(HTTPContext *c) -{ - int len; - - while (c->buffer_ptr >= c->buffer_end) { - if (http_prepare_data(c) < 0) - return -1; - } - - len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr); - if (len < 0) { - if (errno != EAGAIN && errno != EINTR) { - /* error : close connection */ - return -1; - } - } else { - c->buffer_ptr += len; - c->data_count += len; - } - return 0; -} - -static int master_receive(int fd) -{ - int len, size; - FifoBuffer *f = &http_fifo; - UINT8 *rptr; - - size = f->end - f->wptr; - if (size > master_count) - size = master_count; - len = read(fd, f->wptr, size); - if (len == -1) { - if (errno != EAGAIN && errno != EINTR) - return -1; - } else if (len == 0) { - return -1; - } else { - master_wptr += len; - if (master_wptr >= f->end) - master_wptr = f->buffer; - master_count -= len; - if (master_count == 0) { - if (master_state == MASTERSTATE_RECEIVE_HEADER) { - /* XXX: use generic fifo read to extract packet header */ - rptr = master_wptr; - if (rptr == f->buffer) - rptr = f->end - 1; - else - rptr--; - master_count = *rptr; - if (rptr == f->buffer) - rptr = f->end - 1; - else - rptr--; - master_count |= *rptr << 8; - master_state = MASTERSTATE_RECEIVE_DATA; - } else { - /* update fifo wptr */ - f->wptr = master_wptr; - master_state = MASTERSTATE_RECEIVE_HEADER; - } - } - } - return 0; -} - -static void get_arg(char *buf, int buf_size, const char **pp) -{ - const char *p; - char *q; - - p = *pp; - while (isspace(*p)) p++; - q = buf; - while (!isspace(*p) && *p != '\0') { - if ((q - buf) < buf_size - 1) - *q++ = *p; - p++; - } - *q = '\0'; - *pp = p; -} - -/* add a codec and check if it does not already exists */ -AVEncodeContext *add_codec(int codec_id, - AVEncodeContext *av) -{ - AVEncoder *codec; - FFCodec *ctx, **pctx; - AVEncodeContext *av1; - - codec = avencoder_find(codec_id); - if (!codec) - return NULL; - - /* compute default parameters */ - av->codec = codec; - switch(codec->type) { - case CODEC_TYPE_AUDIO: - if (av->bit_rate == 0) - av->bit_rate = 64000; - if (av->rate == 0) - av->rate = 22050; - if (av->channels == 0) - av->channels = 1; - break; - case CODEC_TYPE_VIDEO: - if (av->bit_rate == 0) - av->bit_rate = 64000; - if (av->rate == 0) - av->rate = 5; - if (av->width == 0 || av->height == 0) { - av->width = 160; - av->height = 128; - } - break; - } - - /* find if the codec already exists */ - pctx = &first_codec; - while (*pctx != NULL) { - av1 = &(*pctx)->enc; - if (av1->codec == av->codec && - av1->bit_rate == av->bit_rate && - av1->rate == av->rate) { - - switch(av->codec->type) { - case CODEC_TYPE_AUDIO: - if (av1->channels == av->channels) - goto found; - break; - case CODEC_TYPE_VIDEO: - if (av1->width == av->width && - av1->height == av->height && - av1->gop_size == av->gop_size) - goto found; - break; - } - } - pctx = &(*pctx)->next; - } - - ctx = malloc(sizeof(FFCodec)); - if (!ctx) - return NULL; - memset(ctx, 0, sizeof(FFCodec)); - *pctx = ctx; - - memcpy(&ctx->enc, av, sizeof(AVEncodeContext)); - return &ctx->enc; - found: - ctx = *pctx; - return &ctx->enc; -} - -int parse_ffconfig(const char *filename) -{ - FILE *f; - char line[1024]; - char cmd[64]; - char arg[1024]; - const char *p; - int val, errors, line_num; - FFStream **last_stream, *stream; - AVEncodeContext audio_enc, video_enc; - - f = fopen(filename, "r"); - if (!f) { - perror(filename); - return -1; - } - - errors = 0; - line_num = 0; - first_stream = NULL; - first_codec = NULL; - last_stream = &first_stream; - stream = NULL; - for(;;) { - if (fgets(line, sizeof(line), f) == NULL) - break; - line_num++; - p = line; - while (isspace(*p)) - p++; - if (*p == '\0' || *p == '#') - continue; - - get_arg(cmd, sizeof(cmd), &p); - - if (!strcasecmp(cmd, "Port")) { - get_arg(arg, sizeof(arg), &p); - my_addr.sin_port = htons (atoi(arg)); - } else if (!strcasecmp(cmd, "BindAddress")) { - get_arg(arg, sizeof(arg), &p); - if (!inet_aton(arg, &my_addr.sin_addr)) { - fprintf(stderr, "%s:%d: Invalid IP address: %s\n", - filename, line_num, arg); - errors++; - } - } else if (!strcasecmp(cmd, "MasterServer")) { - get_arg(master_url, sizeof(master_url), &p); - if (!strstart(master_url, "http://", NULL)) { - fprintf(stderr, "%s:%d: Invalid URL for master server: %s\n", - filename, line_num, master_url); - errors++; - } - } else if (!strcasecmp(cmd, "MaxClients")) { - get_arg(arg, sizeof(arg), &p); - val = atoi(arg); - if (val < 1 || val > HTTP_MAX_CONNECTIONS) { - fprintf(stderr, "%s:%d: Invalid MaxClients: %s\n", - filename, line_num, arg); - errors++; - } else { - nb_max_connections = val; - } - } else if (!strcasecmp(cmd, "CustomLog")) { - get_arg(logfilename, sizeof(logfilename), &p); - } else if (!strcasecmp(cmd, "next; - - get_arg(stream->filename, sizeof(stream->filename), &p); - q = strrchr(stream->filename, '>'); - if (*q) - *q = '\0'; - stream->fmt = guess_format(NULL, stream->filename, NULL); - memset(&audio_enc, 0, sizeof(AVEncodeContext)); - memset(&video_enc, 0, sizeof(AVEncodeContext)); - } - } else if (!strcasecmp(cmd, "Format")) { - get_arg(arg, sizeof(arg), &p); - if (!strcmp(arg, "master")) { - stream->stream_type = STREAM_TYPE_MASTER; - stream->fmt = NULL; - } else if (!strcmp(arg, "status")) { - stream->stream_type = STREAM_TYPE_STATUS; - stream->fmt = NULL; - } else { - stream->stream_type = STREAM_TYPE_LIVE; - stream->fmt = guess_format(arg, NULL, NULL); - if (!stream->fmt) { - fprintf(stderr, "%s:%d: Unknown Format: %s\n", - filename, line_num, arg); - errors++; - } - } - } else if (!strcasecmp(cmd, "AudioBitRate")) { - get_arg(arg, sizeof(arg), &p); - if (stream) { - audio_enc.bit_rate = atoi(arg) * 1000; - } - } else if (!strcasecmp(cmd, "AudioChannels")) { - get_arg(arg, sizeof(arg), &p); - if (stream) { - audio_enc.channels = atoi(arg); - } - } else if (!strcasecmp(cmd, "AudioSampleRate")) { - get_arg(arg, sizeof(arg), &p); - if (stream) { - audio_enc.rate = atoi(arg); - } - } else if (!strcasecmp(cmd, "VideoBitRate")) { - get_arg(arg, sizeof(arg), &p); - if (stream) { - video_enc.bit_rate = atoi(arg) * 1000; - } - } else if (!strcasecmp(cmd, "VideoFrameRate")) { - get_arg(arg, sizeof(arg), &p); - if (stream) { - video_enc.rate = atoi(arg); - } - } else if (!strcasecmp(cmd, "VideoGopSize")) { - get_arg(arg, sizeof(arg), &p); - if (stream) { - video_enc.gop_size = atoi(arg); - } - } else if (!strcasecmp(cmd, "VideoIntraOnly")) { - if (stream) { - video_enc.gop_size = 1; - } - } else if (!strcasecmp(cmd, "")) { - if (!stream) { - fprintf(stderr, "%s:%d: No corresponding for \n", - filename, line_num); - errors++; - } - if (stream->fmt) { - if (stream->fmt->audio_codec != CODEC_ID_NONE) { - stream->audio_enc = add_codec(stream->fmt->audio_codec, - &audio_enc); - } - - if (stream->fmt->video_codec != CODEC_ID_NONE) - stream->video_enc = add_codec(stream->fmt->video_codec, - &video_enc); - } - stream = NULL; - } else { - fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n", - filename, line_num, cmd); - errors++; - } - } - - fclose(f); - if (errors) - return -1; - else - return 0; -} - - -void *http_server_thread(void *arg) -{ - http_server(my_addr); - return NULL; -} - -static void write_packet(FFCodec *ffenc, - UINT8 *buf, int size) -{ - PacketHeader hdr; - AVEncodeContext *enc = &ffenc->enc; - UINT8 *wptr; - mk_header(&hdr, enc, size); - wptr = http_fifo.wptr; - fifo_write(&http_fifo, (UINT8 *)&hdr, sizeof(hdr), &wptr); - fifo_write(&http_fifo, buf, size, &wptr); - /* atomic modification of wptr */ - http_fifo.wptr = wptr; - ffenc->data_count += size; - ffenc->avg_frame_size = ffenc->avg_frame_size * AVG_COEF + size * (1.0 - AVG_COEF); -} - -#define AUDIO_FIFO_SIZE 8192 - -int av_grab(void) -{ - UINT8 audio_buf[AUDIO_FIFO_SIZE/2]; - UINT8 audio_buf1[AUDIO_FIFO_SIZE/2]; - UINT8 audio_out[AUDIO_FIFO_SIZE/2]; - UINT8 video_buffer[128*1024]; - char buf[256]; - short *samples; - int ret; - int audio_fd; - FFCodec *ffenc; - AVEncodeContext *enc; - int frame_size, frame_bytes; - int use_audio, use_video; - int frame_rate, sample_rate, channels; - int width, height, frame_number; - UINT8 *picture[3]; - - use_audio = 0; - use_video = 0; - frame_rate = 0; - sample_rate = 0; - frame_size = 0; - channels = 1; - width = 0; - height = 0; - frame_number = 0; - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - avencoder_string(buf, sizeof(buf), enc); - fprintf(stderr, " %s\n", buf); - if (avencoder_open(enc, enc->codec) < 0) { - fprintf(stderr, "Incorrect encode parameters\n"); - return -1; - } - switch(enc->codec->type) { - case CODEC_TYPE_AUDIO: - use_audio = 1; - if (enc->rate > sample_rate) - sample_rate = enc->rate; - if (enc->frame_size > frame_size) - frame_size = enc->frame_size; - if (enc->channels > channels) - channels = enc->channels; - fifo_init(&ffenc->fifo, AUDIO_FIFO_SIZE); - break; - case CODEC_TYPE_VIDEO: - use_video = 1; - if (enc->rate > frame_rate) - frame_rate = enc->rate; - if (enc->width > width) - width = enc->width; - if (enc->height > height) - height = enc->height; - break; - } - ffenc = ffenc->next; - } - - /* audio */ - samples = NULL; - audio_fd = -1; - if (use_audio) { - printf("Audio sampling: %d Hz, %s\n", - sample_rate, channels == 2 ? "stereo" : "mono"); - audio_fd = audio_open(sample_rate, channels); - if (audio_fd < 0) { - fprintf(stderr, "Could not open audio device\n"); - exit(1); - } - } - - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - if (enc->codec->type == CODEC_TYPE_AUDIO && - (enc->channels != channels || - enc->rate != sample_rate)) { - audio_resample_init(&ffenc->resample, enc->channels, channels, - enc->rate, sample_rate); - } - ffenc = ffenc->next; - } - - /* video */ - if (use_video) { - printf("Video sampling: %dx%d, %d fps\n", - width, height, frame_rate); - ret = v4l_init(frame_rate, width, height); - if (ret < 0) { - fprintf(stderr,"Could not init video 4 linux capture\n"); - exit(1); - } - } - - for(;;) { - /* read & compress audio frames */ - if (use_audio) { - int ret, nb_samples, nb_samples_out; - UINT8 *buftmp; - - for(;;) { - ret = read(audio_fd, audio_buf, AUDIO_FIFO_SIZE/2); - if (ret <= 0) - break; - /* fill each codec fifo by doing the right sample - rate conversion. This is not optimal because we - do too much work, but it is easy to do */ - nb_samples = ret / (channels * 2); - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - if (enc->codec->type == CODEC_TYPE_AUDIO) { - /* rate & stereo convertion */ - if (enc->channels == channels && - enc->rate == sample_rate) { - buftmp = audio_buf; - nb_samples_out = nb_samples; - } else { - buftmp = audio_buf1; - nb_samples_out = audio_resample(&ffenc->resample, - (short *)buftmp, (short *)audio_buf, - nb_samples); - - } - fifo_write(&ffenc->fifo, buftmp, nb_samples_out * enc->channels * 2, - &ffenc->fifo.wptr); - } - ffenc = ffenc->next; - } - - /* compress as many frame as possible with each audio codec */ - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - if (enc->codec->type == CODEC_TYPE_AUDIO) { - frame_bytes = enc->frame_size * 2 * enc->channels; - - while (fifo_read(&ffenc->fifo, audio_buf, frame_bytes, &ffenc->fifo.rptr) == 0) { - ret = avencoder_encode(enc, - audio_out, sizeof(audio_out), audio_buf); - write_packet(ffenc, audio_out, ret); - } - } - ffenc = ffenc->next; - } - } - } - - if (use_video) { - ret = v4l_read_picture (picture, width, height, - frame_number); - if (ret < 0) - break; - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - if (enc->codec->type == CODEC_TYPE_VIDEO) { - int n1, n2; - /* feed each codec with its requested frame rate */ - n1 = (frame_number * enc->rate) / frame_rate; - n2 = ((frame_number + 1) * enc->rate) / frame_rate; - if (n2 > n1) { - ret = avencoder_encode(enc, video_buffer, sizeof(video_buffer), picture); - write_packet(ffenc, video_buffer, ret); - } - } - ffenc = ffenc->next; - } - frame_number++; - } - } - - ffenc = first_codec; - while (ffenc != NULL) { - enc = &ffenc->enc; - avencoder_close(enc); - ffenc = ffenc->next; - } - close(audio_fd); - return 0; -} - - -void help(void) -{ - printf("ffserver version 1.0, Copyright (c) 2000 Gerard Lantau\n" - "usage: ffserver [-L] [-h] [-f configfile]\n" - "Hyper fast multi format Audio/Video streaming server\n" - "\n" - "-L : print the LICENCE\n" - "-h : this help\n" - "-f configfile : use configfile instead of /etc/ffserver.conf\n" - ); -} - -void licence(void) -{ - printf( - "ffserver version 1.0\n" - "Copyright (c) 2000 Gerard Lantau\n" - "This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" - ); -} - -int main(int argc, char **argv) -{ - pthread_t http_server_tid; - const char *config_filename; - int c; - - /* codecs */ - register_avencoder(&ac3_encoder); - register_avencoder(&mp2_encoder); - register_avencoder(&mpeg1video_encoder); - register_avencoder(&h263_encoder); - register_avencoder(&rv10_encoder); - register_avencoder(&mjpeg_encoder); - - /* audio video formats */ - register_avformat(&mp2_format); - register_avformat(&ac3_format); - register_avformat(&mpeg_mux_format); - register_avformat(&mpeg1video_format); - register_avformat(&h263_format); - register_avformat(&rm_format); - register_avformat(&ra_format); - register_avformat(&asf_format); - register_avformat(&mpjpeg_format); - register_avformat(&jpeg_format); - register_avformat(&swf_format); - - config_filename = "/etc/ffserver.conf"; - - for(;;) { - c = getopt_long_only(argc, argv, "Lh?f:", NULL, NULL); - if (c == -1) - break; - switch(c) { - case 'L': - licence(); - exit(1); - case '?': - case 'h': - help(); - exit(1); - case 'f': - config_filename = optarg; - break; - default: - exit(2); - } - } - - /* address on which the server will handle connections */ - my_addr.sin_family = AF_INET; - my_addr.sin_port = htons (8080); - my_addr.sin_addr.s_addr = htonl (INADDR_ANY); - nb_max_connections = 5; - first_stream = NULL; - logfilename[0] = '\0'; - - if (parse_ffconfig(config_filename) < 0) { - fprintf(stderr, "Incorrect config file - exiting.\n"); - exit(1); - } - - /* open log file if needed */ - if (logfilename[0] != '\0') { - if (!strcmp(logfilename, "-")) - logfile = stdout; - else - logfile = fopen(logfilename, "w"); - } - - /* init fifo */ - http_fifo_write_count = 0; - if (fifo_init(&http_fifo, FIFO_MAX_SIZE) < 0) { - fprintf(stderr, "Could not allow receive fifo\n"); - exit(1); - } - - if (master_url[0] == '\0') { - /* no master server: we grab ourself */ - - /* launch server thread */ - if (pthread_create(&http_server_tid, NULL, - http_server_thread, NULL) != 0) { - fprintf(stderr, "Could not create http server thread\n"); - exit(1); - } - - /* launch the audio / video grab */ - if (av_grab() < 0) { - fprintf(stderr, "Could not start audio/video grab\n"); - exit(1); - } - } else { - /* master server : no thread are needed */ - if (http_server(my_addr) < 0) { - fprintf(stderr, "Could start http server\n"); - exit(1); - } - } - - return 0; -} diff --git a/formats.c b/formats.c deleted file mode 100644 index 10aae461ea..0000000000 --- a/formats.c +++ /dev/null @@ -1,373 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpegenc.h" - -AVFormat *first_format; -/* XXX: suppress it ! */ -int data_out_size; - -const char *comment_string = -"+title=Test Video +author=FFMpeg +copyright=Free +comment=Generated by FFMpeg 1.0"; - -void register_avformat(AVFormat *format) -{ - AVFormat **p; - p = &first_format; - while (*p != NULL) p = &(*p)->next; - *p = format; - format->next = NULL; -} - -AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type) -{ - AVFormat *fmt, *fmt_found; - int score_max, score; - const char *ext, *p; - char ext1[32], *q; - - /* find the proper file type */ - fmt_found = NULL; - score_max = 0; - fmt = first_format; - while (fmt != NULL) { - score = 0; - if (fmt->name && short_name && !strcmp(fmt->name, short_name)) - score += 100; - if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type)) - score += 10; - if (filename && fmt->extensions) { - ext = strrchr(filename, '.'); - if (ext) { - ext++; - p = fmt->extensions; - for(;;) { - q = ext1; - while (*p != '\0' && *p != ',') - *q++ = *p++; - *q = '\0'; - if (!strcasecmp(ext1, ext)) { - score += 5; - break; - } - if (*p == '\0') - break; - p++; - } - } - } - if (score > score_max) { - score_max = score; - fmt_found = fmt; - } - fmt = fmt->next; - } - return fmt_found; -} - -/* return TRUE if val is a prefix of str. If it returns TRUE, ptr is - set to the next character in 'str' after the prefix */ -int strstart(const char *str, const char *val, const char **ptr) -{ - const char *p, *q; - p = str; - q = val; - while (*q != '\0') { - if (*p != *q) - return 0; - p++; - q++; - } - if (ptr) - *ptr = p; - return 1; -} - -/* simple formats */ -int raw_write_header(struct AVFormatContext *s) -{ - return 0; -} - -int raw_write_audio(struct AVFormatContext *s, - unsigned char *buf, int size) -{ - put_buffer(&s->pb, buf, size); - put_flush_packet(&s->pb); - return 0; -} - -int raw_write_video(struct AVFormatContext *s, - unsigned char *buf, int size) -{ - put_buffer(&s->pb, buf, size); - put_flush_packet(&s->pb); - return 0; -} - -int raw_write_trailer(struct AVFormatContext *s) -{ - return 0; -} - -AVFormat mp2_format = { - "mp2", - "MPEG audio layer 2", - "audio/x-mpeg", - "mp2,mp3", - CODEC_ID_MP2, - 0, - raw_write_header, - raw_write_audio, - NULL, - raw_write_trailer, -}; - -AVFormat ac3_format = { - "ac3", - "raw ac3", - "audio/x-ac3", - "ac3", - CODEC_ID_AC3, - 0, - raw_write_header, - raw_write_audio, - NULL, - raw_write_trailer, -}; - -AVFormat h263_format = { - "h263", - "raw h263", - "video/x-h263", - "h263", - 0, - CODEC_ID_H263, - raw_write_header, - NULL, - raw_write_video, - raw_write_trailer, -}; - -AVFormat mpeg1video_format = { - "mpeg1video", - "MPEG1 video", - "video/mpeg", - "mpg,mpeg", - 0, - CODEC_ID_MPEG1VIDEO, - raw_write_header, - NULL, - raw_write_video, - raw_write_trailer, -}; - -/* encoder management */ -AVEncoder *first_encoder; - -void register_avencoder(AVEncoder *format) -{ - AVEncoder **p; - p = &first_encoder; - while (*p != NULL) p = &(*p)->next; - *p = format; - format->next = NULL; -} - -int avencoder_open(AVEncodeContext *avctx, AVEncoder *codec) -{ - int ret; - - avctx->codec = codec; - avctx->frame_number = 0; - avctx->priv_data = malloc(codec->priv_data_size); - if (!avctx->priv_data) - return -ENOMEM; - memset(avctx->priv_data, 0, codec->priv_data_size); - ret = avctx->codec->init(avctx); - if (ret < 0) { - free(avctx->priv_data); - avctx->priv_data = NULL; - return ret; - } - return 0; -} - -int avencoder_encode(AVEncodeContext *avctx, UINT8 *buf, int buf_size, void *data) -{ - int ret; - - ret = avctx->codec->encode(avctx, buf, buf_size, data); - avctx->frame_number++; - return ret; -} - -int avencoder_close(AVEncodeContext *avctx) -{ - if (avctx->codec->close) - avctx->codec->close(avctx); - free(avctx->priv_data); - avctx->priv_data = NULL; - return 0; -} - -AVEncoder *avencoder_find(enum CodecID id) -{ - AVEncoder *p; - p = first_encoder; - while (p) { - if (p->id == id) - return p; - p = p->next; - } - return NULL; -} - - -void avencoder_string(char *buf, int buf_size, AVEncodeContext *enc) -{ - switch(enc->codec->type) { - case CODEC_TYPE_VIDEO: - snprintf(buf, buf_size, - "Video: %s, %dx%d, %d fps, %d kb/s", - enc->codec->name, enc->width, enc->height, enc->rate, enc->bit_rate / 1000); - break; - case CODEC_TYPE_AUDIO: - snprintf(buf, buf_size, - "Audio: %s, %d Hz, %s, %d kb/s", - enc->codec->name, enc->rate, - enc->channels == 2 ? "stereo" : "mono", - enc->bit_rate / 1000); - break; - default: - abort(); - } -} - -/* PutByteFormat */ - -int init_put_byte(PutByteContext *s, - unsigned char *buffer, - int buffer_size, - void *opaque, - void (*write_packet)(void *opaque, UINT8 *buf, int buf_size), - int (*write_seek)(void *opaque, long long offset, int whence)) -{ - s->buffer = buffer; - s->buf_ptr = buffer; - s->buf_end = buffer + buffer_size; - s->opaque = opaque; - s->write_packet = write_packet; - s->write_seek = write_seek; - s->pos = 0; - return 0; -} - - -static void flush_buffer(PutByteContext *s) -{ - if (s->buf_ptr > s->buffer) { - if (s->write_packet) - s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); - s->pos += s->buf_ptr - s->buffer; - } - s->buf_ptr = s->buffer; -} - -void put_byte(PutByteContext *s, int b) -{ - *(s->buf_ptr)++ = b; - if (s->buf_ptr >= s->buf_end) - flush_buffer(s); -} - -void put_buffer(PutByteContext *s, unsigned char *buf, int size) -{ - int len; - - while (size > 0) { - len = (s->buf_end - s->buf_ptr); - if (len > size) - len = size; - memcpy(s->buf_ptr, buf, len); - s->buf_ptr += len; - - if (s->buf_ptr >= s->buf_end) - flush_buffer(s); - - buf += len; - size -= len; - } -} - -void put_flush_packet(PutByteContext *s) -{ - flush_buffer(s); -} - -/* XXX: this seek is not correct if we go after the end of the written data */ -long long put_seek(PutByteContext *s, long long offset, int whence) -{ - long long offset1; - - if (whence != SEEK_CUR && whence != SEEK_SET) - return -1; - if (whence == SEEK_CUR) - offset += s->pos + s->buf_ptr - s->buffer; - - offset1 = offset - s->pos; - if (offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) { - /* can do the seek inside the buffer */ - s->buf_ptr = s->buffer + offset1; - } else { - if (!s->write_seek) - return -1; - flush_buffer(s); - s->write_seek(s->opaque, offset, whence); - } - return offset; -} - -long long put_pos(PutByteContext *s) -{ - return put_seek(s, 0, SEEK_CUR); -} - -void put_le32(PutByteContext *s, unsigned int val) -{ - put_byte(s, val); - put_byte(s, val >> 8); - put_byte(s, val >> 16); - put_byte(s, val >> 24); -} - -void put_le64(PutByteContext *s, unsigned long long val) -{ - put_le32(s, val & 0xffffffff); - put_le32(s, val >> 32); -} - -void put_le16(PutByteContext *s, unsigned int val) -{ - put_byte(s, val); - put_byte(s, val >> 8); -} - -void put_tag(PutByteContext *s, char *tag) -{ - while (*tag) { - put_byte(s, *tag++); - } -} - diff --git a/grab.c b/grab.c deleted file mode 100644 index 807d4c5420..0000000000 --- a/grab.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Linux audio/video grab interface - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpegenc.h" -#include "mpegvideo.h" - -long long gettime(void) -{ - struct timeval tv; - gettimeofday(&tv,NULL); - return (long long)tv.tv_sec * 1000000 + tv.tv_usec; -} - -/* v4l capture */ - -const char *v4l_device = "/dev/video"; - -static struct video_capability video_cap; -int video_fd = -1; -UINT8 *video_buf, *picture_buf; -struct video_mbuf gb_buffers; -struct video_mmap gb_buf; -struct video_audio audio; -int gb_frame = 0; -long long time_frame; -int frame_rate; -int use_mmap = 0; - -int v4l_init(int rate, int width, int height) -{ - frame_rate = rate; - - video_fd = open(v4l_device, O_RDWR); - - if (ioctl(video_fd,VIDIOCGCAP,&video_cap) < 0) { - perror("VIDIOCGCAP"); - return -1; - } - - /* unmute audio */ - ioctl(video_fd, VIDIOCGAUDIO, &audio); - audio.flags &= ~VIDEO_AUDIO_MUTE; - ioctl(video_fd, VIDIOCSAUDIO, &audio); - - if (!(video_cap.type & VID_TYPE_CAPTURE)) { - /* try to use read based access */ - struct video_window win; - int val; - - win.x = 0; - win.y = 0; - win.width = width; - win.height = height; - win.chromakey = -1; - win.flags = 0; - - ioctl(video_fd, VIDIOCSWIN, &win); - - val = 1; - ioctl(video_fd, VIDIOCCAPTURE, &val); - video_buf = malloc( width * height * 2); - picture_buf = malloc( (width * height * 3) / 2); - use_mmap = 0; - return 0; - } - - if (ioctl(video_fd,VIDIOCGMBUF,&gb_buffers) < 0) { - perror("ioctl VIDIOCGMBUF"); - } - - video_buf = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0); - if ((unsigned char*)-1 == video_buf) { - perror("mmap"); - return -1; - } - gb_frame = 0; - time_frame = gettime(); - - /* start to grab the first frame */ - gb_buf.frame = 1 - gb_frame; - gb_buf.height = height; - gb_buf.width = width; - gb_buf.format = VIDEO_PALETTE_YUV420P; - - if (ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf) < 0) { - if (errno == EAGAIN) - fprintf(stderr,"Cannot Sync\n"); - else - perror("VIDIOCMCAPTURE"); - return -1; - } - use_mmap = 1; - return 0; -} - -/* test with read call and YUV422 stream */ -static int v4l_basic_read_picture(UINT8 *picture[3], - int width, int height, - int picture_number) -{ - int x, y; - UINT8 *p, *lum, *cb, *cr; - - if (read(video_fd, video_buf, width * height * 2) < 0) - perror("read"); - - picture[0] = picture_buf; - picture[1] = picture_buf + width * height; - picture[2] = picture_buf + (width * height) + (width * height) / 4; - - /* XXX: optimize */ - lum = picture[0]; - cb = picture[1]; - cr = picture[2]; - p = video_buf; - for(y=0;y -#include -#include -#include -#include "avcodec.h" - -#include "ac3enc.h" -#include "ac3tab.h" - -//#define DEBUG -//#define DEBUG_BITALLOC -#define NDEBUG -#include - -#define MDCT_NBITS 9 -#define N (1 << MDCT_NBITS) -#define NB_BLOCKS 6 /* number of PCM blocks inside an AC3 frame */ - -/* new exponents are sent if their Norm 1 exceed this number */ -#define EXP_DIFF_THRESHOLD 1000 - -/* exponent encoding strategy */ -#define EXP_REUSE 0 -#define EXP_NEW 1 - -#define EXP_D15 1 -#define EXP_D25 2 -#define EXP_D45 3 - -static void fft_init(int ln); -static void ac3_crc_init(void); - -static inline INT16 fix15(float a) -{ - int v; - v = (int)(a * (float)(1 << 15)); - if (v < -32767) - v = -32767; - else if (v > 32767) - v = 32767; - return v; -} - -static inline int calc_lowcomp1(int a, int b0, int b1) -{ - if ((b0 + 256) == b1) { - a = 384 ; - } else if (b0 > b1) { - a = a - 64; - if (a < 0) a=0; - } - return a; -} - -static inline int calc_lowcomp(int a, int b0, int b1, int bin) -{ - if (bin < 7) { - if ((b0 + 256) == b1) { - a = 384 ; - } else if (b0 > b1) { - a = a - 64; - if (a < 0) a=0; - } - } else if (bin < 20) { - if ((b0 + 256) == b1) { - a = 320 ; - } else if (b0 > b1) { - a= a - 64; - if (a < 0) a=0; - } - } else { - a = a - 128; - if (a < 0) a=0; - } - return a; -} - -/* AC3 bit allocation. The algorithm is the one described in the AC3 - spec with some optimizations because of our simplified encoding - assumptions. */ -void parametric_bit_allocation(AC3EncodeContext *s, UINT8 *bap, - INT8 *exp, int start, int end, - int snroffset, int fgain) -{ - int bin,i,j,k,end1,v,v1,bndstrt,bndend,lowcomp,begin; - int fastleak,slowleak,address,tmp; - INT16 psd[256]; /* scaled exponents */ - INT16 bndpsd[50]; /* interpolated exponents */ - INT16 excite[50]; /* excitation */ - INT16 mask[50]; /* masking value */ - - /* exponent mapping to PSD */ - for(bin=start;bin end) end1=end; - for(i=j;i= 0) { - adr=c >> 1; - if (adr > 255) adr=255; - v=v + latab[adr]; - } else { - adr=(-c) >> 1; - if (adr > 255) adr=255; - v=v1 + latab[adr]; - } - j++; - } - bndpsd[k]=v; - k++; - } while (end > bndtab[k]); - - /* excitation function */ - bndstrt = masktab[start]; - bndend = masktab[end-1] + 1; - - lowcomp = 0; - lowcomp = calc_lowcomp1(lowcomp, bndpsd[0], bndpsd[1]) ; - excite[0] = bndpsd[0] - fgain - lowcomp ; - lowcomp = calc_lowcomp1(lowcomp, bndpsd[1], bndpsd[2]) ; - excite[1] = bndpsd[1] - fgain - lowcomp ; - begin = 7 ; - for (bin = 2; bin < 7; bin++) { - lowcomp = calc_lowcomp1(lowcomp, bndpsd[bin], bndpsd[bin+1]) ; - fastleak = bndpsd[bin] - fgain ; - slowleak = bndpsd[bin] - s->sgain ; - excite[bin] = fastleak - lowcomp ; - if (bndpsd[bin] <= bndpsd[bin+1]) { - begin = bin + 1 ; - break ; - } - } - - end1=bndend; - if (end1 > 22) end1=22; - - for (bin = begin; bin < end1; bin++) { - lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin) ; - - fastleak -= s->fdecay ; - v = bndpsd[bin] - fgain; - if (fastleak < v) fastleak = v; - - slowleak -= s->sdecay ; - v = bndpsd[bin] - s->sgain; - if (slowleak < v) slowleak = v; - - v=fastleak - lowcomp; - if (slowleak > v) v=slowleak; - - excite[bin] = v; - } - - for (bin = 22; bin < bndend; bin++) { - fastleak -= s->fdecay ; - v = bndpsd[bin] - fgain; - if (fastleak < v) fastleak = v; - slowleak -= s->sdecay ; - v = bndpsd[bin] - s->sgain; - if (slowleak < v) slowleak = v; - - v=fastleak; - if (slowleak > v) v = slowleak; - excite[bin] = v; - } - - /* compute masking curve */ - - for (bin = bndstrt; bin < bndend; bin++) { - v1 = excite[bin]; - tmp = s->dbknee - bndpsd[bin]; - if (tmp > 0) { - v1 += tmp >> 2; - } - v=hth[bin >> s->halfratecod][s->fscod]; - if (v1 > v) v=v1; - mask[bin] = v; - } - - /* compute bit allocation */ - - i = start ; - j = masktab[start] ; - do { - v=mask[j]; - v -= snroffset ; - v -= s->floor ; - if (v < 0) v = 0; - v &= 0x1fe0 ; - v += s->floor ; - - end1=bndtab[j] + bndsz[j]; - if (end1 > end) end1=end; - - for (k = i; k < end1; k++) { - address = (psd[i] - v) >> 5 ; - if (address < 0) address=0; - else if (address > 63) address=63; - bap[i] = baptab[address]; - i++; - } - } while (end > bndtab[j++]) ; -} - -typedef struct IComplex { - short re,im; -} IComplex; - -static void fft_init(int ln) -{ - int i, j, m, n; - float alpha; - - n = 1 << ln; - - for(i=0;i<(n/2);i++) { - alpha = 2 * M_PI * (float)i / (float)n; - costab[i] = fix15(cos(alpha)); - sintab[i] = fix15(sin(alpha)); - } - - for(i=0;i> j) & 1) << (ln-j-1); - } - fft_rev[i]=m; - } -} - -/* butter fly op */ -#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \ -{\ - int ax, ay, bx, by;\ - bx=pre1;\ - by=pim1;\ - ax=qre1;\ - ay=qim1;\ - pre = (bx + ax) >> 1;\ - pim = (by + ay) >> 1;\ - qre = (bx - ax) >> 1;\ - qim = (by - ay) >> 1;\ -} - -#define MUL16(a,b) ((a) * (b)) - -#define CMUL(pre, pim, are, aim, bre, bim) \ -{\ - pre = (MUL16(are, bre) - MUL16(aim, bim)) >> 15;\ - pim = (MUL16(are, bim) + MUL16(bre, aim)) >> 15;\ -} - - -/* do a 2^n point complex fft on 2^ln points. */ -static void fft(IComplex *z, int ln) -{ - int j, l, np, np2; - int nblocks, nloops; - register IComplex *p,*q; - int tmp_re, tmp_im; - - np = 1 << ln; - - /* reverse */ - for(j=0;j> 1); - do { - BF(p[0].re, p[0].im, p[1].re, p[1].im, - p[0].re, p[0].im, p[1].re, p[1].im); - p+=2; - } while (--j != 0); - - /* pass 1 */ - - p=&z[0]; - j=np >> 2; - do { - BF(p[0].re, p[0].im, p[2].re, p[2].im, - p[0].re, p[0].im, p[2].re, p[2].im); - BF(p[1].re, p[1].im, p[3].re, p[3].im, - p[1].re, p[1].im, p[3].im, -p[3].re); - p+=4; - } while (--j != 0); - - /* pass 2 .. ln-1 */ - - nblocks = np >> 3; - nloops = 1 << 2; - np2 = np >> 1; - do { - p = z; - q = z + nloops; - for (j = 0; j < nblocks; ++j) { - - BF(p->re, p->im, q->re, q->im, - p->re, p->im, q->re, q->im); - - p++; - q++; - for(l = nblocks; l < np2; l += nblocks) { - CMUL(tmp_re, tmp_im, costab[l], -sintab[l], q->re, q->im); - BF(p->re, p->im, q->re, q->im, - p->re, p->im, tmp_re, tmp_im); - p++; - q++; - } - p += nloops; - q += nloops; - } - nblocks = nblocks >> 1; - nloops = nloops << 1; - } while (nblocks != 0); -} - -/* do a 512 point mdct */ -static void mdct512(INT32 *out, INT16 *in) -{ - int i, re, im, re1, im1; - INT16 rot[N]; - IComplex x[N/4]; - - /* shift to simplify computations */ - for(i=0;i> 1; - im = -((int)rot[N/2+2*i] - (int)rot[N/2-1-2*i]) >> 1; - CMUL(x[i].re, x[i].im, re, im, -xcos1[i], xsin1[i]); - } - - fft(x, MDCT_NBITS - 2); - - /* post rotation */ - for(i=0;i EXP_DIFF_THRESHOLD) - exp_strategy[i][ch] = EXP_NEW; - else - exp_strategy[i][ch] = EXP_REUSE; - } - /* now select the encoding strategy type : if exponents are often - recoded, we use a coarse encoding */ - i = 0; - while (i < NB_BLOCKS) { - j = i + 1; - while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE) - j++; - switch(j - i) { - case 1: - exp_strategy[i][ch] = EXP_D45; - break; - case 2: - case 3: - exp_strategy[i][ch] = EXP_D25; - break; - default: - exp_strategy[i][ch] = EXP_D15; - break; - } - i = j; - } -} - -/* set exp[i] to min(exp[i], exp1[i]) */ -static void exponent_min(UINT8 exp[N/2], UINT8 exp1[N/2], int n) -{ - int i; - - for(i=0;i= 0 && exp_min <= 24); - for(j=1;j 15) - exp1[0] = 15; - - /* Iterate until the delta constraints between each groups are - satisfyed. I'm sure it is possible to find a better algorithm, - but I am lazy */ - do { - recurse = 0; - for(i=1;i<=nb_groups;i++) { - delta = exp1[i] - exp1[i-1]; - if (delta > 2) { - /* if delta too big, we encode a smaller exponent */ - exp1[i] = exp1[i-1] + 2; - } else if (delta < -2) { - /* if delta is too small, we must decrease the previous - exponent, which means we must recurse */ - recurse = 1; - exp1[i-1] = exp1[i] + 2; - } - } - } while (recurse); - - /* now we have the exponent values the decoder will see */ - encoded_exp[0] = exp1[0]; - k = 1; - for(i=1;i<=nb_groups;i++) { - for(j=0;jmant1_cnt == 0) - bits += 5; - if (++s->mant1_cnt == 3) - s->mant1_cnt = 0; - break; - case 2: - /* 3 mantissa in 7 bits */ - if (s->mant2_cnt == 0) - bits += 7; - if (++s->mant2_cnt == 3) - s->mant2_cnt = 0; - break; - case 3: - bits += 3; - break; - case 4: - /* 2 mantissa in 7 bits */ - if (s->mant4_cnt == 0) - bits += 7; - if (++s->mant4_cnt == 2) - s->mant4_cnt = 0; - break; - case 14: - bits += 14; - break; - case 15: - bits += 16; - break; - default: - bits += mant - 1; - break; - } - } - return bits; -} - - -static int bit_alloc(AC3EncodeContext *s, - UINT8 bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2], - UINT8 encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2], - UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS], - int frame_bits, int csnroffst, int fsnroffst) -{ - int i, ch; - - /* compute size */ - for(i=0;imant1_cnt = 0; - s->mant2_cnt = 0; - s->mant4_cnt = 0; - for(ch=0;chnb_channels;ch++) { - parametric_bit_allocation(s, bap[i][ch], encoded_exp[i][ch], - 0, s->nb_coefs[ch], - (((csnroffst-15) << 4) + - fsnroffst) << 2, - fgaintab[s->fgaincod[ch]]); - frame_bits += compute_mantissa_size(s, bap[i][ch], - s->nb_coefs[ch]); - } - } -#if 0 - printf("csnr=%d fsnr=%d frame_bits=%d diff=%d\n", - csnroffst, fsnroffst, frame_bits, - 16 * s->frame_size - ((frame_bits + 7) & ~7)); -#endif - return 16 * s->frame_size - frame_bits; -} - -#define SNR_INC1 4 - -static int compute_bit_allocation(AC3EncodeContext *s, - UINT8 bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2], - UINT8 encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2], - UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS], - int frame_bits) -{ - int i, ch; - int csnroffst, fsnroffst; - UINT8 bap1[NB_BLOCKS][AC3_MAX_CHANNELS][N/2]; - - /* init default parameters */ - s->sdecaycod = 2; - s->fdecaycod = 1; - s->sgaincod = 1; - s->dbkneecod = 2; - s->floorcod = 4; - for(ch=0;chnb_channels;ch++) - s->fgaincod[ch] = 4; - - /* compute real values */ - s->sdecay = sdecaytab[s->sdecaycod] >> s->halfratecod; - s->fdecay = fdecaytab[s->fdecaycod] >> s->halfratecod; - s->sgain = sgaintab[s->sgaincod]; - s->dbknee = dbkneetab[s->dbkneecod]; - s->floor = floortab[s->floorcod]; - - /* header size */ - frame_bits += 65; - if (s->acmod == 2) - frame_bits += 2; - - /* audio blocks */ - for(i=0;inb_channels * 2 + 2; - if (s->acmod == 2) - frame_bits++; - frame_bits += 2 * s->nb_channels; - for(ch=0;chnb_channels;ch++) { - if (exp_strategy[i][ch] != EXP_REUSE) - frame_bits += 6 + 2; - } - frame_bits++; /* baie */ - frame_bits++; /* snr */ - frame_bits += 2; /* delta / skip */ - } - frame_bits++; /* cplinu for block 0 */ - /* bit alloc info */ - frame_bits += 2*4 + 3 + 6 + s->nb_channels * (4 + 3); - - /* CRC */ - frame_bits += 16; - - /* now the big work begins : do the bit allocation. Modify the snr - offset until we can pack everything in the requested frame size */ - - csnroffst = s->csnroffst; - while (csnroffst >= 0 && - bit_alloc(s, bap, encoded_exp, exp_strategy, frame_bits, csnroffst, 0) < 0) - csnroffst -= SNR_INC1; - if (csnroffst < 0) { - fprintf(stderr, "Error !!!\n"); - return -1; - } - while ((csnroffst + SNR_INC1) <= 63 && - bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits, - csnroffst + SNR_INC1, 0) >= 0) { - csnroffst += SNR_INC1; - memcpy(bap, bap1, sizeof(bap1)); - } - while ((csnroffst + 1) <= 63 && - bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits, csnroffst + 1, 0) >= 0) { - csnroffst++; - memcpy(bap, bap1, sizeof(bap1)); - } - - fsnroffst = 0; - while ((fsnroffst + SNR_INC1) <= 15 && - bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits, - csnroffst, fsnroffst + SNR_INC1) >= 0) { - fsnroffst += SNR_INC1; - memcpy(bap, bap1, sizeof(bap1)); - } - while ((fsnroffst + 1) <= 15 && - bit_alloc(s, bap1, encoded_exp, exp_strategy, frame_bits, - csnroffst, fsnroffst + 1) >= 0) { - fsnroffst++; - memcpy(bap, bap1, sizeof(bap1)); - } - - s->csnroffst = csnroffst; - for(ch=0;chnb_channels;ch++) - s->fsnroffst[ch] = fsnroffst; -#if defined(DEBUG_BITALLOC) - { - int j; - - for(i=0;i<6;i++) { - for(ch=0;chnb_channels;ch++) { - printf("Block #%d Ch%d:\n", i, ch); - printf("bap="); - for(j=0;jnb_coefs[ch];j++) { - printf("%d ",bap[i][ch][j]); - } - printf("\n"); - } - } - } -#endif - return 0; -} - -static int AC3_encode_init(AVEncodeContext *avctx) -{ - int freq = avctx->rate; - int bitrate = avctx->bit_rate; - int channels = avctx->channels; - AC3EncodeContext *s = avctx->priv_data; - int i, j, k, l, ch, v; - float alpha; - static unsigned short freqs[3] = { 48000, 44100, 32000 }; - - avctx->frame_size = AC3_FRAME_SIZE; - avctx->key_frame = 1; /* always key frame */ - - /* number of channels */ - if (channels == 1) - s->acmod = 1; - else if (channels == 2) - s->acmod = 2; - else - return -1; - s->nb_channels = channels; - - /* frequency */ - for(i=0;i<3;i++) { - for(j=0;j<3;j++) - if ((freqs[j] >> i) == freq) - goto found; - } - return -1; - found: - s->sample_rate = freq; - s->halfratecod = i; - s->fscod = j; - s->bsid = 8 + s->halfratecod; - s->bsmod = 0; /* complete main audio service */ - - /* bitrate & frame size */ - bitrate /= 1000; - for(i=0;i<19;i++) { - if ((bitratetab[i] >> s->halfratecod) == bitrate) - break; - } - if (i == 19) - return -1; - s->bit_rate = bitrate; - s->frmsizecod = i << 1; - s->frame_size_min = (bitrate * 1000 * AC3_FRAME_SIZE) / (freq * 16); - /* for now we do not handle fractional sizes */ - s->frame_size = s->frame_size_min; - - /* bit allocation init */ - for(ch=0;chnb_channels;ch++) { - /* bandwidth for each channel */ - /* XXX: should compute the bandwidth according to the frame - size, so that we avoid anoying high freq artefacts */ - s->chbwcod[ch] = 50; /* sample bandwidth as mpeg audio layer 2 table 0 */ - s->nb_coefs[ch] = ((s->chbwcod[ch] + 12) * 3) + 37; - } - /* initial snr offset */ - s->csnroffst = 40; - - /* compute bndtab and masktab from bandsz */ - k = 0; - l = 0; - for(i=0;i<50;i++) { - bndtab[i] = l; - v = bndsz[i]; - for(j=0;jpb, frame, AC3_MAX_CODED_FRAME_SIZE, NULL, NULL); - - put_bits(&s->pb, 16, 0x0b77); /* frame header */ - put_bits(&s->pb, 16, 0); /* crc1: will be filled later */ - put_bits(&s->pb, 2, s->fscod); - put_bits(&s->pb, 6, s->frmsizecod + (s->frame_size - s->frame_size_min)); - put_bits(&s->pb, 5, s->bsid); - put_bits(&s->pb, 3, s->bsmod); - put_bits(&s->pb, 3, s->acmod); - if (s->acmod == 2) { - put_bits(&s->pb, 2, 0); /* surround not indicated */ - } - put_bits(&s->pb, 1, 0); /* no LFE */ - put_bits(&s->pb, 5, 31); /* dialog norm: -31 db */ - put_bits(&s->pb, 1, 0); /* no compression control word */ - put_bits(&s->pb, 1, 0); /* no lang code */ - put_bits(&s->pb, 1, 0); /* no audio production info */ - put_bits(&s->pb, 1, 0); /* no copyright */ - put_bits(&s->pb, 1, 1); /* original bitstream */ - put_bits(&s->pb, 1, 0); /* no time code 1 */ - put_bits(&s->pb, 1, 0); /* no time code 2 */ - put_bits(&s->pb, 1, 0); /* no addtional bit stream info */ -} - -/* symetric quantization on 'levels' levels */ -static inline int sym_quant(int c, int e, int levels) -{ - int v; - - if (c >= 0) { - v = (levels * (c << e)) >> 25; - v = (levels >> 1) + v; - } else { - v = (levels * ((-c) << e)) >> 25; - v = (levels >> 1) - v; - } - assert (v >= 0 && v < levels); - return v; -} - -/* asymetric quantization on 2^qbits levels */ -static inline int asym_quant(int c, int e, int qbits) -{ - int lshift, m, v; - - lshift = e + qbits - 24; - if (lshift >= 0) - v = c << lshift; - else - v = c >> (-lshift); - /* rounding */ - v = (v + 1) >> 1; - m = (1 << (qbits-1)); - if (v >= m) - v = m - 1; - assert(v >= -m); - return v & ((1 << qbits)-1); -} - -/* Output one audio block. There are NB_BLOCKS audio blocks in one AC3 - frame */ -static void output_audio_block(AC3EncodeContext *s, - UINT8 exp_strategy[AC3_MAX_CHANNELS], - UINT8 encoded_exp[AC3_MAX_CHANNELS][N/2], - UINT8 bap[AC3_MAX_CHANNELS][N/2], - INT32 mdct_coefs[AC3_MAX_CHANNELS][N/2], - INT8 global_exp[AC3_MAX_CHANNELS], - int block_num) -{ - int ch, nb_groups, group_size, i, baie; - UINT8 *p; - UINT16 qmant[AC3_MAX_CHANNELS][N/2]; - int exp0, exp1; - int mant1_cnt, mant2_cnt, mant4_cnt; - UINT16 *qmant1_ptr, *qmant2_ptr, *qmant4_ptr; - int delta0, delta1, delta2; - - for(ch=0;chnb_channels;ch++) - put_bits(&s->pb, 1, 0); /* 512 point MDCT */ - for(ch=0;chnb_channels;ch++) - put_bits(&s->pb, 1, 1); /* no dither */ - put_bits(&s->pb, 1, 0); /* no dynamic range */ - if (block_num == 0) { - /* for block 0, even if no coupling, we must say it. This is a - waste of bit :-) */ - put_bits(&s->pb, 1, 1); /* coupling strategy present */ - put_bits(&s->pb, 1, 0); /* no coupling strategy */ - } else { - put_bits(&s->pb, 1, 0); /* no new coupling strategy */ - } - - if (s->acmod == 2) { - put_bits(&s->pb, 1, 0); /* no matrixing (but should be used in the future) */ - } - -#if defined(DEBUG) - { - static int count = 0; - printf("Block #%d (%d)\n", block_num, count++); - } -#endif - /* exponent strategy */ - for(ch=0;chnb_channels;ch++) { - put_bits(&s->pb, 2, exp_strategy[ch]); - } - - for(ch=0;chnb_channels;ch++) { - if (exp_strategy[ch] != EXP_REUSE) - put_bits(&s->pb, 6, s->chbwcod[ch]); - } - - /* exponents */ - for (ch = 0; ch < s->nb_channels; ch++) { - switch(exp_strategy[ch]) { - case EXP_REUSE: - continue; - case EXP_D15: - group_size = 1; - break; - case EXP_D25: - group_size = 2; - break; - default: - case EXP_D45: - group_size = 4; - break; - } - nb_groups = (s->nb_coefs[ch] + (group_size * 3) - 4) / (3 * group_size); - p = encoded_exp[ch]; - - /* first exponent */ - exp1 = *p++; - put_bits(&s->pb, 4, exp1); - - /* next ones are delta encoded */ - for(i=0;ipb, 7, ((delta0 * 5 + delta1) * 5) + delta2); - } - - put_bits(&s->pb, 2, 0); /* no gain range info */ - } - - /* bit allocation info */ - baie = (block_num == 0); - put_bits(&s->pb, 1, baie); - if (baie) { - put_bits(&s->pb, 2, s->sdecaycod); - put_bits(&s->pb, 2, s->fdecaycod); - put_bits(&s->pb, 2, s->sgaincod); - put_bits(&s->pb, 2, s->dbkneecod); - put_bits(&s->pb, 3, s->floorcod); - } - - /* snr offset */ - put_bits(&s->pb, 1, baie); /* always present with bai */ - if (baie) { - put_bits(&s->pb, 6, s->csnroffst); - for(ch=0;chnb_channels;ch++) { - put_bits(&s->pb, 4, s->fsnroffst[ch]); - put_bits(&s->pb, 3, s->fgaincod[ch]); - } - } - - put_bits(&s->pb, 1, 0); /* no delta bit allocation */ - put_bits(&s->pb, 1, 0); /* no data to skip */ - - /* mantissa encoding : we use two passes to handle the grouping. A - one pass method may be faster, but it would necessitate to - modify the output stream. */ - - /* first pass: quantize */ - mant1_cnt = mant2_cnt = mant4_cnt = 0; - qmant1_ptr = qmant2_ptr = qmant4_ptr = NULL; - - for (ch = 0; ch < s->nb_channels; ch++) { - int b, c, e, v; - - for(i=0;inb_coefs[ch];i++) { - c = mdct_coefs[ch][i]; - e = encoded_exp[ch][i] - global_exp[ch]; - b = bap[ch][i]; - switch(b) { - case 0: - v = 0; - break; - case 1: - v = sym_quant(c, e, 3); - switch(mant1_cnt) { - case 0: - qmant1_ptr = &qmant[ch][i]; - v = 9 * v; - mant1_cnt = 1; - break; - case 1: - *qmant1_ptr += 3 * v; - mant1_cnt = 2; - v = 128; - break; - default: - *qmant1_ptr += v; - mant1_cnt = 0; - v = 128; - break; - } - break; - case 2: - v = sym_quant(c, e, 5); - switch(mant2_cnt) { - case 0: - qmant2_ptr = &qmant[ch][i]; - v = 25 * v; - mant2_cnt = 1; - break; - case 1: - *qmant2_ptr += 5 * v; - mant2_cnt = 2; - v = 128; - break; - default: - *qmant2_ptr += v; - mant2_cnt = 0; - v = 128; - break; - } - break; - case 3: - v = sym_quant(c, e, 7); - break; - case 4: - v = sym_quant(c, e, 11); - switch(mant4_cnt) { - case 0: - qmant4_ptr = &qmant[ch][i]; - v = 11 * v; - mant4_cnt = 1; - break; - default: - *qmant4_ptr += v; - mant4_cnt = 0; - v = 128; - break; - } - break; - case 5: - v = sym_quant(c, e, 15); - break; - case 14: - v = asym_quant(c, e, 14); - break; - case 15: - v = asym_quant(c, e, 16); - break; - default: - v = asym_quant(c, e, b - 1); - break; - } - qmant[ch][i] = v; - } - } - - /* second pass : output the values */ - for (ch = 0; ch < s->nb_channels; ch++) { - int b, q; - - for(i=0;inb_coefs[ch];i++) { - q = qmant[ch][i]; - b = bap[ch][i]; - switch(b) { - case 0: - break; - case 1: - if (q != 128) - put_bits(&s->pb, 5, q); - break; - case 2: - if (q != 128) - put_bits(&s->pb, 7, q); - break; - case 3: - put_bits(&s->pb, 3, q); - break; - case 4: - if (q != 128) - put_bits(&s->pb, 7, q); - break; - case 14: - put_bits(&s->pb, 14, q); - break; - case 15: - put_bits(&s->pb, 16, q); - break; - default: - put_bits(&s->pb, b - 1, q); - break; - } - } - } -} - -/* compute the ac3 crc */ - -#define CRC16_POLY ((1 << 0) | (1 << 2) | (1 << 15) | (1 << 16)) - -static void ac3_crc_init(void) -{ - unsigned int c, n, k; - - for(n=0;n<256;n++) { - c = n << 8; - for (k = 0; k < 8; k++) { - if (c & (1 << 15)) - c = ((c << 1) & 0xffff) ^ (CRC16_POLY & 0xffff); - else - c = c << 1; - } - crc_table[n] = c; - } -} - -static unsigned int ac3_crc(UINT8 *data, int n, unsigned int crc) -{ - int i; - for(i=0;i> 8)] ^ (crc << 8)) & 0xffff; - } - return crc; -} - -static unsigned int mul_poly(unsigned int a, unsigned int b, unsigned int poly) -{ - unsigned int c; - - c = 0; - while (a) { - if (a & 1) - c ^= b; - a = a >> 1; - b = b << 1; - if (b & (1 << 16)) - b ^= poly; - } - return c; -} - -static unsigned int pow_poly(unsigned int a, unsigned int n, unsigned int poly) -{ - unsigned int r; - r = 1; - while (n) { - if (n & 1) - r = mul_poly(r, a, poly); - a = mul_poly(a, a, poly); - n >>= 1; - } - return r; -} - - -/* compute log2(max(abs(tab[]))) */ -static int log2_tab(INT16 *tab, int n) -{ - int i, v; - - v = 0; - for(i=0;i 0) { - for(i=0;i>= lshift; - } - } -} - -/* fill the end of the frame and compute the two crcs */ -static int output_frame_end(AC3EncodeContext *s) -{ - int frame_size, frame_size_58, n, crc1, crc2, crc_inv; - UINT8 *frame; - - frame_size = s->frame_size; /* frame size in words */ - /* align to 8 bits */ - flush_put_bits(&s->pb); - /* add zero bytes to reach the frame size */ - frame = s->pb.buf; - n = 2 * s->frame_size - (s->pb.buf_ptr - frame) - 2; - assert(n >= 0); - memset(s->pb.buf_ptr, 0, n); - - /* Now we must compute both crcs : this is not so easy for crc1 - because it is at the beginning of the data... */ - frame_size_58 = (frame_size >> 1) + (frame_size >> 3); - crc1 = ac3_crc(frame + 4, (2 * frame_size_58) - 4, 0); - /* XXX: could precompute crc_inv */ - crc_inv = pow_poly((CRC16_POLY >> 1), (16 * frame_size_58) - 16, CRC16_POLY); - crc1 = mul_poly(crc_inv, crc1, CRC16_POLY); - frame[2] = crc1 >> 8; - frame[3] = crc1; - - crc2 = ac3_crc(frame + 2 * frame_size_58, (frame_size - frame_size_58) * 2 - 2, 0); - frame[2*frame_size - 2] = crc2 >> 8; - frame[2*frame_size - 1] = crc2; - - // printf("n=%d frame_size=%d\n", n, frame_size); - return frame_size * 2; -} - -int AC3_encode_frame(AVEncodeContext *avctx, - unsigned char *frame, int buf_size, void *data) -{ - AC3EncodeContext *s = avctx->priv_data; - short *samples = data; - int i, j, k, v, ch; - INT16 input_samples[N]; - INT32 mdct_coef[NB_BLOCKS][AC3_MAX_CHANNELS][N/2]; - UINT8 exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2]; - UINT8 exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS]; - UINT8 encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2]; - UINT8 bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2]; - INT8 exp_samples[NB_BLOCKS][AC3_MAX_CHANNELS]; - int frame_bits; - - frame_bits = 0; - for(ch=0;chnb_channels;ch++) { - /* fixed mdct to the six sub blocks & exponent computation */ - for(i=0;ilast_samples[ch], N/2 * sizeof(INT16)); - sinc = s->nb_channels; - sptr = samples + (sinc * (N/2) * i) + ch; - for(j=0;jlast_samples[ch][j] = v; - sptr += sinc; - } - - /* apply the MDCT window */ - for(j=0;j> 15; - input_samples[N-j-1] = MUL16(input_samples[N-j-1], - ac3_window[j]) >> 15; - } - - /* Normalize the samples to use the maximum available - precision */ - v = 14 - log2_tab(input_samples, N); - if (v < 0) - v = 0; - exp_samples[i][ch] = v - 8; - lshift_tab(input_samples, N, v); - - /* do the MDCT */ - mdct512(mdct_coef[i][ch], input_samples); - - /* compute "exponents". We take into account the - normalization there */ - for(j=0;j= 24) { - e = 24; - mdct_coef[i][ch][j] = 0; - } - } - exp[i][ch][j] = e; - } - } - - compute_exp_strategy(exp_strategy, exp, ch); - - /* compute the exponents as the decoder will see them. The - EXP_REUSE case must be handled carefully : we select the - min of the exponents */ - i = 0; - while (i < NB_BLOCKS) { - j = i + 1; - while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE) { - exponent_min(exp[i][ch], exp[j][ch], s->nb_coefs[ch]); - j++; - } - frame_bits += encode_exp(encoded_exp[i][ch], - exp[i][ch], s->nb_coefs[ch], - exp_strategy[i][ch]); - /* copy encoded exponents for reuse case */ - for(k=i+1;knb_coefs[ch] * sizeof(UINT8)); - } - i = j; - } - } - - compute_bit_allocation(s, bap, encoded_exp, exp_strategy, frame_bits); - /* everything is known... let's output the frame */ - output_frame_header(s, frame); - - for(i=0;i emax) - emax = e; - err += e * e; - } - printf("err2=%f emax=%f\n", err / (N/2), emax); -} - -void test_ac3(void) -{ - AC3EncodeContext ctx; - unsigned char frame[AC3_MAX_CODED_FRAME_SIZE]; - short samples[AC3_FRAME_SIZE]; - int ret, i; - - AC3_encode_init(&ctx, 44100, 64000, 1); - - fft_test(); - mdct_test(); - - for(i=0;i -#include -#include -#include -#include -#include "common.h" - -#define NDEBUG -#include - -void init_put_bits(PutBitContext *s, - UINT8 *buffer, int buffer_size, - void *opaque, - void (*write_data)(void *, UINT8 *, int)) -{ - s->buf = buffer; - s->buf_ptr = s->buf; - s->buf_end = s->buf + buffer_size; - s->bit_cnt=0; - s->bit_buf=0; - s->data_out_size = 0; - s->write_data = write_data; - s->opaque = opaque; -} - -static void flush_buffer(PutBitContext *s) -{ - int size; - if (s->write_data) { - size = s->buf_ptr - s->buf; - if (size > 0) - s->write_data(s->opaque, s->buf, size); - s->buf_ptr = s->buf; - s->data_out_size += size; - } -} - -void put_bits(PutBitContext *s, int n, unsigned int value) -{ - unsigned int bit_buf; - int bit_cnt; - - assert(n == 32 || value < (1U << n)); - - bit_buf = s->bit_buf; - bit_cnt = s->bit_cnt; - - // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); - /* XXX: optimize */ - if (n < (32-bit_cnt)) { - bit_buf |= value << (32 - n - bit_cnt); - bit_cnt+=n; - } else { - bit_buf |= value >> (n + bit_cnt - 32); - *(UINT32 *)s->buf_ptr = htonl(bit_buf); - //printf("bitbuf = %08x\n", bit_buf); - s->buf_ptr+=4; - if (s->buf_ptr >= s->buf_end) - flush_buffer(s); - bit_cnt=bit_cnt + n - 32; - if (bit_cnt == 0) { - bit_buf = 0; - } else { - bit_buf = value << (32 - bit_cnt); - } - } - - s->bit_buf = bit_buf; - s->bit_cnt = bit_cnt; -} - -/* return the number of bits output */ -long long get_bit_count(PutBitContext *s) -{ - return (s->buf_ptr - s->buf + s->data_out_size) * 8 + (long long)s->bit_cnt; -} - -void align_put_bits(PutBitContext *s) -{ - put_bits(s,(8 - s->bit_cnt) & 7,0); -} - -/* pad the end of the output stream with zeros */ -void flush_put_bits(PutBitContext *s) -{ - while (s->bit_cnt > 0) { - /* XXX: should test end of buffer */ - *s->buf_ptr++=s->bit_buf >> 24; - s->bit_buf<<=8; - s->bit_cnt-=8; - } - flush_buffer(s); - s->bit_cnt=0; - s->bit_buf=0; -} - -/* for jpeg : espace 0xff with 0x00 after it */ -void jput_bits(PutBitContext *s, int n, unsigned int value) -{ - unsigned int bit_buf, b; - int bit_cnt, i; - - assert(n == 32 || value < (1U << n)); - - bit_buf = s->bit_buf; - bit_cnt = s->bit_cnt; - - //printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); - /* XXX: optimize */ - if (n < (32-bit_cnt)) { - bit_buf |= value << (32 - n - bit_cnt); - bit_cnt+=n; - } else { - bit_buf |= value >> (n + bit_cnt - 32); - /* handle escape */ - for(i=0;i<4;i++) { - b = (bit_buf >> 24); - *(s->buf_ptr++) = b; - if (b == 0xff) - *(s->buf_ptr++) = 0; - bit_buf <<= 8; - } - /* we flush the buffer sooner to handle worst case */ - if (s->buf_ptr >= (s->buf_end - 8)) - flush_buffer(s); - - bit_cnt=bit_cnt + n - 32; - if (bit_cnt == 0) { - bit_buf = 0; - } else { - bit_buf = value << (32 - bit_cnt); - } - } - - s->bit_buf = bit_buf; - s->bit_cnt = bit_cnt; -} - -/* pad the end of the output stream with zeros */ -void jflush_put_bits(PutBitContext *s) -{ - unsigned int b; - - while (s->bit_cnt > 0) { - b = s->bit_buf >> 24; - *s->buf_ptr++ = b; - if (b == 0xff) - *s->buf_ptr++ = 0; - s->bit_buf<<=8; - s->bit_cnt-=8; - } - flush_buffer(s); - s->bit_cnt=0; - s->bit_buf=0; -} - diff --git a/libav/common.h b/libav/common.h deleted file mode 100644 index 18473eb8e8..0000000000 --- a/libav/common.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned int UINT32; -typedef signed char INT8; -typedef signed short INT16; -typedef signed int INT32; - -/* bit I/O */ - -struct PutBitContext; - -typedef void (*WriteDataFunc)(void *, UINT8 *, int); - -typedef struct PutBitContext { - UINT8 *buf, *buf_ptr, *buf_end; - int bit_cnt; - UINT32 bit_buf; - long long data_out_size; /* in bytes */ - void *opaque; - WriteDataFunc write_data; -} PutBitContext; - -void init_put_bits(PutBitContext *s, - UINT8 *buffer, int buffer_size, - void *opaque, - void (*write_data)(void *, UINT8 *, int)); -void put_bits(PutBitContext *s, int n, unsigned int value); -long long get_bit_count(PutBitContext *s); -void align_put_bits(PutBitContext *s); -void flush_put_bits(PutBitContext *s); - -/* jpeg specific put_bits */ -void jput_bits(PutBitContext *s, int n, unsigned int value); -void jflush_put_bits(PutBitContext *s); - -/* misc math functions */ - -extern inline int log2(unsigned int v) -{ - int n; - - n = 0; - if (v & 0xffff0000) { - v >>= 16; - n += 16; - } - if (v & 0xff00) { - v >>= 8; - n += 8; - } - if (v & 0xf0) { - v >>= 4; - n += 4; - } - if (v & 0xc) { - v >>= 2; - n += 2; - } - if (v & 0x2) { - n++; - } - return n; -} - -#endif diff --git a/libav/h263data.h b/libav/h263data.h deleted file mode 100644 index 1cf6f4d802..0000000000 --- a/libav/h263data.h +++ /dev/null @@ -1,151 +0,0 @@ -/* DCT coefficients. Four tables, two for last = 0, two for last = 1. - the sign bit must be added afterwards. */ - -/* first part of coeffs for last = 0. Indexed by [run][level-1] */ - -static const UINT8 coeff_tab0[2][12][2] = -{ - /* run = 0 */ - { - {0x02, 2}, {0x0f, 4}, {0x15, 6}, {0x17, 7}, - {0x1f, 8}, {0x25, 9}, {0x24, 9}, {0x21,10}, - {0x20,10}, {0x07,11}, {0x06,11}, {0x20,11} - }, - /* run = 1 */ - { - {0x06, 3}, {0x14, 6}, {0x1e, 8}, {0x0f,10}, - {0x21,11}, {0x50,12}, {0x00, 0}, {0x00, 0}, - {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} - } -}; - -/* rest of coeffs for last = 0. indexing by [run-2][level-1] */ - -static const UINT8 coeff_tab1[25][4][2] = -{ - /* run = 2 */ - { - {0x0e, 4}, {0x1d, 8}, {0x0e,10}, {0x51,12} - }, - /* run = 3 */ - { - {0x0d, 5}, {0x23, 9}, {0x0d,10}, {0x00, 0} - }, - /* run = 4-26 */ - { - {0x0c, 5}, {0x22, 9}, {0x52,12}, {0x00, 0} - }, - { - {0x0b, 5}, {0x0c,10}, {0x53,12}, {0x00, 0} - }, - { - {0x13, 6}, {0x0b,10}, {0x54,12}, {0x00, 0} - }, - { - {0x12, 6}, {0x0a,10}, {0x00, 0}, {0x00, 0} - }, - { - {0x11, 6}, {0x09,10}, {0x00, 0}, {0x00, 0} - }, - { - {0x10, 6}, {0x08,10}, {0x00, 0}, {0x00, 0} - }, - { - {0x16, 7}, {0x55,12}, {0x00, 0}, {0x00, 0} - }, - { - {0x15, 7}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x14, 7}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1c, 8}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1b, 8}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x21, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x20, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1f, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1e, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1d, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1c, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1b, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x1a, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x22,11}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x23,11}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x56,12}, {0x00, 0}, {0x00, 0}, {0x00, 0} - }, - { - {0x57,12}, {0x00, 0}, {0x00, 0}, {0x00, 0} - } -}; - -/* first coeffs of last = 1. indexing by [run][level-1] */ - -static const UINT8 coeff_tab2[2][3][2] = -{ - /* run = 0 */ - { - {0x07, 4}, {0x19, 9}, {0x05,11} - }, - /* run = 1 */ - { - {0x0f, 6}, {0x04,11}, {0x00, 0} - } -}; - -/* rest of coeffs for last = 1. indexing by [run-2] */ - -static const UINT8 coeff_tab3[40][2] = -{ - {0x0e, 6}, {0x0d, 6}, {0x0c, 6}, - {0x13, 7}, {0x12, 7}, {0x11, 7}, {0x10, 7}, - {0x1a, 8}, {0x19, 8}, {0x18, 8}, {0x17, 8}, - {0x16, 8}, {0x15, 8}, {0x14, 8}, {0x13, 8}, - {0x18, 9}, {0x17, 9}, {0x16, 9}, {0x15, 9}, - {0x14, 9}, {0x13, 9}, {0x12, 9}, {0x11, 9}, - {0x07,10}, {0x06,10}, {0x05,10}, {0x04,10}, - {0x24,11}, {0x25,11}, {0x26,11}, {0x27,11}, - {0x58,12}, {0x59,12}, {0x5a,12}, {0x5b,12}, - {0x5c,12}, {0x5d,12}, {0x5e,12}, {0x5f,12}, - {0x00, 0} -}; - -/* intra MCBPC, mb_type = 3 */ -static UINT8 intra_MCBPC_code[4] = { 1, 1, 2, 3 }; -static UINT8 intra_MCBPC_bits[4] = { 1, 3, 3, 3 }; - -/* inter MCBPC, mb_type = 0 then 3 */ -static UINT8 inter_MCBPC_code[8] = { 1, 3, 2, 5, 3, 4, 3, 3 }; -static UINT8 inter_MCBPC_bits[8] = { 1, 4, 4, 6, 5, 8, 8, 7 }; - -static UINT8 cbpy_tab[16][2] = -{ - {3,4}, {5,5}, {4,5}, {9,4}, {3,5}, {7,4}, {2,6}, {11,4}, - {2,5}, {3,6}, {5,4}, {10,4}, {4,4}, {8,4}, {6,4}, {3,2} -}; - - diff --git a/libav/h263enc.c b/libav/h263enc.c deleted file mode 100644 index 59db1ee512..0000000000 --- a/libav/h263enc.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * H263 backend for ffmpeg encoder - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include "common.h" -#include "mpegvideo.h" -#include "h263data.h" - -void h263_picture_header(MpegEncContext *s, int picture_number) -{ - int format; - - align_put_bits(&s->pb); - put_bits(&s->pb, 22, 0x20); - put_bits(&s->pb, 8, ((s->picture_number * 30) / s->frame_rate) & 0xff); - - put_bits(&s->pb, 1, 1); /* marker */ - put_bits(&s->pb, 1, 0); /* h263 id */ - put_bits(&s->pb, 1, 0); /* split screen off */ - put_bits(&s->pb, 1, 0); /* camera off */ - put_bits(&s->pb, 1, 0); /* freeze picture release off */ - - if (s->width == 128 && s->height == 96) - format = 1; - else if (s->width == 176 && s->height == 144) - format = 2; - else if (s->width == 352 && s->height == 288) - format = 3; - else if (s->width == 704 && s->height == 576) - format = 4; - else if (s->width == 1408 && s->height == 1152) - format = 5; - else - abort(); - - put_bits(&s->pb, 3, format); - - put_bits(&s->pb, 1, (s->pict_type == P_TYPE)); - - put_bits(&s->pb, 1, 0); /* unrestricted motion vector: off */ - - put_bits(&s->pb, 1, 0); /* SAC: off */ - - put_bits(&s->pb, 1, 0); /* advanced prediction mode: off */ - - put_bits(&s->pb, 1, 0); /* not PB frame */ - - put_bits(&s->pb, 5, s->qscale); - - put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */ - - put_bits(&s->pb, 1, 0); /* no PEI */ -} - -static void h263_encode_block(MpegEncContext *s, DCTELEM *block, - int n); - -void h263_encode_mb(MpegEncContext *s, - DCTELEM block[6][64], - int motion_x, int motion_y) -{ - int cbpc, cbpy, i, cbp; - - if (!s->mb_intra) { - /* compute cbp */ - cbp = 0; - for(i=0;i<6;i++) { - if (s->block_last_index[i] >= 0) - cbp |= 1 << (5 - i); - } - if ((cbp | motion_x | motion_y) == 0) { - /* skip macroblock */ - put_bits(&s->pb, 1, 1); - return; - } - - put_bits(&s->pb, 1, 0); /* mb coded */ - cbpc = cbp & 3; - put_bits(&s->pb, - inter_MCBPC_bits[cbpc], - inter_MCBPC_code[cbpc]); - cbpy = cbp >> 2; - cbpy ^= 0xf; - put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); - - /* motion vectors: zero */ - put_bits(&s->pb, 1, 1); - put_bits(&s->pb, 1, 1); - - } else { - /* compute cbp */ - cbp = 0; - for(i=0;i<6;i++) { - if (s->block_last_index[i] >= 1) - cbp |= 1 << (5 - i); - } - - cbpc = cbp & 3; - if (s->pict_type == I_TYPE) { - put_bits(&s->pb, - intra_MCBPC_bits[cbpc], - intra_MCBPC_code[cbpc]); - } else { - put_bits(&s->pb, 1, 0); /* mb coded */ - put_bits(&s->pb, - inter_MCBPC_bits[cbpc + 4], - inter_MCBPC_code[cbpc + 4]); - } - cbpy = cbp >> 2; - put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); - } - - /* encode each block */ - for(i=0;i<6;i++) { - h263_encode_block(s, block[i], i); - } -} - -static void h263_encode_block(MpegEncContext *s, DCTELEM *block, int n) -{ - int level, run, last, i, j, last_index, last_non_zero, sign, alevel; - int code, len; - - if (s->mb_intra) { - /* DC coef */ - level = block[0]; - if (level == 128) - put_bits(&s->pb, 8, 0xff); - else - put_bits(&s->pb, 8, level & 0xff); - i = 1; - } else { - i = 0; - } - - /* AC coefs */ - last_index = s->block_last_index[n]; - last_non_zero = i - 1; - for(;i<=last_index;i++) { - j = zigzag_direct[i]; - level = block[j]; - if (level) { - run = i - last_non_zero - 1; - last = (i == last_index); - sign = 0; - alevel = level; - if (level < 0) { - sign = 1; - alevel = -level; - } - len = 0; - code = 0; /* only to disable warning */ - if (last == 0) { - if (run < 2 && alevel < 13 ) { - len = coeff_tab0[run][alevel-1][1]; - code = coeff_tab0[run][alevel-1][0]; - } else if (run >= 2 && run < 27 && alevel < 5) { - len = coeff_tab1[run-2][alevel-1][1]; - code = coeff_tab1[run-2][alevel-1][0]; - } - } else { - if (run < 2 && alevel < 4) { - len = coeff_tab2[run][alevel-1][1]; - code = coeff_tab2[run][alevel-1][0]; - } else if (run >= 2 && run < 42 && alevel == 1) { - len = coeff_tab3[run-2][1]; - code = coeff_tab3[run-2][0]; - } - } - - if (len != 0) { - code = (code << 1) | sign; - put_bits(&s->pb, len + 1, code); - } else { - /* escape */ - put_bits(&s->pb, 7, 3); - put_bits(&s->pb, 1, last); - put_bits(&s->pb, 6, run); - put_bits(&s->pb, 8, level & 0xff); - } - - last_non_zero = i; - } - } -} - -/* write RV 1.0 compatible frame header */ -void rv10_encode_picture_header(MpegEncContext *s, int picture_number) -{ - align_put_bits(&s->pb); - - put_bits(&s->pb, 1, 1); /* marker */ - - put_bits(&s->pb, 1, (s->pict_type == P_TYPE)); - - put_bits(&s->pb, 1, 0); /* not PB frame */ - - put_bits(&s->pb, 5, s->qscale); - - if (s->pict_type == I_TYPE) { - /* specific MPEG like DC coding not used */ - } - - /* if multiple packets per frame are sent, the position at which - to display the macro blocks is coded here */ - put_bits(&s->pb, 6, 0); /* mb_x */ - put_bits(&s->pb, 6, 0); /* mb_y */ - put_bits(&s->pb, 12, s->mb_width * s->mb_height); - - put_bits(&s->pb, 3, 0); /* ignored */ -} - diff --git a/libav/jfdctfst.c b/libav/jfdctfst.c deleted file mode 100644 index 620a03078c..0000000000 --- a/libav/jfdctfst.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * jfdctfst.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains a fast, not so accurate integer implementation of the - * forward DCT (Discrete Cosine Transform). - * - * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with fixed-point math, - * accuracy is lost due to imprecise representation of the scaled - * quantization values. The smaller the quantization table entry, the less - * precise the scaled value, so this implementation does worse with high- - * quality-setting files than with low-quality ones. - */ - -#include -#include -#include "common.h" -#include "mpegvideo.h" - -#define DCTSIZE 8 -#define GLOBAL(x) x -#define RIGHT_SHIFT(x, n) ((x) >> (n)) -#define SHIFT_TEMPS - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jfdctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * Again to save a few shifts, the intermediate results between pass 1 and - * pass 2 are not upscaled, but are represented only to integral precision. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - -#define CONST_BITS 8 - - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 8 -#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ -#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ -#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ -#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ -#else -#define FIX_0_382683433 FIX(0.382683433) -#define FIX_0_541196100 FIX(0.541196100) -#define FIX_0_707106781 FIX(0.707106781) -#define FIX_1_306562965 FIX(1.306562965) -#endif - - -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - -#ifndef USE_ACCURATE_ROUNDING -#undef DESCALE -#define DESCALE(x,n) RIGHT_SHIFT(x, n) -#endif - - -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - -#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) - - -/* - * Perform the forward DCT on one block of samples. - */ - -GLOBAL(void) -jpeg_fdct_ifast (DCTELEM * data) -{ - DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - DCTELEM tmp10, tmp11, tmp12, tmp13; - DCTELEM z1, z2, z3, z4, z5, z11, z13; - DCTELEM *dataptr; - int ctr; - SHIFT_TEMPS - - /* Pass 1: process rows. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. */ - - dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - - /* Even part */ - - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; - - /* Odd part */ - - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; - - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ - } -} diff --git a/libav/jrevdct.c b/libav/jrevdct.c deleted file mode 100644 index 26715b0b18..0000000000 --- a/libav/jrevdct.c +++ /dev/null @@ -1,1584 +0,0 @@ -/* - * jrevdct.c - * - * Copyright (C) 1991, 1992, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains the basic inverse-DCT transformation subroutine. - * - * This implementation is based on an algorithm described in - * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT - * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, - * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. - * The primary algorithm described there uses 11 multiplies and 29 adds. - * We use their alternate method with 12 multiplies and 32 adds. - * The advantage of this method is that no data path contains more than one - * multiplication; this allows a very simple and accurate implementation in - * scaled fixed-point arithmetic, with a minimal number of shifts. - * - * I've made lots of modifications to attempt to take advantage of the - * sparse nature of the DCT matrices we're getting. Although the logic - * is cumbersome, it's straightforward and the resulting code is much - * faster. - * - * A better way to do this would be to pass in the DCT block as a sparse - * matrix, perhaps with the difference cases encoded. - */ - -typedef int INT32; - -/* Definition of Contant integer scale factor. */ -#define CONST_BITS 13 - -/* Misc DCT definitions */ -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ - -#define GLOBAL /* a function referenced thru EXTERNs */ - -typedef int DCTELEM; -typedef DCTELEM DCTBLOCK[DCTSIZE2]; - -void j_rev_dct (DCTELEM *data); - - -#define GLOBAL /* a function referenced thru EXTERNs */ -#define ORIG_DCT 1 - -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define SHIFT_TEMPS INT32 shift_temp; -#define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) -#else -#define SHIFT_TEMPS -#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -/* - * This routine is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* - * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT - * on each column. Direct algorithms are also available, but they are - * much more complex and seem not to be any faster when reduced to code. - * - * The poop on this scaling stuff is as follows: - * - * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) - * larger than the true IDCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D IDCT, - * because the y0 and y4 inputs need not be divided by sqrt(N). - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (To scale up 12-bit sample data further, an - * intermediate INT32 array would be needed.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - -#ifdef EIGHT_BIT_SAMPLES -#define PASS1_BITS 2 -#else -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -#define ONE ((INT32) 1) - -#define CONST_SCALE (ONE << CONST_BITS) - -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * IMPORTANT: if your compiler doesn't do this arithmetic at compile time, - * you will pay a significant penalty in run time. In that case, figure - * the correct integer constant values and insert them by hand. - */ - -#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) - -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - -#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) -#define SCALE(x,n) ((INT32)(x) << n) - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; - * this provides a useful speedup on many machines. - * There is no way to specify a 16x16->32 multiply in portable C, but - * some C compilers will do the right thing if you provide the correct - * combination of casts. - * NB: for 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#ifdef EIGHT_BIT_SAMPLES -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) -#endif -#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ -#define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const))) -#endif -#endif - -#if 0 -/* force a multiplication for x86 where a multiply is fast). We - force the non constant operand to be in a register because - otherwise it may be a 16 bit memory reference, which is not allowed - by imull */ -#define MULTIPLY(a,b) \ -({\ - int res;\ - asm("imull %2,%1,%0" : "=r" (res) : "r" ((int)(a)), "i" (b));\ - res;\ -}) -#endif - -#ifndef MULTIPLY /* default definition */ -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -#ifndef ORIG_DCT - -#undef SSMUL -#define SSMUL(var1,var2) ((INT16)(var1) * (INT32)(INT16)(var2)) - -/* Precomputed idct value arrays. */ - -STATIC DCTELEM PreIDCT[64][64]; - -/* Pre compute singleton coefficient IDCT values. */ -void init_pre_idct() { - int i; - - for (i = 0; i < 64; i++) { - memset ((char *) PreIDCT[i], 0, 64 * sizeof(DCTELEM)); - PreIDCT[i][i] = 2048; - j_rev_dct (PreIDCT[i]); - } -} - -/* - * Perform the inverse DCT on one block of coefficients. - */ - -void j_rev_dct_sparse (data, pos) - DCTBLOCK data; - int pos; -{ - register DCTELEM *dataptr; - short int val; - DCTELEM *ndataptr; - int coeff, rr; - - /* If DC Coefficient. */ - - if (pos == 0) { - register INT32 *dp; - register INT32 v; - - dp = (INT32*)data; - v = *data; - /* Compute 32 bit value to assign. - * This speeds things up a bit */ - if (v < 0) - val = (short)((v - 3) >> 3); - else - val = (short)((v + 4) >> 3); - v = val | ((INT32)val << 16); - dp[0] = v; dp[1] = v; dp[2] = v; dp[3] = v; - dp[4] = v; dp[5] = v; dp[6] = v; dp[7] = v; - dp[8] = v; dp[9] = v; dp[10] = v; dp[11] = v; - dp[12] = v; dp[13] = v; dp[14] = v; dp[15] = v; - dp[16] = v; dp[17] = v; dp[18] = v; dp[19] = v; - dp[20] = v; dp[21] = v; dp[22] = v; dp[23] = v; - dp[24] = v; dp[25] = v; dp[26] = v; dp[27] = v; - dp[28] = v; dp[29] = v; dp[30] = v; dp[31] = v; - return; - } - - /* Some other coefficient. */ - dataptr = (DCTELEM *)data; - coeff = dataptr[pos]; - ndataptr = PreIDCT[pos]; - - for (rr = 0; rr < 4; rr++) { - dataptr[0] = (DCTELEM)(SSMUL (ndataptr[0] , coeff) >> (CONST_BITS-2)); - dataptr[1] = (DCTELEM)(SSMUL (ndataptr[1] , coeff) >> (CONST_BITS-2)); - dataptr[2] = (DCTELEM)(SSMUL (ndataptr[2] , coeff) >> (CONST_BITS-2)); - dataptr[3] = (DCTELEM)(SSMUL (ndataptr[3] , coeff) >> (CONST_BITS-2)); - dataptr[4] = (DCTELEM)(SSMUL (ndataptr[4] , coeff) >> (CONST_BITS-2)); - dataptr[5] = (DCTELEM)(SSMUL (ndataptr[5] , coeff) >> (CONST_BITS-2)); - dataptr[6] = (DCTELEM)(SSMUL (ndataptr[6] , coeff) >> (CONST_BITS-2)); - dataptr[7] = (DCTELEM)(SSMUL (ndataptr[7] , coeff) >> (CONST_BITS-2)); - dataptr[8] = (DCTELEM)(SSMUL (ndataptr[8] , coeff) >> (CONST_BITS-2)); - dataptr[9] = (DCTELEM)(SSMUL (ndataptr[9] , coeff) >> (CONST_BITS-2)); - dataptr[10] = (DCTELEM)(SSMUL (ndataptr[10], coeff) >> (CONST_BITS-2)); - dataptr[11] = (DCTELEM)(SSMUL (ndataptr[11], coeff) >> (CONST_BITS-2)); - dataptr[12] = (DCTELEM)(SSMUL (ndataptr[12], coeff) >> (CONST_BITS-2)); - dataptr[13] = (DCTELEM)(SSMUL (ndataptr[13], coeff) >> (CONST_BITS-2)); - dataptr[14] = (DCTELEM)(SSMUL (ndataptr[14], coeff) >> (CONST_BITS-2)); - dataptr[15] = (DCTELEM)(SSMUL (ndataptr[15], coeff) >> (CONST_BITS-2)); - dataptr += 16; - ndataptr += 16; - } -} - - -void j_rev_dct (data) - DCTBLOCK data; -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; - int d0, d1, d2, d3, d4, d5, d6, d7; - register DCTELEM *dataptr; - int rowctr; - SHIFT_TEMPS; - - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - - dataptr = data; - - for (rowctr = DCTSIZE - 1; rowctr >= 0; rowctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any row in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * row DCT calculations can be simplified this way. - */ - - register INT32 *idataptr = (INT32*)dataptr; - d0 = dataptr[0]; - d1 = dataptr[1]; - if ((d1 == 0) && (idataptr[1] | idataptr[2] | idataptr[3]) == 0) { - /* AC terms all zero */ - if (d0) { - /* Compute a 32 bit value to assign. */ - DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS); - register INT32 v = (dcval & 0xffff) | - (((INT32)dcval << 16) & 0xffff0000L); - - idataptr[0] = v; - idataptr[1] = v; - idataptr[2] = v; - idataptr[3] = v; - } - - dataptr += DCTSIZE; /* advance pointer to next row */ - continue; - } - d2 = dataptr[2]; - d3 = dataptr[3]; - d4 = dataptr[4]; - d5 = dataptr[5]; - d6 = dataptr[6]; - d7 = dataptr[7]; - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - if (d6) { - if (d4) { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp2 - tmp0; - tmp12 = -(tmp0 + tmp2); - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, - FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - } else { - /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, -FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp0 = SCALE (d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp2 - tmp0; - tmp12 = -(tmp0 + tmp2); - } - } - } else { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d0, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp10 = tmp3; - tmp13 = -tmp3; - tmp11 = tmp2; - tmp12 = -tmp2; - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, - FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp0 = SCALE (d0, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - } else { - /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, - FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp10 = tmp3; - tmp13 = -tmp3; - tmp11 = tmp2; - tmp12 = -tmp2; - } - } - } - } else { - if (d4) { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp0 = SCALE (d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp2 - tmp0; - tmp12 = -(tmp0 + tmp2); - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ - tmp10 = tmp13 = SCALE (d0 + d4, CONST_BITS); - tmp11 = tmp12 = SCALE (d0 - d4, CONST_BITS); - } else { - /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */ - tmp10 = tmp13 = SCALE (d4, CONST_BITS); - tmp11 = tmp12 = -tmp10; - } - } - } else { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp0 = SCALE (d0, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp10 = tmp3; - tmp13 = -tmp3; - tmp11 = tmp2; - tmp12 = -tmp2; - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */ - tmp10 = tmp13 = tmp11 = tmp12 = SCALE (d0, CONST_BITS); - } else { - /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */ - tmp10 = tmp13 = tmp11 = tmp12 = 0; - } - } - } - } - - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - if (d7) { - if (d5) { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ - z1 = d7 + d1; - z2 = d5 + d3; - z3 = d7 + d3; - z4 = d5 + d1; - z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(z1, - FIX(0.899976223)); - z2 = MULTIPLY(z2, - FIX(2.562915447)); - z3 = MULTIPLY(z3, - FIX(1.961570560)); - z4 = MULTIPLY(z4, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ - z1 = d7; - z2 = d5 + d3; - z3 = d7 + d3; - z5 = MULTIPLY(z3 + d5, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - z1 = MULTIPLY(d7, - FIX(0.899976223)); - z2 = MULTIPLY(z2, - FIX(2.562915447)); - z3 = MULTIPLY(z3, - FIX(1.961570560)); - z4 = MULTIPLY(d5, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 = z1 + z4; - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ - z1 = d7 + d1; - z2 = d5; - z3 = d7; - z4 = d5 + d1; - z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(z1, - FIX(0.899976223)); - z2 = MULTIPLY(d5, - FIX(2.562915447)); - z3 = MULTIPLY(d7, - FIX(1.961570560)); - z4 = MULTIPLY(z4, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 = z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ - tmp0 = MULTIPLY(d7, - FIX(0.601344887)); - z1 = MULTIPLY(d7, - FIX(0.899976223)); - z3 = MULTIPLY(d7, - FIX(1.961570560)); - tmp1 = MULTIPLY(d5, - FIX(0.509795578)); - z2 = MULTIPLY(d5, - FIX(2.562915447)); - z4 = MULTIPLY(d5, - FIX(0.390180644)); - z5 = MULTIPLY(d5 + d7, FIX(1.175875602)); - - z3 += z5; - z4 += z5; - - tmp0 += z3; - tmp1 += z4; - tmp2 = z2 + z3; - tmp3 = z1 + z4; - } - } - } else { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ - z1 = d7 + d1; - z3 = d7 + d3; - z5 = MULTIPLY(z3 + d1, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(z1, - FIX(0.899976223)); - z2 = MULTIPLY(d3, - FIX(2.562915447)); - z3 = MULTIPLY(z3, - FIX(1.961570560)); - z4 = MULTIPLY(d1, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 = z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ - z3 = d7 + d3; - - tmp0 = MULTIPLY(d7, - FIX(0.601344887)); - z1 = MULTIPLY(d7, - FIX(0.899976223)); - tmp2 = MULTIPLY(d3, FIX(0.509795579)); - z2 = MULTIPLY(d3, - FIX(2.562915447)); - z5 = MULTIPLY(z3, FIX(1.175875602)); - z3 = MULTIPLY(z3, - FIX(0.785694958)); - - tmp0 += z3; - tmp1 = z2 + z5; - tmp2 += z3; - tmp3 = z1 + z5; - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ - z1 = d7 + d1; - z5 = MULTIPLY(z1, FIX(1.175875602)); - - z1 = MULTIPLY(z1, FIX(0.275899379)); - z3 = MULTIPLY(d7, - FIX(1.961570560)); - tmp0 = MULTIPLY(d7, - FIX(1.662939224)); - z4 = MULTIPLY(d1, - FIX(0.390180644)); - tmp3 = MULTIPLY(d1, FIX(1.111140466)); - - tmp0 += z1; - tmp1 = z4 + z5; - tmp2 = z3 + z5; - tmp3 += z1; - } else { - /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ - tmp0 = MULTIPLY(d7, - FIX(1.387039845)); - tmp1 = MULTIPLY(d7, FIX(1.175875602)); - tmp2 = MULTIPLY(d7, - FIX(0.785694958)); - tmp3 = MULTIPLY(d7, FIX(0.275899379)); - } - } - } - } else { - if (d5) { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ - z2 = d5 + d3; - z4 = d5 + d1; - z5 = MULTIPLY(d3 + z4, FIX(1.175875602)); - - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(d1, - FIX(0.899976223)); - z2 = MULTIPLY(z2, - FIX(2.562915447)); - z3 = MULTIPLY(d3, - FIX(1.961570560)); - z4 = MULTIPLY(z4, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 = z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ - z2 = d5 + d3; - - z5 = MULTIPLY(z2, FIX(1.175875602)); - tmp1 = MULTIPLY(d5, FIX(1.662939225)); - z4 = MULTIPLY(d5, - FIX(0.390180644)); - z2 = MULTIPLY(z2, - FIX(1.387039845)); - tmp2 = MULTIPLY(d3, FIX(1.111140466)); - z3 = MULTIPLY(d3, - FIX(1.961570560)); - - tmp0 = z3 + z5; - tmp1 += z2; - tmp2 += z2; - tmp3 = z4 + z5; - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ - z4 = d5 + d1; - - z5 = MULTIPLY(z4, FIX(1.175875602)); - z1 = MULTIPLY(d1, - FIX(0.899976223)); - tmp3 = MULTIPLY(d1, FIX(0.601344887)); - tmp1 = MULTIPLY(d5, - FIX(0.509795578)); - z2 = MULTIPLY(d5, - FIX(2.562915447)); - z4 = MULTIPLY(z4, FIX(0.785694958)); - - tmp0 = z1 + z5; - tmp1 += z4; - tmp2 = z2 + z5; - tmp3 += z4; - } else { - /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ - tmp0 = MULTIPLY(d5, FIX(1.175875602)); - tmp1 = MULTIPLY(d5, FIX(0.275899380)); - tmp2 = MULTIPLY(d5, - FIX(1.387039845)); - tmp3 = MULTIPLY(d5, FIX(0.785694958)); - } - } - } else { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ - z5 = d1 + d3; - tmp3 = MULTIPLY(d1, FIX(0.211164243)); - tmp2 = MULTIPLY(d3, - FIX(1.451774981)); - z1 = MULTIPLY(d1, FIX(1.061594337)); - z2 = MULTIPLY(d3, - FIX(2.172734803)); - z4 = MULTIPLY(z5, FIX(0.785694958)); - z5 = MULTIPLY(z5, FIX(1.175875602)); - - tmp0 = z1 - z4; - tmp1 = z2 + z4; - tmp2 += z5; - tmp3 += z5; - } else { - /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ - tmp0 = MULTIPLY(d3, - FIX(0.785694958)); - tmp1 = MULTIPLY(d3, - FIX(1.387039845)); - tmp2 = MULTIPLY(d3, - FIX(0.275899379)); - tmp3 = MULTIPLY(d3, FIX(1.175875602)); - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ - tmp0 = MULTIPLY(d1, FIX(0.275899379)); - tmp1 = MULTIPLY(d1, FIX(0.785694958)); - tmp2 = MULTIPLY(d1, FIX(1.175875602)); - tmp3 = MULTIPLY(d1, FIX(1.387039845)); - } else { - /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ - tmp0 = tmp1 = tmp2 = tmp3 = 0; - } - } - } - } - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - dataptr += DCTSIZE; /* advance pointer to next row */ - } - - /* Pass 2: process columns. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - - dataptr = data; - for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { - /* Columns of zeroes can be exploited in the same way as we did with rows. - * However, the row calculation has created many nonzero AC terms, so the - * simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - - d0 = dataptr[DCTSIZE*0]; - d1 = dataptr[DCTSIZE*1]; - d2 = dataptr[DCTSIZE*2]; - d3 = dataptr[DCTSIZE*3]; - d4 = dataptr[DCTSIZE*4]; - d5 = dataptr[DCTSIZE*5]; - d6 = dataptr[DCTSIZE*6]; - d7 = dataptr[DCTSIZE*7]; - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - if (d6) { - if (d4) { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp2 - tmp0; - tmp12 = -(tmp0 + tmp2); - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, - FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - } else { - /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, -FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp0 = SCALE (d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp2 - tmp0; - tmp12 = -(tmp0 + tmp2); - } - } - } else { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d0, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */ - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp10 = tmp3; - tmp13 = -tmp3; - tmp11 = tmp2; - tmp12 = -tmp2; - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, - FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp0 = SCALE (d0, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - } else { - /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */ - tmp2 = MULTIPLY(d6, - FIX(1.306562965)); - tmp3 = MULTIPLY(d6, FIX(0.541196100)); - - tmp10 = tmp3; - tmp13 = -tmp3; - tmp11 = tmp2; - tmp12 = -tmp2; - } - } - } - } else { - if (d4) { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp0 = SCALE (d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp2 - tmp0; - tmp12 = -(tmp0 + tmp2); - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ - tmp10 = tmp13 = SCALE (d0 + d4, CONST_BITS); - tmp11 = tmp12 = SCALE (d0 - d4, CONST_BITS); - } else { - /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */ - tmp10 = tmp13 = SCALE (d4, CONST_BITS); - tmp11 = tmp12 = -tmp10; - } - } - } else { - if (d2) { - if (d0) { - /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp0 = SCALE (d0, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - } else { - /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */ - tmp2 = MULTIPLY(d2, FIX(0.541196100)); - tmp3 = MULTIPLY(d2, FIX(1.306562965)); - - tmp10 = tmp3; - tmp13 = -tmp3; - tmp11 = tmp2; - tmp12 = -tmp2; - } - } else { - if (d0) { - /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */ - tmp10 = tmp13 = tmp11 = tmp12 = SCALE (d0, CONST_BITS); - } else { - /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */ - tmp10 = tmp13 = tmp11 = tmp12 = 0; - } - } - } - } - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - if (d7) { - if (d5) { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ - z1 = d7 + d1; - z2 = d5 + d3; - z3 = d7 + d3; - z4 = d5 + d1; - z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(z1, - FIX(0.899976223)); - z2 = MULTIPLY(z2, - FIX(2.562915447)); - z3 = MULTIPLY(z3, - FIX(1.961570560)); - z4 = MULTIPLY(z4, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ - z1 = d7; - z2 = d5 + d3; - z3 = d7 + d3; - z5 = MULTIPLY(z3 + d5, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - z1 = MULTIPLY(d7, - FIX(0.899976223)); - z2 = MULTIPLY(z2, - FIX(2.562915447)); - z3 = MULTIPLY(z3, - FIX(1.961570560)); - z4 = MULTIPLY(d5, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 = z1 + z4; - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ - z1 = d7 + d1; - z2 = d5; - z3 = d7; - z4 = d5 + d1; - z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(z1, - FIX(0.899976223)); - z2 = MULTIPLY(d5, - FIX(2.562915447)); - z3 = MULTIPLY(d7, - FIX(1.961570560)); - z4 = MULTIPLY(z4, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 = z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ - tmp0 = MULTIPLY(d7, - FIX(0.601344887)); - z1 = MULTIPLY(d7, - FIX(0.899976223)); - z3 = MULTIPLY(d7, - FIX(1.961570560)); - tmp1 = MULTIPLY(d5, - FIX(0.509795578)); - z2 = MULTIPLY(d5, - FIX(2.562915447)); - z4 = MULTIPLY(d5, - FIX(0.390180644)); - z5 = MULTIPLY(d5 + d7, FIX(1.175875602)); - - z3 += z5; - z4 += z5; - - tmp0 += z3; - tmp1 += z4; - tmp2 = z2 + z3; - tmp3 = z1 + z4; - } - } - } else { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ - z1 = d7 + d1; - z3 = d7 + d3; - z5 = MULTIPLY(z3 + d1, FIX(1.175875602)); - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(z1, - FIX(0.899976223)); - z2 = MULTIPLY(d3, - FIX(2.562915447)); - z3 = MULTIPLY(z3, - FIX(1.961570560)); - z4 = MULTIPLY(d1, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 = z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ - z3 = d7 + d3; - - tmp0 = MULTIPLY(d7, - FIX(0.601344887)); - z1 = MULTIPLY(d7, - FIX(0.899976223)); - tmp2 = MULTIPLY(d3, FIX(0.509795579)); - z2 = MULTIPLY(d3, - FIX(2.562915447)); - z5 = MULTIPLY(z3, FIX(1.175875602)); - z3 = MULTIPLY(z3, - FIX(0.785694958)); - - tmp0 += z3; - tmp1 = z2 + z5; - tmp2 += z3; - tmp3 = z1 + z5; - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ - z1 = d7 + d1; - z5 = MULTIPLY(z1, FIX(1.175875602)); - - z1 = MULTIPLY(z1, FIX(0.275899379)); - z3 = MULTIPLY(d7, - FIX(1.961570560)); - tmp0 = MULTIPLY(d7, - FIX(1.662939224)); - z4 = MULTIPLY(d1, - FIX(0.390180644)); - tmp3 = MULTIPLY(d1, FIX(1.111140466)); - - tmp0 += z1; - tmp1 = z4 + z5; - tmp2 = z3 + z5; - tmp3 += z1; - } else { - /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ - tmp0 = MULTIPLY(d7, - FIX(1.387039845)); - tmp1 = MULTIPLY(d7, FIX(1.175875602)); - tmp2 = MULTIPLY(d7, - FIX(0.785694958)); - tmp3 = MULTIPLY(d7, FIX(0.275899379)); - } - } - } - } else { - if (d5) { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ - z2 = d5 + d3; - z4 = d5 + d1; - z5 = MULTIPLY(d3 + z4, FIX(1.175875602)); - - tmp1 = MULTIPLY(d5, FIX(2.053119869)); - tmp2 = MULTIPLY(d3, FIX(3.072711026)); - tmp3 = MULTIPLY(d1, FIX(1.501321110)); - z1 = MULTIPLY(d1, - FIX(0.899976223)); - z2 = MULTIPLY(z2, - FIX(2.562915447)); - z3 = MULTIPLY(d3, - FIX(1.961570560)); - z4 = MULTIPLY(z4, - FIX(0.390180644)); - - z3 += z5; - z4 += z5; - - tmp0 = z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - } else { - /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ - z2 = d5 + d3; - - z5 = MULTIPLY(z2, FIX(1.175875602)); - tmp1 = MULTIPLY(d5, FIX(1.662939225)); - z4 = MULTIPLY(d5, - FIX(0.390180644)); - z2 = MULTIPLY(z2, - FIX(1.387039845)); - tmp2 = MULTIPLY(d3, FIX(1.111140466)); - z3 = MULTIPLY(d3, - FIX(1.961570560)); - - tmp0 = z3 + z5; - tmp1 += z2; - tmp2 += z2; - tmp3 = z4 + z5; - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ - z4 = d5 + d1; - - z5 = MULTIPLY(z4, FIX(1.175875602)); - z1 = MULTIPLY(d1, - FIX(0.899976223)); - tmp3 = MULTIPLY(d1, FIX(0.601344887)); - tmp1 = MULTIPLY(d5, - FIX(0.509795578)); - z2 = MULTIPLY(d5, - FIX(2.562915447)); - z4 = MULTIPLY(z4, FIX(0.785694958)); - - tmp0 = z1 + z5; - tmp1 += z4; - tmp2 = z2 + z5; - tmp3 += z4; - } else { - /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ - tmp0 = MULTIPLY(d5, FIX(1.175875602)); - tmp1 = MULTIPLY(d5, FIX(0.275899380)); - tmp2 = MULTIPLY(d5, - FIX(1.387039845)); - tmp3 = MULTIPLY(d5, FIX(0.785694958)); - } - } - } else { - if (d3) { - if (d1) { - /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ - z5 = d1 + d3; - tmp3 = MULTIPLY(d1, FIX(0.211164243)); - tmp2 = MULTIPLY(d3, - FIX(1.451774981)); - z1 = MULTIPLY(d1, FIX(1.061594337)); - z2 = MULTIPLY(d3, - FIX(2.172734803)); - z4 = MULTIPLY(z5, FIX(0.785694958)); - z5 = MULTIPLY(z5, FIX(1.175875602)); - - tmp0 = z1 - z4; - tmp1 = z2 + z4; - tmp2 += z5; - tmp3 += z5; - } else { - /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ - tmp0 = MULTIPLY(d3, - FIX(0.785694958)); - tmp1 = MULTIPLY(d3, - FIX(1.387039845)); - tmp2 = MULTIPLY(d3, - FIX(0.275899379)); - tmp3 = MULTIPLY(d3, FIX(1.175875602)); - } - } else { - if (d1) { - /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ - tmp0 = MULTIPLY(d1, FIX(0.275899379)); - tmp1 = MULTIPLY(d1, FIX(0.785694958)); - tmp2 = MULTIPLY(d1, FIX(1.175875602)); - tmp3 = MULTIPLY(d1, FIX(1.387039845)); - } else { - /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ - tmp0 = tmp1 = tmp2 = tmp3 = 0; - } - } - } - } - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3); - dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3); - - dataptr++; /* advance pointer to next column */ - } -} - -#else - -/*---- debugging/tracing macros ----*/ - -#if _MSC_VER -#pragma optimize("",on) -#if _MSC_VER > 700 -/*#pragma optimize("l",off)*/ -#endif -#endif - -#define idct_single_pos0() -#define idct_zero_col_stat() -#define idct_zero_row_stat() -#define idct_nonzero_col_stat() -#define idct_nonzero_row_stat() -#define DUMP_COEFS(p) -#define TRACE(args) -#define FAST_DCTPTRS 1 - -#if 0 /* to count cases */ -void idct_single_pos0 (void) { static int count; count++; } -void idct_zero_col_stat (void) { static int count; count++; } -void idct_zero_row_stat (void) { static int count; count++; } -void idct_nonzero_col_stat (void) { static int count; count++; } -void idct_nonzero_row_stat (void) { static int count; count++; } -#undef idct_single_pos0 -#undef idct_zero_col_stat -#undef idct_zero_row_stat -#undef idct_nonzero_col_stat -#undef idct_nonzero_row_stat -#endif - -void init_pre_idct (void) { } - -void j_rev_dct_sparse (DCTBLOCK data, int pos) -{ - /* If just DC Coefficient. */ - - if (pos == 0) { - register DCTELEM *dp, *dq; - DCTELEM dcval; - - idct_single_pos0(); - - dp = data; - dcval = dp[0]; - if (dcval < 0) - dcval = (short)((dcval - 3) >> 3); - else - dcval = (short)((dcval + 4) >> 3); - - if (dcval) { - for (dq = dp + 64; dp < dq; dp += 8) { - dp[3] = dp[2] = dp[1] = dp[0] = dcval; - dp[7] = dp[6] = dp[5] = dp[4] = dcval; - } - } - return; - } - - /* Some other coeff */ - j_rev_dct (data); -} - -#ifndef OPTIMIZE_ASM -void j_rev_dct (DCTBLOCK data) -{ - INT32 tmp0, tmp1, tmp2, tmp3; - INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; - register DCTELEM *dp; - int rowctr; - SHIFT_TEMPS; - - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - - DUMP_COEFS(data); - - dp = data; - for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--, dp += DCTSIZE) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any row in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * row DCT calculations can be simplified this way. - */ - -#if FAST_DCTPTRS -#define d0 dp[0] -#define d1 dp[1] -#define d2 dp[2] -#define d3 dp[3] -#define d4 dp[4] -#define d5 dp[5] -#define d6 dp[6] -#define d7 dp[7] -#else - int d0 = dp[0]; - int d1 = dp[1]; - int d2 = dp[2]; - int d3 = dp[3]; - int d4 = dp[4]; - int d5 = dp[5]; - int d6 = dp[6]; - int d7 = dp[7]; -#endif - -#ifndef NO_ZERO_ROW_TEST - if ((d1 | d2 | d3 | d4 | d5 | d6 | d7) == 0) { - /* AC terms all zero */ - DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS); - - if (d0) { - dp[0] = dcval; - dp[1] = dcval; - dp[2] = dcval; - dp[3] = dcval; - dp[4] = dcval; - dp[5] = dcval; - dp[6] = dcval; - dp[7] = dcval; - } - idct_zero_row_stat(); - continue; - } -#endif - - idct_nonzero_row_stat(); - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - z1 = d7 + d1; - z2 = d5 + d3; - z3 = d7 + d3; - z4 = d5 + d1; - z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */ - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(d5, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(d3, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(d1, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - dp[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - dp[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - dp[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - dp[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - dp[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - dp[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - dp[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - dp[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - } -#if FAST_DCTPTRS -#undef d0 -#undef d1 -#undef d2 -#undef d3 -#undef d4 -#undef d5 -#undef d6 -#undef d7 -#endif - - /* Pass 2: process columns. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - - dp = data; - for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--, dp++) { - /* Columns of zeroes can be exploited in the same way as we did with rows. - * However, the row calculation has created many nonzero AC terms, so the - * simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#if FAST_DCTPTRS -#define d0 dp[DCTSIZE*0] -#define d1 dp[DCTSIZE*1] -#define d2 dp[DCTSIZE*2] -#define d3 dp[DCTSIZE*3] -#define d4 dp[DCTSIZE*4] -#define d5 dp[DCTSIZE*5] -#define d6 dp[DCTSIZE*6] -#define d7 dp[DCTSIZE*7] -#else - int d0 = dp[DCTSIZE*0]; - int d1 = dp[DCTSIZE*1]; - int d2 = dp[DCTSIZE*2]; - int d3 = dp[DCTSIZE*3]; - int d4 = dp[DCTSIZE*4]; - int d5 = dp[DCTSIZE*5]; - int d6 = dp[DCTSIZE*6]; - int d7 = dp[DCTSIZE*7]; -#endif - -#ifndef NO_ZERO_COLUMN_TEST - if ((d1 | d2 | d3 | d4 | d5 | d6 | d7) == 0) { - /* AC terms all zero */ - DCTELEM dcval = (DCTELEM) DESCALE((INT32) d0, PASS1_BITS+3); - - if (d0) { - dp[DCTSIZE*0] = dcval; - dp[DCTSIZE*1] = dcval; - dp[DCTSIZE*2] = dcval; - dp[DCTSIZE*3] = dcval; - dp[DCTSIZE*4] = dcval; - dp[DCTSIZE*5] = dcval; - dp[DCTSIZE*6] = dcval; - dp[DCTSIZE*7] = dcval; - } - idct_zero_col_stat(); - continue; - } -#endif - - idct_nonzero_col_stat(); - - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z1 = MULTIPLY(d2 + d6, FIX(0.541196100)); - tmp2 = z1 + MULTIPLY(d6, - FIX(1.847759065)); - tmp3 = z1 + MULTIPLY(d2, FIX(0.765366865)); - - tmp0 = SCALE (d0 + d4, CONST_BITS); - tmp1 = SCALE (d0 - d4, CONST_BITS); - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ - - z1 = d7 + d1; - z2 = d5 + d3; - z3 = d7 + d3; - z4 = d5 + d1; - z5 = MULTIPLY(z3 + z4, FIX(1.175875602)); /* sqrt(2) * c3 */ - - tmp0 = MULTIPLY(d7, FIX(0.298631336)); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(d5, FIX(2.053119869)); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(d3, FIX(3.072711026)); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(d1, FIX(1.501321110)); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX(0.899976223)); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX(2.562915447)); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX(1.961570560)); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX(0.390180644)); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - dp[DCTSIZE*0] = (DCTELEM)DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*7] = (DCTELEM)DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*1] = (DCTELEM)DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*6] = (DCTELEM)DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*2] = (DCTELEM)DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*5] = (DCTELEM)DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*3] = (DCTELEM)DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3); - dp[DCTSIZE*4] = (DCTELEM)DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3); - } -#if FAST_DCTPTRS -#undef d0 -#undef d1 -#undef d2 -#undef d3 -#undef d4 -#undef d5 -#undef d6 -#undef d7 -#endif -} -#endif /* optimize.asm */ - -#endif diff --git a/libav/mjpegenc.c b/libav/mjpegenc.c deleted file mode 100644 index 027287528c..0000000000 --- a/libav/mjpegenc.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * MJPEG encoder - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include "avcodec.h" -#include "mpegvideo.h" - -typedef struct MJpegContext { - UINT8 huff_size_dc_luminance[12]; - UINT16 huff_code_dc_luminance[12]; - UINT8 huff_size_dc_chrominance[12]; - UINT16 huff_code_dc_chrominance[12]; - - UINT8 huff_size_ac_luminance[256]; - UINT16 huff_code_ac_luminance[256]; - UINT8 huff_size_ac_chrominance[256]; - UINT16 huff_code_ac_chrominance[256]; -} MJpegContext; - -#define SOF0 0xc0 -#define SOI 0xd8 -#define EOI 0xd9 -#define DQT 0xdb -#define DHT 0xc4 -#define SOS 0xda - -#if 0 -/* These are the sample quantization tables given in JPEG spec section K.1. - * The spec says that the values given produce "good" quality, and - * when divided by 2, "very good" quality. - */ -static const unsigned char std_luminance_quant_tbl[64] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 -}; -static const unsigned char std_chrominance_quant_tbl[64] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 -}; -#endif - -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ -static const UINT8 bits_dc_luminance[17] = -{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; -static const UINT8 val_dc_luminance[] = -{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - -static const UINT8 bits_dc_chrominance[17] = -{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; -static const UINT8 val_dc_chrominance[] = -{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - -static const UINT8 bits_ac_luminance[17] = -{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; -static const UINT8 val_ac_luminance[] = -{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - -static const UINT8 bits_ac_chrominance[17] = -{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; - -static const UINT8 val_ac_chrominance[] = -{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - - -/* isn't this function nicer than the one in the libjpeg ? */ -static void build_huffman_codes(UINT8 *huff_size, UINT16 *huff_code, - const UINT8 *bits_table, const UINT8 *val_table) -{ - int i, j, k,nb, code, sym; - - code = 0; - k = 0; - for(i=1;i<=16;i++) { - nb = bits_table[i]; - for(j=0;jhuff_size_dc_luminance, - m->huff_code_dc_luminance, - bits_dc_luminance, - val_dc_luminance); - build_huffman_codes(m->huff_size_dc_chrominance, - m->huff_code_dc_chrominance, - bits_dc_chrominance, - val_dc_chrominance); - build_huffman_codes(m->huff_size_ac_luminance, - m->huff_code_ac_luminance, - bits_ac_luminance, - val_ac_luminance); - build_huffman_codes(m->huff_size_ac_chrominance, - m->huff_code_ac_chrominance, - bits_ac_chrominance, - val_ac_chrominance); - - s->mjpeg_ctx = m; - return 0; -} - -void mjpeg_close(MpegEncContext *s) -{ - free(s->mjpeg_ctx); -} - -static inline void put_marker(PutBitContext *p, int code) -{ - put_bits(p, 8, 0xff); - put_bits(p, 8, code); -} - -/* table_class: 0 = DC coef, 1 = AC coefs */ -static int put_huffman_table(MpegEncContext *s, int table_class, int table_id, - const UINT8 *bits_table, const UINT8 *value_table) -{ - PutBitContext *p = &s->pb; - int n, i; - - put_bits(p, 4, table_class); - put_bits(p, 4, table_id); - - n = 0; - for(i=1;i<=16;i++) { - n += bits_table[i]; - put_bits(p, 8, bits_table[i]); - } - - for(i=0;ipb; - int i, size; - UINT8 *ptr; - - /* quant matrixes */ - put_marker(p, DQT); - put_bits(p, 16, 2 + 1 * (1 + 64)); - put_bits(p, 4, 0); /* 8 bit precision */ - put_bits(p, 4, 0); /* table 0 */ - for(i=0;i<64;i++) { - put_bits(p, 8, s->init_intra_matrix[i]); - } -#if 0 - put_bits(p, 4, 0); /* 8 bit precision */ - put_bits(p, 4, 1); /* table 1 */ - for(i=0;i<64;i++) { - put_bits(p, 8, m->chrominance_matrix[i]); - } -#endif - - /* huffman table */ - put_marker(p, DHT); - flush_put_bits(p); - ptr = p->buf_ptr; - put_bits(p, 16, 0); /* patched later */ - size = 2; - size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance); - size += put_huffman_table(s, 0, 1, bits_dc_chrominance, val_dc_chrominance); - - size += put_huffman_table(s, 1, 0, bits_ac_luminance, val_ac_luminance); - size += put_huffman_table(s, 1, 1, bits_ac_chrominance, val_ac_chrominance); - ptr[0] = size >> 8; - ptr[1] = size; -} - -void mjpeg_picture_header(MpegEncContext *s) -{ - put_marker(&s->pb, SOI); - - jpeg_table_header(s); - - put_marker(&s->pb, SOF0); - - put_bits(&s->pb, 16, 17); - put_bits(&s->pb, 8, 8); /* 8 bits/component */ - put_bits(&s->pb, 16, s->height); - put_bits(&s->pb, 16, s->width); - put_bits(&s->pb, 8, 3); /* 3 components */ - - /* Y component */ - put_bits(&s->pb, 8, 1); /* component number */ - put_bits(&s->pb, 4, 2); /* H factor */ - put_bits(&s->pb, 4, 2); /* V factor */ - put_bits(&s->pb, 8, 0); /* select matrix */ - - /* Cb component */ - put_bits(&s->pb, 8, 2); /* component number */ - put_bits(&s->pb, 4, 1); /* H factor */ - put_bits(&s->pb, 4, 1); /* V factor */ - put_bits(&s->pb, 8, 0); /* select matrix */ - - /* Cr component */ - put_bits(&s->pb, 8, 3); /* component number */ - put_bits(&s->pb, 4, 1); /* H factor */ - put_bits(&s->pb, 4, 1); /* V factor */ - put_bits(&s->pb, 8, 0); /* select matrix */ - - /* scan header */ - put_marker(&s->pb, SOS); - put_bits(&s->pb, 16, 12); /* length */ - put_bits(&s->pb, 8, 3); /* 3 components */ - - /* Y component */ - put_bits(&s->pb, 8, 1); /* index */ - put_bits(&s->pb, 4, 0); /* DC huffman table index */ - put_bits(&s->pb, 4, 0); /* AC huffman table index */ - - /* Cb component */ - put_bits(&s->pb, 8, 2); /* index */ - put_bits(&s->pb, 4, 1); /* DC huffman table index */ - put_bits(&s->pb, 4, 1); /* AC huffman table index */ - - /* Cr component */ - put_bits(&s->pb, 8, 3); /* index */ - put_bits(&s->pb, 4, 1); /* DC huffman table index */ - put_bits(&s->pb, 4, 1); /* AC huffman table index */ - - put_bits(&s->pb, 8, 0); /* Ss (not used) */ - put_bits(&s->pb, 8, 63); /* Se (not used) */ - put_bits(&s->pb, 8, 0); /* (not used) */ -} - -void mjpeg_picture_trailer(MpegEncContext *s) -{ - jflush_put_bits(&s->pb); - put_marker(&s->pb, EOI); -} - -static inline void encode_dc(MpegEncContext *s, int val, - UINT8 *huff_size, UINT16 *huff_code) -{ - int mant, nbits; - - if (val == 0) { - jput_bits(&s->pb, huff_size[0], huff_code[0]); - } else { - mant = val; - if (val < 0) { - val = -val; - mant--; - } - - /* compute the log (XXX: optimize) */ - nbits = 0; - while (val != 0) { - val = val >> 1; - nbits++; - } - - jput_bits(&s->pb, huff_size[nbits], huff_code[nbits]); - - jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); - } -} - -static void encode_block(MpegEncContext *s, DCTELEM *block, int n) -{ - int mant, nbits, code, i, j; - int component, dc, run, last_index, val; - MJpegContext *m = s->mjpeg_ctx; - UINT8 *huff_size_ac; - UINT16 *huff_code_ac; - - /* DC coef */ - component = (n <= 3 ? 0 : n - 4 + 1); - dc = block[0]; /* overflow is impossible */ - val = dc - s->last_dc[component]; - if (n < 4) { - encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance); - huff_size_ac = m->huff_size_ac_luminance; - huff_code_ac = m->huff_code_ac_luminance; - } else { - encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); - huff_size_ac = m->huff_size_ac_chrominance; - huff_code_ac = m->huff_code_ac_chrominance; - } - s->last_dc[component] = dc; - - /* AC coefs */ - - run = 0; - last_index = s->block_last_index[n]; - for(i=1;i<=last_index;i++) { - j = zigzag_direct[i]; - val = block[j]; - if (val == 0) { - run++; - } else { - while (run >= 16) { - jput_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]); - run -= 16; - } - mant = val; - if (val < 0) { - val = -val; - mant--; - } - - /* compute the log (XXX: optimize) */ - nbits = 0; - while (val != 0) { - val = val >> 1; - nbits++; - } - code = (run << 4) | nbits; - - jput_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]); - - jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); - run = 0; - } - } - - /* output EOB only if not already 64 values */ - if (last_index < 63 || run != 0) - jput_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); -} - -void mjpeg_encode_mb(MpegEncContext *s, - DCTELEM block[6][64]) -{ - int i; - for(i=0;i<6;i++) { - encode_block(s, block[i], i); - } -} diff --git a/libav/mpegaudio.c b/libav/mpegaudio.c deleted file mode 100644 index 50ffc3c200..0000000000 --- a/libav/mpegaudio.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * The simplest mpeg audio layer 2 encoder - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include "avcodec.h" -#include "mpegaudio.h" - -#define NDEBUG -#include - -/* define it to use floats in quantization (I don't like floats !) */ -//#define USE_FLOATS - -#define MPA_STEREO 0 -#define MPA_JSTEREO 1 -#define MPA_DUAL 2 -#define MPA_MONO 3 - -#include "mpegaudiotab.h" - -int MPA_encode_init(AVEncodeContext *avctx) -{ - MpegAudioContext *s = avctx->priv_data; - int freq = avctx->rate; - int bitrate = avctx->bit_rate; - int channels = avctx->channels; - int i, v, table; - float a; - - if (channels != 1) - return -1; - - bitrate = bitrate / 1000; - s->freq = freq; - s->bit_rate = bitrate * 1000; - avctx->frame_size = MPA_FRAME_SIZE; - avctx->key_frame = 1; /* always key frame */ - - /* encoding freq */ - s->lsf = 0; - for(i=0;i<3;i++) { - if (freq_tab[i] == freq) - break; - if ((freq_tab[i] / 2) == freq) { - s->lsf = 1; - break; - } - } - if (i == 3) - return -1; - s->freq_index = i; - - /* encoding bitrate & frequency */ - for(i=0;i<15;i++) { - if (bitrate_tab[1-s->lsf][i] == bitrate) - break; - } - if (i == 15) - return -1; - s->bitrate_index = i; - - /* compute total header size & pad bit */ - - a = (float)(bitrate * 1000 * MPA_FRAME_SIZE) / (freq * 8.0); - s->frame_size = ((int)a) * 8; - - /* frame fractional size to compute padding */ - s->frame_frac = 0; - s->frame_frac_incr = (int)((a - floor(a)) * 65536.0); - - /* select the right allocation table */ - if (!s->lsf) { - if ((freq == 48000 && bitrate >= 56) || - (bitrate >= 56 && bitrate <= 80)) - table = 0; - else if (freq != 48000 && bitrate >= 96) - table = 1; - else if (freq != 32000 && bitrate <= 48) - table = 2; - else - table = 3; - } else { - table = 4; - } - /* number of used subbands */ - s->sblimit = sblimit_table[table]; - s->alloc_table = alloc_tables[table]; - -#ifdef DEBUG - printf("%d kb/s, %d Hz, frame_size=%d bits, table=%d, padincr=%x\n", - bitrate, freq, s->frame_size, table, s->frame_frac_incr); -#endif - - s->samples_offset = 0; - - for(i=0;i<512;i++) { - float a = enwindow[i] * 32768.0 * 16.0; - filter_bank[i] = (int)(a); - } - for(i=0;i<64;i++) { - v = (int)(pow(2.0, (3 - i) / 3.0) * (1 << 20)); - if (v <= 0) - v = 1; - scale_factor_table[i] = v; -#ifdef USE_FLOATS - scale_factor_inv_table[i] = pow(2.0, -(3 - i) / 3.0) / (float)(1 << 20); -#else -#define P 15 - scale_factor_shift[i] = 21 - P - (i / 3); - scale_factor_mult[i] = (1 << P) * pow(2.0, (i % 3) / 3.0); -#endif - } - for(i=0;i<128;i++) { - v = i - 64; - if (v <= -3) - v = 0; - else if (v < 0) - v = 1; - else if (v == 0) - v = 2; - else if (v < 3) - v = 3; - else - v = 4; - scale_diff_table[i] = v; - } - - for(i=0;i<17;i++) { - v = quant_bits[i]; - if (v < 0) - v = -v; - else - v = v * 3; - total_quant_bits[i] = 12 * v; - } - - return 0; -} - -/* 32 point floating point IDCT */ -static void idct32(int *out, int *tab, int sblimit, int left_shift) -{ - int i, j; - int *t, *t1, xr; - const int *xp = costab32; - - for(j=31;j>=3;j-=2) tab[j] += tab[j - 2]; - - t = tab + 30; - t1 = tab + 2; - do { - t[0] += t[-4]; - t[1] += t[1 - 4]; - t -= 4; - } while (t != t1); - - t = tab + 28; - t1 = tab + 4; - do { - t[0] += t[-8]; - t[1] += t[1-8]; - t[2] += t[2-8]; - t[3] += t[3-8]; - t -= 8; - } while (t != t1); - - t = tab; - t1 = tab + 32; - do { - t[ 3] = -t[ 3]; - t[ 6] = -t[ 6]; - - t[11] = -t[11]; - t[12] = -t[12]; - t[13] = -t[13]; - t[15] = -t[15]; - t += 16; - } while (t != t1); - - - t = tab; - t1 = tab + 8; - do { - int x1, x2, x3, x4; - - x3 = MUL(t[16], FIX(SQRT2*0.5)); - x4 = t[0] - x3; - x3 = t[0] + x3; - - x2 = MUL(-(t[24] + t[8]), FIX(SQRT2*0.5)); - x1 = MUL((t[8] - x2), xp[0]); - x2 = MUL((t[8] + x2), xp[1]); - - t[ 0] = x3 + x1; - t[ 8] = x4 - x2; - t[16] = x4 + x2; - t[24] = x3 - x1; - t++; - } while (t != t1); - - xp += 2; - t = tab; - t1 = tab + 4; - do { - xr = MUL(t[28],xp[0]); - t[28] = (t[0] - xr); - t[0] = (t[0] + xr); - - xr = MUL(t[4],xp[1]); - t[ 4] = (t[24] - xr); - t[24] = (t[24] + xr); - - xr = MUL(t[20],xp[2]); - t[20] = (t[8] - xr); - t[ 8] = (t[8] + xr); - - xr = MUL(t[12],xp[3]); - t[12] = (t[16] - xr); - t[16] = (t[16] + xr); - t++; - } while (t != t1); - xp += 4; - - for (i = 0; i < 4; i++) { - xr = MUL(tab[30-i*4],xp[0]); - tab[30-i*4] = (tab[i*4] - xr); - tab[ i*4] = (tab[i*4] + xr); - - xr = MUL(tab[ 2+i*4],xp[1]); - tab[ 2+i*4] = (tab[28-i*4] - xr); - tab[28-i*4] = (tab[28-i*4] + xr); - - xr = MUL(tab[31-i*4],xp[0]); - tab[31-i*4] = (tab[1+i*4] - xr); - tab[ 1+i*4] = (tab[1+i*4] + xr); - - xr = MUL(tab[ 3+i*4],xp[1]); - tab[ 3+i*4] = (tab[29-i*4] - xr); - tab[29-i*4] = (tab[29-i*4] + xr); - - xp += 2; - } - - t = tab + 30; - t1 = tab + 1; - do { - xr = MUL(t1[0], *xp); - t1[0] = (t[0] - xr); - t[0] = (t[0] + xr); - t -= 2; - t1 += 2; - xp++; - } while (t >= tab); - - for(i=0;i<32;i++) { - out[i] = tab[bitinv32[i]] << left_shift; - } -} - -static void filter(MpegAudioContext *s, short *samples) -{ - short *p, *q; - int sum, offset, i, j, norm, n; - short tmp[64]; - int tmp1[32]; - int *out; - - // print_pow1(samples, 1152); - - offset = s->samples_offset; - out = &s->sb_samples[0][0][0]; - for(j=0;j<36;j++) { - /* 32 samples at once */ - for(i=0;i<32;i++) - s->samples_buf[offset + (31 - i)] = samples[i]; - - /* filter */ - p = s->samples_buf + offset; - q = filter_bank; - /* maxsum = 23169 */ - for(i=0;i<64;i++) { - sum = p[0*64] * q[0*64]; - sum += p[1*64] * q[1*64]; - sum += p[2*64] * q[2*64]; - sum += p[3*64] * q[3*64]; - sum += p[4*64] * q[4*64]; - sum += p[5*64] * q[5*64]; - sum += p[6*64] * q[6*64]; - sum += p[7*64] * q[7*64]; - tmp[i] = sum >> 14; - p++; - q++; - } - tmp1[0] = tmp[16]; - for( i=1; i<=16; i++ ) tmp1[i] = tmp[i+16]+tmp[16-i]; - for( i=17; i<=31; i++ ) tmp1[i] = tmp[i+16]-tmp[80-i]; - - /* integer IDCT 32 with normalization. XXX: There may be some - overflow left */ - norm = 0; - for(i=0;i<32;i++) { - norm |= abs(tmp1[i]); - } - n = log2(norm) - 12; - if (n > 0) { - for(i=0;i<32;i++) - tmp1[i] >>= n; - } else { - n = 0; - } - - idct32(out, tmp1, s->sblimit, n); - - /* advance of 32 samples */ - samples += 32; - offset -= 32; - out += 32; - /* handle the wrap around */ - if (offset < 0) { - memmove(s->samples_buf + SAMPLES_BUF_SIZE - (512 - 32), - s->samples_buf, (512 - 32) * 2); - offset = SAMPLES_BUF_SIZE - 512; - } - } - s->samples_offset = offset; - - // print_pow(s->sb_samples, 1152); -} - -static void compute_scale_factors(unsigned char scale_code[SBLIMIT], - unsigned char scale_factors[SBLIMIT][3], - int sb_samples[3][12][SBLIMIT], - int sblimit) -{ - int *p, vmax, v, n, i, j, k, code; - int index, d1, d2; - unsigned char *sf = &scale_factors[0][0]; - - for(j=0;j vmax) - vmax = v; - } - /* compute the scale factor index using log 2 computations */ - if (vmax > 0) { - n = log2(vmax); - /* n is the position of the MSB of vmax. now - use at most 2 compares to find the index */ - index = (21 - n) * 3 - 3; - if (index >= 0) { - while (vmax <= scale_factor_table[index+1]) - index++; - } else { - index = 0; /* very unlikely case of overflow */ - } - } else { - index = 63; - } - -#if 0 - printf("%2d:%d in=%x %x %d\n", - j, i, vmax, scale_factor_table[index], index); -#endif - /* store the scale factor */ - assert(index >=0 && index <= 63); - sf[i] = index; - } - - /* compute the transmission factor : look if the scale factors - are close enough to each other */ - d1 = scale_diff_table[sf[0] - sf[1] + 64]; - d2 = scale_diff_table[sf[1] - sf[2] + 64]; - - /* handle the 25 cases */ - switch(d1 * 5 + d2) { - case 0*5+0: - case 0*5+4: - case 3*5+4: - case 4*5+0: - case 4*5+4: - code = 0; - break; - case 0*5+1: - case 0*5+2: - case 4*5+1: - case 4*5+2: - code = 3; - sf[2] = sf[1]; - break; - case 0*5+3: - case 4*5+3: - code = 3; - sf[1] = sf[2]; - break; - case 1*5+0: - case 1*5+4: - case 2*5+4: - code = 1; - sf[1] = sf[0]; - break; - case 1*5+1: - case 1*5+2: - case 2*5+0: - case 2*5+1: - case 2*5+2: - code = 2; - sf[1] = sf[2] = sf[0]; - break; - case 2*5+3: - case 3*5+3: - code = 2; - sf[0] = sf[1] = sf[2]; - break; - case 3*5+0: - case 3*5+1: - case 3*5+2: - code = 2; - sf[0] = sf[2] = sf[1]; - break; - case 1*5+3: - code = 2; - if (sf[0] > sf[2]) - sf[0] = sf[2]; - sf[1] = sf[2] = sf[0]; - break; - default: - abort(); - } - -#if 0 - printf("%d: %2d %2d %2d %d %d -> %d\n", j, - sf[0], sf[1], sf[2], d1, d2, code); -#endif - scale_code[j] = code; - sf += 3; - } -} - -/* The most important function : psycho acoustic module. In this - encoder there is basically none, so this is the worst you can do, - but also this is the simpler. */ -static void psycho_acoustic_model(MpegAudioContext *s, short smr[SBLIMIT]) -{ - int i; - - for(i=0;isblimit;i++) { - smr[i] = (int)(fixed_smr[i] * 10); - } -} - - -#define SB_NOTALLOCATED 0 -#define SB_ALLOCATED 1 -#define SB_NOMORE 2 - -/* Try to maximize the smr while using a number of bits inferior to - the frame size. I tried to make the code simpler, faster and - smaller than other encoders :-) */ -static void compute_bit_allocation(MpegAudioContext *s, - short smr1[SBLIMIT], - unsigned char bit_alloc[SBLIMIT], - int *padding) -{ - int i, b, max_smr, max_sb, current_frame_size, max_frame_size; - int incr; - short smr[SBLIMIT]; - unsigned char subband_status[SBLIMIT]; - const unsigned char *alloc; - - memcpy(smr, smr1, sizeof(short) * s->sblimit); - memset(subband_status, SB_NOTALLOCATED, s->sblimit); - memset(bit_alloc, 0, s->sblimit); - - /* compute frame size and padding */ - max_frame_size = s->frame_size; - s->frame_frac += s->frame_frac_incr; - if (s->frame_frac >= 65536) { - s->frame_frac -= 65536; - s->do_padding = 1; - max_frame_size += 8; - } else { - s->do_padding = 0; - } - - /* compute the header + bit alloc size */ - current_frame_size = 32; - alloc = s->alloc_table; - for(i=0;isblimit;i++) { - incr = alloc[0]; - current_frame_size += incr; - alloc += 1 << incr; - } - for(;;) { - /* look for the subband with the largest signal to mask ratio */ - max_sb = -1; - max_smr = 0x80000000; - for(i=0;isblimit;i++) { - if (smr[i] > max_smr && subband_status[i] != SB_NOMORE) { - max_smr = smr[i]; - max_sb = i; - } - } -#if 0 - printf("current=%d max=%d max_sb=%d alloc=%d\n", - current_frame_size, max_frame_size, max_sb, - bit_alloc[max_sb]); -#endif - if (max_sb < 0) - break; - - /* find alloc table entry (XXX: not optimal, should use - pointer table) */ - alloc = s->alloc_table; - for(i=0;iscale_code[max_sb]] * 6; - incr += total_quant_bits[alloc[1]]; - } else { - /* increments bit allocation */ - b = bit_alloc[max_sb]; - incr = total_quant_bits[alloc[b + 1]] - - total_quant_bits[alloc[b]]; - } - - if (current_frame_size + incr <= max_frame_size) { - /* can increase size */ - b = ++bit_alloc[max_sb]; - current_frame_size += incr; - /* decrease smr by the resolution we added */ - smr[max_sb] = smr1[max_sb] - quant_snr[alloc[b]]; - /* max allocation size reached ? */ - if (b == ((1 << alloc[0]) - 1)) - subband_status[max_sb] = SB_NOMORE; - else - subband_status[max_sb] = SB_ALLOCATED; - } else { - /* cannot increase the size of this subband */ - subband_status[max_sb] = SB_NOMORE; - } - } - *padding = max_frame_size - current_frame_size; - assert(*padding >= 0); - -#if 0 - for(i=0;isblimit;i++) { - printf("%d ", bit_alloc[i]); - } - printf("\n"); -#endif -} - -/* - * Output the mpeg audio layer 2 frame. Note how the code is small - * compared to other encoders :-) - */ -static void encode_frame(MpegAudioContext *s, - unsigned char bit_alloc[SBLIMIT], - int padding) -{ - int i, j, k, l, bit_alloc_bits, b; - unsigned char *sf; - int q[3]; - PutBitContext *p = &s->pb; - - /* header */ - - put_bits(p, 12, 0xfff); - put_bits(p, 1, 1 - s->lsf); /* 1 = mpeg1 ID, 0 = mpeg2 lsf ID */ - put_bits(p, 2, 4-2); /* layer 2 */ - put_bits(p, 1, 1); /* no error protection */ - put_bits(p, 4, s->bitrate_index); - put_bits(p, 2, s->freq_index); - put_bits(p, 1, s->do_padding); /* use padding */ - put_bits(p, 1, 0); /* private_bit */ - put_bits(p, 2, MPA_MONO); - put_bits(p, 2, 0); /* mode_ext */ - put_bits(p, 1, 0); /* no copyright */ - put_bits(p, 1, 1); /* original */ - put_bits(p, 2, 0); /* no emphasis */ - - /* bit allocation */ - j = 0; - for(i=0;isblimit;i++) { - bit_alloc_bits = s->alloc_table[j]; - put_bits(p, bit_alloc_bits, bit_alloc[i]); - j += 1 << bit_alloc_bits; - } - - /* scale codes */ - for(i=0;isblimit;i++) { - if (bit_alloc[i]) - put_bits(p, 2, s->scale_code[i]); - } - - /* scale factors */ - sf = &s->scale_factors[0][0]; - for(i=0;isblimit;i++) { - if (bit_alloc[i]) { - switch(s->scale_code[i]) { - case 0: - put_bits(p, 6, sf[0]); - put_bits(p, 6, sf[1]); - put_bits(p, 6, sf[2]); - break; - case 3: - case 1: - put_bits(p, 6, sf[0]); - put_bits(p, 6, sf[2]); - break; - case 2: - put_bits(p, 6, sf[0]); - break; - } - } - sf += 3; - } - - /* quantization & write sub band samples */ - - for(k=0;k<3;k++) { - for(l=0;l<12;l+=3) { - j = 0; - for(i=0;isblimit;i++) { - bit_alloc_bits = s->alloc_table[j]; - b = bit_alloc[i]; - if (b) { - int qindex, steps, m, sample, bits; - /* we encode 3 sub band samples of the same sub band at a time */ - qindex = s->alloc_table[j+b]; - steps = quant_steps[qindex]; - for(m=0;m<3;m++) { - sample = s->sb_samples[k][l + m][i]; - /* divide by scale factor */ -#ifdef USE_FLOATS - { - float a; - a = (float)sample * scale_factor_inv_table[s->scale_factors[i][k]]; - q[m] = (int)((a + 1.0) * steps * 0.5); - } -#else - { - int q1, e, shift, mult; - e = s->scale_factors[i][k]; - shift = scale_factor_shift[e]; - mult = scale_factor_mult[e]; - - /* normalize to P bits */ - if (shift < 0) - q1 = sample << (-shift); - else - q1 = sample >> shift; - q1 = (q1 * mult) >> P; - q[m] = ((q1 + (1 << P)) * steps) >> (P + 1); - } -#endif - if (q[m] >= steps) - q[m] = steps - 1; - assert(q[m] >= 0 && q[m] < steps); - } - bits = quant_bits[qindex]; - if (bits < 0) { - /* group the 3 values to save bits */ - put_bits(p, -bits, - q[0] + steps * (q[1] + steps * q[2])); -#if 0 - printf("%d: gr1 %d\n", - i, q[0] + steps * (q[1] + steps * q[2])); -#endif - } else { -#if 0 - printf("%d: gr3 %d %d %d\n", - i, q[0], q[1], q[2]); -#endif - put_bits(p, bits, q[0]); - put_bits(p, bits, q[1]); - put_bits(p, bits, q[2]); - } - } - /* next subband in alloc table */ - j += 1 << bit_alloc_bits; - } - } - } - - /* padding */ - for(i=0;ipriv_data; - short *samples = data; - short smr[SBLIMIT]; - unsigned char bit_alloc[SBLIMIT]; - int padding; - - filter(s, samples); - compute_scale_factors(s->scale_code, s->scale_factors, - s->sb_samples, s->sblimit); - psycho_acoustic_model(s, smr); - compute_bit_allocation(s, smr, bit_alloc, &padding); - - init_put_bits(&s->pb, frame, MPA_MAX_CODED_FRAME_SIZE, NULL, NULL); - - encode_frame(s, bit_alloc, padding); - - s->nb_samples += MPA_FRAME_SIZE; - return s->pb.buf_ptr - s->pb.buf; -} - - -AVEncoder mp2_encoder = { - "mp2", - CODEC_TYPE_AUDIO, - CODEC_ID_MP2, - sizeof(MpegAudioContext), - MPA_encode_init, - MPA_encode_frame, - NULL, -}; diff --git a/libav/mpegaudio.h b/libav/mpegaudio.h deleted file mode 100644 index 0734d3466b..0000000000 --- a/libav/mpegaudio.h +++ /dev/null @@ -1,31 +0,0 @@ - -/* max compressed frame size */ -#define MPA_MAX_CODED_FRAME_SIZE 1200 - -#define MPA_FRAME_SIZE 1152 - -#define SAMPLES_BUF_SIZE 4096 -#define SBLIMIT 32 /* number of subbands */ -#define DCT_BITS 14 /* number of bits for the DCT */ -#define MUL(a,b) (((a) * (b)) >> DCT_BITS) -#define FIX(a) ((int)((a) * (1 << DCT_BITS))) - -typedef struct MpegAudioContext { - PutBitContext pb; - int freq, bit_rate; - int lsf; /* 1 if mpeg2 low bitrate selected */ - int bitrate_index; /* bit rate */ - int freq_index; - int frame_size; /* frame size, in bits, without padding */ - long long nb_samples; /* total number of samples encoded */ - /* padding computation */ - int frame_frac, frame_frac_incr, do_padding; - short samples_buf[SAMPLES_BUF_SIZE]; /* buffer for filter */ - int samples_offset; /* offset in samples_buf */ - int sb_samples[3][12][SBLIMIT]; - unsigned char scale_factors[SBLIMIT][3]; /* scale factors */ - unsigned char scale_code[SBLIMIT]; /* code to group 3 scale factors */ - int sblimit; /* number of used subbands */ - const unsigned char *alloc_table; -} MpegAudioContext; - diff --git a/libav/mpegaudiotab.h b/libav/mpegaudiotab.h deleted file mode 100644 index 05bdb9eea1..0000000000 --- a/libav/mpegaudiotab.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * mpeg audio layer 2 tables. Most of them come from the mpeg audio - * specification. - * - * Copyright (c) 2000 Gerard Lantau. - * - * The licence of this code is contained in file LICENCE found in the - * same archive - */ - -static const unsigned short bitrate_tab[2][15] = { - {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}, /* mpeg2 lsf */ - {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384}, /* mpeg1 */ -}; - -static const unsigned short freq_tab[3] = { 44100, 48000, 32000 }; - -#define SQRT2 1.41421356237309514547 - -static const int costab32[30] = { - FIX(0.54119610014619701222), - FIX(1.3065629648763763537), - - FIX(0.50979557910415917998), - FIX(2.5629154477415054814), - FIX(0.89997622313641556513), - FIX(0.60134488693504528634), - - FIX(0.5024192861881556782), - FIX(5.1011486186891552563), - FIX(0.78815462345125020249), - FIX(0.64682178335999007679), - FIX(0.56694403481635768927), - FIX(1.0606776859903470633), - FIX(1.7224470982383341955), - FIX(0.52249861493968885462), - - FIX(10.19000812354803287), - FIX(0.674808341455005678), - FIX(1.1694399334328846596), - FIX(0.53104259108978413284), - FIX(2.0577810099534108446), - FIX(0.58293496820613388554), - FIX(0.83934964541552681272), - FIX(0.50547095989754364798), - FIX(3.4076084184687189804), - FIX(0.62250412303566482475), - FIX(0.97256823786196078263), - FIX(0.51544730992262455249), - FIX(1.4841646163141661852), - FIX(0.5531038960344445421), - FIX(0.74453627100229857749), - FIX(0.5006029982351962726), -}; - -static const int bitinv32[32] = { - 0, 16, 8, 24, 4, 20, 12, 28, - 2, 18, 10, 26, 6, 22, 14, 30, - 1, 17, 9, 25, 5, 21, 13, 29, - 3, 19, 11, 27, 7, 23, 15, 31 -}; - - -static short filter_bank[512]; - -static const double enwindow[512] = {0.000000000, - -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000477, -0.000000954, -0.000000954, - -0.000000954, -0.000000954, -0.000001431, -0.000001431, -0.000001907, -0.000001907, -0.000002384, -0.000002384, - -0.000002861, -0.000003338, -0.000003338, -0.000003815, -0.000004292, -0.000004768, -0.000005245, -0.000006199, - -0.000006676, -0.000007629, -0.000008106, -0.000009060, -0.000010014, -0.000011444, -0.000012398, -0.000013828, - -0.000014782, -0.000016689, -0.000018120, -0.000019550, -0.000021458, -0.000023365, -0.000025272, -0.000027657, - -0.000030041, -0.000032425, -0.000034809, -0.000037670, -0.000040531, -0.000043392, -0.000046253, -0.000049591, - -0.000052929, -0.000055790, -0.000059605, -0.000062943, -0.000066280, -0.000070095, -0.000073433, -0.000076771, - -0.000080585, -0.000083923, -0.000087261, -0.000090599, -0.000093460, -0.000096321, -0.000099182, 0.000101566, - 0.000103951, 0.000105858, 0.000107288, 0.000108242, 0.000108719, 0.000108719, 0.000108242, 0.000106812, - 0.000105381, 0.000102520, 0.000099182, 0.000095367, 0.000090122, 0.000084400, 0.000077724, 0.000069618, - 0.000060558, 0.000050545, 0.000039577, 0.000027180, 0.000013828, -0.000000954, -0.000017166, -0.000034332, - -0.000052929, -0.000072956, -0.000093937, -0.000116348, -0.000140190, -0.000165462, -0.000191212, -0.000218868, - -0.000247478, -0.000277042, -0.000307560, -0.000339031, -0.000371456, -0.000404358, -0.000438213, -0.000472546, - -0.000507355, -0.000542164, -0.000576973, -0.000611782, -0.000646591, -0.000680923, -0.000714302, -0.000747204, - -0.000779152, -0.000809669, -0.000838757, -0.000866413, -0.000891685, -0.000915051, -0.000935555, -0.000954151, - -0.000968933, -0.000980854, -0.000989437, -0.000994205, -0.000995159, -0.000991821, -0.000983715, 0.000971317, - 0.000953674, 0.000930786, 0.000902653, 0.000868797, 0.000829220, 0.000783920, 0.000731945, 0.000674248, - 0.000610352, 0.000539303, 0.000462532, 0.000378609, 0.000288486, 0.000191689, 0.000088215, -0.000021458, - -0.000137329, -0.000259876, -0.000388145, -0.000522137, -0.000661850, -0.000806808, -0.000956535, -0.001111031, - -0.001269817, -0.001432419, -0.001597881, -0.001766682, -0.001937389, -0.002110004, -0.002283096, -0.002457142, - -0.002630711, -0.002803326, -0.002974033, -0.003141880, -0.003306866, -0.003467083, -0.003622532, -0.003771782, - -0.003914356, -0.004048824, -0.004174709, -0.004290581, -0.004395962, -0.004489899, -0.004570484, -0.004638195, - -0.004691124, -0.004728317, -0.004748821, -0.004752159, -0.004737377, -0.004703045, -0.004649162, -0.004573822, - -0.004477024, -0.004357815, -0.004215240, -0.004049301, -0.003858566, -0.003643036, -0.003401756, 0.003134727, - 0.002841473, 0.002521515, 0.002174854, 0.001800537, 0.001399517, 0.000971317, 0.000515938, 0.000033379, - -0.000475883, -0.001011848, -0.001573563, -0.002161503, -0.002774239, -0.003411293, -0.004072189, -0.004756451, - -0.005462170, -0.006189346, -0.006937027, -0.007703304, -0.008487225, -0.009287834, -0.010103703, -0.010933399, - -0.011775017, -0.012627602, -0.013489246, -0.014358521, -0.015233517, -0.016112804, -0.016994476, -0.017876148, - -0.018756866, -0.019634247, -0.020506859, -0.021372318, -0.022228718, -0.023074150, -0.023907185, -0.024725437, - -0.025527000, -0.026310921, -0.027073860, -0.027815342, -0.028532982, -0.029224873, -0.029890060, -0.030526638, - -0.031132698, -0.031706810, -0.032248020, -0.032754898, -0.033225536, -0.033659935, -0.034055710, -0.034412861, - -0.034730434, -0.035007000, -0.035242081, -0.035435200, -0.035586357, -0.035694122, -0.035758972, 0.035780907, - 0.035758972, 0.035694122, 0.035586357, 0.035435200, 0.035242081, 0.035007000, 0.034730434, 0.034412861, - 0.034055710, 0.033659935, 0.033225536, 0.032754898, 0.032248020, 0.031706810, 0.031132698, 0.030526638, - 0.029890060, 0.029224873, 0.028532982, 0.027815342, 0.027073860, 0.026310921, 0.025527000, 0.024725437, - 0.023907185, 0.023074150, 0.022228718, 0.021372318, 0.020506859, 0.019634247, 0.018756866, 0.017876148, - 0.016994476, 0.016112804, 0.015233517, 0.014358521, 0.013489246, 0.012627602, 0.011775017, 0.010933399, - 0.010103703, 0.009287834, 0.008487225, 0.007703304, 0.006937027, 0.006189346, 0.005462170, 0.004756451, - 0.004072189, 0.003411293, 0.002774239, 0.002161503, 0.001573563, 0.001011848, 0.000475883, -0.000033379, - -0.000515938, -0.000971317, -0.001399517, -0.001800537, -0.002174854, -0.002521515, -0.002841473, 0.003134727, - 0.003401756, 0.003643036, 0.003858566, 0.004049301, 0.004215240, 0.004357815, 0.004477024, 0.004573822, - 0.004649162, 0.004703045, 0.004737377, 0.004752159, 0.004748821, 0.004728317, 0.004691124, 0.004638195, - 0.004570484, 0.004489899, 0.004395962, 0.004290581, 0.004174709, 0.004048824, 0.003914356, 0.003771782, - 0.003622532, 0.003467083, 0.003306866, 0.003141880, 0.002974033, 0.002803326, 0.002630711, 0.002457142, - 0.002283096, 0.002110004, 0.001937389, 0.001766682, 0.001597881, 0.001432419, 0.001269817, 0.001111031, - 0.000956535, 0.000806808, 0.000661850, 0.000522137, 0.000388145, 0.000259876, 0.000137329, 0.000021458, - -0.000088215, -0.000191689, -0.000288486, -0.000378609, -0.000462532, -0.000539303, -0.000610352, -0.000674248, - -0.000731945, -0.000783920, -0.000829220, -0.000868797, -0.000902653, -0.000930786, -0.000953674, 0.000971317, - 0.000983715, 0.000991821, 0.000995159, 0.000994205, 0.000989437, 0.000980854, 0.000968933, 0.000954151, - 0.000935555, 0.000915051, 0.000891685, 0.000866413, 0.000838757, 0.000809669, 0.000779152, 0.000747204, - 0.000714302, 0.000680923, 0.000646591, 0.000611782, 0.000576973, 0.000542164, 0.000507355, 0.000472546, - 0.000438213, 0.000404358, 0.000371456, 0.000339031, 0.000307560, 0.000277042, 0.000247478, 0.000218868, - 0.000191212, 0.000165462, 0.000140190, 0.000116348, 0.000093937, 0.000072956, 0.000052929, 0.000034332, - 0.000017166, 0.000000954, -0.000013828, -0.000027180, -0.000039577, -0.000050545, -0.000060558, -0.000069618, - -0.000077724, -0.000084400, -0.000090122, -0.000095367, -0.000099182, -0.000102520, -0.000105381, -0.000106812, - -0.000108242, -0.000108719, -0.000108719, -0.000108242, -0.000107288, -0.000105858, -0.000103951, 0.000101566, - 0.000099182, 0.000096321, 0.000093460, 0.000090599, 0.000087261, 0.000083923, 0.000080585, 0.000076771, - 0.000073433, 0.000070095, 0.000066280, 0.000062943, 0.000059605, 0.000055790, 0.000052929, 0.000049591, - 0.000046253, 0.000043392, 0.000040531, 0.000037670, 0.000034809, 0.000032425, 0.000030041, 0.000027657, - 0.000025272, 0.000023365, 0.000021458, 0.000019550, 0.000018120, 0.000016689, 0.000014782, 0.000013828, - 0.000012398, 0.000011444, 0.000010014, 0.000009060, 0.000008106, 0.000007629, 0.000006676, 0.000006199, - 0.000005245, 0.000004768, 0.000004292, 0.000003815, 0.000003338, 0.000003338, 0.000002861, 0.000002384, - 0.000002384, 0.000001907, 0.000001907, 0.000001431, 0.000001431, 0.000000954, 0.000000954, 0.000000954, - 0.000000954, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477, 0.000000477 - }; - -static int scale_factor_table[64]; -#ifdef USE_FLOATS -static float scale_factor_inv_table[64]; -#else -static INT8 scale_factor_shift[64]; -static unsigned short scale_factor_mult[64]; -#endif -static unsigned char scale_diff_table[128]; - -static const int sblimit_table[5] = { 27 , 30 , 8, 12 , 30 }; - -static const int quant_steps[17] = { - 3, 5, 7, 9, 15, - 31, 63, 127, 255, 511, - 1023, 2047, 4095, 8191, 16383, - 32767, 65535 -}; - -/* we use a negative value if grouped */ -static const int quant_bits[17] = { - -5, -7, 3, -10, 4, - 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, - 15, 16 -}; - -/* signal to noise ratio of each quantification step (could be - computed from quant_steps[]). The values are dB multiplied by 10 -*/ -static unsigned short quant_snr[17] = { - 70, 110, 160, 208, - 253, 316, 378, 439, - 499, 559, 620, 680, - 740, 800, 861, 920, - 980 -}; - - -/* total number of bits per allocation group */ -static unsigned short total_quant_bits[17]; - -/* encoding tables which give the quantization index. Note how it is - possible to store them efficiently ! */ -static const unsigned char alloc_table_0[] = { - 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, -}; - -static const unsigned char alloc_table_1[] = { - 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 3, 0, 1, 2, 3, 4, 5, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, - 2, 0, 1, 16, -}; - -static const unsigned char alloc_table_2[] = { - 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, -}; - -static const unsigned char alloc_table_3[] = { - 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, -}; - -static const unsigned char alloc_table_4[] = { - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 3, 0, 1, 3, 4, 5, 6, 7, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, - 2, 0, 1, 3, -}; - -const unsigned char *alloc_tables[5] = -{ alloc_table_0, alloc_table_1, alloc_table_2, alloc_table_3, alloc_table_4, }; - -/* fixed psycho acoustic model. Values of SNR taken from the 'toolame' - project */ -const float fixed_smr[SBLIMIT] = { - 30, 17, 16, 10, 3, 12, 8, 2.5, - 5, 5, 6, 6, 5, 6, 10, 6, - -4, -10, -21, -30, -42, -55, -68, -75, - -75, -75, -75, -75, -91, -107, -110, -108 -}; - -const unsigned char nb_scale_factors[4] = { 3, 2, 1, 2 }; diff --git a/libav/mpegencodevlc.h b/libav/mpegencodevlc.h deleted file mode 100644 index 3952fd0472..0000000000 --- a/libav/mpegencodevlc.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * RV 1.0 compatible encoder. - * Copyright (c) 2000 Gerard Lantau. - * - * The licence of this code is contained in file LICENCE found in the - * same archive - */ - -const unsigned char vlc_dc_table[256] = { - 0, 1, 2, 2, - 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -}; - -const unsigned char vlc_dc_lum_code[9] = { - 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e, -}; -const unsigned char vlc_dc_lum_bits[9] = { - 3, 2, 2, 3, 3, 4, 5, 6, 7, -}; - -const unsigned char vlc_dc_chroma_code[9] = { - 0x0, 0x1, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, -}; -const unsigned char vlc_dc_chroma_bits[9] = { - 2, 2, 2, 3, 4, 5, 6, 7, 8, -}; - -/* - * Copyright (c) 1995 The Regents of the University of California. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose, without fee, and without written agreement is - * hereby granted, provided that the above copyright notice and the following - * two paragraphs appear in all copies of this software. - * - * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT - * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF - * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#define HUFF_MAXRUN 32 -#define HUFF_MAXLEVEL 41 - -static const int huff_maxlevel[HUFF_MAXRUN] = { 41, 19, 6, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; - -static const UINT8 huff_table0[41] = { 0x0, 0x6, 0x8, 0xa, 0xc, 0x4c, 0x42, 0x14, 0x3a, 0x30, 0x26, 0x20, 0x34, 0x32, 0x30, 0x2e, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20 }; -static const UINT8 huff_bits0[41] = { 0, 3, 5, 6, 8, 9, 9, 11, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; - -static const UINT8 huff_table1[19] = { 0x0, 0x6, 0xc, 0x4a, 0x18, 0x36, 0x2c, 0x2a, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x26, 0x24, 0x22, 0x20 }; -static const UINT8 huff_bits1[19] = { 0, 4, 7, 9, 11, 13, 14, 14, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17 }; - -static const UINT8 huff_table2[6] = { 0x0, 0xa, 0x8, 0x16, 0x28, 0x28 }; -static const UINT8 huff_bits2[6] = { 0, 5, 8, 11, 13, 14 }; - -static const UINT8 huff_table3[5] = { 0x0, 0xe, 0x48, 0x38, 0x26 }; -static const UINT8 huff_bits3[5] = { 0, 6, 9, 13, 14 }; - -static const UINT8 huff_table4[4] = { 0x0, 0xc, 0x1e, 0x24 }; -static const UINT8 huff_bits4[4] = { 0, 6, 11, 13 }; - -static const UINT8 huff_table5[4] = { 0x0, 0xe, 0x12, 0x24 }; -static const UINT8 huff_bits5[4] = { 0, 7, 11, 14 }; - -static const UINT8 huff_table6[4] = { 0x0, 0xa, 0x3c, 0x28 }; -static const UINT8 huff_bits6[4] = { 0, 7, 13, 17 }; - -static const UINT8 huff_table7[3] = { 0x0, 0x8, 0x2a }; -static const UINT8 huff_bits7[3] = { 0, 7, 13 }; - -static const UINT8 huff_table8[3] = { 0x0, 0xe, 0x22 }; -static const UINT8 huff_bits8[3] = { 0, 8, 13 }; - -static const UINT8 huff_table9[3] = { 0x0, 0xa, 0x22 }; -static const UINT8 huff_bits9[3] = { 0, 8, 14 }; - -static const UINT8 huff_table10[3] = { 0x0, 0x4e, 0x20 }; -static const UINT8 huff_bits10[3] = { 0, 9, 14 }; - -static const UINT8 huff_table11[3] = { 0x0, 0x46, 0x34 }; -static const UINT8 huff_bits11[3] = { 0, 9, 17 }; - -static const UINT8 huff_table12[3] = { 0x0, 0x44, 0x32 }; -static const UINT8 huff_bits12[3] = { 0, 9, 17 }; - -static const UINT8 huff_table13[3] = { 0x0, 0x40, 0x30 }; -static const UINT8 huff_bits13[3] = { 0, 9, 17 }; - -static const UINT8 huff_table14[3] = { 0x0, 0x1c, 0x2e }; -static const UINT8 huff_bits14[3] = { 0, 11, 17 }; - -static const UINT8 huff_table15[3] = { 0x0, 0x1a, 0x2c }; -static const UINT8 huff_bits15[3] = { 0, 11, 17 }; - -static const UINT8 huff_table16[3] = { 0x0, 0x10, 0x2a }; -static const UINT8 huff_bits16[3] = { 0, 11, 17 }; - -static const UINT8 huff_table17[2] = { 0x0, 0x3e }; -static const UINT8 huff_bits17[2] = { 0, 13 }; - -static const UINT8 huff_table18[2] = { 0x0, 0x34 }; -static const UINT8 huff_bits18[2] = { 0, 13 }; - -static const UINT8 huff_table19[2] = { 0x0, 0x32 }; -static const UINT8 huff_bits19[2] = { 0, 13 }; - -static const UINT8 huff_table20[2] = { 0x0, 0x2e }; -static const UINT8 huff_bits20[2] = { 0, 13 }; - -static const UINT8 huff_table21[2] = { 0x0, 0x2c }; -static const UINT8 huff_bits21[2] = { 0, 13 }; - -static const UINT8 huff_table22[2] = { 0x0, 0x3e }; -static const UINT8 huff_bits22[2] = { 0, 14 }; - -static const UINT8 huff_table23[2] = { 0x0, 0x3c }; -static const UINT8 huff_bits23[2] = { 0, 14 }; - -static const UINT8 huff_table24[2] = { 0x0, 0x3a }; -static const UINT8 huff_bits24[2] = { 0, 14 }; - -static const UINT8 huff_table25[2] = { 0x0, 0x38 }; -static const UINT8 huff_bits25[2] = { 0, 14 }; - -static const UINT8 huff_table26[2] = { 0x0, 0x36 }; -static const UINT8 huff_bits26[2] = { 0, 14 }; - -static const UINT8 huff_table27[2] = { 0x0, 0x3e }; -static const UINT8 huff_bits27[2] = { 0, 17 }; - -static const UINT8 huff_table28[2] = { 0x0, 0x3c }; -static const UINT8 huff_bits28[2] = { 0, 17 }; - -static const UINT8 huff_table29[2] = { 0x0, 0x3a }; -static const UINT8 huff_bits29[2] = { 0, 17 }; - -static const UINT8 huff_table30[2] = { 0x0, 0x38 }; -static const UINT8 huff_bits30[2] = { 0, 17 }; - -static const UINT8 huff_table31[2] = { 0x0, 0x36 }; -static const UINT8 huff_bits31[2] = { 0, 17 }; - -static const UINT8 *huff_table[32] = { huff_table0, huff_table1, huff_table2, huff_table3, huff_table4, huff_table5, huff_table6, huff_table7, huff_table8, huff_table9, huff_table10, huff_table11, huff_table12, huff_table13, huff_table14, huff_table15, huff_table16, huff_table17, huff_table18, huff_table19, huff_table20, huff_table21, huff_table22, huff_table23, huff_table24, huff_table25, huff_table26, huff_table27, huff_table28, huff_table29, huff_table30, huff_table31 }; - -static const UINT8 *huff_bits[32] = { huff_bits0, huff_bits1, huff_bits2, huff_bits3, huff_bits4, huff_bits5, huff_bits6, huff_bits7, huff_bits8, huff_bits9, huff_bits10, huff_bits11, huff_bits12, huff_bits13, huff_bits14, huff_bits15, huff_bits16, huff_bits17, huff_bits18, huff_bits19, huff_bits20, huff_bits21, huff_bits22, huff_bits23, huff_bits24, huff_bits25, huff_bits26, huff_bits27, huff_bits28, huff_bits29, huff_bits30, huff_bits31 }; - -static const UINT8 mbAddrIncrTable[][2] = { - {0x0, 0}, - {0x1, 1}, - {0x3, 3}, - {0x2, 3}, - {0x3, 4}, - {0x2, 4}, - {0x3, 5}, - {0x2, 5}, - {0x7, 7}, - {0x6, 7}, - {0xb, 8}, - {0xa, 8}, - {0x9, 8}, - {0x8, 8}, - {0x7, 8}, - {0x6, 8}, - {0x17, 10}, - {0x16, 10}, - {0x15, 10}, - {0x14, 10}, - {0x13, 10}, - {0x12, 10}, - {0x23, 11}, - {0x22, 11}, - {0x21, 11}, - {0x20, 11}, - {0x1f, 11}, - {0x1e, 11}, - {0x1d, 11}, - {0x1c, 11}, - {0x1b, 11}, - {0x1a, 11}, - {0x19, 11}, - {0x18, 11}}; - -static const UINT8 mbPatTable[][2] = { - {0x0, 0}, - {0xb, 5}, - {0x9, 5}, - {0xd, 6}, - {0xd, 4}, - {0x17, 7}, - {0x13, 7}, - {0x1f, 8}, - {0xc, 4}, - {0x16, 7}, - {0x12, 7}, - {0x1e, 8}, - {0x13, 5}, - {0x1b, 8}, - {0x17, 8}, - {0x13, 8}, - {0xb, 4}, - {0x15, 7}, - {0x11, 7}, - {0x1d, 8}, - {0x11, 5}, - {0x19, 8}, - {0x15, 8}, - {0x11, 8}, - {0xf, 6}, - {0xf, 8}, - {0xd, 8}, - {0x3, 9}, - {0xf, 5}, - {0xb, 8}, - {0x7, 8}, - {0x7, 9}, - {0xa, 4}, - {0x14, 7}, - {0x10, 7}, - {0x1c, 8}, - {0xe, 6}, - {0xe, 8}, - {0xc, 8}, - {0x2, 9}, - {0x10, 5}, - {0x18, 8}, - {0x14, 8}, - {0x10, 8}, - {0xe, 5}, - {0xa, 8}, - {0x6, 8}, - {0x6, 9}, - {0x12, 5}, - {0x1a, 8}, - {0x16, 8}, - {0x12, 8}, - {0xd, 5}, - {0x9, 8}, - {0x5, 8}, - {0x5, 9}, - {0xc, 5}, - {0x8, 8}, - {0x4, 8}, - {0x4, 9}, - {0x7, 3}, - {0xa, 5}, /* grrr... 61, 62, 63 added - Kevin */ - {0x8, 5}, - {0xc, 6} -}; - -const UINT8 zigzag_direct[64] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 -}; - -static unsigned char const default_intra_matrix[64] = { - 8, 16, 19, 22, 26, 27, 29, 34, - 16, 16, 22, 24, 27, 29, 34, 37, - 19, 22, 26, 27, 29, 34, 34, 38, - 22, 22, 26, 27, 29, 34, 37, 40, - 22, 26, 27, 29, 32, 35, 40, 48, - 26, 27, 29, 32, 35, 40, 48, 58, - 26, 27, 29, 34, 38, 46, 56, 69, - 27, 29, 35, 38, 46, 56, 69, 83 -}; - -/* XXX: could hardcode this matrix */ -static unsigned char const default_non_intra_matrix[64] = { - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, -}; - -static unsigned char const frame_rate_tab[9] = { - 0, 24, 24, 25, 30, 30, 50, 60, 60, -}; diff --git a/libav/mpegvideo.c b/libav/mpegvideo.c deleted file mode 100644 index 4987b38af4..0000000000 --- a/libav/mpegvideo.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * The simplest mpeg encoder - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include "avcodec.h" -#include "mpegvideo.h" - -//#define DEBUG - -/* depends on JPEG librarie */ -extern void jpeg_fdct_ifast (DCTELEM * data); - -/* depends on mpeg */ -extern void j_rev_dct (DCTELEM *data); - -/* for jpeg fast DCT */ -#define CONST_BITS 14 - -static const unsigned short aanscales[64] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 -}; - -static UINT8 cropTbl[256 + 2 * MAX_NEG_CROP]; -static UINT32 squareTbl[512]; - -static void encode_picture(MpegEncContext *s, int picture_number); -static void rate_control_init(MpegEncContext *s); -static int rate_estimate_qscale(MpegEncContext *s); -static void mpeg1_skip_picture(MpegEncContext *s, int pict_num); - -#include "mpegencodevlc.h" - -static void put_header(MpegEncContext *s, int header) -{ - align_put_bits(&s->pb); - put_bits(&s->pb, 32, header); -} - -static void convert_matrix(int *qmat, const UINT8 *quant_matrix, int qscale) -{ - int i; - - for(i=0;i<64;i++) { - qmat[i] = (int)((1 << 22) * 16384.0 / (aanscales[i] * qscale * quant_matrix[i])); - } -} - - -int MPV_encode_init(AVEncodeContext *avctx) -{ - MpegEncContext *s = avctx->priv_data; - int pict_size, c_size, i; - UINT8 *pict; - - s->bit_rate = avctx->bit_rate; - s->frame_rate = avctx->rate; - s->width = avctx->width; - s->height = avctx->height; - s->gop_size = avctx->gop_size; - if (s->gop_size <= 1) { - s->intra_only = 1; - s->gop_size = 12; - } else { - s->intra_only = 0; - } - - switch(avctx->codec->id) { - case CODEC_ID_MPEG1VIDEO: - s->out_format = FMT_MPEG1; - break; - case CODEC_ID_MJPEG: - s->out_format = FMT_MJPEG; - s->intra_only = 1; /* force intra only for jpeg */ - if (mjpeg_init(s) < 0) - return -1; - break; - case CODEC_ID_H263: - s->out_format = FMT_H263; - break; - case CODEC_ID_RV10: - s->out_format = FMT_H263; - s->h263_rv10 = 1; - break; - default: - return -1; - } - - switch(s->frame_rate) { - case 24: - s->frame_rate_index = 2; - break; - case 25: - s->frame_rate_index = 3; - break; - case 30: - s->frame_rate_index = 5; - break; - case 50: - s->frame_rate_index = 6; - break; - case 60: - s->frame_rate_index = 8; - break; - default: - /* we accept lower frame rates than 24 for low bit rate mpeg */ - if (s->frame_rate >= 1 && s->frame_rate < 24) { - s->frame_rate_index = 2; - } else { - return -1; - } - break; - } - - /* init */ - s->mb_width = s->width / 16; - s->mb_height = s->height / 16; - - c_size = s->width * s->height; - pict_size = (c_size * 3) / 2; - pict = malloc(pict_size); - if (pict == NULL) - return -1; - s->last_picture[0] = pict; - s->last_picture[1] = pict + c_size; - s->last_picture[2] = pict + c_size + (c_size / 4); - - pict = malloc(pict_size); - if (pict == NULL) - return -1; - s->last_picture[0] = pict; - s->last_picture[1] = pict + c_size; - s->last_picture[2] = pict + c_size + (c_size / 4); - - pict = malloc(pict_size); - if (pict == NULL) { - free(s->last_picture[0]); - return -1; - } - s->current_picture[0] = pict; - s->current_picture[1] = pict + c_size; - s->current_picture[2] = pict + c_size + (c_size / 4); - - for(i=0;i<256;i++) cropTbl[i + MAX_NEG_CROP] = i; - for(i=0;ipicture_number = 0; - s->fake_picture_number = 0; - - return 0; -} - -int MPV_encode_end(AVEncodeContext *avctx) -{ - MpegEncContext *s = avctx->priv_data; -#if 0 - /* end of sequence */ - if (s->out_format == FMT_MPEG1) { - put_header(s, SEQ_END_CODE); - } - - if (!s->flush_frames) - flush_put_bits(&s->pb); -#endif - free(s->last_picture[0]); - free(s->current_picture[0]); - if (s->out_format == FMT_MJPEG) - mjpeg_close(s); - return 0; -} - -int MPV_encode_picture(AVEncodeContext *avctx, - unsigned char *buf, int buf_size, void *data) -{ - MpegEncContext *s = avctx->priv_data; - int i; - - memcpy(s->new_picture, data, 3 * sizeof(UINT8 *)); - - init_put_bits(&s->pb, buf, buf_size, NULL, NULL); - - /* group of picture */ - if (s->out_format == FMT_MPEG1) { - unsigned int vbv_buffer_size; - unsigned int time_code, fps, n; - - if ((s->picture_number % s->gop_size) == 0) { - /* mpeg1 header repeated every gop */ - put_header(s, SEQ_START_CODE); - - put_bits(&s->pb, 12, s->width); - put_bits(&s->pb, 12, s->height); - put_bits(&s->pb, 4, 1); /* 1/1 aspect ratio */ - put_bits(&s->pb, 4, s->frame_rate_index); - put_bits(&s->pb, 18, 0x3ffff); - put_bits(&s->pb, 1, 1); /* marker */ - /* vbv buffer size: slightly greater than an I frame. We add - some margin just in case */ - vbv_buffer_size = (3 * s->I_frame_bits) / (2 * 8); - put_bits(&s->pb, 10, (vbv_buffer_size + 16383) / 16384); - put_bits(&s->pb, 1, 1); /* constrained parameter flag */ - put_bits(&s->pb, 1, 0); /* no custom intra matrix */ - put_bits(&s->pb, 1, 0); /* no custom non intra matrix */ - - put_header(s, GOP_START_CODE); - put_bits(&s->pb, 1, 0); /* do drop frame */ - /* time code : we must convert from the real frame rate to a - fake mpeg frame rate in case of low frame rate */ - fps = frame_rate_tab[s->frame_rate_index]; - time_code = s->fake_picture_number; - s->gop_picture_number = time_code; - put_bits(&s->pb, 5, (time_code / (fps * 3600)) % 24); - put_bits(&s->pb, 6, (time_code / (fps * 60)) % 60); - put_bits(&s->pb, 1, 1); - put_bits(&s->pb, 6, (time_code / fps) % 60); - put_bits(&s->pb, 6, (time_code % fps)); - put_bits(&s->pb, 1, 1); /* closed gop */ - put_bits(&s->pb, 1, 0); /* broken link */ - } - - if (s->frame_rate < 24 && s->picture_number > 0) { - /* insert empty P pictures to slow down to the desired - frame rate. Each fake pictures takes about 20 bytes */ - fps = frame_rate_tab[s->frame_rate_index]; - n = ((s->picture_number * fps) / s->frame_rate) - 1; - while (s->fake_picture_number < n) { - mpeg1_skip_picture(s, s->fake_picture_number - - s->gop_picture_number); - s->fake_picture_number++; - } - - } - s->fake_picture_number++; - } - - - if (!s->intra_only) { - /* first picture of GOP is intra */ - if ((s->picture_number % s->gop_size) == 0) - s->pict_type = I_TYPE; - else - s->pict_type = P_TYPE; - } else { - s->pict_type = I_TYPE; - } - avctx->key_frame = (s->pict_type == I_TYPE); - - encode_picture(s, s->picture_number); - - /* swap current and last picture */ - for(i=0;i<3;i++) { - UINT8 *tmp; - - tmp = s->last_picture[i]; - s->last_picture[i] = s->current_picture[i]; - s->current_picture[i] = tmp; - } - s->picture_number++; - - if (s->out_format == FMT_MJPEG) - mjpeg_picture_trailer(s); - - flush_put_bits(&s->pb); - s->total_bits += (s->pb.buf_ptr - s->pb.buf) * 8; - return s->pb.buf_ptr - s->pb.buf; -} - -/* insert a fake P picture */ -static void mpeg1_skip_picture(MpegEncContext *s, int pict_num) -{ - unsigned int mb_incr; - - /* mpeg1 picture header */ - put_header(s, PICTURE_START_CODE); - /* temporal reference */ - put_bits(&s->pb, 10, pict_num & 0x3ff); - - put_bits(&s->pb, 3, P_TYPE); - put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */ - - put_bits(&s->pb, 1, 1); /* integer coordinates */ - put_bits(&s->pb, 3, 1); /* forward_f_code */ - - put_bits(&s->pb, 1, 0); /* extra bit picture */ - - /* only one slice */ - put_header(s, SLICE_MIN_START_CODE); - put_bits(&s->pb, 5, 1); /* quantizer scale */ - put_bits(&s->pb, 1, 0); /* slice extra information */ - - mb_incr = 1; - put_bits(&s->pb, mbAddrIncrTable[mb_incr][1], - mbAddrIncrTable[mb_incr][0]); - - /* empty macroblock */ - put_bits(&s->pb, 3, 1); /* motion only */ - - /* zero motion x & y */ - put_bits(&s->pb, 1, 1); - put_bits(&s->pb, 1, 1); - - /* output a number of empty slice */ - mb_incr = s->mb_width * s->mb_height - 1; - while (mb_incr > 33) { - put_bits(&s->pb, 11, 0x008); - mb_incr -= 33; - } - put_bits(&s->pb, mbAddrIncrTable[mb_incr][1], - mbAddrIncrTable[mb_incr][0]); - - /* empty macroblock */ - put_bits(&s->pb, 3, 1); /* motion only */ - - /* zero motion x & y */ - put_bits(&s->pb, 1, 1); - put_bits(&s->pb, 1, 1); -} - -static int pix_sum(UINT8 *pix, int line_size) -{ - int s, i, j; - - s = 0; - for(i=0;i<16;i++) { - for(j=0;j<16;j+=8) { - s += pix[0]; - s += pix[1]; - s += pix[2]; - s += pix[3]; - s += pix[4]; - s += pix[5]; - s += pix[6]; - s += pix[7]; - pix += 8; - } - pix += line_size - 16; - } - return s; -} - -static int pix_norm1(UINT8 *pix, int line_size) -{ - int s, i, j; - UINT32 *sq = squareTbl + 256; - - s = 0; - for(i=0;i<16;i++) { - for(j=0;j<16;j+=8) { - s += sq[pix[0]]; - s += sq[pix[1]]; - s += sq[pix[2]]; - s += sq[pix[3]]; - s += sq[pix[4]]; - s += sq[pix[5]]; - s += sq[pix[6]]; - s += sq[pix[7]]; - pix += 8; - } - pix += line_size - 16; - } - return s; -} - -static int pix_norm(UINT8 *pix1, UINT8 *pix2, int line_size) -{ - int s, i, j; - UINT32 *sq = squareTbl + 256; - - s = 0; - for(i=0;i<16;i++) { - for(j=0;j<16;j+=8) { - s += sq[pix1[0] - pix2[0]]; - s += sq[pix1[1] - pix2[1]]; - s += sq[pix1[2] - pix2[2]]; - s += sq[pix1[3] - pix2[3]]; - s += sq[pix1[4] - pix2[4]]; - s += sq[pix1[5] - pix2[5]]; - s += sq[pix1[6] - pix2[6]]; - s += sq[pix1[7] - pix2[7]]; - pix1 += 8; - pix2 += 8; - } - pix1 += line_size - 16; - pix2 += line_size - 16; - } - return s; -} - - -static int estimate_motion(MpegEncContext *s, - int mb_x, int mb_y, - int *mx_ptr, int *my_ptr) -{ - UINT8 *pix, *ppix; - int sum, varc, vard; - - pix = s->new_picture[0] + (mb_y * 16 * s->width) + mb_x * 16; - ppix = s->last_picture[0] + (mb_y * 16 * s->width) + mb_x * 16; - - sum = pix_sum(pix, s->width); - varc = pix_norm1(pix, s->width); - vard = pix_norm(pix, ppix, s->width); - - vard = vard >> 8; - sum = sum >> 8; - varc = (varc >> 8) - sum * sum; - - *mx_ptr = 0; - *my_ptr = 0; - if (vard <= 64) { - return 0; - } else if (vard < varc) { - return 0; - } else { - return 1; - } -} - -static void get_pixels(DCTELEM *block, const UINT8 *pixels, int line_size); -static void put_pixels(const DCTELEM *block, UINT8 *pixels, int line_size); -static void sub_pixels(DCTELEM *block, const UINT8 *pixels, int line_size); -static void add_pixels(DCTELEM *block, const UINT8 *pixels, int line_size); -static int dct_quantize(MpegEncContext *s, DCTELEM *block, int qscale); -static void encode_block(MpegEncContext *s, - DCTELEM *block, - int component); -static void dct_unquantize(MpegEncContext *s, DCTELEM *block, int qscale); -static void mpeg1_encode_mb(MpegEncContext *s, int mb_x, int mb_y, - DCTELEM block[6][64], - int motion_x, int motion_y); - -static void encode_picture(MpegEncContext *s, int picture_number) -{ - int mb_x, mb_y; - UINT8 *ptr; - DCTELEM block[6][64]; - int i, motion_x, motion_y; - - s->picture_number = picture_number; - s->qscale = rate_estimate_qscale(s); - - /* precompute matrix */ - if (s->out_format == FMT_MJPEG) { - /* for mjpeg, we do include qscale in the matrix */ - s->init_intra_matrix[0] = default_intra_matrix[0]; - for(i=1;i<64;i++) - s->init_intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3; - convert_matrix(s->intra_matrix, s->init_intra_matrix, 8); - } else { - convert_matrix(s->intra_matrix, default_intra_matrix, s->qscale); - convert_matrix(s->non_intra_matrix, default_non_intra_matrix, s->qscale); - } - - switch(s->out_format) { - case FMT_MJPEG: - mjpeg_picture_header(s); - break; - case FMT_H263: - if (s->h263_rv10) - rv10_encode_picture_header(s, picture_number); - else - h263_picture_header(s, picture_number); - break; - case FMT_MPEG1: - /* mpeg1 picture header */ - put_header(s, PICTURE_START_CODE); - /* temporal reference */ - put_bits(&s->pb, 10, (s->fake_picture_number - - s->gop_picture_number) & 0x3ff); - - put_bits(&s->pb, 3, s->pict_type); - put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */ - - if (s->pict_type == P_TYPE) { - put_bits(&s->pb, 1, 1); /* integer coordinates */ - put_bits(&s->pb, 3, 1); /* forward_f_code */ - } - - put_bits(&s->pb, 1, 0); /* extra bit picture */ - - /* only one slice */ - put_header(s, SLICE_MIN_START_CODE); - put_bits(&s->pb, 5, s->qscale); /* quantizer scale */ - put_bits(&s->pb, 1, 0); /* slice extra information */ - break; - } - - /* init last dc values */ - /* XXX: quant matrix value is implied here */ - s->last_dc[0] = 128; - s->last_dc[1] = 128; - s->last_dc[2] = 128; - s->mb_incr = 1; - - for(mb_y=0; mb_y < s->mb_height; mb_y++) { - for(mb_x=0; mb_x < s->mb_width; mb_x++) { - /* compute motion vector and macro block type (intra or non intra) */ - motion_x = 0; - motion_y = 0; - if (s->pict_type == P_TYPE) { - s->mb_intra = estimate_motion(s, mb_x, mb_y, - &motion_x, - &motion_y); - } else { - s->mb_intra = 1; - } - - /* reset intra predictors if non intra mb */ - if (!s->mb_intra) { - s->last_dc[0] = 128; - s->last_dc[1] = 128; - s->last_dc[2] = 128; - } - - /* get the pixels */ - ptr = s->new_picture[0] + (mb_y * 16 * s->width) + mb_x * 16; - get_pixels(block[0], ptr, s->width); - get_pixels(block[1], ptr + 8, s->width); - get_pixels(block[2], ptr + 8 * s->width, s->width); - get_pixels(block[3], ptr + 8 * s->width + 8, s->width); - ptr = s->new_picture[1] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8; - get_pixels(block[4],ptr, s->width >> 1); - - ptr = s->new_picture[2] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8; - get_pixels(block[5],ptr, s->width >> 1); - - /* subtract previous frame if non intra */ - if (!s->mb_intra) { - ptr = s->last_picture[0] + - ((mb_y * 16 + motion_y) * s->width) + (mb_x * 16 + motion_x); - - sub_pixels(block[0], ptr, s->width); - sub_pixels(block[1], ptr + 8, s->width); - sub_pixels(block[2], ptr + s->width * 8, s->width); - sub_pixels(block[3], ptr + 8 + s->width * 8, s->width); - ptr = s->last_picture[1] + - ((mb_y * 8 + (motion_y >> 1)) * (s->width >> 1)) + - (mb_x * 8 + (motion_x >> 1)); - sub_pixels(block[4], ptr, s->width >> 1); - ptr = s->last_picture[2] + - ((mb_y * 8 + (motion_y >> 1)) * (s->width >> 1)) + - (mb_x * 8 + (motion_x >> 1)); - sub_pixels(block[5], ptr, s->width >> 1); - } - - /* DCT & quantize */ - for(i=0;i<6;i++) { - int last_index; - last_index = dct_quantize(s, block[i], s->qscale); - s->block_last_index[i] = last_index; - } - - /* huffman encode */ - switch(s->out_format) { - case FMT_MPEG1: - mpeg1_encode_mb(s, mb_x, mb_y, block, motion_x, motion_y); - break; - case FMT_H263: - h263_encode_mb(s, block, motion_x, motion_y); - break; - case FMT_MJPEG: - mjpeg_encode_mb(s, block); - break; - } - - /* decompress blocks so that we keep the state of the decoder */ - if (!s->intra_only) { - for(i=0;i<6;i++) { - if (s->block_last_index[i] >= 0) { - dct_unquantize(s, block[i], s->qscale); - } - } - - if (!s->mb_intra) { - ptr = s->last_picture[0] + - ((mb_y * 16 + motion_y) * s->width) + (mb_x * 16 + motion_x); - - add_pixels(block[0], ptr, s->width); - add_pixels(block[1], ptr + 8, s->width); - add_pixels(block[2], ptr + s->width * 8, s->width); - add_pixels(block[3], ptr + 8 + s->width * 8, s->width); - ptr = s->last_picture[1] + - ((mb_y * 8 + (motion_y >> 1)) * (s->width >> 1)) + - (mb_x * 8 + (motion_x >> 1)); - add_pixels(block[4], ptr, s->width >> 1); - ptr = s->last_picture[2] + - ((mb_y * 8 + (motion_y >> 1)) * (s->width >> 1)) + - (mb_x * 8 + (motion_x >> 1)); - add_pixels(block[5], ptr, s->width >> 1); - } - - /* write the pixels */ - ptr = s->current_picture[0] + (mb_y * 16 * s->width) + mb_x * 16; - put_pixels(block[0], ptr, s->width); - put_pixels(block[1], ptr + 8, s->width); - put_pixels(block[2], ptr + 8 * s->width, s->width); - put_pixels(block[3], ptr + 8 * s->width + 8, s->width); - ptr = s->current_picture[1] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8; - put_pixels(block[4],ptr, s->width >> 1); - - ptr = s->current_picture[2] + (mb_y * 8 * (s->width >> 1)) + mb_x * 8; - put_pixels(block[5],ptr, s->width >> 1); - } - } - } -} - -static void mpeg1_encode_mb(MpegEncContext *s, int mb_x, int mb_y, - DCTELEM block[6][64], - int motion_x, int motion_y) -{ - int mb_incr, i, cbp; - - /* compute cbp */ - cbp = 0; - for(i=0;i<6;i++) { - if (s->block_last_index[i] >= 0) - cbp |= 1 << (5 - i); - } - - /* skip macroblock, except if first or last macroblock of a slice */ - if ((cbp | motion_x | motion_y) == 0 && - (!((mb_x | mb_y) == 0 || - (mb_x == s->mb_width - 1 && mb_y == s->mb_height - 1)))) { - s->mb_incr++; - } else { - /* output mb incr */ - mb_incr = s->mb_incr; - - while (mb_incr > 33) { - put_bits(&s->pb, 11, 0x008); - mb_incr -= 33; - } - put_bits(&s->pb, mbAddrIncrTable[mb_incr][1], - mbAddrIncrTable[mb_incr][0]); - - if (s->pict_type == I_TYPE) { - put_bits(&s->pb, 1, 1); /* macroblock_type : macroblock_quant = 0 */ - } else { - if (s->mb_intra) { - put_bits(&s->pb, 5, 0x03); - } else { - if (motion_x == 0 && motion_y == 0) { - if (cbp != 0) { - put_bits(&s->pb, 2, 1); /* macroblock_pattern only */ - put_bits(&s->pb, mbPatTable[cbp][1], mbPatTable[cbp][0]); - } else { - put_bits(&s->pb, 3, 1); /* motion only & zero motion vectors */ - /* zero motion x & y */ - put_bits(&s->pb, 1, 1); - put_bits(&s->pb, 1, 1); - } - } else { - /* XXX: not used yet */ - put_bits(&s->pb, mbPatTable[cbp][1], mbPatTable[cbp][0]); - } - } - - } - - for(i=0;i<6;i++) { - if (cbp & (1 << (5 - i))) { - encode_block(s, block[i], i); - } - } - s->mb_incr = 1; - } -} - -static void get_pixels(DCTELEM *block, const UINT8 *pixels, int line_size) -{ - DCTELEM *p; - const UINT8 *pix; - int i; - - /* read the pixels */ - p = block; - pix = pixels; - for(i=0;i<8;i++) { - p[0] = pix[0]; - p[1] = pix[1]; - p[2] = pix[2]; - p[3] = pix[3]; - p[4] = pix[4]; - p[5] = pix[5]; - p[6] = pix[6]; - p[7] = pix[7]; - pix += line_size; - p += 8; - } -} - -static void put_pixels(const DCTELEM *block, UINT8 *pixels, int line_size) -{ - const DCTELEM *p; - UINT8 *pix; - int i; - UINT8 *cm = cropTbl + MAX_NEG_CROP; - - /* read the pixels */ - p = block; - pix = pixels; - for(i=0;i<8;i++) { - pix[0] = cm[p[0]]; - pix[1] = cm[p[1]]; - pix[2] = cm[p[2]]; - pix[3] = cm[p[3]]; - pix[4] = cm[p[4]]; - pix[5] = cm[p[5]]; - pix[6] = cm[p[6]]; - pix[7] = cm[p[7]]; - pix += line_size; - p += 8; - } -} - -static void sub_pixels(DCTELEM *block, const UINT8 *pixels, int line_size) -{ - DCTELEM *p; - const UINT8 *pix; - int i; - - /* read the pixels */ - p = block; - pix = pixels; - for(i=0;i<8;i++) { - p[0] -= pix[0]; - p[1] -= pix[1]; - p[2] -= pix[2]; - p[3] -= pix[3]; - p[4] -= pix[4]; - p[5] -= pix[5]; - p[6] -= pix[6]; - p[7] -= pix[7]; - pix += line_size; - p += 8; - } -} - -static void add_pixels(DCTELEM *block, const UINT8 *pixels, int line_size) -{ - DCTELEM *p; - const UINT8 *pix; - int i; - - /* read the pixels */ - p = block; - pix = pixels; - for(i=0;i<8;i++) { - p[0] += pix[0]; - p[1] += pix[1]; - p[2] += pix[2]; - p[3] += pix[3]; - p[4] += pix[4]; - p[5] += pix[5]; - p[6] += pix[6]; - p[7] += pix[7]; - pix += line_size; - p += 8; - } -} - -#define USE_FAST_MUL - -static int dct_quantize(MpegEncContext *s, - DCTELEM *block, - int qscale) -{ - int i, j, level, last_non_zero; -#ifdef USE_FAST_MUL - const int *qmat; -#else - const UINT8 *qmat; -#endif - - jpeg_fdct_ifast (block); - - if (s->mb_intra) { - block[0] = (block[0] + 4 * 8) >> 6; - i = 1; - last_non_zero = 0; - if (s->out_format == FMT_H263) { -#ifdef USE_FAST_MUL - qmat = s->non_intra_matrix; -#else - qmat = default_non_intra_matrix; -#endif - } else { -#ifdef USE_FAST_MUL - qmat = s->intra_matrix; -#else - qmat = default_intra_matrix; -#endif - } - } else { - i = 0; - last_non_zero = -1; -#ifdef USE_FAST_MUL - qmat = s->non_intra_matrix; -#else - qmat = default_non_intra_matrix; -#endif - } - - for(;i<64;i++) { - j = zigzag_direct[i]; - level = block[j]; -#ifdef USE_FAST_MUL - level = (level * qmat[j]) / (1 << 22); -#else - /* post dct normalization */ - level = (level << 11) / aanscales[j]; - /* quantification */ - level = (8 * level) / (qscale * qmat[j]); -#endif - block[j] = level; - if (level) - last_non_zero = i; - } - return last_non_zero; -} - -static void dct_unquantize(MpegEncContext *s, - DCTELEM *block, int qscale) -{ - int i, level, coeff; - const UINT8 *quant_matrix; - - if (s->mb_intra) { - block[0] = block[0] << 3; - if (s->out_format == FMT_H263) { - i = 1; - goto unquant_even; - } - quant_matrix = default_intra_matrix; - for(i=1;i<64;i++) { - block[i] = (block[i] * qscale * quant_matrix[i]) >> 3; - } - } else { - i = 0; - unquant_even: - quant_matrix = default_non_intra_matrix; - for(;i<64;i++) { - level = block[i]; - if (level) { - if (level < 0) { - coeff = (((level << 1) - 1) * qscale * - ((int) (quant_matrix[i]))) >> 4; - coeff += (coeff & 1); - } else { - coeff = (((level << 1) + 1) * qscale * - ((int) (quant_matrix[i]))) >> 4; - coeff -= (coeff & 1); - } - block[i] = coeff; - } - } - } - - j_rev_dct(block); -} - - -static inline void encode_dc(MpegEncContext *s, int diff, int component) -{ - int adiff, index; - - // printf("dc=%d c=%d\n", diff, component); - adiff = abs(diff); - index = vlc_dc_table[adiff]; - if (component == 0) { - put_bits(&s->pb, vlc_dc_lum_bits[index], vlc_dc_lum_code[index]); - } else { - put_bits(&s->pb, vlc_dc_chroma_bits[index], vlc_dc_chroma_code[index]); - } - if (diff > 0) { - put_bits(&s->pb, index, (diff & ((1 << index) - 1))); - } else if (diff < 0) { - put_bits(&s->pb, index, ((diff - 1) & ((1 << index) - 1))); - } -} - -static void encode_block(MpegEncContext *s, - DCTELEM *block, - int n) -{ - int alevel, level, last_non_zero, dc, diff, i, j, run, last_index; - int code, nbits, component; - - last_index = s->block_last_index[n]; - - /* DC coef */ - if (s->mb_intra) { - component = (n <= 3 ? 0 : n - 4 + 1); - dc = block[0]; /* overflow is impossible */ - diff = dc - s->last_dc[component]; - encode_dc(s, diff, component); - s->last_dc[component] = dc; - i = 1; - } else { - /* encode the first coefficient : needs to be done here because - it is handled slightly differently */ - level = block[0]; - if (abs(level) == 1) { - code = ((UINT32)level >> 31); /* the sign bit */ - put_bits(&s->pb, 2, code | 0x02); - i = 1; - } else { - i = 0; - last_non_zero = -1; - goto next_coef; - } - } - - /* now quantify & encode AC coefs */ - last_non_zero = i - 1; - for(;i<=last_index;i++) { - j = zigzag_direct[i]; - level = block[j]; - next_coef: -#if 0 - if (level != 0) - printf("level[%d]=%d\n", i, level); -#endif - /* encode using VLC */ - if (level != 0) { - run = i - last_non_zero - 1; - alevel = abs(level); - // printf("run=%d level=%d\n", run, level); - if ( (run < HUFF_MAXRUN) && (alevel < huff_maxlevel[run])) { - /* encode using the Huffman tables */ - code = (huff_table[run])[alevel]; - nbits = (huff_bits[run])[alevel]; - code |= ((UINT32)level >> 31); /* the sign bit */ - - put_bits(&s->pb, nbits, code); - } else { - /* escape: only clip in this case */ - if (level > 255) - level = 255; - else if (level < -255) - level = -255; - put_bits(&s->pb, 6, 0x1); - put_bits(&s->pb, 6, run); - if (alevel < 128) { - put_bits(&s->pb, 8, level & 0xff); - } else { - if (level < 0) { - put_bits(&s->pb, 16, 0x8001 + level + 255); - } else { - put_bits(&s->pb, 16, level & 0xffff); - } - } - } - last_non_zero = i; - } - } - /* end of block */ - put_bits(&s->pb, 2, 0x2); -} - - -/* rate control */ - -/* an I frame is I_FRAME_SIZE_RATIO bigger than a P frame */ -#define I_FRAME_SIZE_RATIO 1.5 -#define QSCALE_K 20 - -static void rate_control_init(MpegEncContext *s) -{ - s->wanted_bits = 0; - - if (s->intra_only) { - s->I_frame_bits = s->bit_rate / s->frame_rate; - s->P_frame_bits = s->I_frame_bits; - } else { - s->P_frame_bits = (int) ((float)(s->gop_size * s->bit_rate) / - (float)(s->frame_rate * (I_FRAME_SIZE_RATIO + s->gop_size - 1))); - s->I_frame_bits = (int)(s->P_frame_bits * I_FRAME_SIZE_RATIO); - } - -#if defined(DEBUG) - printf("I_frame_size=%d P_frame_size=%d\n", - s->I_frame_bits, s->P_frame_bits); -#endif -} - - -/* - * This heuristic is rather poor, but at least we do not have to - * change the qscale at every macroblock. - */ -static int rate_estimate_qscale(MpegEncContext *s) -{ - long long total_bits = s->total_bits; - float q; - int qscale, diff; - - if (s->pict_type == I_TYPE) { - s->wanted_bits += s->I_frame_bits; - } else { - s->wanted_bits += s->P_frame_bits; - } - diff = s->wanted_bits - total_bits; - q = 31.0 - (float)diff / (QSCALE_K * s->mb_height * s->mb_width); - /* adjust for I frame */ - if (s->pict_type == I_TYPE && !s->intra_only) { - q /= I_FRAME_SIZE_RATIO; - } - - if (q < 1) - q = 1; - else if (q > 31) - q = 31; - qscale = (int)(q + 0.5); -#if defined(DEBUG) - printf("%d: total=%Ld br=%0.1f diff=%d qest=%0.1f\n", - s->picture_number, - total_bits, (float)s->frame_rate * total_bits / s->picture_number, - diff, q); -#endif - return qscale; -} - -AVEncoder mpeg1video_encoder = { - "mpeg1video", - CODEC_TYPE_VIDEO, - CODEC_ID_MPEG1VIDEO, - sizeof(MpegEncContext), - MPV_encode_init, - MPV_encode_picture, - MPV_encode_end, -}; - -AVEncoder h263_encoder = { - "h263", - CODEC_TYPE_VIDEO, - CODEC_ID_H263, - sizeof(MpegEncContext), - MPV_encode_init, - MPV_encode_picture, - MPV_encode_end, -}; - -AVEncoder rv10_encoder = { - "rv10", - CODEC_TYPE_VIDEO, - CODEC_ID_RV10, - sizeof(MpegEncContext), - MPV_encode_init, - MPV_encode_picture, - MPV_encode_end, -}; - -AVEncoder mjpeg_encoder = { - "mjpeg", - CODEC_TYPE_VIDEO, - CODEC_ID_MJPEG, - sizeof(MpegEncContext), - MPV_encode_init, - MPV_encode_picture, - MPV_encode_end, -}; diff --git a/libav/mpegvideo.h b/libav/mpegvideo.h deleted file mode 100644 index e1fbe044a0..0000000000 --- a/libav/mpegvideo.h +++ /dev/null @@ -1,94 +0,0 @@ -/* mpegencode.c */ - -/* Start codes. */ -#define SEQ_END_CODE 0x000001b7 -#define SEQ_START_CODE 0x000001b3 -#define GOP_START_CODE 0x000001b8 -#define PICTURE_START_CODE 0x00000100 -#define SLICE_MIN_START_CODE 0x00000101 -#define SLICE_MAX_START_CODE 0x000001af -#define EXT_START_CODE 0x000001b5 -#define USER_START_CODE 0x000001b2 - -/* Macros for picture code type. */ -#define I_TYPE 1 -#define P_TYPE 2 -#define B_TYPE 3 - -typedef int DCTELEM; - -enum OutputFormat { - FMT_MPEG1, - FMT_H263, - FMT_MJPEG, -}; - -#define MAX_NEG_CROP 384 - -#define MPEG_BUF_SIZE (16 * 1024) - -typedef struct MpegEncContext { - /* the following parameters must be initialized before encoding */ - int width, height; /* picture size. must be a multiple of 16 */ - int gop_size; - int frame_rate; /* number of frames per second */ - int intra_only; /* if true, only intra pictures are generated */ - int bit_rate; /* wanted bit rate */ - enum OutputFormat out_format; /* output format */ - int h263_rv10; /* use RV10 variation for H263 */ - - /* the following fields are managed internally by the encoder */ - - /* bit output */ - PutBitContext pb; - - /* sequence parameters */ - int picture_number; - int fake_picture_number; /* picture number at the bitstream frame rate */ - int gop_picture_number; /* index of the first picture of a GOP */ - int mb_width, mb_height; - UINT8 *new_picture[3]; /* picture to be compressed */ - UINT8 *last_picture[3]; /* previous picture */ - UINT8 *current_picture[3]; /* buffer to store the decompressed current picture */ - int last_dc[3]; - int qscale; - int pict_type; - int frame_rate_index; - /* macroblock layer */ - int mb_incr; - int mb_intra; - /* matrix transmitted in the bitstream */ - UINT8 init_intra_matrix[64]; - /* precomputed matrix (combine qscale and DCT renorm) */ - int intra_matrix[64]; - int non_intra_matrix[64]; - int block_last_index[6]; /* last non zero coefficient in block */ - - void *opaque; /* private data for the user */ - - /* bit rate control */ - int I_frame_bits; /* wanted number of bits per I frame */ - int P_frame_bits; /* same for P frame */ - long long wanted_bits; - long long total_bits; - struct MJpegContext *mjpeg_ctx; -} MpegEncContext; - -extern const UINT8 zigzag_direct[64]; - -/* h263enc.c */ - -void h263_encode_mb(MpegEncContext *s, - DCTELEM block[6][64], - int motion_x, int motion_y); -void h263_picture_header(MpegEncContext *s, int picture_number); -void rv10_encode_picture_header(MpegEncContext *s, int picture_number); - -/* mjpegenc.c */ - -int mjpeg_init(MpegEncContext *s); -void mjpeg_close(MpegEncContext *s); -void mjpeg_encode_mb(MpegEncContext *s, - DCTELEM block[6][64]); -void mjpeg_picture_header(MpegEncContext *s); -void mjpeg_picture_trailer(MpegEncContext *s); diff --git a/libav/resample.c b/libav/resample.c deleted file mode 100644 index 008153b0d6..0000000000 --- a/libav/resample.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Sample rate convertion for both audio and video - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include "avcodec.h" - -#define NDEBUG -#include - -#define FRAC_BITS 16 -#define FRAC (1 << FRAC_BITS) - -static void init_mono_resample(ReSampleChannelContext *s, float ratio) -{ - ratio = 1.0 / ratio; - s->iratio = (int)floor(ratio); - if (s->iratio == 0) - s->iratio = 1; - s->incr = (int)((ratio / s->iratio) * FRAC); - s->frac = 0; - s->last_sample = 0; - s->icount = s->iratio; - s->isum = 0; - s->inv = (FRAC / s->iratio); -} - -/* fractional audio resampling */ -static int fractional_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) -{ - unsigned int frac, incr; - int l0, l1; - short *q, *p, *pend; - - l0 = s->last_sample; - incr = s->incr; - frac = s->frac; - - p = input; - pend = input + nb_samples; - q = output; - - l1 = *p++; - for(;;) { - /* interpolate */ - *q++ = (l0 * (FRAC - frac) + l1 * frac) >> FRAC_BITS; - frac = frac + s->incr; - while (frac >= FRAC) { - if (p >= pend) - goto the_end; - frac -= FRAC; - l0 = l1; - l1 = *p++; - } - } - the_end: - s->last_sample = l1; - s->frac = frac; - return q - output; -} - -static int integer_downsample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) -{ - short *q, *p, *pend; - int c, sum; - - p = input; - pend = input + nb_samples; - q = output; - - c = s->icount; - sum = s->isum; - - for(;;) { - sum += *p++; - if (--c == 0) { - *q++ = (sum * s->inv) >> FRAC_BITS; - c = s->iratio; - sum = 0; - } - if (p >= pend) - break; - } - s->isum = sum; - s->icount = c; - return q - output; -} - -/* n1: number of samples */ -static void stereo_to_mono(short *output, short *input, int n1) -{ - short *p, *q; - int n = n1; - - p = input; - q = output; - while (n >= 4) { - q[0] = (p[0] + p[1]) >> 1; - q[1] = (p[2] + p[3]) >> 1; - q[2] = (p[4] + p[5]) >> 1; - q[3] = (p[6] + p[7]) >> 1; - q += 4; - p += 8; - n -= 4; - } - while (n > 0) { - q[0] = (p[0] + p[1]) >> 1; - q++; - p += 2; - n--; - } -} - -/* XXX: should use more abstract 'N' channels system */ -static void stereo_split(short *output1, short *output2, short *input, int n) -{ - int i; - - for(i=0;iiratio > 1) { - buftmp = buf1; - nb_samples = integer_downsample(s, buftmp, input, nb_samples); - } else { - buftmp = input; - } - - /* then do a fractional resampling with linear interpolation */ - if (s->incr != FRAC) { - nb_samples = fractional_resample(s, output, buftmp, nb_samples); - } else { - memcpy(output, buftmp, nb_samples * sizeof(short)); - } - return nb_samples; -} - -/* ratio = output_rate / input_rate */ -int audio_resample_init(ReSampleContext *s, - int output_channels, int input_channels, - int output_rate, int input_rate) -{ - int i; - - s->ratio = (float)output_rate / (float)input_rate; - - if (output_channels > 2 || input_channels > 2) - return -1; - s->input_channels = input_channels; - s->output_channels = output_channels; - - for(i=0;ichannel_ctx[i], s->ratio); - } - return 0; -} - -/* resample audio. 'nb_samples' is the number of input samples */ -/* XXX: optimize it ! */ -/* XXX: do it with polyphase filters, since the quality here is - HORRIBLE. Return the number of samples available in output */ -int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) -{ - int i, nb_samples1; - short buf[5][nb_samples]; - short *buftmp1, *buftmp2[2], *buftmp3[2]; - - if (s->input_channels == s->output_channels && s->ratio == 1.0) { - /* nothing to do */ - memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); - return nb_samples; - } - - if (s->input_channels == 2 && - s->output_channels == 1) { - buftmp1 = buf[0]; - stereo_to_mono(buftmp1, input, nb_samples); - } else if (s->input_channels == 1 && - s->output_channels == 2) { - /* XXX: do it */ - abort(); - } else { - buftmp1 = input; - } - - if (s->output_channels == 2) { - buftmp2[0] = buf[1]; - buftmp2[1] = buf[2]; - buftmp3[0] = buf[3]; - buftmp3[1] = buf[4]; - stereo_split(buftmp2[0], buftmp2[1], buftmp1, nb_samples); - } else { - buftmp2[0] = buftmp1; - buftmp3[0] = output; - } - - /* resample each channel */ - nb_samples1 = 0; /* avoid warning */ - for(i=0;ioutput_channels;i++) { - nb_samples1 = mono_resample(&s->channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples); - } - - if (s->output_channels == 2) { - stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1); - } - - return nb_samples1; -} diff --git a/mpegenc.h b/mpegenc.h deleted file mode 100644 index a7941be463..0000000000 --- a/mpegenc.h +++ /dev/null @@ -1,127 +0,0 @@ - -#include "avcodec.h" - -/* byte stream handling */ - -typedef struct { - unsigned char *buffer; - unsigned char *buf_ptr, *buf_end; - void *opaque; - void (*write_packet)(void *opaque, UINT8 *buf, int buf_size); - int (*write_seek)(void *opaque, long long offset, int whence); - long long pos; /* position in the file of the current buffer */ -} PutByteContext; - -int init_put_byte(PutByteContext *s, - unsigned char *buffer, - int buffer_size, - void *opaque, - void (*write_packet)(void *opaque, UINT8 *buf, int buf_size), - int (*write_seek)(void *opaque, long long offset, int whence)); - -void put_byte(PutByteContext *s, int b); -void put_buffer(PutByteContext *s, unsigned char *buf, int size); -void put_le32(PutByteContext *s, unsigned int val); -void put_le64(PutByteContext *s, unsigned long long val); -void put_le16(PutByteContext *s, unsigned int val); -void put_tag(PutByteContext *s, char *tag); - -long long put_seek(PutByteContext *s, long long offset, int whence); -long long put_pos(PutByteContext *s); - -void put_flush_packet(PutByteContext *s); - -/* udp.c */ - -typedef struct { - int udp_socket; - int max_payload_size; /* in bytes */ -} UDPContext; - -int udp_tx_open(UDPContext *s, - const char *uri, - int local_port); -void udp_tx_close(UDPContext *s); -void udp_write_data(void *opaque, UINT8 *buf, int size); - -/* generic functions */ - -struct AVFormatContext; - -typedef struct AVFormat { - char *name; - char *long_name; - char *mime_type; - char *extensions; /* comma separated extensions */ - enum CodecID audio_codec; - enum CodecID video_codec; - int (*write_header)(struct AVFormatContext *); - int (*write_audio_frame)(struct AVFormatContext *, - unsigned char *buf, int size); - int (*write_video_picture)(struct AVFormatContext *, - unsigned char *buf, int size); - int (*write_trailer)(struct AVFormatContext *); - struct AVFormat *next; -} AVFormat; - -typedef struct AVFormatContext { - struct AVFormat *format; - void *priv_data; - PutByteContext pb; - AVEncodeContext *video_enc; - AVEncodeContext *audio_enc; - int is_streamed; /* true if the stream is generated as being streamed */ -} AVFormatContext; - -extern AVFormat *first_format; -extern int data_out_size; -extern const char *comment_string; - -/* rv10enc.c */ -extern AVFormat rm_format; -extern AVFormat ra_format; - -/* mpegmux.c */ -extern AVFormat mpeg_mux_format; - -/* asfenc.c */ -extern AVFormat asf_format; - -/* jpegenc.c */ -extern AVFormat mpjpeg_format; -extern AVFormat jpeg_format; - -/* swfenc.c */ -extern AVFormat swf_format; - -/* formats.c */ -void register_avformat(AVFormat *format); -AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type); - -void register_avencoder(AVEncoder *format); -AVEncoder *avencoder_find(enum CodecID id); -void avencoder_string(char *buf, int buf_size, AVEncodeContext *enc); - -int avencoder_open(AVEncodeContext *avctx, AVEncoder *codec); -int avencoder_encode(AVEncodeContext *avctx, UINT8 *buf, int buf_size, void *data); -int avencoder_close(AVEncodeContext *avctx); - -extern AVFormat mp2_format; -extern AVFormat ac3_format; -extern AVFormat h263_format; -extern AVFormat mpeg1video_format; - -int strstart(const char *str, const char *val, const char **ptr); - - -/* grab.c */ - -extern const char *v4l_device; - -long long gettime(void); -int v4l_init(int rate, int width, int height); -int v4l_read_picture(UINT8 *picture[3], - int width, int height, - int picture_number); - -int audio_open(int freq, int channels); diff --git a/mpegmux.c b/mpegmux.c deleted file mode 100644 index fff01525a5..0000000000 --- a/mpegmux.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Output a MPEG1 multiplexed video/audio stream - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpegenc.h" -#include "mpegvideo.h" -#include "mpegaudio.h" - -#define MAX_PAYLOAD_SIZE 4096 -#define NB_STREAMS 2 - -typedef struct { - UINT8 buffer[MAX_PAYLOAD_SIZE]; - int buffer_ptr; - UINT8 id; - int max_buffer_size; - int packet_number; - AVEncodeContext *enc; - float pts; -} StreamInfo; - -typedef struct { - int packet_size; /* required packet size */ - int packet_number; - int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */ - int system_header_freq; - int mux_rate; /* bitrate in units of 50 bytes/s */ - /* stream info */ - int nb_streams; - StreamInfo streams[NB_STREAMS]; - AVFormatContext *ctx; -} MpegMuxContext; - -#define PACK_START_CODE ((unsigned int)0x000001ba) -#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb) -#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00) -#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100) -#define ISO_11172_END_CODE ((unsigned int)0x000001b9) - -#define AUDIO_ID 0xc0 -#define VIDEO_ID 0xe0 - -static int put_pack_header(MpegMuxContext *s, UINT8 *buf, long long timestamp) -{ - PutBitContext pb; - - init_put_bits(&pb, buf, 128, NULL, NULL); - - put_bits(&pb, 32, PACK_START_CODE); - put_bits(&pb, 4, 0x2); - put_bits(&pb, 3, (timestamp >> 30) & 0x07); - put_bits(&pb, 1, 1); - put_bits(&pb, 15, (timestamp >> 15) & 0x7fff); - put_bits(&pb, 1, 1); - put_bits(&pb, 15, (timestamp) & 0x7fff); - put_bits(&pb, 1, 1); - put_bits(&pb, 1, 1); - put_bits(&pb, 22, s->mux_rate); - - flush_put_bits(&pb); - return pb.buf_ptr - pb.buf; -} - -static int put_system_header(MpegMuxContext *s, UINT8 *buf) -{ - int audio_bound, video_bound; - int size, rate_bound, i; - PutBitContext pb; - - init_put_bits(&pb, buf, 128, NULL, NULL); - - put_bits(&pb, 32, SYSTEM_HEADER_START_CODE); - put_bits(&pb, 16, 0); - put_bits(&pb, 1, 1); - - rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */ - put_bits(&pb, 22, rate_bound); - put_bits(&pb, 1, 1); /* marker */ - audio_bound = 1; /* at most one audio stream */ - put_bits(&pb, 6, audio_bound); - - put_bits(&pb, 1, 0); /* variable bitrate */ - put_bits(&pb, 1, 0); /* non constrainted bit stream */ - - put_bits(&pb, 1, 1); /* audio locked */ - put_bits(&pb, 1, 1); /* video locked */ - put_bits(&pb, 1, 1); /* marker */ - - video_bound = 1; /* at most one video stream */ - put_bits(&pb, 5, video_bound); - put_bits(&pb, 8, 0xff); /* reserved byte */ - - /* audio stream info */ - for(i=0;inb_streams;i++) { - put_bits(&pb, 8, s->streams[i].id); /* stream ID */ - put_bits(&pb, 2, 3); - put_bits(&pb, 1, 1); /* buffer bound scale = 1024 */ - put_bits(&pb, 13, s->streams[i].max_buffer_size); /* max buffer size */ - } - /* no more streams */ - put_bits(&pb, 1, 0); - flush_put_bits(&pb); - size = pb.buf_ptr - pb.buf; - /* patch packet size */ - buf[4] = (size - 6) >> 8; - buf[5] = (size - 6) & 0xff; - - return size; -} - -/* Format a packet header for a total size of 'total_size'. Return the - header size */ -static int put_packet_header(MpegMuxContext *s, - int id, long long timestamp, - UINT8 *buffer, int total_size) -{ - UINT8 *buf_ptr; - PutBitContext pb; - int size, payload_size; - -#if 0 - printf("packet ID=%2x PTS=%0.3f size=%d\n", - id, timestamp / 90000.0, total_size); -#endif - - buf_ptr = buffer; - - if ((s->packet_number % s->pack_header_freq) == 0) { - /* output pack and systems header */ - size = put_pack_header(s, buf_ptr, timestamp); - buf_ptr += size; - if ((s->packet_number % s->system_header_freq) == 0) { - size = put_system_header(s, buf_ptr); - buf_ptr += size; - } - } - - payload_size = total_size - ((buf_ptr - buffer) + 6 + 5); - /* packet header */ - init_put_bits(&pb, buf_ptr, 128, NULL, NULL); - - put_bits(&pb, 32, PACKET_START_CODE_PREFIX + id); - put_bits(&pb, 16, payload_size + 5); - /* presentation time stamp */ - put_bits(&pb, 4, 0x02); - put_bits(&pb, 3, (timestamp >> 30) & 0x07); - put_bits(&pb, 1, 1); - put_bits(&pb, 15, (timestamp >> 15) & 0x7fff); - put_bits(&pb, 1, 1); - put_bits(&pb, 15, (timestamp) & 0x7fff); - put_bits(&pb, 1, 1); - - flush_put_bits(&pb); - - s->packet_number++; - return pb.buf_ptr - buffer; -} - -int mpeg_mux_init(AVFormatContext *ctx) -{ - MpegMuxContext *s; - int bitrate, i; - - s = malloc(sizeof(MpegMuxContext)); - if (!s) - return -1; - memset(s, 0, sizeof(MpegMuxContext)); - ctx->priv_data = s; - s->ctx = ctx; - s->packet_number = 0; - - /* XXX: hardcoded */ - s->packet_size = 2048; - s->nb_streams = 2; - s->streams[0].id = AUDIO_ID; - s->streams[0].max_buffer_size = 10; /* in KBytes */ - s->streams[0].enc = ctx->audio_enc; - s->streams[1].id = VIDEO_ID; - s->streams[1].max_buffer_size = 50; /* in KBytes */ - s->streams[1].enc = ctx->video_enc; - - /* we increase slightly the bitrate to take into account the - headers. XXX: compute it exactly */ - bitrate = 2000; - for(i=0;inb_streams;i++) { - bitrate += s->streams[i].enc->bit_rate; - } - s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50); - /* every 2 seconds */ - s->pack_header_freq = 2 * bitrate / s->packet_size / 8; - /* every 10 seconds */ - s->system_header_freq = s->pack_header_freq * 5; - - for(i=0;istreams[i].buffer_ptr = 0; - s->streams[i].packet_number = 0; - s->streams[i].pts = 0; - } - return 0; -} - -int mpeg_mux_end(AVFormatContext *ctx) -{ - PutBitContext pb; - UINT8 buffer[128]; - - /* write the end header */ - init_put_bits(&pb, buffer, sizeof(buffer), NULL, NULL); - put_bits(&pb, 32, ISO_11172_END_CODE); - - put_buffer(&ctx->pb, buffer, pb.buf_ptr - buffer); - put_flush_packet(&ctx->pb); - return 0; -} - -static void write_stream(MpegMuxContext *s, StreamInfo *stream, UINT8 *buf, int size) -{ - int len, len1, header_size; - long long pts; - while (size > 0) { - if (stream->buffer_ptr == 0) { - pts = stream->pts * 90000.0; - header_size = put_packet_header(s, stream->id, pts, stream->buffer, s->packet_size); - stream->buffer_ptr = header_size; - } - len = size; - len1 = s->packet_size - stream->buffer_ptr; - if (len > len1) - len = len1; - memcpy(stream->buffer + stream->buffer_ptr, buf, len); - stream->buffer_ptr += len; - if (stream->buffer_ptr == s->packet_size) { - /* output the packet */ - put_buffer(&s->ctx->pb, stream->buffer, s->packet_size); - put_flush_packet(&s->ctx->pb); - stream->buffer_ptr = 0; - stream->packet_number++; - } - buf += len; - size -= len; - } -} - -static int mpeg_mux_write_audio(AVFormatContext *ctx, UINT8 *buf, int size) -{ - MpegMuxContext *s = ctx->priv_data; - - write_stream(s, &s->streams[0], buf, size); - s->streams[0].pts += (float)s->streams[0].enc->frame_size / s->streams[0].enc->rate; - return 0; -} - -int mpeg_mux_write_video(AVFormatContext *ctx, UINT8 *buf, int size) -{ - MpegMuxContext *s = ctx->priv_data; - - write_stream(s, &s->streams[1], buf, size); - s->streams[1].pts += 1.0 / (float)s->streams[1].enc->rate; - - return 0; -} - -AVFormat mpeg_mux_format = { - "mpeg1", - "MPEG1 multiplex format", - "video/mpeg", - "mpg,mpeg", - CODEC_ID_MP2, - CODEC_ID_MPEG1VIDEO, - mpeg_mux_init, - mpeg_mux_write_audio, - mpeg_mux_write_video, - mpeg_mux_end, -}; diff --git a/rmenc.c b/rmenc.c deleted file mode 100644 index 60a3b2a3ad..0000000000 --- a/rmenc.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * RV 1.0 compatible encoder. - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include "mpegenc.h" -#include "mpegvideo.h" - -/* in ms */ -#define BUFFER_DURATION 0 - -typedef struct { - int nb_packets; - int packet_total_size; - int packet_max_size; - /* codec related output */ - int bit_rate; - float frame_rate; - int nb_frames; /* current frame number */ - int total_frames; /* total number of frames */ - int num; - AVEncodeContext *enc; -} StreamInfo; - -typedef struct { - StreamInfo streams[2]; - StreamInfo *audio_stream, *video_stream; - int nb_streams; - int data_pos; /* position of the data after the header */ -} RMContext; - -static void put_long(PutByteContext *s, unsigned int val) -{ - put_byte(s, val >> 24); - put_byte(s, val >> 16); - put_byte(s, val >> 8); - put_byte(s, val); -} - -static void put_short(PutByteContext *s, unsigned int val) -{ - put_byte(s, val >> 8); - put_byte(s, val); -} - -static void put_str(PutByteContext *s, const char *tag) -{ - put_short(s,strlen(tag)); - while (*tag) { - put_byte(s, *tag++); - } -} - -static void put_str8(PutByteContext *s, const char *tag) -{ - put_byte(s, strlen(tag)); - while (*tag) { - put_byte(s, *tag++); - } -} - -int find_tag(const char *tag, char *buf, int buf_size, const char *str) -{ - int len = strlen(tag); - char *q; - - buf[0] = '\0'; - while (*str) { - if (*str == '+' && !strncmp(str + 1, tag, len) && str[len+1] == '=') { - str += len + 2; - q = buf; - while (*str && *str != '+' && (q - buf) < (buf_size - 1)) { - *q++ = *str++; - } - /* remove trailing spaces */ - while (q > buf && q[-1] == ' ') q--; - *q = '\0'; - return 1; - } - str++; - } - return 0; -} - -static void rv10_write_header(AVFormatContext *ctx, - int data_size, int index_pos) -{ - RMContext *rm = ctx->priv_data; - PutByteContext *s = &ctx->pb; - StreamInfo *stream; - unsigned char *data_offset_ptr, *start_ptr; - char title[1024], author[1024], copyright[1024], comment[1024]; - const char *desc, *mimetype; - int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; - int bit_rate, v, duration, flags, data_pos; - - start_ptr = s->buf_ptr; - - put_tag(s, ".RMF"); - put_long(s,18); /* header size */ - put_short(s,0); - put_long(s,0); - put_long(s,4 + rm->nb_streams); /* num headers */ - - put_tag(s,"PROP"); - put_long(s, 50); - put_short(s, 0); - packet_max_size = 0; - packet_total_size = 0; - nb_packets = 0; - bit_rate = 0; - duration = 0; - for(i=0;inb_streams;i++) { - StreamInfo *stream = &rm->streams[i]; - bit_rate += stream->bit_rate; - if (stream->packet_max_size > packet_max_size) - packet_max_size = stream->packet_max_size; - nb_packets += stream->nb_packets; - packet_total_size += stream->packet_total_size; - /* select maximum duration */ - v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate); - if (v > duration) - duration = v; - } - put_long(s, bit_rate); /* max bit rate */ - put_long(s, bit_rate); /* avg bit rate */ - put_long(s, packet_max_size); /* max packet size */ - if (nb_packets > 0) - packet_avg_size = packet_total_size / nb_packets; - else - packet_avg_size = 0; - put_long(s, packet_avg_size); /* avg packet size */ - put_long(s, nb_packets); /* num packets */ - put_long(s, duration); /* duration */ - put_long(s, BUFFER_DURATION); /* preroll */ - put_long(s, index_pos); /* index offset */ - /* computation of data the data offset */ - data_offset_ptr = s->buf_ptr; - put_long(s, 0); /* data offset : will be patched after */ - put_short(s, rm->nb_streams); /* num streams */ - flags = 1 | 2; /* save allowed & perfect play */ - if (ctx->is_streamed) - flags |= 4; /* live broadcast */ - put_short(s, flags); - - /* comments */ - find_tag("title", title, sizeof(title), comment_string); - find_tag("author", author, sizeof(author), comment_string); - find_tag("copyright", copyright, sizeof(copyright), comment_string); - find_tag("comment", comment, sizeof(comment), comment_string); - - put_tag(s,"CONT"); - size = strlen(title) + strlen(author) + strlen(copyright) + strlen(comment) + - 4 * 2 + 10; - put_long(s,size); - put_short(s,0); - put_str(s, title); - put_str(s, author); - put_str(s, copyright); - put_str(s, comment); - - for(i=0;inb_streams;i++) { - int codec_data_size; - - stream = &rm->streams[i]; - - if (stream->enc->codec->type == CODEC_TYPE_AUDIO) { - desc = "The Audio Stream"; - mimetype = "audio/x-pn-realaudio"; - codec_data_size = 73; - } else { - desc = "The Video Stream"; - mimetype = "video/x-pn-realvideo"; - codec_data_size = 34; - } - - put_tag(s,"MDPR"); - size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size; - put_long(s, size); - put_short(s, 0); - - put_short(s, i); /* stream number */ - put_long(s, stream->bit_rate); /* max bit rate */ - put_long(s, stream->bit_rate); /* avg bit rate */ - put_long(s, stream->packet_max_size); /* max packet size */ - if (stream->nb_packets > 0) - packet_avg_size = stream->packet_total_size / - stream->nb_packets; - else - packet_avg_size = 0; - put_long(s, packet_avg_size); /* avg packet size */ - put_long(s, 0); /* start time */ - put_long(s, BUFFER_DURATION); /* preroll */ - /* duration */ - put_long(s, (int)(stream->total_frames * 1000 / stream->frame_rate)); - put_str8(s, desc); - put_str8(s, mimetype); - put_long(s, codec_data_size); - - if (stream->enc->codec->type == CODEC_TYPE_AUDIO) { - int coded_frame_size, fscode, sample_rate; - sample_rate = stream->enc->rate; - coded_frame_size = (stream->enc->bit_rate * - stream->enc->frame_size) / (8 * sample_rate); - /* audio codec info */ - put_tag(s, ".ra"); - put_byte(s, 0xfd); - put_long(s, 0x00040000); /* version */ - put_tag(s, ".ra4"); - put_long(s, 0x01b53530); /* stream length */ - put_short(s, 4); /* unknown */ - put_long(s, 0x39); /* header size */ - - switch(sample_rate) { - case 48000: - case 24000: - case 12000: - fscode = 1; - break; - default: - case 44100: - case 22050: - case 11025: - fscode = 2; - break; - case 32000: - case 16000: - case 8000: - fscode = 3; - } - put_short(s, fscode); /* codec additional info, for AC3, seems - to be a frequency code */ - /* special hack to compensate rounding errors... */ - if (coded_frame_size == 557) - coded_frame_size--; - put_long(s, coded_frame_size); /* frame length */ - put_long(s, 0x51540); /* unknown */ - put_long(s, 0x249f0); /* unknown */ - put_long(s, 0x249f0); /* unknown */ - put_short(s, 0x01); - /* frame length : seems to be very important */ - put_short(s, coded_frame_size); - put_long(s, 0); /* unknown */ - put_short(s, stream->enc->rate); /* sample rate */ - put_long(s, 0x10); /* unknown */ - put_short(s, stream->enc->channels); - put_str8(s, "Int0"); /* codec name */ - put_str8(s, "dnet"); /* codec name */ - put_short(s, 0); /* title length */ - put_short(s, 0); /* author length */ - put_short(s, 0); /* copyright length */ - put_byte(s, 0); /* end of header */ - } else { - /* video codec info */ - put_long(s,34); /* size */ - put_tag(s,"VIDORV10"); - put_short(s, stream->enc->width); - put_short(s, stream->enc->height); - put_short(s, 24); /* frames per seconds ? */ - put_long(s,0); /* unknown meaning */ - put_short(s, 12); /* unknown meaning */ - put_long(s,0); /* unknown meaning */ - put_short(s, 8); /* unknown meaning */ - /* Seems to be the codec version: only use basic H263. The next - versions seems to add a diffential DC coding as in - MPEG... nothing new under the sun */ - put_long(s,0x10000000); - //put_long(s,0x10003000); - } - } - - /* patch data offset field */ - data_pos = s->buf_ptr - start_ptr; - rm->data_pos = data_pos; - data_offset_ptr[0] = data_pos >> 24; - data_offset_ptr[1] = data_pos >> 16; - data_offset_ptr[2] = data_pos >> 8; - data_offset_ptr[3] = data_pos; - - /* data stream */ - put_tag(s,"DATA"); - put_long(s,data_size + 10 + 8); - put_short(s,0); - - put_long(s, nb_packets); /* number of packets */ - put_long(s,0); /* next data header */ -} - -static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, - int length, int key_frame) -{ - int timestamp; - PutByteContext *s = &ctx->pb; - - stream->nb_packets++; - stream->packet_total_size += length; - if (length > stream->packet_max_size) - stream->packet_max_size = length; - - put_short(s,0); /* version */ - put_short(s,length + 12); - put_short(s, stream->num); /* stream number */ - timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate; - put_long(s, timestamp); /* timestamp */ - put_byte(s, 0); /* reserved */ - put_byte(s, key_frame ? 2 : 0); /* flags */ -} - -static int rm_write_header(AVFormatContext *s) -{ - StreamInfo *stream; - RMContext *rm; - int n; - - rm = malloc(sizeof(RMContext)); - if (!rm) - return -1; - memset(rm, 0, sizeof(RMContext)); - s->priv_data = rm; - n = 0; - if (s->audio_enc) { - stream = &rm->streams[n]; - memset(stream, 0, sizeof(StreamInfo)); - stream->num = n; - rm->audio_stream = stream; - stream->bit_rate = s->audio_enc->bit_rate; - stream->frame_rate = (float)s->audio_enc->rate / (float)s->audio_enc->frame_size; - stream->enc = s->audio_enc; - /* XXX: dummy values */ - stream->packet_max_size = 1024; - stream->nb_packets = 1000; - stream->total_frames = stream->nb_packets; - n++; - } - if (s->video_enc) { - stream = &rm->streams[n]; - memset(stream, 0, sizeof(StreamInfo)); - stream->num = n; - rm->video_stream = stream; - stream->bit_rate = s->video_enc->bit_rate; - stream->frame_rate = s->video_enc->rate; - stream->enc = s->video_enc; - /* XXX: dummy values */ - stream->packet_max_size = 4096; - stream->nb_packets = 1000; - stream->total_frames = stream->nb_packets; - n++; - } - rm->nb_streams = n; - - rv10_write_header(s, 0, 0); - put_flush_packet(&s->pb); - return 0; -} - -static int rm_write_audio(AVFormatContext *s, UINT8 *buf, int size) -{ - UINT8 buf1[size]; - RMContext *rm = s->priv_data; - PutByteContext *pb = &s->pb; - StreamInfo *stream = rm->audio_stream; - int i; - - write_packet_header(s, stream, size, stream->enc->key_frame); - - /* for AC3, the words seems to be reversed */ - for(i=0;inb_frames++; - return 0; -} - -static int rm_write_video(AVFormatContext *s, UINT8 *buf, int size) -{ - RMContext *rm = s->priv_data; - PutByteContext *pb = &s->pb; - StreamInfo *stream = rm->video_stream; - int key_frame = stream->enc->key_frame; - - /* XXX: this is incorrect: should be a parameter */ - - /* Well, I spent some time finding the meaning of these bits. I am - not sure I understood everything, but it works !! */ -#if 1 - write_packet_header(s, stream, size + 7, key_frame); - /* bit 7: '1' if final packet of a frame converted in several packets */ - put_byte(pb, 0x81); - /* bit 7: '1' if I frame. bits 6..0 : sequence number in current - frame starting from 1 */ - if (key_frame) { - put_byte(pb, 0x81); - } else { - put_byte(pb, 0x01); - } - put_short(pb, 0x4000 | (size)); /* total frame size */ - put_short(pb, 0x4000 | (size)); /* offset from the start or the end */ -#else - /* seems to be used for prefetch/error correction. Help me ! */ - write_packet_header(s, size + 6); - put_byte(pb, 0xc0); - put_short(pb, 0x4000 | size); /* total frame size */ - put_short(pb, 0x4000 + packet_number * 126); -#endif - put_byte(pb, stream->nb_frames & 0xff); - - put_buffer(pb, buf, size); - put_flush_packet(pb); - - stream->nb_frames++; - return 0; -} - -static int rm_write_trailer(AVFormatContext *s) -{ - RMContext *rm = s->priv_data; - int data_size, index_pos, i; - PutByteContext *pb = &s->pb; - - if (!s->is_streamed) { - /* end of file: finish to write header */ - index_pos = put_seek(pb, 0, SEEK_CUR); - data_size = index_pos - rm->data_pos; - - /* index */ - put_tag(pb, "INDX"); - put_long(pb, 10 + 10 * rm->nb_streams); - put_short(pb, 0); - - for(i=0;inb_streams;i++) { - put_long(pb, 0); /* zero indices */ - put_short(pb, i); /* stream number */ - put_long(pb, 0); /* next index */ - } - /* undocumented end header */ - put_long(pb, 0); - put_long(pb, 0); - - put_seek(pb, 0, SEEK_SET); - for(i=0;inb_streams;i++) - rm->streams[i].total_frames = rm->streams[i].nb_frames; - rv10_write_header(s, data_size, index_pos); - } else { - /* undocumented end header */ - put_long(pb, 0); - put_long(pb, 0); - } - put_flush_packet(pb); - - free(rm); - return 0; -} - -AVFormat rm_format = { - "rm", - "rm format", - "audio/x-pn-realaudio", - "rm,ra", - CODEC_ID_AC3, - CODEC_ID_RV10, - rm_write_header, - rm_write_audio, - rm_write_video, - rm_write_trailer, -}; - -AVFormat ra_format = { - "ra", - "ra format", - "audio/x-pn-realaudio", - "ra", - CODEC_ID_AC3, - CODEC_ID_NONE, - rm_write_header, - rm_write_audio, - NULL, - rm_write_trailer, -}; diff --git a/swfenc.c b/swfenc.c deleted file mode 100644 index 7a645e8c7a..0000000000 --- a/swfenc.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Flash Compatible Streaming Format - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include "mpegenc.h" - -#include - -/* should have a generic way to indicate probable size */ -#define DUMMY_FILE_SIZE (100 * 1024 * 1024) -#define DUMMY_DURATION 600 /* in seconds */ - -#define TAG_END 0 -#define TAG_SHOWFRAME 1 -#define TAG_DEFINESHAPE 2 -#define TAG_FREECHARACTER 3 -#define TAG_PLACEOBJECT 4 -#define TAG_REMOVEOBJECT 5 -#define TAG_JPEG2 21 - -#define TAG_LONG 0x100 - -/* flags for shape definition */ -#define FLAG_MOVETO 0x01 -#define FLAG_SETFILL0 0x02 -#define FLAG_SETFILL1 0x04 - -/* character id used */ -#define BITMAP_ID 0 -#define SHAPE_ID 1 - -typedef struct { - long long duration_pos; - long long tag_pos; - int tag; -} SWFContext; - -static void put_swf_tag(AVFormatContext *s, int tag) -{ - SWFContext *swf = s->priv_data; - PutByteContext *pb = &s->pb; - - swf->tag_pos = put_pos(pb); - swf->tag = tag; - /* reserve some room for the tag */ - if (tag & TAG_LONG) { - put_le16(pb, 0); - put_le32(pb, 0); - } else { - put_le16(pb, 0); - } -} - -static void put_swf_end_tag(AVFormatContext *s) -{ - SWFContext *swf = s->priv_data; - PutByteContext *pb = &s->pb; - long long pos; - int tag_len, tag; - - pos = put_pos(pb); - tag_len = pos - swf->tag_pos - 2; - tag = swf->tag; - put_seek(pb, swf->tag_pos, SEEK_SET); - if (tag & TAG_LONG) { - tag &= ~TAG_LONG; - put_le16(pb, (tag << 6) | 0x3f); - put_le32(pb, tag_len - 4); - } else { - assert(tag_len < 0x3f); - put_le16(pb, (tag << 6) | tag_len); - } - put_seek(pb, pos, SEEK_SET); -} - -static inline void max_nbits(int *nbits_ptr, int val) -{ - int n; - - if (val == 0) - return; - val = abs(val); - n = 1; - while (val != 0) { - n++; - val >>= 1; - } - if (n > *nbits_ptr) - *nbits_ptr = n; -} - -static void put_swf_rect(PutByteContext *pb, - int xmin, int xmax, int ymin, int ymax) -{ - PutBitContext p; - UINT8 buf[256]; - int nbits, mask; - - init_put_bits(&p, buf, sizeof(buf), NULL, NULL); - - nbits = 0; - max_nbits(&nbits, xmin); - max_nbits(&nbits, xmax); - max_nbits(&nbits, ymin); - max_nbits(&nbits, ymax); - mask = (1 << nbits) - 1; - - /* rectangle info */ - put_bits(&p, 5, nbits); - put_bits(&p, nbits, xmin & mask); - put_bits(&p, nbits, xmax & mask); - put_bits(&p, nbits, ymin & mask); - put_bits(&p, nbits, ymax & mask); - - flush_put_bits(&p); - put_buffer(pb, buf, p.buf_ptr - p.buf); -} - -static void put_swf_line_edge(PutBitContext *pb, int dx, int dy) -{ - int nbits, mask; - - put_bits(pb, 1, 1); /* edge */ - put_bits(pb, 1, 1); /* line select */ - nbits = 2; - max_nbits(&nbits, dx); - max_nbits(&nbits, dy); - - mask = (1 << nbits) - 1; - put_bits(pb, 4, nbits - 2); /* 16 bits precision */ - if (dx == 0) { - put_bits(pb, 1, 0); - put_bits(pb, 1, 1); - put_bits(pb, nbits, dy & mask); - } else if (dy == 0) { - put_bits(pb, 1, 0); - put_bits(pb, 1, 0); - put_bits(pb, nbits, dx & mask); - } else { - put_bits(pb, 1, 1); - put_bits(pb, nbits, dx & mask); - put_bits(pb, nbits, dy & mask); - } -} - -#define FRAC_BITS 16 - -/* put matrix (not size optimized */ -static void put_swf_matrix(PutByteContext *pb, - int a, int b, int c, int d, int tx, int ty) -{ - PutBitContext p; - UINT8 buf[256]; - - init_put_bits(&p, buf, sizeof(buf), NULL, NULL); - - put_bits(&p, 1, 1); /* a, d present */ - put_bits(&p, 5, 20); /* nb bits */ - put_bits(&p, 20, a); - put_bits(&p, 20, d); - - put_bits(&p, 1, 1); /* b, c present */ - put_bits(&p, 5, 20); /* nb bits */ - put_bits(&p, 20, c); - put_bits(&p, 20, b); - - put_bits(&p, 5, 20); /* nb bits */ - put_bits(&p, 20, tx); - put_bits(&p, 20, ty); - - flush_put_bits(&p); - put_buffer(pb, buf, p.buf_ptr - p.buf); -} - -static int swf_write_header(AVFormatContext *s) -{ - SWFContext *swf; - PutByteContext *pb = &s->pb; - AVEncodeContext *enc = s->video_enc; - PutBitContext p; - UINT8 buf1[256]; - - swf = malloc(sizeof(SWFContext)); - if (!swf) - return -1; - s->priv_data = swf; - - put_tag(pb, "FWS"); - put_byte(pb, 3); /* version (should use 4 for mpeg audio support) */ - put_le32(pb, DUMMY_FILE_SIZE); /* dummy size - (will be patched if not streamed) */ - - put_swf_rect(pb, 0, enc->width, 0, enc->height); - put_le16(pb, enc->rate << 8); /* frame rate */ - swf->duration_pos = put_pos(pb); - put_le16(pb, DUMMY_DURATION * enc->rate); /* frame count */ - - /* define a shape with the jpeg inside */ - - put_swf_tag(s, TAG_DEFINESHAPE); - - put_le16(pb, SHAPE_ID); /* ID of shape */ - /* bounding rectangle */ - put_swf_rect(pb, 0, enc->width, 0, enc->height); - /* style info */ - put_byte(pb, 1); /* one fill style */ - put_byte(pb, 0x41); /* clipped bitmap fill */ - put_le16(pb, BITMAP_ID); /* bitmap ID */ - /* position of the bitmap */ - put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, - 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0); - put_byte(pb, 0); /* no line style */ - - /* shape drawing */ - init_put_bits(&p, buf1, sizeof(buf1), NULL, NULL); - put_bits(&p, 4, 1); /* one fill bit */ - put_bits(&p, 4, 0); /* zero line bit */ - - put_bits(&p, 1, 0); /* not an edge */ - put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0); - put_bits(&p, 5, 1); /* nbits */ - put_bits(&p, 1, 0); /* X */ - put_bits(&p, 1, 0); /* Y */ - put_bits(&p, 1, 1); /* set fill style 1 */ - - /* draw the rectangle ! */ - put_swf_line_edge(&p, enc->width, 0); - put_swf_line_edge(&p, 0, enc->height); - put_swf_line_edge(&p, -enc->width, 0); - put_swf_line_edge(&p, 0, -enc->height); - - /* end of shape */ - put_bits(&p, 1, 0); /* not an edge */ - put_bits(&p, 5, 0); - - flush_put_bits(&p); - put_buffer(pb, buf1, p.buf_ptr - p.buf); - - put_swf_end_tag(s); - - put_flush_packet(&s->pb); - return 0; -} - -static int swf_write_video(AVFormatContext *s, UINT8 *buf, int size) -{ - PutByteContext *pb = &s->pb; - AVEncodeContext *enc = s->video_enc; - static int tag_id = 0; - - if (enc->frame_number > 1) { - /* remove the shape */ - put_swf_tag(s, TAG_REMOVEOBJECT); - put_le16(pb, SHAPE_ID); /* shape ID */ - put_le16(pb, 1); /* depth */ - put_swf_end_tag(s); - - /* free the bitmap */ - put_swf_tag(s, TAG_FREECHARACTER); - put_le16(pb, BITMAP_ID); - put_swf_end_tag(s); - } - - put_swf_tag(s, TAG_JPEG2 | TAG_LONG); - - put_le16(pb, tag_id); /* ID of the image */ - - /* a dummy jpeg header seems to be required */ - put_byte(pb, 0xff); - put_byte(pb, 0xd8); - put_byte(pb, 0xff); - put_byte(pb, 0xd9); - /* write the jpeg image */ - put_buffer(pb, buf, size); - - put_swf_end_tag(s); - - /* draw the shape */ - - put_swf_tag(s, TAG_PLACEOBJECT); - put_le16(pb, SHAPE_ID); /* shape ID */ - put_le16(pb, 1); /* depth */ - put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0); - put_swf_end_tag(s); - - /* output the frame */ - put_swf_tag(s, TAG_SHOWFRAME); - put_swf_end_tag(s); - - put_flush_packet(&s->pb); - return 0; -} - -static int swf_write_trailer(AVFormatContext *s) -{ - SWFContext *swf = s->priv_data; - PutByteContext *pb = &s->pb; - int file_size; - AVEncodeContext *enc = s->video_enc; - - put_swf_tag(s, TAG_END); - put_swf_end_tag(s); - - put_flush_packet(&s->pb); - - /* patch file size and number of frames if not streamed */ - if (!s->is_streamed) { - file_size = put_pos(pb); - put_seek(pb, 4, SEEK_SET); - put_le32(pb, file_size); - put_seek(pb, swf->duration_pos, SEEK_SET); - put_le16(pb, enc->frame_number); - } - free(swf); - return 0; -} - -AVFormat swf_format = { - "swf", - "Flash format", - "application/x-shockwave-flash", - "swf", - CODEC_ID_NONE, - CODEC_ID_MJPEG, - swf_write_header, - NULL, - swf_write_video, - swf_write_trailer, -}; diff --git a/udp.c b/udp.c deleted file mode 100644 index 44fd7f36f8..0000000000 --- a/udp.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * UDP prototype streaming system - * Copyright (c) 2000 Gerard Lantau. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpegenc.h" - -#define UDP_TX_BUF_SIZE 32768 -/* put it in UDP context */ -static struct sockaddr_in dest_addr; - -/* return non zero if error */ -int udp_tx_open(UDPContext *s, - const char *uri, - int local_port) -{ - struct sockaddr_in my_addr; - const char *p, *q; - char hostname[1024]; - int port, udp_socket, tmp; - struct hostent *hp; - - /* fill the dest addr */ - p = uri; - if (!strstart(p, "udp:", &p)) - return -1; - q = strchr(p, ':'); - if (!q) - return -1; - memcpy(hostname, p, q - p); - hostname[q - p] = '\0'; - port = strtol(q+1, NULL, 10); - if (port <= 0) - return -1; - - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); - if ((inet_aton(hostname, &dest_addr.sin_addr)) == 0) { - hp = gethostbyname(hostname); - if (!hp) - return -1; - memcpy ((char *) &dest_addr.sin_addr, hp->h_addr, hp->h_length); - } - - udp_socket = socket(PF_INET, SOCK_DGRAM, 0); - if (udp_socket < 0) - return -1; - - my_addr.sin_family = AF_INET; - my_addr.sin_port = htons(local_port); - my_addr.sin_addr.s_addr = htonl (INADDR_ANY); - - /* the bind is needed to give a port to the socket now */ - if (bind(udp_socket,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) - goto fail; - - /* limit the tx buf size to limit latency */ - - tmp = UDP_TX_BUF_SIZE; - if (setsockopt(udp_socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { - perror("setsockopt sndbuf"); - goto fail; - } - - s->udp_socket = udp_socket; - s->max_payload_size = 1024; - return 0; - fail: - return -1; -} - -void udp_tx_close(UDPContext *s) -{ - close(s->udp_socket); -} - -extern int data_out_size; - -void udp_write_data(void *opaque, UINT8 *buf, int size) -{ - UDPContext *s = opaque; - int ret, len; - - /* primitive way to avoid big packets */ - data_out_size += size; - while (size > 0) { - len = size; - if (len > s->max_payload_size) - len = s->max_payload_size; - - ret = sendto (s->udp_socket, buf, len, 0, - (struct sockaddr *) &dest_addr, - sizeof (dest_addr)); - if (ret < 0) - perror("sendto"); - buf += len; - size -= len; - } -} -