diff options
Diffstat (limited to 'src/filters/parser/DiracSplitter/libdirac')
127 files changed, 43815 insertions, 0 deletions
diff --git a/src/filters/parser/DiracSplitter/libdirac/AUTHORS b/src/filters/parser/DiracSplitter/libdirac/AUTHORS new file mode 100644 index 000000000..9bb2340f7 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/AUTHORS @@ -0,0 +1,48 @@ +ORIGINAL AUTHORS +~~~~~~~~~~~~~~~~ + +Thomas Davies, BBC Research and Development +dirac@rd.bbc.co.uk + +CONTRIBUTORS +~~~~~~~~~~~~ +(in no particular order) + +Richard Felton, BBC Research and Development +dirac@rd.bbc.co.uk + +Scott Robert Ladd, Coyote Gulch Productions +coyote@coyotegulch.com + +Stuart Cunningham, BBC Research and Development +dirac@rd.bbc.co.uk + +Anuradha Suraparaju, BBC Research and Development +dirac@rd.bbc.co.uk + +Chris Bowley, BBC Research and Development +dirac@rd.bbc.co.uk + +Tim Borer, BBC Research and Development +dirac@rd.bbc.co.uk + +Peter Meerwald +pmeerw@users.sourceforge.net + +Steve Bearcroft +bearcrsw@users.sourceforge.net + +Zen +ogg@illiminable.com + +Mike Ferenduros +mike_ferenduros@users.sourceforge.net + +Andrew Kennedy, BBC Research and Development +dirac@rd.bbc.co.uk + +Peter Bleackley, BBC Research and Development +dirac@rd.bbc.co.uk + +Myo Tun, Brunel University +myo.tun@brunel.ac.uk diff --git a/src/filters/parser/DiracSplitter/libdirac/COPYING b/src/filters/parser/DiracSplitter/libdirac/COPYING new file mode 100644 index 000000000..a05cad15d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/COPYING @@ -0,0 +1,1332 @@ +The Dirac software source code is licensed under the Mozilla Public License +Version 1.1, which is included below. The provisions of this license allow +for relicensing under other licenses, which are specified in the license +preamble at the beginning of each source-code file. For the purposes of this +distribution, the licenses under which relicensing is possible are uniformly +specified to be the GNU Public License Version 2.0 and the GNU Lesser Public +License Version 2.1. These may be downloaded from www.gnu.org/licenses; however +copies are also provided in Annex A and Annex B to this document. + + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + +ANNEX A: The GNU GENERAL PUBLIC LICENSE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +ANNEX B : THE GNU LESSER GENERAL PUBLIC LICENSE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + + diff --git a/src/filters/parser/DiracSplitter/libdirac/INSTALL b/src/filters/parser/DiracSplitter/libdirac/INSTALL new file mode 100644 index 000000000..fc3fba48a --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need `configure.ac' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CXX=c89 CXXFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/src/filters/parser/DiracSplitter/libdirac/NEWS b/src/filters/parser/DiracSplitter/libdirac/NEWS new file mode 100644 index 000000000..b4df9db28 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/NEWS @@ -0,0 +1,271 @@ +dirac_0.8,0 +=========== +Major release complying with the latest Dirac Bytestream Specification. + +- Support for interlaced coding +- Fixed bug with DC weight being set incorrectly +- Improved constant bit-rate coding mode so that quality crashes and + rate explosions are reduced. +- Improved motion estimation +- Added support for full-seach block matching. +- Fixed bugs reported by valgrind. +- API changes to conform with spec revision 1.0.0.pre9_02. Application using + Dirac libraries will need to be recompiled. +- Added support for larger wavelet-depths in non-MMX mode. +- Released patches to MPlayer, FFmpeg to comply with this release. Earlier + patch to transcode can be used with release. +- DirectShow Filter released to be able to play back Dirac v0.8.x files in + Windows Media Player. + +dirac_0.7.0 +=========== +Major release complying with Dirac ByteStream Specification 1.0.0_pre4. The +specification is available on the Dirac Homepage on Sourceforge. + +- Added support for Constant Bit Rate Coding. +- Improved quality of encoded pictures at low bit-rates and for difficult + sequences. +- Improved motion vector data partitioning to allow for parallel encoding + and decoding of this data especially in hardware. +- Added support for integral motion vector precision. +- Improved Arithmetic coding. Arithmetic coding is lots faster now. +- Minor bug-fixes to ensure compliance with spec. +- Solution and Project files for Visual C++ 2005 Express edition. +- Encoder and Decoder API header files have changed so applications + using the old API will have to be recompiled. +- Released patches to MPlayer, FFmpeg to comply with this release. Earlier + patch to transcode can be used with release. +- DirecShow Filter released to be able to play back Dirac v0.7.0 files in + Windows Media Player. +- The Dirac programming guide has been updated to reflect changes to the + Encoder API headers. +- The Algorithm API is OUT OF DATE. Please refer to the Specification + document (link http://dirac.sourceforge.net/specification.html) for + latest algorithmic changes related to the decoder side. The Algorithm + document will be updated shortly. +- Bugs fixed: 1362673, 1508532, 1588191 +- Patches applied: 1537623 + +dirac_0.6.0 +=========== +- Major release complying with Dirac ByteStream Specification. The + specification is available on the Dirac Homepage on Sourceforge. +- Encoder and Decoder API have changed in this release so applications + using the older API will have to be recompiled. +- Released patches to MPlayer, FFmpeg to comply with this release. Earlier + patch to transcode can be used with release. +- DirecShow Filter released to be able to play back Dirac v0.6.0 files in + Windows Media Player. +- Bugs fixed: 1501636, 1383890 + +dirac_0.5.4 +=========== +- Added support for lossless encoding. +- Improved Decoder performance by upto 20%. +- Improved encoder performance by modifications to motion estimation +- Modified encoder CLI so that diagnostics data and locally decoded output + is not generated by default. This improved the encoding efficiency. +- Patches : 1303281, 1309571 +- Bugs: 1291478, 1291481, 1291789, 1328565 + +dirac_0.5.3 +=========== +- Fixed encoder CLI. Added rigorous command line input checks . + The encoder exits with error message when command line argument is not + valid. +- Fixed HD block size to improve motion compensation and prediction +- Fixed bug with computing MV costs. +- MMX opts to wavelet transform, motion compensation and upconversion which + improved decoder speed by 25-30%. +- Improved chroma fidelity by increasing bits allocated to chroma +- Wavelet filter type is part of bitstream. +- Fixed bug with the way median is calculated in motion prediction. +- Replaced constant quality encoding control mechanism with a mechanism + that used constant constant Lagrangian paramemters. +- MMX optimisations are automatically used if underlying architecture + supports it. +- Improved motion estimation. +- Modified arithmetic coding to use a look-up table for division. + +- Patches: 1211899, 1216297 +- Bugs: 1209017, 1209053, 1212581, 1245129, 1240709 + +dirac_0.5.2 +=========== + - Changed encoder command line interface to accept all encoding parameters. + E.g. frame dimensions, chroma format, frame rate, etc. Header files + are no longer required. Refer to section 4.3 of README for details. + - Applied patch supplied by Mike Ferenduros to make the TwoDArray class + more efficient + - An overall increase in decoding speed by 20% by speeding up Motion + compensation, frame clip, and wavelet transform. + - Arithmetic coding speedup + - Added support for multiple wavelet filter types + - Added support for variable motion vector precision. + - Updated bitstream version. Encoder/Decoder apps in this release will not + be able to decode bitstreams generated by earlier versions. + - Released a source code patch for MPlayer-1.0pre7 to enable Dirac play + back support. + - Released a source code patch for ffmpeg-0.4.9-pre1 to enable Dirac encode + and decode. + - Released a source code patch for transcode-0.6.14 to enable Dirac encode + and decode using the patched ffmpeg-0.4.9-pre1. + - Patches Applied: 1151976 (partial), 1156674 + - Bugs fixed : 1159031 + +dirac_0.5.1 +=========== + - Significant speedup in the Arithmetic coding and decoding engines + - Modified wavelet coefficient coding to code blocks of coeffients with + skip flags if all coefficients are zero. This improves compression + performance and decoding speed. + - Modified block prediction mode coding to improve compression performance. + - Fixed bug in assigning costs to lists of vectors in block matching. + - MMX optimisation for calculating block differences in Motion Estimation. + This resulted in 20-30% improvement in encoding speed. The configure + flag --enable-mmx enables compile time MMX optimisation detection. + Currently works only on GNU/Linux. + - New script create_dirac_testfile.pl to generate input formats + compatible with Dirac from rgb files. Step 3, Section 4.2 in README + describes how to use the script. + - Released a source code patch for MPlayer-1.0pre6a to enable Dirac play + back support. + - Released DirectShow filter for Dirac to enable playback of Dirac bitstreams + using Windows Media Player + - Reinstituted bi-directional prediction + - Added support for multiple quantisers. + - Code restructure and tidying. + - Updated bitstream version. Encoder/Decoder apps in this release will not + be able to decode bitstreams generated by earlier versions. + - Patches applied: 1081736,1081743 + +dirac_0.5.0 +=========== + - Added C interface for the encoder application. Refer to the api + documentation in dirac_encoder.h or in the Programmer's Guide at + http://dirac.sourceforge.net/documentation/code/programmers_guide/index.htm + - Updated bitstream version. Encoder/Decoder apps in this release will not + be able to decode bitstreams generated by earlier versions. + - Improvements to Constant Quality encoding engine to improve stability. + - Speed-ups to motion compensation and wavelet transform for faster decoding + - Removed rounding errors from motion compensation. + - Fixed bugs with clipping and encoding black or white areas. + - Fixed bug with overflow in context modelling for arithmetic coding of + HD pictures. + - Added unit tests for motion compensation classes and wavelet classes. + - The number of frames parameter is no longer required. All existing picture + header files must be recreated using make_header for this parameter to be + omitted. Otherwise, incorrect bit rates will be reported by the encoder + application. + - Updated algortihm documentation. + - Restructured libraries so that only two libraries are generated - an encoder + library and a decoder library. 'make install' will now install only the + public API libraries and header files, the encoder and decoder apps and the + conversion and instrumentation utilities. + - Added support for building shared and/or static libraries using libtool + under UNIX, GNU/Linux. Shared and static libraries are built by default. + - Added support for building shared or static libraries under MS Windows + using MSYS and the no cost MSVC++ 2003 toolkit. Shared libraries are built + by default. + - Added support for building the codec using MS Visual C++ .NET 2003 under + MS Windows. Options are available to build Dlls and static libraries. + The _declspec mechanism is used to export the Encoder and Decoder public + "C" API. + - New target 'valgrind-check' added to make under Linux. + - Build under MS Windows using nmake no longer supported. + - Bug fixes: 1050816, 1055692, 1050757, 1044503, 1044501, 1044499 + - Patches Applied: 1055714, 1055707, 1061923, 1071429, 1059342 + +dirac-0.4.3 +=========== + - Quality metric has changed from PSNR to one based on 4th powers of errors. + This results in pictures with more stable quality and fewer artefacts. + - Fixed bug with scaling motion vectors for non 4:4:4 formats. + - Fixed bug in encoder in downconverting a picture with odd valued dimensions + - Fixed bug in encoder in handling input with 4:1:1 chroma format. + - Fixed bug in diagnostics tool in handling input with 4:1:1 chroma format. + - Updated algorithm documentation + +dirac-0.4.2 +=========== + - Fixed bugs in writing instrumentation data while encoding which + caused the diagnostics tool to go into an infinite loop + - Fixed bug in diagnostic tool when handling reference 2 and only + one reference frame is available + - Number of frames in encoded output header is now set correctly to + the number of frames encoded. + - Fixed bug with bit-rate being miscalculated when only a section of the + sequence is encoded. + - Fixed bug with setting DC band perceptual weight. + +dirac-0.4.1 +=========== + - Added support for build under Microsoft Windows using gnu autotools, + MSYS and no-cost MS VC++ 2003 compiler + + - Fixed bug in building unit tests when older versions of cppunit are + installed + + - Fixed bugs in measurement of PSNR and motion estimation process + +dirac-0.4.0 +=========== + - Added constant quality encoding interface using PSNR + as the quality measure, and using multi-pass frame + coding + - Added Intra-frame insertion and cut detection + - Added C interface for the decoder application to allow + interfacing to player software. Refer to the api documentation + in dirac_parser.h. + - Implemented unique frame headers to facilitate bit-stream + parsing + - Added instrumentation output from encoder and an + instrumentation display tool for visualising encoder + decisions to help with algorithmic development + - Cleansed and refactored numerous code files to add comments, + improve readability and modularity + - Added a unit testing framework based on cppunit for testing + classes + - Fixed bug with vertical block separation always being set + to 8 pixels + - Added feature to encode only a section of input video rather + than the whole sequence + - Tweaked motion estimation parameters to improve performance, + mostly for higher-res pictures + - Included document describing the syntax of Dirac bitstream v0.1 + in the doc directory. + - Fixed bug 1008694 (Out-of-tree building fails) + - Fixed header and pkconfig installation + - Updated algorithm documentation + +Dirac-0.3.1 +=========== + - Fixed compiling under Windows + - Video conversion utilites now build under Windows + - Colour conversion matrix coefficients corrected in conversion utilites + +Dirac-0.3.0 +=========== + - Added conversion utilities for going to and from RGB and + various YUV formats, plus bitmaps + - Fixed serious artifacts when frame dimensions are not multiples of 32 + - Performance speed up writing output to disk + - Changed .hdr format from binary to text for cross-platform interoperability + - Added autotest framework with simple colour-bars test + - Added format conversion, MPlayer and ImageMagick examples to README + - Added decoder support for arbitrary temporal prediction structures + - Added support for I-frame only coding + - Added support for coding with a single initial I-frame + - Extended code documentation to all major classes + +Dirac-0.2.0 +=========== + - Fixed crash when frame dimensions are not multiples of 32 + - Removed dependency on XParam library + - Removed libtool for faster compiles and ease of debugging + - Included doxygen documentation of major classes + - Initial "programmer's guide" documentation - doc/dirac_algor.tex + +Dirac-0.1.0 +=========== + - Initial Sourceforge release. diff --git a/src/filters/parser/DiracSplitter/libdirac/README b/src/filters/parser/DiracSplitter/libdirac/README new file mode 100644 index 000000000..c2374f9cb --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/README @@ -0,0 +1,496 @@ +README for the Dirac video codec +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +by the BBC R&D Dirac team (dirac@rd.bbc.co.uk) + + +1. Executive Summary +~~~~~~~~~~~~~~~~~~~~ + +Dirac is an open source video codec. It uses a traditional hybrid video codec +architecture, but with the wavelet transform instead of the usual block +transforms. Motion compensation uses overlapped blocks to reduce block +artefacts that would upset the transform coding stage. + +Dirac can code just about any size of video, from streaming up to HD and +beyond, although certain presets are defined for different applications and +standards. These cover the parameters that need to be set for the encoder to +work, such as block sizes and temporal prediction structures, which must +otherwise be set by hand. + +Dirac is intended to develop into real coding and decoding software, capable +of plugging into video processing applications and media players that need +compression. It is intended to develop into a simple set of reliable but +effective coding tools that work over a wide variety of content and formats, +using well-understood compression techniques, in a clear and accessible +software structure. It is not intended as a demonstration or reference coder. + + +2. Documentation +~~~~~~~~~~~~~~~~ + +A user guide and a guide to the software is in progress. More details on +running the codec can be found at http://dirac.sourceforge.net/ + + +3. Building and installing +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + GNU/Linux, Unix, MacOS X, Cygwin, Mingw + --------------------------------------- + ./configure --enable-debug + (to enable extra debug compile options) + OR + ./configure --enable-profile + (to enable the g++ profiling flag -pg) + OR + ./configure --disable-mmx + (to disable MMX optimisation which is enabled by default) + OR + ./configure --enable-debug --enable-profile + (to enable extra debug compile options and profiling options) + OR + ./configure + + By default, both shared and static libraries are built. To build all-static + libraries use + ./configure --disable-shared + + To build shared libraries only use + ./configure --disable-static + + make + make install + + The INSTALL file documents arguments to ./configure such as + --prefix=/usr/local (specify the installation location prefix). + + + MSYS and Microsoft Visual C++ + ----------------------------- + Download and install the no-cost Microsoft Visual C++ 2005 Express + Edition from + http://msdn.microsoft.com/vstudio/express/visualc/ + + Download and install MSYS (the MinGW Minimal SYStem), MSYS-1.0.10.exe, + from http://www.mingw.org/download.shtml. An MSYS icon will be available + on the desktop. + + Click on the MSYS icon on the desktop to open a MSYS shell window. + + Create a .profile file to set up the environment variables required. + vi .profile + + Include the following three lines in the .profile file. + + PATH=/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/Common7/IDE:/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/BIN:/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/Common7/Tools:/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/SDK/v2.0/bin:/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/VCPackages:$PATH + + INCLUDE=/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/include + + LIB=/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/VC/LIB:/c/Program\ Files/Microsoft\ Visual\ Studio\ 8/SDK/v2.0/lib:$LIB + + (Replace /c/Program\ Files/Microsoft\ Visual\ Studio\ 8/ with + the location where VC++ 2005 is installed if necessary) + + + Exit from the MSYS shell and click on the MSYS icon on the desktop to open + a new MSYS shell window for the .profile to take effect. + + Change directory to the directory where Dirac was unpacked. By default + only the dynamic libraries are built. + + ./configure CXX=cl LD=cl --enable-debug + (to enable extra debug compile options) + OR + ./configure CXX=cl LD=cl --disable-shared + (to build static libraries) + OR + ./configure CXX=cl LD=cl + make + make install + + The INSTALL file documents arguments to ./configure such as + --prefix=/usr/local (specify the installation location prefix). + + Microsoft Visual C++ .NET 2005 + ------------------------------ + Download and install the no-cost Microsoft Visual C++ 2005 Express + Edition from + http://msdn.microsoft.com/vstudio/express/visualc/ + + The MS VC++ 2005 solution and project files are in win32/VisualStudio + directory. Double-click on the solution file, dirac.sln, in the + win32/VisualStudio directory. The target 'Everything' builds the codec + libraries and utilities. Four build-types are supported + + Debug - builds unoptimised encoder and decoder dlls with debug symbols + Release - builds optimised encoder and decoder dlls + Debug-mmx - builds unoptimised encoder and decoder dlls with debug symbols + and mmx optimisations enabled. + Release-mmx - builds optimised encoder and decoder dlls with mmx + optimisations enabled. + Static-Debug - builds unoptimised encoder and decoder static libraries + with debug symbols + Static-Release - builds optimised encoder and decoder static libraries + Static-Debug-mmx - builds unoptimised encoder and decoder static libraries + with debug symbols and mmx optmisations enabled. + Static-Release-mmx - builds optimised encoder and decoder static libraries + with mmx optmisations enabled. + + Static libraries are created in the win32/VS2003/lib/<build-type> directory. + + Encoder and Decoder dlls and import libraries, encoder and decoder apps are + created in the win32/VisualStudio/bin/<build-type> directory. The "C" public + API is exported using the _declspec(dllexport) mechanism. + + Conversion utilites are created in the + win32/VS2003/utils/conversion/<build-type> directory. Only static versions are built. + Instrumentation utility is created in the + win32/VisualStudio/utils/instrumentation/<build-type> directory. Only static + versions are built. + + + Microsoft Visual C++ .NET 2003 + ------------------------------ + + NOTE: Since Visual C++ 2005 Express edition is freely available to + download, and the project and solution files for VC++ 2003 and VC++ + 2005 are different, VC++ 2003 project and solution files will not + be maintained in future releases. So it is suggested that the users + upgrade their VC++ environment to VC++ 2005. + + The MS VC++ .NET 2003 solution and project files are in win32/VS2003 + directory. Double-click on the solution file, dirac.sln, in the + win32/VS2003 directory. The target 'Everything' builds the codec + libraries and utilities. Four build-types are supported + + Debug - builds unoptimised encoder and decoder dlls with debug symbols + Release - builds optimised encoder and decoder dlls + Debug-mmx - builds unoptimised encoder and decoder dlls with debug symbols + and mmx optimisations enabled. + Release-mmx - builds optimised encoder and decoder dlls with mmx + optimisations enabled. + Static-Debug - builds unoptimised encoder and decoder static libraries + with debug symbols + Static-Release - builds optimised encoder and decoder static libraries + Static-Debug-mmx - builds unoptimised encoder and decoder static libraries + with debug symbols and mmx optmisations enabled. + Static-Release-mmx - builds optimised encoder and decoder static libraries + with mmx optmisations enabled. + + Static libraries are created in the win32/VS2003/lib/<build-type> directory. + + Encoder and Decoder dlls and import libraries, encoder and decoder apps are + created in the win32/VS2003/bin/<build-type> directory. The "C" public API + is exported using the _declspec(dllexport) mechanism. + + Conversion utilites are created in the + win32/VS2003/utils/conversion/<build-type> directory. Only static versions + are built. + + Instrumentation utility is created in the + win32/VS2003/utils/instrumentation/<build-type> directory. Only static + versions are built. + + +4. Running the example programs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +4.1 Command-line parameters + +At the moment there is a simple command-line parser class which is +used in all the executables. The general procedure for running a program +is to type: + + prog_name -<flag_name> flag_val ... param1 param2 ... + +In other words, options are prefixed by a dash; some options take values, +while others are boolean options that enable specific features. For example: +When running the encoder, the -qf options requires a numeric argument +specifying the "quality factor" for encoding. The -verbose option enables +detailed output and does not require an argument. + +Running any program without arguments will display a list of parameters and +options. + +4.2 File formats + +The example coder and decoder use raw 8-bit planar YUV data. This means that +data is stored bytewise, with a frame of Y followed by a frame of U followed +by a frame of V, all scanned in the usual raster order. The video dimensions +, frame rate and chroma are passed to the encoder via command line arguments. + +Other file formats are supported by means of conversion utilities that +may be found in the subdirectory util/conversion. These will convert to +and from raw RGB format, and support all the standard raw YUV formats as +well as bitmaps. Raw RGB can be obtained as an output from standard conversion +utilities such as ImageMagick. + +Example. + Compress an image sequence of 100 frames of 352x288 video in tiff format. + + Step 1. + + Use your favourite conversion routine to produce a single raw RGB file of + all the data. If your routine converts frame-by-frame then you will + need to concatenate the output. + + Step 2. + + Convert from RGB to the YUV format of your choice. For example, to do + 420, type + + RGBtoYUV420 <file.rgb >file.yuv 352 288 100 + + Note that this uses stdin and stdout to read and write the data. + + We have provided a script create_test_data.pl to help convert rgb format + files into all the input formats supported by Dirac. The command line + arguments it supports can be listed using + + create_test_data.pl -use + + Sample usage is + + create_test_data.pl -width=352 -height=288 -num_frames=100 file.rgb + + (This assumes that the RGBtoYUV utilities are in a directory specified in + PATH variable. If not in the path, then use options -convutildir and to set + the directories where the script can find the conversion utilities.) + + The scripts then outputs files in all chroma formats (420, 422, + 444) supported by Dirac to the current directory. + + + Step 4. + + Run the encoder. This will produce a locally decoded output in the + same format if the locally decoded output is enabled using the -local flag. + + Step 5. + + Convert back to RGB. + + YUV420toRGB <file.yuv >file.rgb 352 288 100 + + Step 6. + + Use your favourite conversion utility to convert to the format of your + choice. + +You can also use the transcode utility to convert data to and from Dirac's +native formats (see http://zebra.fh-weingarten.de/~transcode/): + + This example uses a 720x576x50 DV source, and transcodes to 720x576 YUV in + 4:2:0 chroma format. Cascading codecs (DV + Dirac) is generally a bad idea + - use this only if you don't have any other source of uncompressed video. + + transcode -i source.dv -x auto,null --dv_yuy2_mode -k -V -y raw,null -o file.avi + tcextract -i test.avi -x rgb > file.yuv + +Viewing and playback utilities for uncompressed video include MPlayer and +ImageMagick's display command. + + Continuing the 352x288 4:2:0 example above, to display a single frame + of raw YUV with ImageMagick use the following (use <spacebar> to see + subsequent frames): + + display -size 352x288 test.yuv + + Raw YUV 420 data can also be played back in MPlayer - use the following + MPlayer command: + + mplayer -fps 15 -rawvideo on:size=152064:w=352:h=288 test.yuv + + (at the time of writing MPlayer could not playback 4:2:2 or 4:4:4 YUV data) + + +4.3 Encoding + +The basic encoding syntax is to type + +dirac_encoder [options] file_in file_out + +This will compress file_in and produce an output file_out of compressed data. + +A locally decoded output file_out.local-dec.yuv and instrumentation data +file_out.imt (for debugging the encoder and of interest to developers only) +are also produced if the -local flag is enabled on the command line. + +There are a large number of optional parameters that can be used to run the +encoder, all of which are listed below. To encode video you need three types of +parameter need to be set: + +a) quality factor or target bit rate +b) source parameters (width, height, frame rate, chroma format) +c) encoding parameters (motion compensation block sizes, preferred viewing + distance) + +In practice you don't have to set all these directly because presets can be used +to use appropriate default values. + +a) The most important parameters are the quality factor or target bit rate. + +The quality factor is specified by using the option + +qf : Overall quality factor (>0) + +This value is greater than 0, the higher the number, the better +the quality. Typical high quality is 8-10, but it will vary from sequence to +sequence, sometimes higher and sometimes lower. + +The target bit rate is set using the option + +targetrate : Target bit rate in Kb/s + +This will attempt to maintain constant bit rate over the sequence. It works +reasonably well, but actual bit rate, especially over short sequences, may be +slightly different from the target. + +Setting -targetrate overrides -qf, in that CBR will still be applied, although +the initial quality will be set by the given qf value. This might help the CBR +algorithm to adapt faster. + +Setting -lossless overrides both -qf and -targetrate, and enforces lossless +coding. + +b) Source parameters need to be set as the imput is just a raw YUV file and +the encoder doesn't have any information about it. + +The best way to set source parameters is to use a preset for +different video formats. + +The available preset options are: +QSIF : width=176; height=120; 4:2:0 format; 14.98 frames/sec +QCIF : width=176; height=144; 4:2:0 format; 12.5 frames/sec +SIF : width=352; height=240; 4:2:0 format; 14.98 frames/sec +CIF : width=352; height=288; 4:2:0 format; 12.5 frames/sec +4SIF : width=704; height=480; 4:2:0 format; 14.98 frames/sec +4CIF : width=704; height=576; 4:2:0 format; 12.5 frames/sec +SD480 : width=720; height=480; 4:2:2 format; 29.97 frames/sec +SD576 : width=720; height=576; 4:2:2 format; 25 frames/sec +HD720P60 : width=1280; height=720; 4:2:2 format; 60 frames/sec +HD720P50 : width=1280; height=720; 4:2:2 format; 50 frames/sec +HD1080I60 : width=1920; height=1080; 4:2:2 format; 29,97 frames/sec +HD1080I50 : width=1920; height=1080; 4:2:2 format; 25 frames/sec +HD1080P60 : width=1920; height=1080; 4:2:2 format; 59.94 frames/sec +HD1080P50 : width=1920; height=1080; 4:2:2 format; 50 frames/sec + +The default format used is CUSTOM format which has the following preset values +width=640; height=480; 4:2:0 format; 23.97 frames/sec. + +If your video is not one of these formats, you should pick the nearest preset +and override the parameters that are different. + +Example 1 Simple coding example. Code a 720x576 sequence in 420 format to +high quality. + +Solution. + + dirac_encoder -cformat 2 -SD576 -qf 9 test.yuv test_out.drc + +Example 2. Code a 720x486 sequence at 29.97 frames/sec in 422 format to +medium quality + +Solution + + dirac_encoder -SD576 -width 720 -height 486 -fr 29.97 -cformat 1 -qf 7 test.yuv test_out.drc + +Source parameters that affect coding are: + +width : Width of video frame +height : Height of video frame +cformat : Chroma format. It accepts a number between 0 and 4. + 0 - 4:4:4, 1 - 4:2:2, 2 - 4:2:0 +fr : Frame rate. Can be a decimal number or a fraction. Examples + of acceptable values are 25, 29.97, 12.5, 30000/1001. +source_type : Source material type - progressive or interlaced +field_dominance : If source is interlaced, field dominance type - topfieldfirst + (default) or bottomfieldfirst + +Fora complete list of source parameters, refer to Annex C of the Dirac +Specification. + +WARNING!! If you use a preset but don't override source parameters that +are different, then Dirac will still compress, but the bit rate will be +much, much higher and there may well be serious artefacts. The encoder prints +out the parameters it's actually using before starting encoding (in verbose +mode only), so that you can abort at this point. + +c) The presets ALSO set encoding parameters. That's why it's a very good idea +to use presets, as the encoding parameters are a bit obscure. They're still +supported for those who want to experiment, but use with care. + +Encoding parameters are: + +L1_sep : the separation between L1 frames (frames that are predicted but + also used as reference frames, like P frames in MPEG-2) +num_L1 : the number of L1 frames before the next intra frame +xblen : the width of blocks used for motion compensation +yblen : the height of blocks used for motion compensation +xbsep : the horizontal separation between blocks. Always <xblen +ybsep : the vertical separation between blocks. Always <yblen +cpd : normalised viewing distance parameter, in cycles per degree. +iwlt_filter : transform filter to use when encoding INTRA frames, Valid + values are DD9_7, LEGALL5_3, DD13_7, HAAR0, HAAR1, FIDELITY, + DAUB97. Default value is DD9_5. +rwlt_filter : transform filter to use when encoding INTER frames, Valid + values are DD9_7, LEGALL5_3, DD13_7, HAAR0, HAAR1, FIDELITY, + DAUB97. Default value is LEGALL5_3. +wlt_depth : transform depth, i.e number of times the component is split + while applying the wavelet transform +no_spartition : Do not split a subband into coefficient blocks before + entropy coding +multi_quants : If subbands are split into multiple coefficient blocks before + entropy coding, assign different quantisers to each block + within the subband. +denoise : Apply a denoising filter to the input video before encoding + (note PSNR statistics will be computed relative to the denoised + video if -local is enabled) +lossless : Lossless coding.(overrides -qf and -targetrate) +mv_prec : Motion vector precision. Valid values are 1 (Pixel precision), + 1/2 (half-pixel precision), 1/4 (quarter pixel precision which + is the default), 1/8 ( Eighth pixel precision). +full_search : Use full search motion estimation +interlaced : Set coding type to interlaced for interlaced for interlaced + material. Default coding type is progressive. + +Modifying L1_sep and num_L1 allows for new GOP structures to be used, and +should be entirely safe. There are two non-GOP modes that can also be used for +encoding: setting num_L1=0 gives I-frame only coding, and setting num_L1<0 +will produce a sequence with infinitely many L1 frames i.e. with a single I +frame at the beginning of the sequence. + +Modifying the block parameters is strongly deprecated: it's likely to break +the encoder as there are many constraints. Modifying cpd will not break +anything, but will change the way noise is distributed which may be more (or +less) suitable for your application. Setting cpd equal zero turns off +perceptual weighting altogether. + +For more information, see the algorithm documentation on the website: +http://dirac.sourceforge.net + +Other options. The encoder also supports some other options, which are + +verbose : turn on verbosity (if you don't, you won't see the final bitrate!) +start : code from this frame number +stop : code up until this frame number +local : Generate diagnostics and locally decoded output (to avoid running a + decoder to see your video) + +Using -start and -stop allows a small section to be coded, rather than the +whole thing. + +If the -local flag is present in the command line, the encoder produces +diagnostic information about motion vectors that can be used to debug the +encoder algorithm. It also produces a locally decoded picture so that you +don't have to run the decoder to see what the pictures are like. + +4.4 Decoding + +Decoding is much simpler. Just point the decoder input at the bitstream and the +output to a file: + + dirac_decoder -verbose test_enc test_dec + +will decode test_enc into test_dec with running commentary. diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac.vcproj b/src/filters/parser/DiracSplitter/libdirac/libdirac.vcproj new file mode 100644 index 000000000..548585fbd --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac.vcproj @@ -0,0 +1,809 @@ +<?xml version="1.0" encoding="windows-1250"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="libdirac"
+ ProjectGUID="{12BE3440-A1F3-4C48-A229-30CB619EA276}"
+ RootNamespace="libdirac"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\..\..\common.vsprops;..\..\..\..\debug.vsprops"
+ UseOfMFC="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/MP"
+ AdditionalIncludeDirectories="."
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ DisableSpecificWarnings="4800;"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\lib\libdiracD.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\..\..\common.vsprops;..\..\..\..\debug.vsprops"
+ UseOfMFC="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="."
+ PreprocessorDefinitions="_WIN64;_DEBUG;_LIB"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\lib64\libdiracD.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\..\..\common.vsprops;..\..\..\..\release.vsprops"
+ UseOfMFC="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="."
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_MMX"
+ BufferSecurityCheck="true"
+ EnableEnhancedInstructionSet="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ DisableSpecificWarnings="4244;4800;4355"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\lib\libdiracR.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="..\..\..\..\common.vsprops;..\..\..\..\release.vsprops"
+ UseOfMFC="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="."
+ PreprocessorDefinitions="_WIN64;NDEBUG;_LIB;HAVE_MMX"
+ BufferSecurityCheck="true"
+ EnableEnhancedInstructionSet="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\..\..\lib64\libdiracR.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\libdirac_byteio\accessunit_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\arith_codec.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\band_codec.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\band_vlc.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\bit_manager.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\block_match.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\cmd_line.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\codingparams_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\common.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\comp_compress.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\comp_decompress.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\component_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\dirac_assertions.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\dirac_byte_stats.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\dirac_byte_stream.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\dirac_cppparser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\dirac_encoder.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\dirac_exception.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\dirac_parser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\displayparams_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\downconvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\downconvert_mmx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\enc_picture.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\enc_queue.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\endofsequence_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_mode_decn.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_subpel.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_utils.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_utils_mmx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\mot_comp.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\mot_comp_mmx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\motion.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\motion_estimate.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\mv_codec.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\mvdata_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\mvdataelement_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\parseparams_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\parseunit_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\pic_io.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\picture.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\picture_buffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\picture_compress.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\picture_decompress.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\pixel_match.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\prefilter.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\quality_monitor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\quant_chooser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\rate_control.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\seq_compress.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\seq_decompress.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\subband_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\transform_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\upconvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\upconvert_mmx.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\video_format_defaults.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\wavelet_utils.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ GeneratePreprocessedFile="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ GeneratePreprocessedFile="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\libdirac_common\wavelet_utils_mmx.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ GeneratePreprocessedFile="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ GeneratePreprocessedFile="0"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\libdirac_byteio\accessunit_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\arith_codec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\arrays.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\band_codec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\band_codec_template.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\band_vlc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\bit_manager.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\block_match.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\cmd_line.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\codingparams_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\common_types.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\comp_compress.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\comp_decompress.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\component_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\decoder_types.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\dirac_assertions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\dirac_byte_stats.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\dirac_byte_stream.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\dirac_cppparser.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\dirac_encoder.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\dirac_exception.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\dirac_inttypes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\dirac_parser.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\dirac_types.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\displayparams_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\downconvert.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\enc_picture.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\enc_queue.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\endofsequence_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_mode_decn.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_subpel.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\me_utils_mmx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\mot_comp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\mot_comp_mmx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\motion.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\motion_estimate.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\mv_codec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\mvdata_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\mvdataelement_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\parseparams_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\parseunit_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\pic_io.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\picture.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\picture_buffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\picture_byteio.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\picture_compress.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\picture_decompress.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_motionest\pixel_match.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\prefilter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\quality_monitor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\quant_chooser.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\rate_control.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_encoder\seq_compress.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_decoder\seq_decompress.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\subband_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_byteio\transform_byteio.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\upconvert.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\video_format_defaults.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libdirac_common\wavelet_utils.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ <Global
+ Name="DevPartner_IsInstrumented"
+ Value="0"
+ />
+ </Globals>
+</VisualStudioProject>
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/accessunit_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/accessunit_byteio.cpp new file mode 100644 index 000000000..33bb8ff9f --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/accessunit_byteio.cpp @@ -0,0 +1,192 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: accessunit_byteio.cpp,v 1.7 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/dirac_exception.h> +#include <libdirac_byteio/accessunit_byteio.h> + +using namespace dirac; + +// Constructor for encoding +SequenceHeaderByteIO::SequenceHeaderByteIO( SourceParams& src_params, + EncoderParams& enc_params): +ParseUnitByteIO(), +m_parseparams_byteio(*this, m_parse_params, enc_params), +// create default source parameters for comparisions +m_default_src_params(src_params.GetVideoFormat()), +m_src_params(src_params), +m_sourceparams_byteio( m_src_params, + m_default_src_params, + *this), +m_codec_params(enc_params), +m_codingparams_byteio(m_src_params, + m_codec_params, + m_default_src_params, + *this) +{ +} + +// Constructor for decoding +SequenceHeaderByteIO::SequenceHeaderByteIO(const ParseUnitByteIO& parseunit_byteio, + ParseParams& parse_params, + SourceParams& src_params, + CodecParams& codec_params) : +ParseUnitByteIO(parseunit_byteio), +m_parseparams_byteio( parseunit_byteio, parse_params), +m_src_params(src_params), +m_sourceparams_byteio( m_src_params, + m_default_src_params, + parseunit_byteio), +m_codec_params(codec_params), +m_codingparams_byteio( m_src_params, + m_codec_params, + m_default_src_params, + parseunit_byteio) +{ +} + +SequenceHeaderByteIO::~SequenceHeaderByteIO() +{ +} + +//-----public------------------------------------------------------ +bool SequenceHeaderByteIO::Input() +{ + //int o=mp_stream->tellg(); + InputParseParams(); + + // Inout Video format + SetByteParams(m_parseparams_byteio); + VideoFormat vf = IntToVideoFormat(ReadUint()); + if(vf==VIDEO_FORMAT_UNDEFINED) + DIRAC_THROW_EXCEPTION( + ERR_INVALID_VIDEO_FORMAT, + "Dirac does not recognise the specified video-format", + SEVERITY_ACCESSUNIT_ERROR); + + SourceParams src_params(vf, true); + m_src_params = src_params; + + InputSourceParams(); + + CodecParams codec_params(vf); + m_codec_params = codec_params; + + InputCodingParams(); + + return true; +} + +void SequenceHeaderByteIO::Output() +{ + OutputParseParams(); + + // Output the video format + SetByteParams(m_parseparams_byteio); + WriteUint(static_cast<int>(m_src_params.GetVideoFormat())); + + OutputSourceParams(); + + OutputCodingParams(); + +} + +int SequenceHeaderByteIO::GetSize() const +{ + return ParseUnitByteIO::GetSize()+ + m_parseparams_byteio.GetSize()+ + ByteIO::GetSize() + + m_sourceparams_byteio.GetSize()+ + m_codingparams_byteio.GetSize(); +} + + + +//-------private------------------------------------------------------- + +unsigned char SequenceHeaderByteIO::CalcParseCode() const +{ + unsigned char code = 0; + + // no further mods required + + return code; +} + + +void SequenceHeaderByteIO::InputSourceParams() +{ + // copy current input params + m_sourceparams_byteio.SetByteParams(*this); + + m_sourceparams_byteio.Input(); +} + +void SequenceHeaderByteIO::InputParseParams() +{ + m_parseparams_byteio.Input(); +} + +void SequenceHeaderByteIO::InputCodingParams() +{ + // copy current input params + m_codingparams_byteio.SetByteParams(m_sourceparams_byteio); + + m_codingparams_byteio.Input(); +} + +void SequenceHeaderByteIO::OutputSourceParams() +{ + // copy current output params + m_sourceparams_byteio.SetByteParams(*this); + + m_sourceparams_byteio.Output(); +} + +void SequenceHeaderByteIO::OutputParseParams() +{ + m_parseparams_byteio.Output(); +} + +void SequenceHeaderByteIO::OutputCodingParams() +{ + // copy current output params + m_codingparams_byteio.SetByteParams(m_sourceparams_byteio); + + m_codingparams_byteio.Output(); +} + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/accessunit_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/accessunit_byteio.h new file mode 100644 index 000000000..2c2966ed8 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/accessunit_byteio.h @@ -0,0 +1,182 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: accessunit_byteio.h,v 1.7 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy(Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class SequenceHeaderByteIO +*/ +#ifndef accessunit_byteio_h +#define accessunit_byteio_h + +//LOCAL INCLUDES +#include <libdirac_byteio/parseunit_byteio.h> // Parent class +#include <libdirac_byteio/parseparams_byteio.h> // ParseParamsByteIO class +#include <libdirac_byteio/displayparams_byteio.h> // SourceParamsByteIO class +#include <libdirac_byteio/codingparams_byteio.h> // CodingParamsByteIO class + +namespace dirac +{ + /** + * A random access point within a Dirac bytestream + */ + class SequenceHeaderByteIO : public ParseUnitByteIO + { + public: + + /** + * Constructor (encoding) + *@param src_params Source parameters for current AccessUnit + *@param enc_params Encoder parameters for current AccessUnit + */ + SequenceHeaderByteIO( SourceParams& src_params, + EncoderParams& enc_params); + + /** + * Constructor (decoding) + *@param parseunit_byteio Source of data + *@param parse_params Destination of parse paramters data + *@param src_params Destination of source paramters data + *@param codec_params Destination of coding paramters data + */ + SequenceHeaderByteIO(const ParseUnitByteIO& parseunit_byteio, + ParseParams& parse_params, + SourceParams& src_params, + CodecParams& codec_params); + + /** + * Destructor + */ + ~SequenceHeaderByteIO(); + + /** + * Parses data in Dirac-stream format (decoding) + */ + bool Input(); + + /** + * Writes access-unit info to Dirac stream-format (encoding) + */ + void Output(); + + /* + * Gets size of access-unit (in bytes) + */ + int GetSize() const; + + /** + * Gets parse-unit type + */ + ParseUnitType GetType() const { return PU_SEQ_HEADER;} + + private: + + /** + * Calculates parse-code based on access-unit parameters (encoding) + *@return Char bit-set + */ + unsigned char CalcParseCode() const; + + /** + * Parse source attributes from bytestream-compatible input (decoding) + */ + void InputSourceParams(); + + /** + * Parse parse attributes from bytestream-compatible input (decoding) + */ + void InputParseParams(); + + /** + * Parse Coding attributes from bytestream-compatible input (decoding) + */ + void InputCodingParams(); + + /** + * Output source attributes for bytestream-compatible output (encoding) + */ + void OutputSourceParams(); + + /** + * Output parse attributes for bytestream-compatible output (encoding) + */ + void OutputParseParams(); + + /** + * Output coding attributes for bytestream-compatible output (encoding) + */ + void OutputCodingParams(); + + /** + * Current parse parameters + */ + ParseParams m_parse_params; + + + /** + * Parse-params byte input/output + */ + ParseParamsByteIO m_parseparams_byteio; + + /** + * Default source parameters + */ + SourceParams m_default_src_params; + + /** + * Current source parameters + */ + SourceParams& m_src_params; + + /** + * Source-params byte input/output + */ + SourceParamsByteIO m_sourceparams_byteio; + + /** + * Current codec parameters + */ + CodecParams& m_codec_params; + + /** + * Coding-params byte input/output + */ + CodingParamsByteIO m_codingparams_byteio; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/byteio.cpp new file mode 100644 index 000000000..12b129953 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/byteio.cpp @@ -0,0 +1,299 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: byteio.cpp,v 1.4 2008/03/14 08:17:36 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author), +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <cmath> +#include <libdirac_byteio/byteio.h> +using namespace dirac; +using namespace std; + +ByteIO::ByteIO(bool new_stream): +m_current_byte(0), +m_current_pos(0), +m_num_bytes(0), +m_new_stream(true), +m_bits_left(0) +{ + if(new_stream) + mp_stream = new stringstream(stringstream::in | stringstream::out | + stringstream::binary); + + +} + +ByteIO::ByteIO(const ByteIO& stream_data): +m_current_byte(0), +m_current_pos(0), +m_num_bytes(0), +m_new_stream(false), +m_bits_left(0) +{ + mp_stream=stream_data.mp_stream; +} + + +ByteIO::~ByteIO() +{ + if (m_new_stream) + delete mp_stream; +} + +const string ByteIO::GetBytes() +{ + return mp_stream->str(); +} + +int ByteIO::GetSize() const +{ + return m_num_bytes; +} + +void ByteIO::SetByteParams(const ByteIO& byte_io) +{ + mp_stream=byte_io.mp_stream; + m_current_byte=byte_io.m_current_byte; + m_current_pos=byte_io.m_current_pos; +} + +//----------protected--------------------------------------------------------------- + +void ByteIO::ByteAlignInput() +{ + m_current_pos=0; + m_current_byte=0; +} + +void ByteIO::ByteAlignOutput() +{ + if(m_current_pos!=0) + OutputCurrentByte(); +} + +int ByteIO::ReadBit() +{ + if(m_current_pos == CHAR_BIT) + m_current_pos=0; + + if (m_current_pos == 0) + m_current_byte = InputUnByte(); +#if 1 + // MSB to LSB + return GetBit(m_current_byte, (CHAR_BIT-1-m_current_pos++)); +#else + // LSB to MSB + return GetBit(m_current_byte, m_current_pos++); +#endif +} + +int ByteIO::ReadBitB() +{ + if (m_bits_left) + { + --m_bits_left; + return ReadBit(); + } + else + return 1; +} + +bool ByteIO::ReadBool() +{ + return ReadBit(); +} + +bool ByteIO::ReadBoolB() +{ + return ReadBitB(); +} + +unsigned int ByteIO::ReadNBits(int count) +{ + unsigned int val = 0; + for (int i = 0; i < count; ++i) + { + val <<= 1; + val += ReadBit(); + } + return val; +} + +void ByteIO::FlushInputB() +{ + while(m_bits_left) + { + ReadBit(); + --m_bits_left; + } +} + +int ByteIO::ReadSint() +{ + + int val = ReadUint(); + bool bit; + + //get the sign + if (val != 0) + { + bit = ReadBit(); + if (bit ) + val = -val; + } + return val; +} + +int ByteIO::ReadSintB() +{ + + int val = ReadUintB(); + bool bit; + + //get the sign + if (val != 0) + { + bit = ReadBitB(); + if (bit ) + val = -val; + } + return val; +} + +unsigned int ByteIO::ReadUint() +{ + unsigned int value = 1; + while (!ReadBit()) + { + value <<= 1; + if (ReadBit()) + value +=1; + } + --value; + return value; +} + +unsigned int ByteIO::ReadUintB() +{ + unsigned int value = 1; + while (!ReadBitB()) + { + value <<= 1; + if (ReadBitB()) + value +=1; + } + --value; + return value; +} + +void ByteIO::WriteBit(const bool& bit) +{ + if(bit) +#if 1 + // MSB to LSB + SetBit(m_current_byte, CHAR_BIT-1-m_current_pos); +#else + // LSB to MSB + SetBit(m_current_byte, m_current_pos); +#endif + + if ( m_current_pos == CHAR_BIT-1) + { + // If a whole byte has been written, output to stream + OutputCurrentByte(); + m_current_byte = 0; + m_current_pos = 0; + } + else + // Shift mask to next bit in the output byte + ++m_current_pos; +} + +void ByteIO::WriteNBits(unsigned int val, int count) +{ + do + { + WriteBit(val & ( 1 << (count-1))); + count--; + } + while(count > 0); +} + +int ByteIO::WriteNBits(unsigned int val) +{ + int nbits = static_cast<int>(log(static_cast<double>(val))/log(2.0)) + 1; + WriteNBits(val, nbits); + return nbits; +} + +void ByteIO::WriteSint(int val) +{ + unsigned int value = (val >= 0 ? val : -val); + //output magnitude + WriteUint(value); + + //do sign + if (val<0) WriteBit(1); + else if (val>0) WriteBit(0); +} + +void ByteIO::WriteUint(unsigned int value) +{ + unsigned int val = value+1; + + int num_follow_zeroes = 0; + + while (val >= (1U <<num_follow_zeroes)) + ++num_follow_zeroes; + --num_follow_zeroes; + + for (int i=num_follow_zeroes-1; i>=0; --i) + { + WriteBit(BIT_ZERO); + WriteBit(val&(1<<i)); + } + WriteBit(BIT_ONE); +} + +void ByteIO::RemoveRedundantBytes(const int size) +{ + int prev_pos = mp_stream->tellg(); + string data=mp_stream->str(); + data.erase(0, size); + mp_stream->str(data); + m_num_bytes=data.size(); + if(data.size()) + SeekGet(max(prev_pos-size, 0), ios_base::beg); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/byteio.h new file mode 100644 index 000000000..db885d658 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/byteio.h @@ -0,0 +1,397 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: byteio.h,v 1.11 2009/01/21 05:18:09 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author), +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class ByteIO. +*/ +#ifndef byteio_h +#define byteio_h + +// SYSTEM INCLUDES +#include <iostream> // IO classes +#include <sstream> // IO classes +#include <iomanip> // setw +#include <climits> // CHAR_BIT + +//LOCAL INCLUDEs +#include <libdirac_byteio/dirac_byte_stats.h> // stores stats + +namespace dirac +{ + + // BIT DEFS + #define BIT_ZERO 0 + #define BIT_ONE 1 + + // most significant bit in a character + #define MS_BIT (1 << (CHAR_BIT - 1)) + + /* array index for character containing bit */ + //#define BIT_IN_CHAR(bit) (1 << (CHAR_BIT-1-bit)) + #define BIT_IN_CHAR(bit) (1 << bit) + + + /** + * Class ByteIO - top-level class for reading/writing bytes to a stream + */ + class ByteIO + { + public: + + /** + * Default constructor + *@param new_stream <B>Has Creates & owns data buffer </B> + */ + ByteIO(bool new_stream=true); + + /** + * Constructor + *@param stream_data Copies data buffer details + */ + ByteIO(const ByteIO& stream_data); + + /** + * Destructor + */ + virtual ~ByteIO(); + + /** + * Gathers byte-stream statistics + *@param dirac_byte_stats Collates byte information + */ + virtual void CollateByteStats(DiracByteStats& dirac_byte_stats) + { dirac_byte_stats.Clear(); } + + /** + * Get bytes in Dirac-bytestream format + */ + virtual const std::string GetBytes(); + + /** + * Get position of read stream pointer + */ + int GetReadBytePosition() const { return mp_stream->tellg();}; + + + /** + *Gets size (in bytes) + */ + virtual int GetSize() const; + + /** + * Copies stream source/destination info + *@param byte_io Byte source/destination + */ + void SetByteParams(const ByteIO& byte_io); + + /** + * Sync input for byte-alignment + */ + void ByteAlignOutput(); + + /** + * Ouputs an unsigned integer in interleaved exp Golomb format + *@param value Integer to be output + */ + //void OutputVarLengthUint(const unsigned int& value); + void WriteUint(unsigned int value); + + /** + * Sets input size in bits. Read is limited by this + */ + void SetBitsLeft(int left_bits) { m_bits_left = left_bits; } + + /** + * Sets input size in bits. Read is limited by this + */ + int BitsLeft(void) { return m_bits_left; } + + protected: + + inline bool CanRead() const { return(!mp_stream->eof()); } + + inline bool GetBit(unsigned char& c, int pos) const { return (c & BIT_IN_CHAR(pos)); } + + inline void SetBit(unsigned char& c, int pos) const { c |= BIT_IN_CHAR(pos); } + + inline void SetBits(unsigned char& c, unsigned char bits) const { c |= bits; } + + /** + * Sync input for byte-alignment + */ + void ByteAlignInput(); + + + /** + * Reads boolean value + */ + bool ReadBool(); + + /** + * Reads boolean value - bounded i/o + */ + bool ReadBoolB(); + + /** + * Reads next bit + */ + int ReadBit(); + + /** + * Reads next bit - bounded i/o + */ + int ReadBitB(); + + /** + * Reads next 'count' bits + *@param count number of bits to be read + *@return unsigned interger read + */ + unsigned int ReadNBits(int count); + + /** + * Reads from stream + *@param data Start of char buffer + *@param count Number of bytes to read + */ + void InputBytes(char* data, int count) + { + //int j=mp_stream->tellg(); + mp_stream->read(data, count); + + //int h=mp_stream->tellg(); + } + + /** + * Flushes the bounde input + */ + void FlushInputB(); + + /** + * Reads a signed integer in interleaved exp-Golomb format + *return Signed integer read + */ + //int InputVarLengthInt(); + int ReadSint(); + + /** + * Reads a signed integer in interleaved exp-Golomb format from bounded input + *return Signed integer read + */ + int ReadSintB(); + + /** + * Reads an unsigned integer in interleaved exp Golomb format + *@return Unsigned Integer read + */ + //unsigned int InputVarLengthUint(); + unsigned int ReadUint(); + + /** + * Reads an unsigned integer in interleaved exp Golomb format from bounded input + *@return Unsigned Integer read + */ + //unsigned int InputVarLengthUint(); + unsigned int ReadUintB(); + + /** + * Reads a fixed length unsigned integer from the stream in big endian + *@param byte_size Number of bytes in fixed length integer + *@return Unsigned Integer read + */ + //inline unsigned int InputFixedLengthUint(const int byte_size) { + inline unsigned int ReadUintLit(const int byte_size) { + unsigned int val=0; + for(int i=0; i < byte_size; ++i) + { + val <<= 8; + val += (unsigned char)mp_stream->get(); + } + m_num_bytes+=byte_size; + return val; + } + + /** + * Reads a byte from the stream + */ + inline unsigned char InputUnByte() {m_num_bytes++ ; return mp_stream->get(); } + + /** + * Reads a series of bytes from a stream + */ + inline std::string InputUnString(const int count) + { + std::string str; + for(int index=0; index < count; ++index) + str.push_back(InputUnByte()); + return str; + } + + /** + * Outputs a bit + *@param bit 1/0 Output + */ + void WriteBit(const bool& bit); + + /** + * Outputs an unsigned integer + *@param val Integer to be output + *@return number of bits written + */ + int WriteNBits(unsigned int val); + + /** + * Outputs an n bit integer + *@param val Unsigned Integer to be output + *@param count number of bits to be written + */ + void WriteNBits(unsigned int val, int count); + + + + /** + * Outputs a series of bytes + */ + void OutputBytes(const std::string& bytes) { + int cur_pos = mp_stream->tellg(); + mp_stream->str(mp_stream->str()+bytes); + m_num_bytes+=bytes.size(); + // *mp_stream << bytes; + mp_stream->seekg(std::max(cur_pos,0), std::ios_base::beg); + } + + /** + * Outputs current byte contents + */ + inline void OutputCurrentByte() + { + if (m_current_pos) + { + *mp_stream << (m_current_byte); + ++m_num_bytes; + m_current_pos = 0; + m_current_byte = 0; + } + }; + + /** + * Outputs an integer in Golomb signed integer format + *@param val Integer to be output + */ + //void OutputVarLengthInt(const int val); + void WriteSint(int val); + + /** + * Output unsigned int value in big endian format + * @param value Integer to be output + * @param length number of bytes in val to output + */ + //inline void OutputFixedLengthUint(const unsigned int& value, const int& length) + inline void WriteUintLit(const unsigned int& value, const int& length) + { + for(int i=length-1; i >=0 ; --i) + { + unsigned char cp = (value>>(i*8))&0xff; + *mp_stream << cp; + } + m_num_bytes+=length; + } + + /** + * Removes portion of byte-stream no longer required + *@param count Number of bytes to be removed from beginning of stream + */ + void RemoveRedundantBytes(const int count); + + inline void SeekGet(const int offset, std::ios_base::seekdir dir) + { + mp_stream->seekg(offset, dir); + } + + /** + * Input/output steam + */ + std::stringstream* mp_stream; + + + private: + + /** + * ArithCodec can see internals for getting/setting bits + */ + friend class ArithCodecBase; + + /** + * VLC entropy coder can see internals for getting/setting bits + */ + friend class ArithCodecToVLCAdapter; + + /** + * Char used for temporary storage of op data bits + */ + unsigned char m_current_byte; + + /** + * Used to set individual bit within the current header byte + */ + int m_current_pos; + + /** + * Number of bytes processed + */ + int m_num_bytes; + + /** + * stream alloc flag + */ + bool m_new_stream; + + /** + * num bits left to read + */ + int m_bits_left; + protected: + + + }; + + + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/codingparams_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/codingparams_byteio.cpp new file mode 100644 index 000000000..7326b4562 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/codingparams_byteio.cpp @@ -0,0 +1,134 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: codingparams_byteio.cpp,v 1.9 2008/04/29 08:51:52 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/codingparams_byteio.h> +#include <libdirac_common/common.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; + +CodingParamsByteIO::CodingParamsByteIO(const SourceParams& src_params, + CodecParams& codec_params, + const SourceParams& default_source_params, + const ByteIO& stream_data): +ByteIO(stream_data), +m_src_params(src_params), +m_codec_params(codec_params), +m_default_source_params(default_source_params) +{ + +} + +CodingParamsByteIO::~CodingParamsByteIO() +{ +} + +//---------public--------------------------------------------------- + +void CodingParamsByteIO::Input() +{ + // input picture coding mode + InputPictureCodingMode(); + + m_codec_params.SetTopFieldFirst(m_src_params.TopFieldFirst()); + + // Set the dimensions to frame dimensions + m_codec_params.SetXl(m_src_params.Xl()); + m_codec_params.SetYl(m_src_params.Yl()); + + m_codec_params.SetChromaXl(m_src_params.ChromaWidth()); + m_codec_params.SetChromaYl(m_src_params.ChromaHeight()); + + // If source was coded as fields, halve the vertical dimensions + // to set them to field dimensions + if (m_codec_params.FieldCoding()) + { + m_codec_params.SetYl(m_codec_params.Yl()>>1); + m_codec_params.SetChromaYl(m_codec_params.ChromaYl()>>1); + } + + unsigned int luma_depth = static_cast<unsigned int> + ( + std::log((double)m_src_params.LumaExcursion())/std::log(2.0) + 1 + ); + m_codec_params.SetLumaDepth(luma_depth); + + unsigned int chroma_depth = static_cast<unsigned int> + ( + std::log((double)m_src_params.ChromaExcursion())/std::log(2.0) + 1 + ); + m_codec_params.SetChromaDepth(chroma_depth); + + // byte align + ByteAlignInput(); +} + + +void CodingParamsByteIO::Output() +{ + // output picture coding mode flag + OutputPictureCodingMode(); + + // byte align + ByteAlignOutput(); +} + +//-------------private--------------------------------------------------------------- + +void CodingParamsByteIO::InputPictureCodingMode() +{ + unsigned int coding_mode = ReadUint(); + if (coding_mode > 1) + { + std::ostringstream errstr; + errstr << "Picture coding mode " << coding_mode + << " out of range [0-1]"; + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_ACCESSUNIT_ERROR); + } + m_codec_params.SetPictureCodingMode(coding_mode); +} + + +void CodingParamsByteIO::OutputPictureCodingMode() +{ + WriteUint(m_codec_params.FieldCoding() ? 1 : 0); +} + + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/codingparams_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/codingparams_byteio.h new file mode 100644 index 000000000..b96b037a0 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/codingparams_byteio.h @@ -0,0 +1,135 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: codingparams_byteio.h,v 1.3 2007/12/05 01:42:40 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class CodingParamsByteIO +*/ +#ifndef codingparams_byteio_h +#define codingparams_byteio_h + + +// DIRAC INCLUDES +#include <libdirac_common/common.h> // CodecParams, SourceParams + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class + + +namespace dirac +{ + + /** + * Represents compressed sequence-parameter data used in an AccessUnit + */ + class CodingParamsByteIO : public ByteIO + { + public: + + /** + * Constructor + *@param src_params Source parameters + *@param codec_params Coding parameters + *@param default_source_params Default source parameters + *@param stream_data Source/Destination of data + */ + CodingParamsByteIO(const SourceParams& src_params, + CodecParams& codec_params, + const SourceParams& default_source_params, + const ByteIO& stream_data); + + + /** + * Destructor + */ + ~CodingParamsByteIO(); + + /** + * Reads sequence information from Dirac byte-format + */ + void Input(); + + /** + * Outputs sequence information to Dirac byte-format + */ + void Output(); + + protected: + + + private: + + /** + * Reads number of bits used to compress input signal + */ + void InputVideoDepth(); + + /** + * Reads picture coding mode - 0 - frames, 1 - fields + */ + void InputPictureCodingMode(); + + /** + * Outputs number of bits used to compress input signal + */ + void OutputVideoDepth(); + + /** + * Outputs how input was coded - i.e. frames or fields + */ + void OutputPictureCodingMode(); + + /** + * Source paramters for intput/output + */ + const SourceParams& m_src_params; + + /** + * Coding paramters for intput/output + */ + CodecParams& m_codec_params; + + /** + * Default source parameters + */ + const SourceParams& m_default_source_params; + + }; + + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/component_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/component_byteio.cpp new file mode 100644 index 000000000..07f5433d1 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/component_byteio.cpp @@ -0,0 +1,98 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: component_byteio.cpp,v 1.2 2008/04/29 08:51:52 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/component_byteio.h> + +using namespace dirac; +using namespace std; + +ComponentByteIO::ComponentByteIO(CompSort cs, + const ByteIO& byteio): +ByteIO(byteio), +m_compsort(cs) +{} + +ComponentByteIO::ComponentByteIO(CompSort cs): +ByteIO(), +m_compsort(cs) +{} + +ComponentByteIO::~ComponentByteIO() +{} + +//--------------public---------------------------------------------- + +void ComponentByteIO::AddSubband(SubbandByteIO* p_subband_byteio) +{ + OutputBytes(p_subband_byteio->GetBytes()); +} + +void ComponentByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats) +{ + // set number of component bytes + switch(m_compsort) + { + case Y_COMP: + dirac_byte_stats.SetByteCount(STAT_YCOMP_BYTE_COUNT, + GetSize()); + break; + case U_COMP: + dirac_byte_stats.SetByteCount(STAT_UCOMP_BYTE_COUNT, + GetSize()); + break; + case V_COMP: + dirac_byte_stats.SetByteCount(STAT_VCOMP_BYTE_COUNT, + GetSize()); + break; + } +} + +bool ComponentByteIO::Input() +{ + + return true; +} + +void ComponentByteIO::Output() +{ + + +} + + +//-------------private------------------------------------------------------- + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/component_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/component_byteio.h new file mode 100644 index 000000000..e80b0877a --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/component_byteio.h @@ -0,0 +1,125 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class ComponentByteIO +*/ +#ifndef component_byteio_h +#define component_byteio_h + + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class +#include <libdirac_byteio/subband_byteio.h> // child-type + +// DIRAC includes + +// SYSTEM INCLUDES +#include <vector> + +namespace dirac +{ + /** + * Picture component in Dirac bytestream format + */ + class ComponentByteIO : public ByteIO + { + public: + + /** + * Constructor + *@param cs Picture-component type + *@param byteIO Input/output Byte stream + */ + ComponentByteIO(CompSort cs, + const ByteIO& byteIO); + + /** + * Constructor + *@param cs Picture-component type + */ + ComponentByteIO(CompSort cs); + + /** + * Destructor + */ + ~ComponentByteIO(); + + /** + * Gathers byte stats on the component data + *@param dirac_byte_stats Stat container + */ + void CollateByteStats(DiracByteStats& dirac_byte_stats); + + /** + * Add a subband byte-stream to this component + *@param p_subband_byteio Subband to be added + */ + void AddSubband(SubbandByteIO *p_subband_byteio); + + /** + * Inputs data from Dirac stream-format + */ + bool Input(); + + /** + * Outputs picture values to Dirac stream-format + */ + void Output(); + + + + protected: + + + private: + + /** + * Picture component type + */ + CompSort m_compsort; + + /** + * List of subbands in output/input order + */ + std::vector<ByteIO*> m_subband_list; + + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stats.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stats.cpp new file mode 100644 index 000000000..9c697bc3d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stats.cpp @@ -0,0 +1,84 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_byte_stats.cpp,v 1.3 2008/04/29 12:27:49 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/dirac_byte_stats.h> + +using namespace dirac; +using namespace std; + + +DiracByteStats::DiracByteStats() +{ +} + +DiracByteStats::DiracByteStats(const DiracByteStats& dirac_byte_stats): +m_byte_count(dirac_byte_stats.m_byte_count) +{ +} + +DiracByteStats::~DiracByteStats() +{ +} + + +void DiracByteStats::Clear() +{ + m_byte_count.clear(); +} + +int64_t DiracByteStats::GetBitCount(const StatType& stat_type) const +{ + return GetByteCount(stat_type) * CHAR_BIT; +} + +int64_t DiracByteStats::GetByteCount(const StatType& stat_type) const +{ + std::map<StatType, int64_t>::const_iterator it; + it = m_byte_count.find(stat_type); + if(it==m_byte_count.end()) + return 0; + + return it->second; +} + +void DiracByteStats::SetByteCount(const StatType& stat_type, int64_t count) +{ + if(m_byte_count.find(stat_type)==m_byte_count.end()) + m_byte_count[stat_type]=0; + + m_byte_count[stat_type]+=count; + } diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stats.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stats.h new file mode 100644 index 000000000..0da273f0a --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stats.h @@ -0,0 +1,120 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_byte_stats.h,v 1.5 2008/05/06 09:35:51 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class DiracByteStats +*/ +#ifndef dirac_byte_stats_h +#define dirac_byte_stats_h + +// SYSTEM INCLUDES +#include <map> // for byte-counts +#include <climits> + +#include <libdirac_common/dirac_inttypes.h> + +namespace dirac +{ + + #ifdef _MSC_VER + // char length + #define CHAR_BIT 8 +#endif + + typedef enum { + STAT_TOTAL_BYTE_COUNT=0, + STAT_MV_BYTE_COUNT, + STAT_YCOMP_BYTE_COUNT, + STAT_UCOMP_BYTE_COUNT, + STAT_VCOMP_BYTE_COUNT + } StatType; + + + /** + * Class DiracByteStats - for collecting statistics on aspects of the Dirac byte-stream + */ + class DiracByteStats + { + public: + /** + * Constructor + */ + DiracByteStats(); + + /** + * Copy constructor + */ + DiracByteStats(const DiracByteStats& dirac_byte_stats); + + /** + * Destructor + */ + ~DiracByteStats(); + + /** + * Clears data + */ + void Clear(); + + /** + * Gets number of bits for a particular stat-type + */ + int64_t GetBitCount(const StatType& stat_type) const; + + /** + * Gets number of bytes for a particular stat-type + */ + int64_t GetByteCount(const StatType& stat_type) const; + + /** + * Sets number of bytes for a particular stat-type + */ + void SetByteCount(const StatType& stat_type, int64_t count); + + + private: + + /** + * Map of byte-counts + */ + std::map<StatType, int64_t> m_byte_count; + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stream.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stream.cpp new file mode 100644 index 000000000..a45e54706 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stream.cpp @@ -0,0 +1,264 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_byte_stream.cpp,v 1.8 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/dirac_byte_stream.h> +#include <libdirac_byteio/endofsequence_byteio.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; +using namespace std; + +DiracByteStream::DiracByteStream(): +ByteIO(), +mp_prev_parse_unit(NULL) +{ +} + +DiracByteStream::~DiracByteStream() +{ + delete mp_prev_parse_unit; +} + +//---------------decoding---------------------------------------------------- + +void DiracByteStream::AddBytes(char* start, + int count) +{ + // add to input stream + string str(start, count); + ByteIO::OutputBytes(str); + +} + +DiracByteStats DiracByteStream::GetLastUnitStats() +{ + DiracByteStats dirac_byte_stats; + + if(m_parse_unit_list.empty()) + return dirac_byte_stats; + + ParseUnitByteIO* p_parse_unit = m_parse_unit_list.back().second; + p_parse_unit->CollateByteStats(dirac_byte_stats); + + return dirac_byte_stats; +} + +void DiracByteStream::Reset(ParseUnitByteIO* p_curr_unit, int pos) +{ + delete p_curr_unit; + SeekGet(pos, ios_base::beg); +} + +ParseUnitByteIO* DiracByteStream::GetNextParseUnit() +{ + if(GetSize()==0) + return NULL; + + int pos=0; + if(mp_prev_parse_unit) + { + // remove the unwanted bytes associated with the previous parse-unit + int prev_offset = mp_prev_parse_unit->GetNextParseOffset(); + RemoveRedundantBytes(prev_offset ? prev_offset : mp_prev_parse_unit->GetSize()); + delete mp_prev_parse_unit; + mp_prev_parse_unit=NULL; + if(!GetSize()) + return NULL; + } + + ParseUnitByteIO* p_curr_unit=NULL; + + while(true) + { + pos = GetReadBytePosition(); + + p_curr_unit = new ParseUnitByteIO(*this); + if (!p_curr_unit->Input()) + { + Reset(p_curr_unit, pos); + return NULL; + } + + // skip past current unit + if(!p_curr_unit->CanSkip()) + { + Reset(p_curr_unit, pos); + return NULL; + } + + if (p_curr_unit->IsEndOfSequence()) + { + break; + } + + // look to see if next unit validates the current one + if(!p_curr_unit->IsValid()) + { + // delete the unit - it's invalid + delete p_curr_unit; + // remove unwanted portion of bytes + RemoveRedundantBytes(pos); + // look for next potential parse-unit + continue; + } + break; + } // while + + // Remove all redundant bytes that are not part of a parse unit + int remove_size = std::max (0, GetReadBytePosition()-p_curr_unit->GetSize()); + if (remove_size) + { + //std::cerr << "Size="<<GetSize() << " Un-useful bytes=" << remove_size << std::endl; + RemoveRedundantBytes(remove_size); + } + + mp_prev_parse_unit=p_curr_unit; + return p_curr_unit; +} + +DiracByteStats DiracByteStream::GetSequenceStats() const +{ + return m_sequence_stats; +} + +//---------------encoding----------------------------------------------------- + +void DiracByteStream::AddSequenceHeader(SequenceHeaderByteIO *p_seqheader_byteio) +{ + // set previous parse-unit details + ParseUnitByteIO *mp_previous_parse_unit=mp_prev_parse_unit; + + if(!m_parse_unit_list.empty()) + mp_previous_parse_unit = m_parse_unit_list.back().second; + + // set adjacent parse-unit + p_seqheader_byteio->SetAdjacentParseUnits(mp_previous_parse_unit); + + // push onto to pending list + m_parse_unit_list.push(std::make_pair (PU_SEQ_HEADER, p_seqheader_byteio) ); + + // set previous parse-unit + mp_previous_parse_unit = p_seqheader_byteio; + + // save stats + p_seqheader_byteio->CollateByteStats(m_sequence_stats); +} + +void DiracByteStream::AddPicture(PictureByteIO *p_frame_byteio) +{ + // set previous parse-unit details + ParseUnitByteIO *mp_previous_parse_unit=mp_prev_parse_unit; + + if(!m_parse_unit_list.empty()) + mp_previous_parse_unit = m_parse_unit_list.back().second; + + // set adjacent parse-unit + p_frame_byteio->SetAdjacentParseUnits(mp_previous_parse_unit); + + // push onto to pending list + m_parse_unit_list.push(std::make_pair(PU_PICTURE, p_frame_byteio ) ); + + // set previous parse-unit + mp_previous_parse_unit = p_frame_byteio; + + // save stats + p_frame_byteio->CollateByteStats(m_sequence_stats); +} + +void DiracByteStream::Clear() +{ + while(!m_parse_unit_list.empty()) + { + ParseUnitByteIO* p_parse_unit=m_parse_unit_list.front().second; + m_parse_unit_list.pop(); + if(m_parse_unit_list.empty()) + { + delete mp_prev_parse_unit; + mp_prev_parse_unit=p_parse_unit; + } + else + delete p_parse_unit; + } +} + +DiracByteStats DiracByteStream::EndSequence() +{ + // create + EndOfSequenceByteIO *p_endofsequence_byteio = new EndOfSequenceByteIO(*this); + + // set previous parse-unit details + ParseUnitByteIO *mp_previous_parse_unit=mp_prev_parse_unit; + + if(!m_parse_unit_list.empty()) + mp_previous_parse_unit = m_parse_unit_list.back().second; + + // set adjacent parse-unit + p_endofsequence_byteio->SetAdjacentParseUnits(mp_previous_parse_unit); + + // push onto to pending list + m_parse_unit_list.push(std::make_pair(PU_END_OF_SEQUENCE, p_endofsequence_byteio) ); + + p_endofsequence_byteio->CollateByteStats(m_sequence_stats); + + // clear stats + DiracByteStats seq_stats(m_sequence_stats); + m_sequence_stats.Clear(); + + // return seq stats + return seq_stats; +} + +const string DiracByteStream::GetBytes() +{ + // take copy + ParseUnitList parse_list = m_parse_unit_list; + mp_stream->str(""); + + while(!parse_list.empty()) + { + *mp_stream << parse_list.front().second->GetBytes(); + parse_list.pop(); + } + + return mp_stream->str(); +} + +bool DiracByteStream::IsUnitAvailable() const +{ + return !m_parse_unit_list.empty(); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stream.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stream.h new file mode 100644 index 000000000..d448b5fca --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/dirac_byte_stream.h @@ -0,0 +1,158 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_byte_stream.h,v 1.4 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class DiracByteStream +*/ +#ifndef dirac_byte_stream_h +#define dirac_byte_stream_h + +//SYSTEM INCLUDES +#include <queue> + +//LOCAL INCLUDES +#include "byteio.h" // Parent class +#include "accessunit_byteio.h" // manages parse-unit types +#include "picture_byteio.h" // manages parse-unit types + +namespace dirac +{ + + /** + * Represents a series of bytes in the Dirac bytestream specfication format. + * These bytes are grouped into more managable parse units by this class. + */ + class DiracByteStream : public ByteIO + { + public: + + /** + * Constructor + */ + DiracByteStream(); + + /** + * Destructor + */ + ~DiracByteStream(); + + /** + * Adds Dirac-formatted bytes to internal-byte-stream for processing + *@param start Start of char list + *@param count Number of chars + */ + void AddBytes(char* start, int count); + + /** + * Gets the statistics of the most recent parse-unit to be processed + *@return Byte-statistics + */ + DiracByteStats GetLastUnitStats(); + + /** + * Gets the next parse-unit in the current byte-stream + */ + ParseUnitByteIO* GetNextParseUnit(); + + + /** + * Gets stats for current sequence + */ + DiracByteStats GetSequenceStats() const; + + /** + * Adds a random access point to the current Dirac byte stream + *@param p_seqheader_byteio Sequence header data. + */ + void AddSequenceHeader(SequenceHeaderByteIO *p_seqheader_byteio); + + /** + * Adds a picture to the current Dirac byte stream + *@param p_frame_byteio Picture stream. This class is now responsible for deleting. + */ + void AddPicture(PictureByteIO *p_frame_byteio); + + /** + * Clear parse-units + */ + void Clear(); + + /** + * Insert end-of-sequence data + *@return Sequence stats + */ + DiracByteStats EndSequence(); + + /** + * Gets a pointer to all current output bytes + */ + const std::string GetBytes(); + + /** + * Any info pending? + */ + bool IsUnitAvailable() const; + + private: + + void Reset(ParseUnitByteIO* p_curr_unit, int pos); + + private: + + /** + * Parse-units in Dirac stream + */ + typedef std::queue< std::pair <ParseUnitType, ParseUnitByteIO*> > ParseUnitList; + ParseUnitList m_parse_unit_list; + + /** + * Last unit to be processed + * Required for specifying the previous parse-unit + */ + ParseUnitByteIO* mp_prev_parse_unit; + + /** + * Stats for current sequence + */ + DiracByteStats m_sequence_stats; + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/displayparams_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/displayparams_byteio.cpp new file mode 100644 index 000000000..e74a4f278 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/displayparams_byteio.cpp @@ -0,0 +1,502 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: displayparams_byteio.cpp,v 1.10 2008/01/31 11:25:15 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/displayparams_byteio.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; + +SourceParamsByteIO::SourceParamsByteIO( SourceParams& src_params, + const SourceParams& default_src_params, + const ByteIO& stream_data): +ByteIO(stream_data), +m_src_params(src_params), +m_default_src_params(default_src_params) +{ + + +} + +SourceParamsByteIO::~SourceParamsByteIO() +{ +} + +//-----------------public---------------------------------------------------- + +void SourceParamsByteIO::Input() +{ + // input frame dimensions + InputFrameSize(); + + // input chroma sampling format + InputChromaSamplingFormat(); + + // input scan format + InputScanFormat(); + + // input frame rate + InputFrameRate(); + + // input pixel aspect ratio + InputPixelAspectRatio(); + + // input clean area + InputCleanArea(); + + // input signal range + InputSignalRange(); + + // input colour spec + InputColourSpecification(); +} + +void SourceParamsByteIO::Output() +{ + // output frame dimensions + OutputFrameSize(); + + // output chroma sampling format + OutputChromaSamplingFormat(); + + // output scan format + OutputScanFormat(); + + // output frame rate + OutputFrameRate(); + + // output pixel aspect ratio + OutputPixelAspectRatio(); + + // output clean area + OutputCleanArea(); + + // output signal range + OutputSignalRange(); + + // output colour spec + OutputColourSpecification(); +} + +//-------------------private----------------------------------------------- +void SourceParamsByteIO::InputFrameSize() +{ + bool custom_flag = ReadBool(); + + if(!custom_flag) + return; + + // set custom width + m_src_params.SetXl(ReadUint()); + + // set custom height + m_src_params.SetYl(ReadUint()); +} + +void SourceParamsByteIO::InputChromaSamplingFormat() +{ + bool chroma_flag = ReadBool(); + + if(!chroma_flag) + return; + + // set chroma + ChromaFormat chroma_format = IntToChromaFormat(ReadUint()); + if(chroma_format==formatNK) + DIRAC_THROW_EXCEPTION( + ERR_INVALID_CHROMA_FORMAT, + "Dirac does not recognise the specified chroma-format", + SEVERITY_ACCESSUNIT_ERROR) + m_src_params.SetCFormat(chroma_format); +} + +void SourceParamsByteIO::InputPixelAspectRatio() +{ + bool pixel_aspect_ratio_flag = ReadBool(); + if(!pixel_aspect_ratio_flag) + return; + + // read index value + int pixel_aspect_ratio_index = ReadUint(); + PixelAspectRatioType pixel_aspect_ratio=IntToPixelAspectRatioType(pixel_aspect_ratio_index); + if(pixel_aspect_ratio==PIXEL_ASPECT_RATIO_UNDEFINED) + DIRAC_THROW_EXCEPTION( + ERR_INVALID_PIXEL_ASPECT_RATIO, + "Dirac does not recognise the specified pixel_aspect_ratio", + SEVERITY_ACCESSUNIT_ERROR) + + if(pixel_aspect_ratio_index!=PIXEL_ASPECT_RATIO_CUSTOM) + { + m_src_params.SetPixelAspectRatio(pixel_aspect_ratio); + } + else + { + // read num/denom + int numerator = ReadUint(); + int denominator = ReadUint(); + m_src_params.SetPixelAspectRatio(numerator, denominator); + } + +} + +void SourceParamsByteIO::InputCleanArea() +{ + bool clean_area_flag = ReadBool(); + if(!clean_area_flag) + return; + + m_src_params.SetCleanWidth( ReadUint() ); + m_src_params.SetCleanHeight( ReadUint() ); + m_src_params.SetLeftOffset( ReadUint() ); + m_src_params.SetTopOffset( ReadUint() ); +} + +void SourceParamsByteIO::InputColourMatrix() +{ + bool colour_matrix_flag = ReadBool(); + if(!colour_matrix_flag) + return; + + // read index value + int colour_matrix_index = ReadUint(); + m_src_params.SetColourMatrixIndex(colour_matrix_index); +} + +void SourceParamsByteIO::InputColourPrimaries() +{ + bool colour_primaries_flag = ReadBool(); + if(!colour_primaries_flag) + return; + + // read index value + int colour_primaries_index = ReadUint(); + m_src_params.SetColourPrimariesIndex(colour_primaries_index); +} + +void SourceParamsByteIO::InputColourSpecification() +{ + bool colour_spec_flag = ReadBool(); + if(!colour_spec_flag) + return; + + // read index value + int colour_spec_index = ReadUint(); + m_src_params.SetColourSpecification( colour_spec_index ); + if(colour_spec_index==0) + { + InputColourPrimaries(); + InputColourMatrix(); + InputTransferFunction(); + } +} + +void SourceParamsByteIO::InputFrameRate() +{ + bool fr_flag = ReadBool(); + if(!fr_flag) + return; + + int frame_rate_index = ReadUint(); + FrameRateType frame_rate=IntToFrameRateType(frame_rate_index); + if(frame_rate==FRAMERATE_UNDEFINED) + DIRAC_THROW_EXCEPTION( + ERR_INVALID_PICTURE_RATE, + "Dirac does not recognise the specified frame-rate", + SEVERITY_ACCESSUNIT_ERROR) + + if(frame_rate_index!=FRAMERATE_CUSTOM) + { + m_src_params.SetFrameRate(frame_rate); + } + else + { + // read num/denom + int numerator = ReadUint(); + int denominator = ReadUint(); + m_src_params.SetFrameRate(numerator, denominator); + } +} + +void SourceParamsByteIO::InputScanFormat() +{ + bool scan_flag = ReadBool(); + if(!scan_flag) + return; + + unsigned int source_sampling = ReadUint(); + if (source_sampling > 1) + { + std::ostringstream errstr; + errstr << "Source Sampling " << source_sampling + << " out of range [0-1]"; + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_ACCESSUNIT_ERROR); + } + m_src_params.SetSourceSampling(source_sampling); +} + +void SourceParamsByteIO::InputSignalRange() +{ + bool signal_range_flag = ReadBool(); + if(!signal_range_flag) + return; + + // read index value + int signal_range_index = ReadUint(); + SignalRangeType signal_range = IntToSignalRangeType(signal_range_index); + if(signal_range==SIGNAL_RANGE_UNDEFINED) + DIRAC_THROW_EXCEPTION( + ERR_INVALID_SIGNAL_RANGE, + "Dirac does not recognise the specified signal-range", + SEVERITY_ACCESSUNIT_ERROR) + + if(signal_range_index!=SIGNAL_RANGE_CUSTOM) + { + m_src_params.SetSignalRange(signal_range); + } + else + { + // read luma values + m_src_params.SetLumaOffset( ReadUint() ); + m_src_params.SetLumaExcursion( ReadUint() ); + // read chroma values + m_src_params.SetChromaOffset( ReadUint() ); + m_src_params.SetChromaExcursion( ReadUint() ); + } +} + +void SourceParamsByteIO::InputTransferFunction() +{ + bool trans_fun_flag = ReadBool(); + if(!trans_fun_flag) + return; + + // read index value + int trans_fun_index = ReadUint(); + m_src_params.SetTransferFunctionIndex(trans_fun_index); +} + +void SourceParamsByteIO::OutputFrameSize() +{ + + // output 'is custom' dimensions flag + bool is_custom = (m_src_params.Xl()!=m_default_src_params.Xl() || + m_src_params.Yl()!=m_default_src_params.Yl()); + + WriteBit(is_custom); + + if(!is_custom) + return; + + // set custom X and Y + WriteUint(m_src_params.Xl()); + WriteUint(m_src_params.Yl()); + +} + +void SourceParamsByteIO::OutputChromaSamplingFormat() +{ + // output 'is default' flag + bool not_default = m_src_params.CFormat()!=m_default_src_params.CFormat(); + + WriteBit(not_default); + + if(!not_default) + return; + + // output chroma index + WriteUint(static_cast<int>(m_src_params.CFormat())); +} + + +void SourceParamsByteIO::OutputPixelAspectRatio() +{ + if (m_src_params.PixelAspectRatioIndex()!= PIXEL_ASPECT_RATIO_CUSTOM + && m_src_params.PixelAspectRatioIndex() == m_default_src_params.PixelAspectRatioIndex()) + { + // default frame rate index + WriteBit(0); + return; + } + // Non-defaults + WriteBit(1); + + // Picture rate index + WriteUint(m_src_params.PixelAspectRatioIndex()); + + if (!m_src_params.PixelAspectRatioIndex()) // i,e. custom value + { + WriteUint(m_src_params.PixelAspectRatio().m_num); + WriteUint(m_src_params.PixelAspectRatio().m_denom); + } +} + + +void SourceParamsByteIO::OutputCleanArea() +{ + if (m_src_params.CleanWidth() != m_default_src_params.CleanWidth() || + m_src_params.CleanHeight() != m_default_src_params.CleanHeight() || + m_src_params.LeftOffset() != m_default_src_params.LeftOffset() || + m_src_params.TopOffset() != m_default_src_params.TopOffset()) + { + WriteBit(1); // non-default value + WriteUint(m_src_params.CleanWidth()); + WriteUint(m_src_params.CleanHeight()); + WriteUint(m_src_params.LeftOffset()); + WriteUint(m_src_params.TopOffset()); + } + else + WriteBit(0); // default value +} + +void SourceParamsByteIO::OutputColourSpecification() +{ + if (m_src_params.ColourSpecificationIndex() && + m_src_params.ColourSpecificationIndex() == + m_default_src_params.ColourSpecificationIndex()) + { + // default colour specification + WriteBit(0); + return; + } + + // Non-defaults + WriteBit(1); + // Output Colour specification index + WriteUint(m_src_params.ColourSpecificationIndex()); + + if (!m_src_params.ColourSpecificationIndex()) // i,e, custom values + { + // Output Colour Primaries + if (m_src_params.ColourPrimariesIndex() == m_default_src_params.ColourPrimariesIndex()) + { + // default value + WriteBit(0); + } + else + { + WriteBit(1); + WriteUint(m_src_params.ColourPrimariesIndex()); + } + + // Output Colour Matrix + if (m_src_params.ColourMatrixIndex() == m_default_src_params.ColourMatrixIndex()) + { + // default value + WriteBit(0); + } + else + { + WriteBit(1); + WriteUint(m_src_params.ColourMatrixIndex()); + } + + // Output TransferFunction + if (m_src_params.TransferFunctionIndex() == m_default_src_params.TransferFunctionIndex()) + { + // default value + WriteBit(0); + } + else + { + WriteBit(1); + WriteUint(m_src_params.TransferFunctionIndex()); + } + } +} + +void SourceParamsByteIO::OutputFrameRate() +{ + if (m_src_params.FrameRateIndex()!=FRAMERATE_CUSTOM + && m_src_params.FrameRateIndex() == m_default_src_params.FrameRateIndex()) + { + // default frame rate index + WriteBit(0); + return; + } + // Non-defaults + WriteBit(1); + + // Picture rate index + WriteUint(m_src_params.FrameRateIndex()); + + if (!m_src_params.FrameRateIndex()) // i,e. custom value + { + WriteUint(m_src_params.FrameRate().m_num); + WriteUint(m_src_params.FrameRate().m_denom); + } +} + +void SourceParamsByteIO::OutputScanFormat() +{ + // output 'is default' flag + bool not_interlace_default = m_src_params.SourceSampling()!=m_default_src_params.SourceSampling(); + + WriteBit(not_interlace_default); + + if(!not_interlace_default) + return; + + // output interlace value + WriteUint(m_src_params.SourceSampling()); +} + + +void SourceParamsByteIO::OutputSignalRange() +{ + if (m_src_params.SignalRangeIndex()!=SIGNAL_RANGE_CUSTOM && + m_src_params.SignalRangeIndex() == m_default_src_params.SignalRangeIndex()) + { + // defaults + WriteBit(0); + return; + } + + // Non-defaults + WriteBit(1); + // Output Signal Range Index + WriteUint(m_src_params.SignalRangeIndex()); + + if (!m_src_params.SignalRangeIndex()) // i.e. custom values + { + WriteUint(m_src_params.LumaOffset()); + WriteUint(m_src_params.LumaExcursion()); + WriteUint(m_src_params.ChromaOffset()); + WriteUint(m_src_params.ChromaExcursion()); + } +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/displayparams_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/displayparams_byteio.h new file mode 100644 index 000000000..bc5fe823d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/displayparams_byteio.h @@ -0,0 +1,200 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: displayparams_byteio.h,v 1.4 2008/01/15 04:36:23 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class SourceParamsByteIO +*/ +#ifndef displayparams_byteio_h +#define displayparams_byteio_h + + +// DIRAC INCLUDES +#include <libdirac_common/common.h> // SeqParams + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class + + +namespace dirac +{ + + /** + * Represents compressed source-parameter data contained in a sequence header + */ + class SourceParamsByteIO : public ByteIO + { + public: + + /** + * Constructor for Input/Output + *@param src_params Source parameters + *@param default_src_params Default Source parameters + *@param stream_data Source/Destination of data + */ + SourceParamsByteIO( SourceParams& src_params, + const SourceParams& default_src_params, + const ByteIO& stream_data); + /** + * Destructor + */ + ~SourceParamsByteIO(); + + /** + * Reads source params information from Dirac byte-format + */ + void Input(); + + /** + * Outputs source params information to Dirac byte-format + */ + void Output(); + + protected: + + + private: + + /** + * Reads frame dimensions + */ + void InputFrameSize(); + + /** + * Reads Chroma Sampling Format + */ + void InputChromaSamplingFormat(); + + /** + * Reads pixel aspect ratio info + */ + void InputPixelAspectRatio(); + + /** + * Reads clean-area info + */ + void InputCleanArea(); + + /** + * Reads colour-matrix info + */ + void InputColourMatrix(); + + /** + * Reads primary-colour info + */ + void InputColourPrimaries(); + + /** + * Reads colour spec info + */ + void InputColourSpecification(); + + /** + * Reads frame-rate info + */ + void InputFrameRate(); + + /** + * Reads Scan info + */ + void InputScanFormat(); + + /** + * Reads signal range info + */ + void InputSignalRange(); + + /** + * Reads transfer-function info + */ + void InputTransferFunction(); + + /** + * Outputs frame dimensions + */ + void OutputFrameSize(); + + /** + * Outputs Chroma Sampling Format + */ + void OutputChromaSamplingFormat(); + + /** + * Outputs pixel aspect ratio info + */ + void OutputPixelAspectRatio(); + + /** + * Outputs clean-area info + */ + void OutputCleanArea(); + + /** + * Outputs colour spec info + */ + void OutputColourSpecification(); + + /** + * Outputs frame-rate info + */ + void OutputFrameRate(); + + /** + * Outputs Scan info + */ + void OutputScanFormat(); + + /** + * Outputs signal range info + */ + void OutputSignalRange(); + + /** + * Source parameters for input/ouput + */ + SourceParams& m_src_params; + + /** + * Default source parameters + */ + const SourceParams& m_default_src_params; + }; + + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/endofsequence_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/endofsequence_byteio.cpp new file mode 100644 index 000000000..ca0144e8e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/endofsequence_byteio.cpp @@ -0,0 +1,78 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: endofsequence_byteio.cpp,v 1.2 2007/03/29 16:43:38 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include "endofsequence_byteio.h" + +using namespace dirac; +using namespace std; + + +// start & end of end-of-sequence bits +#define PARSE_CODE_END_OF_SEQUENCE (0x10) + + +EndOfSequenceByteIO::EndOfSequenceByteIO(const ByteIO& byte_io): +ParseUnitByteIO(byte_io) +{ + +} + + +EndOfSequenceByteIO::~EndOfSequenceByteIO() +{ + +} + +void EndOfSequenceByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats) +{ + dirac_byte_stats.SetByteCount(STAT_TOTAL_BYTE_COUNT, GetSize()); +} + + + +//-------------private------------------------------------------------------- + +unsigned char EndOfSequenceByteIO::CalcParseCode() const +{ + unsigned char code = 0; + + // set end-of-sequence parse-code + SetBits(code, PARSE_CODE_END_OF_SEQUENCE); + + return code; +} + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/endofsequence_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/endofsequence_byteio.h new file mode 100644 index 000000000..0bce3997f --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/endofsequence_byteio.h @@ -0,0 +1,104 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: endofsequence_byteio.h,v 1.3 2008/01/31 11:25:15 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class EndOfSequenceByteIO +*/ +#ifndef endofsequence_byteio_h +#define endofsequence_byteio_h + + +//LOCAL INCLUDES +#include <libdirac_byteio/parseunit_byteio.h> // Parent class + +// DIRAC includes +#include <libdirac_common/common.h> // PictureType etc + +namespace dirac +{ + /** + * Signals the end of a sequence in a Dirac-formatted bitstream. Current Accessunit parameters + * are no longer valid for subsequent frames + */ + class EndOfSequenceByteIO : public ParseUnitByteIO + { + public: + + /** + * Constructor + *@param stream_data Stream parameters + */ + EndOfSequenceByteIO(const ByteIO& stream_data); + + /** + * Destructor + */ + ~EndOfSequenceByteIO(); + + + /** + * Gets parse-unit type + */ + ParseUnitType GetType() const { return PU_END_OF_SEQUENCE;} + + /** + * Gathers byte stats on the end of sequence data + *@param dirac_byte_stats Stat container + */ + void CollateByteStats(DiracByteStats& dirac_byte_stats); + protected: + + /** + * Calculates number of bytes to start of next unit + *@return Zero(0) End of sequence does not specify a 'next'unit + */ + int CalcNextUnitOffset() { return 0;} + + private: + + /** + * Calculates parse-code based on picture parameters + *@return Char bit-set + */ + unsigned char CalcParseCode() const; + + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdata_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdata_byteio.cpp new file mode 100644 index 000000000..2ed0357aa --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdata_byteio.cpp @@ -0,0 +1,332 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mvdata_byteio.cpp,v 1.13 2008/08/27 00:17:10 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/mvdata_byteio.h> +#include <libdirac_common/video_format_defaults.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; + +MvDataByteIO::MvDataByteIO(PictureParams& pparams, + PicturePredParams& picpredparams): +ByteIO(), +m_pparams(pparams), +m_picpredparams(picpredparams), +m_splitmode_data(), +m_predmode_data(), +m_mv1hblock_data(), +m_mv1vblock_data(), +m_mv2hblock_data(), +m_mv2vblock_data(), +m_ydcblock_data(), +m_udcblock_data(), +m_vdcblock_data() +{} + +MvDataByteIO::MvDataByteIO(ByteIO &byte_io, PictureParams& pparams, + PicturePredParams& picpredparams): +ByteIO(byte_io), +m_pparams(pparams), +m_picpredparams(picpredparams), +m_splitmode_data(byte_io), +m_predmode_data(byte_io), +m_mv1hblock_data(byte_io), +m_mv1vblock_data(byte_io), +m_mv2hblock_data(byte_io), +m_mv2vblock_data(byte_io), +m_ydcblock_data(byte_io), +m_udcblock_data(byte_io), +m_vdcblock_data(byte_io) +{} + +MvDataByteIO::~MvDataByteIO() +{} + +void MvDataByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats) +{ + // set number of MV bytes + dirac_byte_stats.SetByteCount(STAT_MV_BYTE_COUNT, + GetSize()); +} + +int MvDataByteIO::GetSize() const +{ + if (m_pparams.NumRefs()==2) + return ByteIO::GetSize() + + m_splitmode_data.GetSize()+ + m_predmode_data.GetSize()+ + m_mv1hblock_data.GetSize()+ + m_mv1vblock_data.GetSize()+ + m_mv2hblock_data.GetSize()+ + m_mv2vblock_data.GetSize()+ + m_ydcblock_data.GetSize()+ + m_udcblock_data.GetSize()+ + m_vdcblock_data.GetSize(); + else + return ByteIO::GetSize() + + m_splitmode_data.GetSize()+ + m_predmode_data.GetSize()+ + m_mv1hblock_data.GetSize()+ + m_mv1vblock_data.GetSize()+ + m_ydcblock_data.GetSize()+ + m_udcblock_data.GetSize()+ + m_vdcblock_data.GetSize(); +} + +const std::string MvDataByteIO::GetBytes() +{ + //Output header and block data + if (m_pparams.NumRefs()==2 ) + return ByteIO::GetBytes() + + m_splitmode_data.GetBytes()+ + m_predmode_data.GetBytes()+ + m_mv1hblock_data.GetBytes()+ + m_mv1vblock_data.GetBytes()+ + m_mv2hblock_data.GetBytes()+ + m_mv2vblock_data.GetBytes()+ + m_ydcblock_data.GetBytes()+ + m_udcblock_data.GetBytes()+ + m_vdcblock_data.GetBytes(); + else + return ByteIO::GetBytes() + + m_splitmode_data.GetBytes()+ + m_predmode_data.GetBytes()+ + m_mv1hblock_data.GetBytes()+ + m_mv1vblock_data.GetBytes()+ + m_ydcblock_data.GetBytes()+ + m_udcblock_data.GetBytes()+ + m_vdcblock_data.GetBytes(); +} + +void MvDataByteIO::Input() +{ + // Byte Alignment + ByteAlignInput(); + + // Input Block Params + InputBlockParams(); + + // Input Motion Vector Precision + InputMVPrecision(); + + // Input chroma + InputGlobalMotionParams(); + + // Input Picture Prediction mode + InputFramePredictionMode(); + + // Input picture weights + InputPictureWeights(); + + // Byte Alignment + ByteAlignInput(); +} + +void MvDataByteIO::Output() +{ + // Output Block Params + OutputBlockParams(); + + // Output Motion Vector Precision + OutputMVPrecision(); + + // output global motion + OutputGlobalMotionParams(); + + // output picture prediction mode + OutputFramePredictionMode(); + + // output picture weights + OutputPictureWeights(); + + // Byte Align + ByteAlignOutput(); +} + +//-------------private--------------------------------------------------------------- + +void MvDataByteIO::OutputBlockParams() +{ + const OLBParams& olb_params = m_picpredparams.LumaBParams(2); + + // output custom block params flag + unsigned int pidx = BlockParametersIndex(olb_params); + WriteUint(pidx); + if (pidx == 0) // custom block params + { + // output Xblen + WriteUint(olb_params.Xblen()); + // output Yblen + WriteUint(olb_params.Yblen()); + // output Xbsep + WriteUint(olb_params.Xbsep()); + // output Ybsep + WriteUint(olb_params.Ybsep()); + } +} + +void MvDataByteIO::InputBlockParams() +{ + OLBParams olb_params; + + unsigned int p_idx = ReadUint(); + if (p_idx == 0) + { + // Input Xblen + olb_params.SetXblen(ReadUint()); + // Input Yblen + olb_params.SetYblen(ReadUint()); + // Input Xbsep + olb_params.SetXbsep(ReadUint()); + // Input Ybsep + olb_params.SetYbsep(ReadUint()); + } + else + SetDefaultBlockParameters (olb_params, p_idx); + + m_picpredparams.SetLumaBlockParams(olb_params); +} + +void MvDataByteIO::OutputMVPrecision() +{ + // Output Motion vector precision + WriteUint(m_picpredparams.MVPrecision()); +} + +void MvDataByteIO::InputMVPrecision() +{ + // Input Motion vector precision + MVPrecisionType mv_prec = IntToMVPrecisionType(ReadUint()); + if(mv_prec==MV_PRECISION_UNDEFINED) + DIRAC_THROW_EXCEPTION( + ERR_INVALID_MOTION_VECTOR_PRECISION, + "Dirac does not recognise the specified MV precision", + SEVERITY_PICTURE_ERROR) + + m_picpredparams.SetMVPrecision(mv_prec); +} + +void MvDataByteIO::OutputGlobalMotionParams() +{ + // Always setting global motion to false + // NOTE: FIXME - output actual global motion params in future + // Using Global motion flag + WriteBit(false); +} + +void MvDataByteIO::InputGlobalMotionParams() +{ + // Always setting global motion to false + // Using Global motion flag + if (ReadBool()) + { + m_picpredparams.SetUsingGlobalMotion(true); + + // NOTE: FIXME - input actual global motion params in future + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + "Cannot handle global motion parameters", + SEVERITY_PICTURE_ERROR) + } + else + m_picpredparams.SetUsingGlobalMotion(false); +} + +void MvDataByteIO::OutputFramePredictionMode() +{ + // TODO: Output default picture prediction mode index until other + // modes are supported. + WriteUint(0); +} + +void MvDataByteIO::InputFramePredictionMode() +{ + // TODO - need to process this field when alternative prediction modes + // become available. + unsigned int frame_pred_mode = ReadUint(); + if (frame_pred_mode != 0) + { + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + "Non-default Picture Prediction Mode not supported", + SEVERITY_PICTURE_ERROR); + } +} + + +void MvDataByteIO::OutputPictureWeights() +{ + // Output default weights flags + if (m_picpredparams.PictureWeightsBits() != 1 || + m_picpredparams.Ref1Weight() != 1 || + (m_pparams.Refs().size() > 1 && m_picpredparams.Ref2Weight() != 1) ) + { + WriteBit(true); + // Output weight precision bits + WriteUint(m_picpredparams.PictureWeightsBits()); + // Output Ref1 weight + WriteSint(m_picpredparams.Ref1Weight()); + if (m_pparams.Refs().size() > 1) + { + // Output Ref1 weight + WriteSint(m_picpredparams.Ref2Weight()); + } + } + else + { + WriteBit(false); + } +} + +void MvDataByteIO::InputPictureWeights() +{ + if (ReadBool()) + { + m_picpredparams.SetPictureWeightsPrecision(ReadUint()); + m_picpredparams.SetRef1Weight(ReadSint()); + if (m_pparams.Refs().size() > 1) + m_picpredparams.SetRef2Weight(ReadSint()); + else + m_picpredparams.SetRef2Weight(0); + } + else + { + m_picpredparams.SetPictureWeightsPrecision(1); + m_picpredparams.SetRef1Weight(1); + m_picpredparams.SetRef2Weight(1); + } +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdata_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdata_byteio.h new file mode 100644 index 000000000..578a3594e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdata_byteio.h @@ -0,0 +1,269 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mvdata_byteio.h,v 1.5 2008/09/10 12:28:46 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class MvDataByteIO +*/ +#ifndef MV_DATA_BYTEIO_H +#define MV_DATA_BYTEIO_H + + +// DIRAC INCLUDES +#include <libdirac_common/common.h> // EncParams + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class +#include <libdirac_byteio/mvdataelement_byteio.h>// Member byteio class + + +namespace dirac +{ + /** + * Represents compressed sequence-parameter data used in an AccessUnit + */ + class MvDataByteIO : public ByteIO + { + public: + + /** + * Constructor + *@param pparams Picture Params + *@param picpredparams Picture prediction parameters + */ + MvDataByteIO(PictureParams& pparams, + PicturePredParams& picpredparams); + + /** + * Constructor + *@param byte_io Input/Output Byte stream + *@param pparams Picture Params + *@param picpredparams Picture prediction parameters + */ + MvDataByteIO(ByteIO &byte_io, PictureParams& pparams, + PicturePredParams& picpredparams); + + /** + * Destructor + */ + virtual ~MvDataByteIO(); + + /** + * Gathers byte stats on the motion vector data + *@param dirac_byte_stats Stat container + */ + void CollateByteStats(DiracByteStats& dirac_byte_stats); + + /** + * Outputs motion vector data Dirac byte-format + */ + void Output(); + + /** + * Inputs motion vector information + */ + void Input(); + + + /** + * Get string containing coded bytes + */ + virtual const std::string GetBytes(); + + /** + * Return pointer to the superblock splitting modes ByteIO stream + */ + MvDataElementByteIO* SplitModeData() { return &m_splitmode_data; }; + + /** + * Return pointer to the superblock splitting modes ByteIO stream + */ + MvDataElementByteIO* PredModeData() { return &m_predmode_data; }; + + /** + * Return pointer to the block MVs reference 1 ByteIO stream + */ + MvDataElementByteIO* MV1HorizData() { return &m_mv1hblock_data; }; + + /** + * Return pointer to the block MVs reference 1 ByteIO stream + */ + MvDataElementByteIO* MV1VertData() { return &m_mv1vblock_data; }; + + /** + * Return pointer to the block MV reference 2 ByteIO stream + */ + MvDataElementByteIO* MV2HorizData() { return &m_mv2hblock_data; }; + + /** + * Return pointer to the block MV reference 2 ByteIO stream + */ + MvDataElementByteIO* MV2VertData() { return &m_mv2vblock_data; }; + + /** + * Return pointer to the block Y DC values ByteIO stream + */ + MvDataElementByteIO* YDCData() { return &m_ydcblock_data; }; + + /** + * Return pointer to the block U DC values ByteIO stream + */ + MvDataElementByteIO* UDCData() { return &m_udcblock_data; }; + + /** + * Return pointer to the block V DC values ByteIO stream + */ + MvDataElementByteIO* VDCData() { return &m_vdcblock_data; }; + + /** + * Return the size + */ + int GetSize() const; + + protected: + + + private: + /** + * Inputs block parameters + */ + void InputBlockParams(); + + /** + * Inputs Motion vector precision data + */ + void InputMVPrecision(); + + /** + * Inputs global motion parameters + */ + void InputGlobalMotionParams(); + + /** + * Inputs picture prediction mode + */ + void InputFramePredictionMode(); + + /** + * Inputs Picture Weights + */ + void InputPictureWeights(); + + /** + * Outputs block parameters + */ + void OutputBlockParams(); + + /** + * Outputs Motion vector precision data + */ + void OutputMVPrecision(); + + /** + * Outputs global motion parameters + */ + void OutputGlobalMotionParams(); + + /** + * Outputs picture prediction mode + */ + void OutputFramePredictionMode(); + + /** + * Outputs Picture Weights + */ + void OutputPictureWeights(); + + /** + * Sequence paramters for intput/output + */ + PictureParams& m_pparams; + + /** + * Codec params - EncParams for Output and DecParams for input + */ + PicturePredParams& m_picpredparams; + + /** + * block data containing split modes + */ + MvDataElementByteIO m_splitmode_data; + + /** + * block data containing prediction modes + */ + MvDataElementByteIO m_predmode_data; + + /** + * block data containing horizontal MV components for reference 1 + */ + MvDataElementByteIO m_mv1hblock_data; + + /** + * block data containing vertical MV components for reference 1 + */ + MvDataElementByteIO m_mv1vblock_data; + + /** + * block data containing horizontal MV components for reference 2 + */ + MvDataElementByteIO m_mv2hblock_data; + + /** + * block data containing vertical MV components for reference 2 + */ + MvDataElementByteIO m_mv2vblock_data; + + /** + * block data containing Y DC data + */ + MvDataElementByteIO m_ydcblock_data; + + /** + * block data containing U DC data + */ + MvDataElementByteIO m_udcblock_data; + + /** + * block data containing V DC data + */ + MvDataElementByteIO m_vdcblock_data; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdataelement_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdataelement_byteio.cpp new file mode 100644 index 000000000..f8785616d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdataelement_byteio.cpp @@ -0,0 +1,97 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mvdataelement_byteio.cpp,v 1.2 2007/11/16 04:48:44 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/mvdataelement_byteio.h> +#include <libdirac_common/video_format_defaults.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; + +MvDataElementByteIO::MvDataElementByteIO(): +ByteIO(), +m_block_data() +{ +} + +MvDataElementByteIO::MvDataElementByteIO(ByteIO &byte_io): +ByteIO(byte_io), +m_block_data(byte_io) +{ +} + +MvDataElementByteIO::~MvDataElementByteIO() +{ +} + +/* +void MvDataElementByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats) +{ + // set number of MV bytes + dirac_byte_stats.SetByteCount(STAT_MV_BYTE_COUNT, + GetSize()); +} +*/ +int MvDataElementByteIO::GetSize() const +{ + return ByteIO::GetSize() + m_block_data.GetSize(); +} + +const std::string MvDataElementByteIO::GetBytes() +{ + //Output header and block data + return ByteIO::GetBytes() + m_block_data.GetBytes(); +} + +void MvDataElementByteIO::Input() +{ + // Input block data size + m_block_size = ReadUint(); + + // Byte Alignment + ByteAlignInput(); +} + +void MvDataElementByteIO::Output() +{ + //Output size of block data + WriteUint(m_block_data.GetSize()); + + // Byte Align + ByteAlignOutput(); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdataelement_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdataelement_byteio.h new file mode 100644 index 000000000..2e0aa4211 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/mvdataelement_byteio.h @@ -0,0 +1,126 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mvdataelement_byteio.h,v 1.2 2008/12/16 01:19:30 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class MvDataElementByteIO +*/ +#ifndef MV_DATAELEMENT_BYTEIO_H +#define MV_DATAELEMENT_BYTEIO_H + + +// DIRAC INCLUDES +#include <libdirac_common/common.h> // EncParams + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class + + +namespace dirac +{ + + /** + * Represents compressed sequence-parameter data used in an AccessUnit + */ + class MvDataElementByteIO : public ByteIO + { + public: + + /** + * Constructor + */ + MvDataElementByteIO(); + + /** + * Constructor + *@param byte_io Input/Output Byte stream + */ + MvDataElementByteIO(ByteIO &byte_io); + + /** + * Destructor + */ + virtual ~MvDataElementByteIO(); + + /** + * Outputs motion vector data Dirac byte-format + */ + void Output(); + + /** + * Inputs motion vector information + */ + void Input(); + + + /** + * Get string containing coded bytes + */ + virtual const std::string GetBytes(); + + /** + * Return pointer to the block data ByteIO stream + */ + ByteIO* DataBlock() { return &m_block_data; }; + + /** + * Return the input block data size + */ + unsigned int DataBlockSize() { return m_block_size; } + + /** + * Return the size + */ + int GetSize() const; + + protected: + + /** + * block data + */ + ByteIO m_block_data; + + /** + * In block data size + */ + unsigned int m_block_size; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseparams_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseparams_byteio.cpp new file mode 100644 index 000000000..5034933bc --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseparams_byteio.cpp @@ -0,0 +1,227 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: parseparams_byteio.cpp,v 1.9 2008/10/21 00:04:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <sstream> //For std::ostringstream +#include <libdirac_byteio/parseparams_byteio.h> +#include <libdirac_common/dirac_exception.h> + +const unsigned int PP_AU_PICTURE_NUM_SIZE = 4; + +using namespace dirac; + +ParseParamsByteIO::ParseParamsByteIO( const ByteIO& stream_data, + ParseParams &parse_params, + EncoderParams &enc_params): +ByteIO(stream_data), +m_parse_params(parse_params) +{ + if (enc_params.NumL1() == 0) + { + if (!enc_params.UsingAC()) + { + // Simple Profile + m_parse_params.SetProfile(1); + } + else + { + // Main (Intra) profile + m_parse_params.SetProfile(2); + } + } + else + { + // Main (Long GOP) profile + m_parse_params.SetProfile(8); + } + // FIXME - no support for Low Delay Profile +} + +ParseParamsByteIO::ParseParamsByteIO( const ByteIO& stream_data, + ParseParams &parse_params): +ByteIO(stream_data), +m_parse_params(parse_params) +{ + + +} + +ParseParamsByteIO::~ParseParamsByteIO() +{ +} + +void ParseParamsByteIO::CheckVersion() +{ + std::ostringstream errstr; + ParseParams def_parse_params; + + if (m_parse_params.MajorVersion() > def_parse_params.MajorVersion() || + m_parse_params.MajorVersion() == 0 || + (m_parse_params.MajorVersion() == def_parse_params.MajorVersion() && + m_parse_params.MinorVersion() > def_parse_params.MinorVersion())) + { + errstr << "WARNING: Bitstream version is "; + errstr << m_parse_params.MajorVersion() << "."; + errstr << m_parse_params.MinorVersion() << "."; + errstr << " Supported version is "; + errstr << def_parse_params.MajorVersion() << "."; + errstr << def_parse_params.MinorVersion(); + errstr << ". May not be able to decode bitstream correctly" << std::endl; + } + + if (errstr.str().size()) + { + DiracException err( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + DIRAC_LOG_EXCEPTION(err); + } +} + +void ParseParamsByteIO::CheckProfile() +{ + std::ostringstream errstr; + ParseParams def_parse_params; + + // No profiles were specified in versions 1.0, 1.1, and 2.0 and 2.1. + // So for these versions profile should be 0 in the bitstream + if (m_parse_params.MajorVersion() <= 2 && + m_parse_params.MinorVersion() < 2 && + m_parse_params.Profile() != 0) + { + errstr << "Cannot handle profile " << m_parse_params.Profile() + << " for bitstream version " << m_parse_params.MajorVersion() + << "." << m_parse_params.MinorVersion(); + errstr << ". May not be able to decode bitstream correctly" << std::endl; + } + else if (m_parse_params.MajorVersion() == def_parse_params.MajorVersion() && + m_parse_params.MinorVersion() == def_parse_params.MinorVersion() && + m_parse_params.Profile() != 1 /* Simple */ && + m_parse_params.Profile() != 2 /* Main (Intra) */ && + m_parse_params.Profile() != 8 /* Main (Long GOP) */ + ) + { + errstr << "Cannot handle profile " << m_parse_params.Profile() + << " for bitstream version " << m_parse_params.MajorVersion() + << ". " << m_parse_params.MinorVersion() + << ". Supported profiles are 1 (Simple) " + << " 2 (Main Intra) and 8 (Long GOP)"; + errstr << ". May not be able to decode bitstream correctly" << std::endl; + } + + if (errstr.str().size()) + { + DiracException err( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + DIRAC_LOG_EXCEPTION(err); + } +} + +void ParseParamsByteIO::CheckLevel() +{ + std::ostringstream errstr; + ParseParams def_parse_params; + + // No resources constraints for decoder + if (def_parse_params.Level() == 0) + return; + + // Constraints on Decoder. Can Handles level 1 for Simple and Main (Intra) + // profiles, and level 128 for Main (Long GOP) Profile. + if (def_parse_params.Level() != 0) + { + if ((m_parse_params.Profile() <= 2 && m_parse_params.Level() != 1) || + (m_parse_params.Profile() ==8 && m_parse_params.Level() != 128)) + { + errstr << "Cannot handle Level " << m_parse_params.Level() + << " for bitstream version " << m_parse_params.MajorVersion() + << ". " << m_parse_params.MinorVersion() + << " Profile " << m_parse_params.Profile() + << ". Supported levels are 1 for Profiles 0, 1, 2 " + << " and 128 for Profile 8"; + errstr << ". May not be able to decode bitstream correctly" << std::endl; + } + } + + if (errstr.str().size()) + { + DiracException err( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + DIRAC_LOG_EXCEPTION(err); + } + return; +} + +//-------------public--------------------------------------------------------------- + +void ParseParamsByteIO::Input() +{ + + //input version + m_parse_params.SetMajorVersion(ReadUint()); + m_parse_params.SetMinorVersion(ReadUint()); + + // input profile + m_parse_params.SetProfile(ReadUint()); + + // input level + m_parse_params.SetLevel(ReadUint()); + + CheckVersion(); + + CheckProfile(); + + CheckLevel(); +} + +void ParseParamsByteIO::Output() +{ + // output version + WriteUint(m_parse_params.MajorVersion()); + WriteUint(m_parse_params.MinorVersion()); + + // output profile + WriteUint(m_parse_params.Profile()); + + // output level - does not conform to any defined level + WriteUint(m_parse_params.Level()); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseparams_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseparams_byteio.h new file mode 100644 index 000000000..1e5423f31 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseparams_byteio.h @@ -0,0 +1,117 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: parseparams_byteio.h,v 1.4 2008/05/07 05:47:00 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Scott R Ladd (Original Author), Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class ParseParamsByteIO +*/ +#ifndef parseparams_byteio_h +#define parseparams_byteio_h + + +// DIRAC INCLUDES +#include <libdirac_common/common.h> // DiracEncoder + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class + + +namespace dirac +{ + + /** + * Represents compressed parse-parameter data used in an AccessUnit + */ + class ParseParamsByteIO : public ByteIO + { + public: + + /** + * Constructor + *@param stream_data Destination of data + *@param parse_params Parse parameters + *@param enc_params Encoder parameters + */ + ParseParamsByteIO(const ByteIO& stream_data, + ParseParams &parse_params, + EncoderParams &enc_params); + + /** + * Constructor + *@param stream_data Source of data + *@param parse_params Destination of parse params + */ + ParseParamsByteIO(const ByteIO& stream_data, + ParseParams &parse_params); + + /** + * Destructor + */ + ~ParseParamsByteIO(); + + /** + * Reads parse information from Dirac byte-format + */ + void Input(); + + /** + * Outputs parse information to Dirac byte-format + */ + void Output(); + + /** + * Get access-unit number + */ + int GetIdNumber() const; + + protected: + + private: + void CheckVersion(); + void CheckProfile(); + void CheckLevel(); + + private: + /** + * Reference to parse parameters + */ + ParseParams& m_parse_params; + }; + + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseunit_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseunit_byteio.cpp new file mode 100644 index 000000000..56c0ebb8b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseunit_byteio.cpp @@ -0,0 +1,289 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: parseunit_byteio.cpp,v 1.10 2008/05/02 05:57:19 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/parseunit_byteio.h> +#include <libdirac_common/dirac_exception.h> + +#include <iomanip> + +using namespace dirac; +using namespace std; + +// Fixed parse-prefix +const string PU_PREFIX = "BBCD"; + +// Parse-unit byte sizes +const int PU_NEXT_PARSE_OFFSET_SIZE = 4; +const int PU_PREVIOUS_PARSE_OFFSET_SIZE = 4; +const int PU_PREFIX_SIZE = 4; +const int PU_PARSE_CODE_SIZE = 1; +const int PU_PARSEUNIT_SIZE = PU_NEXT_PARSE_OFFSET_SIZE + PU_PREVIOUS_PARSE_OFFSET_SIZE+ + PU_PREFIX_SIZE + PU_PARSE_CODE_SIZE; + +ParseUnitByteIO::ParseUnitByteIO(): +ByteIO(), +m_previous_parse_offset(0), +m_next_parse_offset(0) +{ + +} + +ParseUnitByteIO::ParseUnitByteIO(const ByteIO& byte_io): +ByteIO(byte_io), +m_previous_parse_offset(0), +m_next_parse_offset(0) +{ + +} + +ParseUnitByteIO::ParseUnitByteIO(const ParseUnitByteIO& parseunit_byteio): +ByteIO(parseunit_byteio), +m_previous_parse_offset(parseunit_byteio.m_previous_parse_offset), +m_next_parse_offset(parseunit_byteio.m_next_parse_offset), +m_parse_code(parseunit_byteio.m_parse_code) +{ +} + +ParseUnitByteIO::~ParseUnitByteIO() +{ + +} + + +//--------------public--------------------------------------------------------- + +void ParseUnitByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats) +{ + dirac_byte_stats.SetByteCount(STAT_TOTAL_BYTE_COUNT, + m_next_parse_offset); +} + +bool ParseUnitByteIO::Input() +{ + + // input prefix + if(!SyncToUnitStart()) + return false; + + // input parse code + m_parse_code = InputUnByte(); + + // input parse-offsets + m_next_parse_offset = ReadUintLit(PU_NEXT_PARSE_OFFSET_SIZE); + + m_previous_parse_offset = ReadUintLit(PU_PREVIOUS_PARSE_OFFSET_SIZE); + + return true; +} + +bool ParseUnitByteIO::IsValid() +{ + if (IsEndOfSequence()) + return true; + + // Skip past the end of current parse unit + SeekGet(m_next_parse_offset-GetSize(), ios_base::cur); + + // check the next series of bytes are the parse-info prefix + string prefix = InputUnString(PU_PREFIX_SIZE); + + if(prefix==PU_PREFIX) + { + unsigned char next_parse_code; + + next_parse_code = InputUnByte(); + // input next unit parse-offsets + int next_unit_next_parse_offset; + next_unit_next_parse_offset = ReadUintLit(PU_NEXT_PARSE_OFFSET_SIZE); + + int next_unit_previous_parse_offset; + next_unit_previous_parse_offset = ReadUintLit(PU_PREVIOUS_PARSE_OFFSET_SIZE); + if (next_unit_previous_parse_offset == m_next_parse_offset) + { + SeekGet(-(m_next_parse_offset-GetSize()+PU_PARSEUNIT_SIZE), ios_base::cur); + return true; + } + } + SeekGet(-(m_next_parse_offset-GetSize()), ios_base::cur); + return false; +} + +bool ParseUnitByteIO::CanSkip() +{ + if(m_next_parse_offset==0 || m_next_parse_offset == GetSize()) + return true; + + // Skip past the end of current parse unit and past the header of the + // next unit + SeekGet(m_next_parse_offset-GetSize() + GetSize(), ios_base::cur); + if(GetReadBytePosition() >= 0) + { + SeekGet(-(m_next_parse_offset-GetSize() + GetSize()), ios_base::cur); + return true; // success + } + + // end of stream reached + mp_stream->clear(); + + return false; +} + +const string ParseUnitByteIO::GetBytes() +{ + stringstream parse_string; + parse_string << PU_PREFIX; + parse_string << CalcParseCode(); + + //FIXME : Need to do this properly. + // Write the parse offsets in Big Endian format + for(int i=PU_NEXT_PARSE_OFFSET_SIZE-1; i >= 0; --i) + { + unsigned char cp = (m_next_parse_offset>>(i*8)) & 0xff; + parse_string << cp; + } + + for(int i=PU_PREVIOUS_PARSE_OFFSET_SIZE-1; i >= 0; --i) + { + unsigned char cp = (m_previous_parse_offset>>(i*8)) & 0xff; + parse_string << cp; + } + + return parse_string.str() + ByteIO::GetBytes(); +} + + +int ParseUnitByteIO::GetSize() const +{ + return PU_PARSEUNIT_SIZE; +} + +int ParseUnitByteIO::GetNextParseOffset() const +{ + return m_next_parse_offset; +} + +int ParseUnitByteIO::GetPreviousParseOffset() const +{ + return m_previous_parse_offset; +} + +void ParseUnitByteIO::SetAdjacentParseUnits(ParseUnitByteIO *p_prev_parseunit) +{ + // set next offset + m_next_parse_offset = CalcNextUnitOffset(); + + if(!p_prev_parseunit) + return; + + // set previous parse offset + m_previous_parse_offset = p_prev_parseunit->m_next_parse_offset; +} + + +ParseUnitType ParseUnitByteIO::GetType() const +{ + if(IsSeqHeader()) + return PU_SEQ_HEADER; + + if(IsCoreSyntax()) + return PU_CORE_PICTURE; + + if(IsLowDelay()) + return PU_LOW_DELAY_PICTURE; + + if(IsPicture()) + return PU_PICTURE; + + if(IsEndOfSequence()) + return PU_END_OF_SEQUENCE; + + if(IsAuxiliaryData()) + return PU_AUXILIARY_DATA; + + if(IsPaddingData()) + return PU_PADDING_DATA; + + return PU_UNDEFINED; +} + +//------------protected------------------------------------------------------- + +int ParseUnitByteIO::CalcNextUnitOffset() +{ + // typically size of current unit + return GetSize(); +} + +bool ParseUnitByteIO::SyncToUnitStart() +{ + // locate parse-unit prefix + string byte_buffer; + + while(CanRead()==true && mp_stream->tellg() >= 0) + { + // ensure current buffer length + if((int)byte_buffer.size() == PU_PREFIX_SIZE) + { + byte_buffer.assign(byte_buffer.substr(1,PU_PREFIX_SIZE-1)); + } + // read next byte + byte_buffer.push_back(InputUnByte()); + + //look to see if we have prefix + if(byte_buffer==PU_PREFIX) + { + // check we can read a parse-unit + //int prev_pos = mp_stream->tellg(); + mp_stream->seekg (PU_PARSEUNIT_SIZE-PU_PREFIX_SIZE, ios_base::cur); + int cur_pos = mp_stream->tellg(); + if (cur_pos < 0) // past end of stream + { + mp_stream->clear(); + return false; + } + mp_stream->seekg(-(PU_PARSEUNIT_SIZE-PU_PREFIX_SIZE), ios_base::cur); + return true; + } + + } + + // Clear the eof flag and throw an error. + mp_stream->clear(); + return false; +} + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseunit_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseunit_byteio.h new file mode 100644 index 000000000..8d7742afa --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/parseunit_byteio.h @@ -0,0 +1,247 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: parseunit_byteio.h,v 1.11 2008/05/02 05:57:19 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class ParseUnitByteIO +*/ +#ifndef parseunit_byteio_h +#define parseunit_byteio_h + +//SYSTEM INLUDES +#include <map> // Byte-map +#include <string> // stores values + +//LOCAL INCLUDES +#include "byteio.h" // Parent class + + +namespace dirac +{ + + /* Types of parse-unit */ + typedef enum { + PU_SEQ_HEADER=0, + PU_PICTURE, + PU_END_OF_SEQUENCE, + PU_AUXILIARY_DATA, + PU_PADDING_DATA, + PU_CORE_PICTURE, + PU_LOW_DELAY_PICTURE, + PU_UNDEFINED + } ParseUnitType; + + /** + * Represents a collection of data in a Dirac bytestream that can be parsed as a + * self-contained unit + */ + class ParseUnitByteIO : public ByteIO + { + public: + + /** + * Constructor + */ + ParseUnitByteIO(); + + /** + * Constructor + *@param byte_io Stream parameters + */ + ParseUnitByteIO(const ByteIO& byte_io); + + /** + * Constructor + *@param parseunit_byteio Parse-unit parameters + */ + ParseUnitByteIO(const ParseUnitByteIO& parseunit_byteio); + + /** + * Destructor + */ + ~ParseUnitByteIO(); + + /** + * Gathers byte stats on the parse-unit data + *@param dirac_byte_stats Stat container + */ + virtual void CollateByteStats(DiracByteStats& dirac_byte_stats); + + /** + * Reads from byte-stream to find parse data + *@return <B>false</B> if not enough data in stream + */ + bool Input(); // decoding + + /** + * Accesses validity of a unit by comparing it with an adjacent unit + */ + bool IsValid(); + + /** + * Can Skip past the entire parse-unit + *@return <B>false</B> Nothing to skip to + */ + bool CanSkip(); + + /** + * Gets string containing coded bytes + */ + virtual const std::string GetBytes(); // encoding + + /** + * Set next/previous parse-unit values + *@param p_prev_parseunit Previous parse-unit + */ + void SetAdjacentParseUnits(ParseUnitByteIO *p_prev_parseunit); // encoding + + /* + * Gets number of bytes input/output within unit + */ + virtual int GetSize() const; + + /** + * Gets expected number of bytes to start of next parse-unit + */ + int GetNextParseOffset() const; + + /** + * Gets number of bytes to start of previous parse-unit + */ + int GetPreviousParseOffset() const; + + /** + * Gets parse-unit type + */ + virtual ParseUnitType GetType() const; + + /** + * Returns true is parse unit is a Sequence Header + */ + bool IsSeqHeader() const + { return m_parse_code==0x00; } + + /** + * Returns true is parse unit is an End of Sequence unit + */ + bool IsEndOfSequence() const + { return m_parse_code==0x10; } + + /** + * Returns true is parse unit is Auxiliary Data + */ + bool IsAuxiliaryData() const + { return (m_parse_code&0xF8)==0x20; } + + /** + * Returns true is parse unit is Padding data + */ + bool IsPaddingData() const + { return m_parse_code==0x30; } + + /** + * Returns true is parse unit is Picture data + */ + bool IsPicture() const + { return ((m_parse_code&0x08)==0x08); } + + /** + * Returns true is parse unit is Low Delay Sybtax unit + */ + bool IsLowDelay() const + { return ((m_parse_code&0x88)==0x88); } + + /** + * Returns true is parse unit is Core syntax unit + */ + bool IsCoreSyntax() const + { return ((m_parse_code&0x88)==0x08); } + + /** + * Returns true is parse unit uses Arithmetic coding + */ + bool IsUsingAC() const + { return ((m_parse_code&0x48)==0x08); } + + protected: + + /** + * Calculates number of bytes to start of next unit + *@return Number of bytes to next unit + */ + virtual int CalcNextUnitOffset(); + + /** + * Pure virtual method for calculating parse-code + *@return Char containing bit-set for parse-unit parameters + */ + virtual unsigned char CalcParseCode() const { return 0;} // encoding + + /** + * Locates start of parse-unit + *@return <B>false</B> if not enough data + */ + bool SyncToUnitStart(); // decoding + + /** + * Get parse code + */ + unsigned char GetParseCode() const { return m_parse_code;} + + private: + + /** + * Number of bytes to next parse-unit + */ + int m_previous_parse_offset; + + /** + * Number of bytes to previous parse-unit + */ + int m_next_parse_offset; + + /** + * Parse-type-identifier + */ + unsigned char m_parse_code; + + }; + + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/picture_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/picture_byteio.cpp new file mode 100644 index 000000000..23231bea7 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/picture_byteio.cpp @@ -0,0 +1,279 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_byteio.cpp,v 1.3 2008/08/14 01:58:39 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Andrew Kennedy (Original Author),
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#include "picture_byteio.h"
+#include <libdirac_common/dirac_exception.h>
+
+using namespace dirac;
+using namespace std;
+
+const unsigned int PP_PICTURE_NUM_SIZE = 4;
+
+const int CODE_ONE_REF_BIT = 0;
+const int CODE_TWO_REF_BIT = 1;
+const int CODE_REF_PICTURE_BIT = 2;
+const int CODE_PUTYPE_1_BIT = 3;
+const int CODE_VLC_ENTROPY_CODING_BIT = 6;
+
+// maximum number of refs allowed
+const unsigned int MAX_NUM_REFS = 2;
+
+PictureByteIO::PictureByteIO(PictureParams& frame_params,
+ int frame_num) :
+ParseUnitByteIO(),
+m_frame_params(frame_params),
+m_frame_num(frame_num),
+m_mv_data(0),
+m_transform_data(0)
+{
+
+}
+
+PictureByteIO::PictureByteIO(PictureParams& frame_params,
+ const ParseUnitByteIO& parseunit_byteio ):
+ParseUnitByteIO(parseunit_byteio),
+m_frame_params(frame_params),
+m_frame_num(0),
+m_mv_data(0),
+m_transform_data(0)
+{
+
+}
+
+
+PictureByteIO::~PictureByteIO()
+{
+ //delete block data
+ if (m_mv_data)
+ {
+ delete m_mv_data;
+ m_mv_data = 0;
+ }
+ if (m_transform_data)
+ {
+ delete m_transform_data;
+ m_transform_data = 0;
+ }
+}
+
+void PictureByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats)
+{
+ if(m_mv_data)
+ m_mv_data->CollateByteStats(dirac_byte_stats);
+ if(m_transform_data)
+ m_transform_data->CollateByteStats(dirac_byte_stats);
+
+ ParseUnitByteIO::CollateByteStats(dirac_byte_stats);
+}
+
+bool PictureByteIO::Input()
+{
+ // set picture type
+ SetPictureType();
+ SetReferenceType();
+ SetEntropyCodingFlag();
+
+ // Use of VLC for entropy coding is supported for
+ // intra frames only
+ if (m_frame_params.GetPictureType() == INTER_PICTURE &&
+ m_frame_params.UsingAC() == false)
+ {
+ DIRAC_THROW_EXCEPTION(
+ ERR_UNSUPPORTED_STREAM_DATA,
+ "VLC codes for entropy coding of coefficient data supported for Intra frames only",
+ SEVERITY_PICTURE_ERROR);
+ }
+
+ // input picture number
+ m_frame_num = ReadUintLit(PP_PICTURE_NUM_SIZE);
+ m_frame_params.SetPictureNum(m_frame_num);
+
+ // input reference Picture numbers
+ InputReferencePictures();
+
+ // input retired Picture numbers list
+ m_frame_params.SetRetiredPictureNum(-1);
+ if (IsRef())
+ InputRetiredPicture();
+
+ // byte align
+ ByteAlignInput();
+
+ return true;
+}
+
+const string PictureByteIO::GetBytes()
+{
+ // Write mv data
+ if(m_frame_params.PicSort().IsInter() && m_mv_data)
+ {
+ OutputBytes(m_mv_data->GetBytes());
+ }
+
+ // Write transform header
+ if (m_transform_data)
+ {
+ OutputBytes(m_transform_data->GetBytes());
+ }
+ return ParseUnitByteIO::GetBytes();
+}
+
+int PictureByteIO::GetSize() const
+{
+ int size = 0;
+ if (m_mv_data)
+ size += m_mv_data->GetSize();
+ if (m_transform_data)
+ size += m_transform_data->GetSize();
+
+ //std::cerr << "Picture Header Size=" << ByteIO::GetSize();
+ //std::cerr << "Data Size=" << size << std::endl;
+
+ return size+ParseUnitByteIO::GetSize()+ByteIO::GetSize();
+}
+
+void PictureByteIO::Output()
+{
+ // output picture number
+ WriteUintLit(m_frame_num, PP_PICTURE_NUM_SIZE);
+
+ if(m_frame_params.GetPictureType()==INTER_PICTURE)
+ {
+ // output reference picture numbers
+ const std::vector<int>& refs = m_frame_params.Refs();
+ for(size_t i=0; i < refs.size() && i < MAX_NUM_REFS; ++i)
+ WriteSint(refs[i] - m_frame_num);
+ }
+
+ // output retired picture
+ ASSERTM (m_frame_params.GetReferenceType() == REFERENCE_PICTURE || m_frame_params.RetiredPictureNum() == -1, "Only Reference frames can retire frames");
+ if(m_frame_params.GetReferenceType() == REFERENCE_PICTURE)
+ {
+ if (m_frame_params.RetiredPictureNum() == -1)
+ WriteSint(0);
+ else
+ {
+ WriteSint (m_frame_params.RetiredPictureNum() - m_frame_num);
+ }
+ }
+ // byte align output
+ ByteAlignOutput();
+
+}
+
+
+//-------------private-------------------------------------------------------
+
+unsigned char PictureByteIO::CalcParseCode() const
+{
+ unsigned char code = 0;
+
+ int num_refs = m_frame_params.Refs().size();
+
+ if(m_frame_params.GetPictureType()==INTER_PICTURE)
+ {
+ // set number of refs
+ if(num_refs == 1)
+ SetBit(code, CODE_ONE_REF_BIT);
+ if(num_refs > 1)
+ SetBit(code, CODE_TWO_REF_BIT);
+ }
+ // set ref type
+ if(m_frame_params.GetReferenceType()==REFERENCE_PICTURE)
+ SetBit(code, CODE_REF_PICTURE_BIT);
+
+ // Set parse unit type
+ SetBit(code, CODE_PUTYPE_1_BIT);
+
+ // Set Entropy Coding type
+ if (!m_frame_params.UsingAC())
+ {
+ SetBit(code, CODE_VLC_ENTROPY_CODING_BIT);
+ }
+ return code;
+
+
+}
+
+void PictureByteIO::InputReferencePictures()
+{
+ // get number of frames referred to
+ int ref_count = NumRefs();
+
+ // get the number of these frames
+ vector<int>& refs = m_frame_params.Refs();
+ refs.resize(ref_count);
+ for(int i=0; i < ref_count; ++i)
+ refs[i]=m_frame_num+ReadSint();
+}
+
+void PictureByteIO::InputRetiredPicture()
+{
+ TESTM(IsRef(), "Retired Picture offset only set for Reference Frames");
+
+ // input retired picture offset
+ int offset = ReadSint();
+ // input retired frames
+ if (offset)
+ {
+ m_frame_params.SetRetiredPictureNum(m_frame_num + offset);
+ }
+}
+
+void PictureByteIO::SetPictureType()
+{
+ if(IsIntra())
+ m_frame_params.SetPictureType(INTRA_PICTURE);
+ else if(IsInter())
+ m_frame_params.SetPictureType(INTER_PICTURE);
+
+}
+
+void PictureByteIO::SetReferenceType()
+{
+ if(IsRef())
+ m_frame_params.SetReferenceType(REFERENCE_PICTURE);
+ else if(IsNonRef())
+ m_frame_params.SetReferenceType(NON_REFERENCE_PICTURE);
+
+}
+
+void PictureByteIO::SetEntropyCodingFlag()
+{
+ m_frame_params.SetUsingAC(IsUsingAC());
+}
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/picture_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/picture_byteio.h new file mode 100644 index 000000000..bdca76f40 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/picture_byteio.h @@ -0,0 +1,208 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_byteio.h,v 1.1 2008/01/31 11:25:15 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Andrew Kennedy (Original Author)
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+/**
+* Definition of class PictureByteIO
+*/
+#ifndef picture_byteio_h
+#define picture_byteio_h
+
+
+//LOCAL INCLUDES
+#include <libdirac_byteio/parseunit_byteio.h> // Parent class
+#include <libdirac_byteio/mvdata_byteio.h> // Contains mvdata streams
+#include <libdirac_byteio/transform_byteio.h> // Transform header
+
+// DIRAC includes
+#include <libdirac_common/common.h> // PictureType etc
+
+
+namespace dirac
+{
+ /**
+ * A compressed picture in Dirac bytestream format
+ */
+ class PictureByteIO : public ParseUnitByteIO
+ {
+ public:
+
+ /**
+ * Constructor
+ *@param frame_params Picture parameters
+ *@param frame_num Picture number
+ */
+ PictureByteIO(PictureParams& frame_params,
+ int frame_num);
+
+
+ /**
+ * Constructor
+ *@param frame_params Destination of data
+ *@param parseunit_byteio Source of data
+ */
+ PictureByteIO(PictureParams& frame_params,
+ const ParseUnitByteIO& parseunit_byteio);
+
+ /**
+ * Destructor
+ */
+ virtual ~PictureByteIO();
+
+ /**
+ * Gathers byte stats on the picture data
+ *@param dirac_byte_stats Stat container
+ */
+ void CollateByteStats(DiracByteStats& dirac_byte_stats);
+
+ /**
+ * Inputs data from Dirac stream-format
+ */
+ bool Input();
+
+ /**
+ * Outputs picture values to Dirac stream-format
+ */
+ void Output();
+
+
+
+ const std::string GetBytes();
+
+ int GetSize() const;
+
+ /**
+ * Gets parse-unit type
+ */
+ ParseUnitType GetType() const { return PU_PICTURE;}
+
+ /**
+ * Returns true is picture in Reference picture
+ */
+ int IsRef() const { return (GetParseCode()&0x0C)==0x0C;}
+
+ /**
+ * Returns true is picture in Non-Reference picture
+ */
+ int IsNonRef() const { return (GetParseCode()&0x0C)==0x08;}
+
+ /**
+ * Gets parse-unit type
+ */
+ int NumRefs() const { return (GetParseCode()&0x03);}
+
+ /**
+ * Returns true is picture is Intra picture
+ */
+ bool IsIntra() const { return IsPicture() && (NumRefs()==0) ; }
+
+ /**
+ * Returns true is picture is Inter picture
+ */
+ bool IsInter() const { return IsPicture() && (NumRefs()>0) ; }
+
+ /***
+ * Sets the MVDataIO
+ */
+ void SetMvData(MvDataByteIO *mv_data) {m_mv_data = mv_data; }
+
+ /***
+ * Sets the TransformByteIo
+ */
+ void SetTransformData(TransformByteIO *transform_data) {m_transform_data = transform_data; }
+
+ protected:
+
+
+ private:
+
+ /**
+ * Calculates parse-code based on picture parameters
+ *@return Char bit-set
+ */
+ unsigned char CalcParseCode() const;
+
+ /**
+ * Reads reference-picture data
+ */
+ void InputReferencePictures();
+
+ /**
+ * Reads retired picture number
+ */
+ void InputRetiredPicture();
+
+ /**
+ * Calculates picture-type (eg INTRA/INTER) of picture
+ */
+ void SetPictureType();
+
+ /**
+ * Calculates reference-type of picture
+ */
+ void SetReferenceType();
+
+ /**
+ * Sets the entropy coding flag in the picture parameters
+ */
+ void SetEntropyCodingFlag();
+
+ /**
+ * Picture parameters
+ */
+ PictureParams& m_frame_params;
+
+ /**
+ * Picture number
+ */
+ int m_frame_num;
+
+ /**
+ * MV data
+ */
+ MvDataByteIO * m_mv_data;
+
+ /**
+ * Transform data
+ */
+ TransformByteIO * m_transform_data;
+
+ };
+
+} // namespace dirac
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/subband_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/subband_byteio.cpp new file mode 100644 index 000000000..63d0607b9 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/subband_byteio.cpp @@ -0,0 +1,137 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: subband_byteio.cpp,v 1.4 2008/04/29 08:51:52 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/subband_byteio.h> + +using namespace dirac; +using namespace std; + +SubbandByteIO::SubbandByteIO(Subband& sub_band, + const ByteIO& byteio): +ByteIO(byteio), +m_subband(sub_band), +m_band_data_length(0) +{ + +} + +SubbandByteIO::SubbandByteIO(Subband& sub_band): +ByteIO(), +m_subband(sub_band), +m_band_data_length(0) +{ + +} + +SubbandByteIO::~SubbandByteIO() +{ + +} + +//--------------public---------------------------------------------- + +bool SubbandByteIO::Input() +{ + // read length of Arith-coded data block + m_band_data_length = ReadUint(); + + // set skip flag if no data + m_subband.SetSkip(m_band_data_length==0 ? true : false); + + // check for zero-length sub-band + if(m_subband.Skipped()) + { + ByteAlignInput(); + return true; + } + + // If we're not skipped, we need a quantisation index for the subband + m_subband.SetQuantIndex(ReadUint() ); + + if ( !m_subband.UsingMultiQuants() ) + { + // Propogate the quantiser index to all the code blocks if we + // don't have multiquants + for ( int j=0 ; j<m_subband.GetCodeBlocks().LengthY() ; ++j ) + for ( int i=0 ; i<m_subband.GetCodeBlocks().LengthX() ; ++i ) + m_subband.GetCodeBlocks()[j][i].SetQuantIndex( m_subband.QuantIndex() ); + } + + // byte align + ByteAlignInput(); + //int f=mp_stream->tellg(); + + return true; +} + +int SubbandByteIO::GetBandDataLength() const +{ + return m_band_data_length; +} + +const string SubbandByteIO::GetBytes() +{ + ByteIO byte_io; + + ByteAlignOutput(); + + // output size + byte_io.WriteUint(GetSize()); + + // check for zero-length sub-band + if(GetSize()==0) + { + byte_io.ByteAlignOutput(); + return byte_io.GetBytes(); + } + + // output quantisation + byte_io.WriteUint(m_subband.QuantIndex()); + + // byte align + byte_io.ByteAlignOutput(); + + //std::cerr << "Subband hdr size=" << byte_io.GetSize(); + //std::cerr << " Arithdata size=" << this->GetSize()<< std::endl; + + return byte_io.GetBytes()+ByteIO::GetBytes(); +} + + + +//-------------private------------------------------------------------------- + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/subband_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/subband_byteio.h new file mode 100644 index 000000000..88d03cf87 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/subband_byteio.h @@ -0,0 +1,115 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: subband_byteio.h,v 1.1 2006/04/20 10:41:56 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class SubbandByteIO +*/ +#ifndef subband_byteio_h +#define subband_byteio_h + + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class + +// DIRAC includes +#include <libdirac_common/wavelet_utils.h> // Subband class + +namespace dirac +{ + /** + * Subband Dirac-bytestream input/output + */ + class SubbandByteIO : public ByteIO + { + public: + + /** + * Constructor + *@param sub_band Corresponding Subband + *@param byteio Source/Destination of data + */ + SubbandByteIO(Subband& sub_band, + const ByteIO& byteio); + + + /* Constructor + *@param sub_band Corresponding Subband + *@param byteio Source/Destination of data + */ + SubbandByteIO(Subband& sub_band); + + /** + * Destructor + */ + ~SubbandByteIO(); + + /** + * Inputs data from Dirac stream-format + */ + bool Input(); + + + /** + * Gets number of bytes in Arith-coded data block + */ + int GetBandDataLength() const; + + /** + * Gets subband bytes in Dirac-bytestream format + */ + const std::string GetBytes(); + + + protected: + + + private: + + /** + * Sub-band that is inputed/outputed + */ + Subband& m_subband; + + /** + * Number of bytes in arith-coded data block + */ + int m_band_data_length; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/transform_byteio.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/transform_byteio.cpp new file mode 100644 index 000000000..6eba5a31d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/transform_byteio.cpp @@ -0,0 +1,169 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: transform_byteio.cpp,v 1.10 2008/01/31 11:25:15 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_byteio/transform_byteio.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; + +TransformByteIO::TransformByteIO(PictureParams& fparams, + CodecParams& cparams): +ByteIO(), +m_fparams(fparams), +m_cparams(cparams), +m_default_cparams(cparams.GetVideoFormat(), fparams.GetPictureType(), fparams.Refs().size(), true) +{ +} + +TransformByteIO::TransformByteIO(ByteIO &byte_io, + PictureParams& fparams, + CodecParams& cparams): +ByteIO(byte_io), +m_fparams(fparams), +m_cparams(cparams), +m_default_cparams(cparams.GetVideoFormat(), fparams.GetPictureType(), fparams.Refs().size(), true) +{ +} + +TransformByteIO::~TransformByteIO() +{ + for(size_t index=0; index < m_component_list.size(); ++index) + delete m_component_list[index]; +} + +void TransformByteIO::CollateByteStats(DiracByteStats& dirac_byte_stats) +{ + // set number of component bytes + for(size_t index=0; index < m_component_list.size(); ++index) + m_component_list[index]->CollateByteStats(dirac_byte_stats); +} + +int TransformByteIO::GetSize() const +{ + //std::cerr << "Transform Size=" << ByteIO::GetSize() << std::endl; + int size=0; + for(size_t index=0; index < m_component_list.size(); ++index) + size += m_component_list[index]->GetSize(); + return ByteIO::GetSize()+size; +} + +const std::string TransformByteIO::GetBytes() +{ + std::string bytes; + for(size_t index=0; index < m_component_list.size(); ++index) + bytes += m_component_list[index]->GetBytes(); + return ByteIO::GetBytes()+bytes; +} + +void TransformByteIO::Output() +{ + // Zero Transform flag - applies only to inter frames + if (m_fparams.PicSort().IsInter()) + WriteBit(false); + // Wavelet index + WriteUint(m_cparams.TransformFilter()); + + // Wavelet Depth + WriteUint(m_cparams.TransformDepth()); + + // Spatial Partition flag + WriteBit(m_cparams.SpatialPartition()); + if (m_cparams.SpatialPartition()) + { + for (unsigned int i = 0; i <= m_cparams.TransformDepth(); ++i) + { + const CodeBlocks &cb = m_cparams.GetCodeBlocks(i); + // Number of Horizontal code blocks for level i + WriteUint(cb.HorizontalCodeBlocks()); + // Number of Vertical code block for level i + WriteUint(cb.VerticalCodeBlocks()); + } + // Code block mode index + WriteUint(m_cparams.GetCodeBlockMode()); + } + // Flush output for bend alignment + ByteAlignOutput(); +} + +void TransformByteIO::Input() +{ + // Byte Alignment + ByteAlignInput(); + + m_cparams.SetZeroTransform(false); + // Zero transform flag - applies only for inter frames + if (m_fparams.PicSort().IsInter()) + m_cparams.SetZeroTransform(ReadBool()); + + if (m_cparams.ZeroTransform()) + return; + + // Transform filter + m_cparams.SetTransformFilter(ReadUint()); + + // transform depth + m_cparams.SetTransformDepth(ReadUint()); + + // Spatial partition flag + m_cparams.SetSpatialPartition(ReadBool()); + + if (m_cparams.SpatialPartition()) + { + // Input number of code blocks for each level + for (unsigned int i = 0; i <= m_cparams.TransformDepth(); ++i) + { + // number of horizontal code blocks for level i + unsigned int hblocks = ReadUint(); + // number of vertical code blocks for level i + unsigned int vblocks = ReadUint(); + m_cparams.SetCodeBlocks(i, hblocks, vblocks); + } + // Code block mode index + m_cparams.SetCodeBlockMode(ReadUint()); + } + // Byte Alignment + ByteAlignInput(); +} + +void TransformByteIO::AddComponent(ComponentByteIO* component_byteio) +{ + m_component_list.push_back(component_byteio); +} + + +//-------------private--------------------------------------------------------------- diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/transform_byteio.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/transform_byteio.h new file mode 100644 index 000000000..6fa1c0c5f --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_byteio/transform_byteio.h @@ -0,0 +1,146 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: transform_byteio.h,v 1.2 2008/01/31 11:25:15 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Definition of class TransformByteIO +*/ +#ifndef TRANSFORM_BYTEIO_H +#define TRANSFORM_BYTEIO_H + +// DIRAC INCLUDES +#include <libdirac_common/common.h> // EncParams + +//LOCAL INCLUDES +#include <libdirac_byteio/byteio.h> // Parent class +#include <libdirac_byteio/component_byteio.h> // Contains tranform-component + + +namespace dirac +{ + + /** + * Represents compressed sequence-parameter data used in an AccessUnit + */ + class TransformByteIO : public ByteIO + { + public: + + /** + * Output Constructor + *@param fparams Picture parameters + *@param c_params Codec params + */ + TransformByteIO(PictureParams& fparams, + CodecParams& c_params); + + /** + * Input Constructor + *@param byte_io ByteIO object for copy constructor + *@param fparams Picture parameters + *@param c_params Codec params + */ + TransformByteIO(ByteIO &byte_io, PictureParams& fparams, + CodecParams& c_params); + + /** + * Destructor + */ + virtual ~TransformByteIO(); + + /** + * Gathers byte stats on the transform data + *@param dirac_byte_stats Stats container + */ + void CollateByteStats(DiracByteStats& dirac_byte_stats); + + /** + * Outputs sequence information to Dirac byte-format + */ + void Output(); + + /** + * Outputs sequence information to Dirac byte-format + */ + void Input(); + + + /** + * Get string containing coded bytes + */ + virtual const std::string GetBytes(); + + /** + * Return the size + */ + int GetSize() const; + + /** + * Adds a Picture-component in Dirac-bytestream format + *@param component_byteio Picture-component bytestream + */ + void AddComponent(ComponentByteIO *component_byteio); + + protected: + + + private: + + /** + * Sequence paramters for intput/output + */ + PictureParams& m_fparams; + + /** + * Codec params - EncParams for Output and DecParams for input + */ + CodecParams& m_cparams; + + /** + * Default Codec params - EncParams for Output and DecParams for input + */ + CodecParams m_default_cparams; + + /*** + * Transform Component data + */ + std::vector<ComponentByteIO *> m_component_list; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arith_codec.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arith_codec.cpp new file mode 100644 index 000000000..756ac19b5 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arith_codec.cpp @@ -0,0 +1,169 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: arith_codec.cpp,v 1.17 2007/11/16 04:48:44 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* Contributor(s): Tim Borer (Author), + Thomas Davies, + Scott R Ladd, + Peter Bleackley, + Steve Bearcroft, + Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/arith_codec.h> + +namespace dirac{ + + const unsigned int Context::lut[256] = { + //LUT corresponds to window = 16 @ p0=0.5 & 8 @ p=1.0 + 0, 2, 5, 8, 11, 15, 20, 24, + 29, 35, 41, 47, 53, 60, 67, 74, + 82, 89, 97, 106, 114, 123, 132, 141, + 150, 160, 170, 180, 190, 201, 211, 222, + 233, 244, 256, 267, 279, 291, 303, 315, + 327, 340, 353, 366, 379, 392, 405, 419, + 433, 447, 461, 475, 489, 504, 518, 533, + 548, 563, 578, 593, 609, 624, 640, 656, + 672, 688, 705, 721, 738, 754, 771, 788, + 805, 822, 840, 857, 875, 892, 910, 928, + 946, 964, 983, 1001, 1020, 1038, 1057, 1076, + 1095, 1114, 1133, 1153, 1172, 1192, 1211, 1231, + 1251, 1271, 1291, 1311, 1332, 1352, 1373, 1393, + 1414, 1435, 1456, 1477, 1498, 1520, 1541, 1562, + 1584, 1606, 1628, 1649, 1671, 1694, 1716, 1738, + 1760, 1783, 1806, 1828, 1851, 1874, 1897, 1920, + 1935, 1942, 1949, 1955, 1961, 1968, 1974, 1980, + 1985, 1991, 1996, 2001, 2006, 2011, 2016, 2021, + 2025, 2029, 2033, 2037, 2040, 2044, 2047, 2050, + 2053, 2056, 2058, 2061, 2063, 2065, 2066, 2068, + 2069, 2070, 2071, 2072, 2072, 2072, 2072, 2072, + 2072, 2071, 2070, 2069, 2068, 2066, 2065, 2063, + 2060, 2058, 2055, 2052, 2049, 2045, 2042, 2038, + 2033, 2029, 2024, 2019, 2013, 2008, 2002, 1996, + 1989, 1982, 1975, 1968, 1960, 1952, 1943, 1934, + 1925, 1916, 1906, 1896, 1885, 1874, 1863, 1851, + 1839, 1827, 1814, 1800, 1786, 1772, 1757, 1742, + 1727, 1710, 1694, 1676, 1659, 1640, 1622, 1602, + 1582, 1561, 1540, 1518, 1495, 1471, 1447, 1422, + 1396, 1369, 1341, 1312, 1282, 1251, 1219, 1186, + 1151, 1114, 1077, 1037, 995, 952, 906, 857, + 805, 750, 690, 625, 553, 471, 376, 255 + }; + + ArithCodecBase::ArithCodecBase(ByteIO* p_byteio, size_t number_of_contexts): + m_context_list( number_of_contexts ), + m_scount( 0 ), + m_byteio(p_byteio ), + m_decode_data_ptr( 0 ) + { + // nothing needed here + } + + ArithCodecBase::~ArithCodecBase() { + delete[] m_decode_data_ptr; } + + + void ArithCodecBase::InitEncoder() + { + // Set the m_code word stuff + m_low_code = 0; + m_range = 0xFFFF; + m_underflow = 0; + } + + void ArithCodecBase::FlushEncoder() + { + + // Do final renormalisation and output + while (((m_low_code+m_range-1)^m_low_code)<0x8000 ) + { + m_byteio->WriteBit( m_low_code & 0x8000); + for (; m_underflow > 0; m_underflow-- ) + m_byteio->WriteBit(~m_low_code & 0x8000); + + m_low_code <<= 1; + m_low_code &= 0xFFFF; + m_range <<= 1; + } + + while ( (m_low_code & 0x4000) && !((m_low_code+m_range-1) & 0x4000) ) + { + m_underflow += 1; + m_low_code ^= 0x4000; + m_low_code <<= 1; + m_low_code &= 0xFFFF; + m_range <<= 1; + } + + m_byteio->WriteBit(m_low_code & 0x4000); + while ( m_underflow >= 0 ) { + m_byteio->WriteBit(~m_low_code & 0x4000); + m_underflow -= 1; } + + // byte align + m_byteio->ByteAlignOutput(); + } + + void ArithCodecBase::InitDecoder(int num_bytes) + { + ReadAllData(num_bytes); + m_input_bits_left = 8; + + m_code = 0; + m_low_code = 0; + + m_range = 0xFFFF; + + m_code = 0; + for (int i=0; i<16; ++i) + { + m_code <<= 1; + m_code += InputBit(); + } + + } + + int ArithCodecBase::ByteCount() const + { + return m_byteio->GetSize(); + } + + void ArithCodecBase::ReadAllData(int num_bytes) + { + if ( m_decode_data_ptr ) + delete[] m_decode_data_ptr; + + m_decode_data_ptr = new char[num_bytes+2]; + m_byteio->InputBytes( m_decode_data_ptr , num_bytes ); + m_decode_data_ptr[num_bytes] = (char)255; + m_decode_data_ptr[num_bytes+1] = (char)255; + + m_data_ptr = m_decode_data_ptr; + } + +}// namespace dirac diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arith_codec.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arith_codec.h new file mode 100644 index 000000000..72da756a4 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arith_codec.h @@ -0,0 +1,469 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: arith_codec.h,v 1.40 2007/11/16 04:48:44 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Richard Felton (Original Author),
+ Thomas Davies,
+ Scott R Ladd,
+ Peter Bleackley,
+ Steve Bearcroft,
+ Anuradha Suraparaju,
+ Tim Borer (major refactor February 2006)
+ Andrew Kennedy
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+
+#ifndef _ARITH_CODEC_H_
+#define _ARITH_CODEC_H_
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//// ////
+////-----------Abstract binary arithmetic coding class---------------////
+////subclass this for coding motion vectors, subband residues etc ...////
+//// ////
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+#include <libdirac_common/common.h>
+#include <libdirac_byteio/byteio.h>
+#include <vector>
+
+namespace dirac
+{
+
+ class Context {
+ public:
+
+ //! Default Constructor.
+ /*!
+ Default constructor initialises counts to 1 each of 0 and 1.
+ */
+ inline Context();
+
+ //Class is POD
+ //Use built in copy constructor, assignment and destructor.
+
+ //! Returns estimate of probability of 0 (false) scaled to 2**16
+
+ inline unsigned int GetScaledProb0( ) const{ return m_prob0;}
+
+ //! Updates context counts
+ inline void Update( bool symbol ) {
+ if (symbol) m_prob0 -= lut[m_prob0>>8];
+ else m_prob0 += lut[255-(m_prob0>>8)];
+ }
+
+ private:
+
+ int m_prob0;
+ static const unsigned int lut[256]; //Probability update table
+ };
+
+ Context::Context(): m_prob0( 0x8000 ) {}
+
+ class ArithCodecBase {
+
+ public:
+
+ //! Constructor
+ /*!
+ Creates an ArithCodec object to decode input based on a set of
+ parameters.
+ \param p_byteio input/output for encoded bits
+ \param number_of_contexts the number of contexts used
+ */
+ ArithCodecBase(ByteIO* p_byteio, size_t number_of_contexts);
+
+ //! Destructor
+ /*!
+ Destructor is virtual as this class is abstract.
+ */
+ virtual ~ArithCodecBase();
+
+ protected:
+
+ //core encode functions
+ ////////////////////////////
+
+ //! Initialises the Encoder
+ void InitEncoder();
+
+ //! encodes a symbol and writes to output
+ void EncodeSymbol(const bool symbol, const int context_num);
+
+ void EncodeUInt(const unsigned int value, const int bin1, const int max_bin);
+
+ void EncodeSInt(const int value, const int bin1, const int max_bin);
+
+ //! flushes the output of the encoder.
+ void FlushEncoder();
+
+ int ByteCount() const;
+
+ // core decode functions
+ ////////////////////////////
+
+ //! Initialise the Decoder
+ void InitDecoder(int num_bytes);
+
+ //! Decodes a symbol given a context number
+ bool DecodeSymbol( int context_num );
+
+ unsigned int DecodeUInt(const int bin1, const int max_bin);
+
+ int DecodeSInt(const int bin1, const int max_bin);
+
+ //! List of contexts
+ std::vector<Context> m_context_list;
+
+ private:
+
+ //! private, bodyless copy constructor: class should not be copied
+ ArithCodecBase(const ArithCodecBase & cpy);
+
+ //! private, bodyless copy operator=: class should not be assigned
+ ArithCodecBase & operator = (const ArithCodecBase & rhs);
+
+
+ // Decode functions
+ ////////////////////////////
+
+ //! Read all the data in
+ void ReadAllData(int num_bytes);
+
+ //! Read in a bit of data
+ inline bool InputBit();
+
+ // Codec data
+ ////////////////////////////
+
+ unsigned int m_scount;
+
+ //! Start of the current code range
+ unsigned int m_low_code;
+
+ //! Length of the current code range
+ unsigned int m_range;
+
+ //! Input/output stream of Dirac-format bytes
+ ByteIO *m_byteio;
+
+ // For encoder only
+
+ //! Number of underflow bits
+ int m_underflow;
+
+ //! A pointer to the data for reading in
+ char* m_decode_data_ptr;
+
+ //! A point to the byte currently being read
+ char* m_data_ptr;
+
+ //! The index of the bit of the byte being read
+ int m_input_bits_left;
+
+ //! The present input code
+ unsigned int m_code;
+
+ };
+
+
+ inline bool ArithCodecBase::DecodeSymbol( int context_num )
+ {
+
+ // Determine the next symbol value by placing code within
+ // the [low,high] interval.
+
+ // Fetch the statistical context to be used
+ Context& ctx = m_context_list[context_num];
+
+ // Decode as per updated specification
+ const unsigned int count = m_code - m_low_code ;
+ const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16;
+ const bool symbol = ( count >= range_x_prob );
+
+ // Rescale the interval
+ if( symbol ) //symbol is 1
+ {
+ m_low_code += range_x_prob;
+ m_range -= range_x_prob;
+ }
+ else //symbol is 0, so m_low_code unchanged
+ {
+ m_range = range_x_prob;
+ }
+
+ // Update the statistical context
+ ctx.Update( symbol );
+
+ while ( m_range<=0x4000 )
+ {
+ if( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 )
+ {
+ // Straddle condition
+ // We must have an underflow situation with
+ // low = 0x01... and high = 0x10...
+ // Flip 2nd bit prior to rescaling
+ m_code ^= 0x4000;
+ m_low_code ^= 0x4000;
+ }
+
+ // Double low and range, throw away top bit of low
+ m_low_code <<= 1;
+ m_range <<= 1;
+ m_low_code &= 0xFFFF;
+
+ // Shift in another bit of code
+ m_code <<= 1;
+ m_code += InputBit();
+ m_code &= 0xFFFF;
+
+ }
+
+ return symbol;
+ }
+
+ inline unsigned int ArithCodecBase::DecodeUInt(const int bin1, const int max_bin) {
+ const int info_ctx = (max_bin+1);
+ int bin = bin1;
+ unsigned int value = 1;
+ while (!DecodeSymbol(bin)) {
+ value <<= 1;
+ if (DecodeSymbol(info_ctx)) value+=1;
+ if (bin<max_bin) bin+=1;
+ }
+ value -= 1;
+ return value;
+ }
+
+ inline int ArithCodecBase::DecodeSInt(const int bin1, const int max_bin) {
+ int value = 0;
+ const int magnitude = DecodeUInt(bin1, max_bin);
+ if (magnitude!=0) {
+ if (DecodeSymbol(max_bin+2)) value=-magnitude;
+ else value=magnitude;
+ }
+ return value;
+ }
+
+ inline void ArithCodecBase::EncodeSymbol(const bool symbol, const int context_num)
+ {
+
+ // Adjust high and low (rescale interval) based on the symbol we are encoding
+
+ Context& ctx = m_context_list[context_num];
+
+ const unsigned int range_x_prob = ( m_range* ctx.GetScaledProb0())>>16;
+
+ if ( symbol ) //symbol is 1
+ {
+ m_low_code += range_x_prob;
+ m_range -= range_x_prob;
+ }
+ else // symbol is 0, so m_low_code unchanged
+ {
+ m_range = range_x_prob;
+ }
+
+ // Update the statistical context
+ ctx.Update( symbol );
+
+ while ( m_range <= 0x4000 )
+ {
+ if ( ( (m_low_code+m_range-1)^m_low_code)>=0x8000 )
+ {
+ // Straddle condition
+ // We must have an underflow situation with
+ // low = 0x01... and high = 0x10...
+
+ m_low_code ^= 0x4000;
+ m_underflow++;
+
+ }
+ else
+ {
+ // Bits agree - output them
+ m_byteio->WriteBit( m_low_code & 0x8000);
+ for (; m_underflow > 0; m_underflow-- )
+ m_byteio->WriteBit(~m_low_code & 0x8000);
+ }
+
+ // Double low value and range
+ m_low_code <<= 1;
+ m_range <<= 1;
+
+ // keep low to 16 bits - throw out top bit
+ m_low_code &= 0xFFFF;
+
+ }
+ }
+
+ inline void ArithCodecBase::EncodeUInt(const unsigned int the_int,
+ const int bin1, const int max_bin) {
+ const int value = (the_int+1);
+ const int info_ctx = (max_bin+1);
+ int bin = bin1;
+ int top_bit = 1;
+ {
+ int max_value = 1;
+ while (value>max_value) {
+ top_bit <<= 1;
+ max_value <<= 1;
+ max_value += 1;
+ }
+ }
+ bool stop = (top_bit==1);
+ EncodeSymbol(stop, bin);
+ while (!stop) {
+ top_bit >>= 1;
+ EncodeSymbol( (value&top_bit), info_ctx);
+ if ( bin < max_bin) bin+=1;
+ stop = (top_bit==1);
+ EncodeSymbol(stop, bin);
+ }
+ }
+
+ inline void ArithCodecBase::EncodeSInt(const int value,
+ const int bin1, const int max_bin) {
+ EncodeUInt(std::abs(value), bin1, max_bin);
+ if (value != 0) {
+ EncodeSymbol( (value < 0), max_bin+2 );
+ }
+ }
+
+
+ //! Abstract binary arithmetic coding class
+ /*!
+ This is an abtract binary arithmetic encoding class, used as the base
+ for concrete classes that encode motion vectors and subband residues.
+ \param T a container (most probably, or array) type
+ */
+
+ template<class T> //T is container/array type
+ class ArithCodec
+ : public ArithCodecBase
+ {
+ public:
+
+ //! Constructor for encoding
+ /*!
+ Creates an ArithCodec object to decode input based on a set of
+ parameters.
+ \param p_byteio input/output for encoded bits
+ \param number_of_contexts the number of contexts used
+ */
+ ArithCodec(ByteIO* p_byteio, size_t number_of_contexts);
+
+
+ //! Destructor
+ /*!
+ Destructor is virtual as this class is abstract.
+ */
+ virtual ~ArithCodec() {}
+
+ //! Compresses the input and returns the number of bits written.
+ /*!
+ Compress takes a type T object (a container or array) and
+ compresses it using the abstract function DoWorkCode() which
+ is overridden in subclasses. It returns the number of
+ bits written.
+ \param in_data the input to be compressed. Non-const,
+ since the compression may be lossy.
+ */
+ int Compress(T & in_data);
+
+ //! Decompresses the bitstream and writes into the output.
+ /*!
+ Decompresses the bitstream, up to the number of bytes
+ specified and writes into the output subclasses.
+ \param out_data the output into which the decompressed data
+ is written.
+ \param num_bytes the number of bytes to be read from the
+ bitstream.
+ */
+ void Decompress(T & out_data, const int num_bytes);
+
+ protected:
+
+ //virtual encode-only functions
+ ///////////////////////////////
+
+ //! Does the work of actually coding the data
+ virtual void DoWorkCode(T & in_data) = 0;
+
+ //! virtual decode-only functions
+ ///////////////////////////////
+ virtual void DoWorkDecode(T & out_data)=0;
+ };
+
+ //Implementation - core functions
+ /////////////////////////////////
+
+ template<class T>
+ ArithCodec<T>::ArithCodec(ByteIO* p_byteio, size_t number_of_contexts):
+ ArithCodecBase(p_byteio, number_of_contexts) {}
+
+
+
+ template<class T>
+ int ArithCodec<T>::Compress(T &in_data)
+ {
+ InitEncoder();
+ DoWorkCode(in_data);
+ FlushEncoder();
+ return ByteCount();
+ }
+
+ template<class T>
+ void ArithCodec<T>::Decompress( T &out_data, const int num_bytes )
+ {
+ InitDecoder(num_bytes);
+ DoWorkDecode( out_data );
+ }
+
+ inline bool ArithCodecBase::InputBit()
+ {
+ if (m_input_bits_left == 0)
+ {
+ m_data_ptr++;
+ m_input_bits_left = 8;
+ }
+ m_input_bits_left--;
+ // MSB to LSB
+ return bool( ( (*m_data_ptr) >> m_input_bits_left ) & 1 );
+ }
+
+}// namespace dirac
+#endif
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arrays.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arrays.h new file mode 100644 index 000000000..276ba5ef2 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/arrays.h @@ -0,0 +1,595 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: arrays.h,v 1.21 2008/03/14 08:17:36 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Peter Meerwald (pmeerw@users.sourceforge.net) +* Mike Ferenduros (mike_ferenzduros@users.sourceforge.net) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _ARRAYS_H_ +#define _ARRAYS_H_ + +//basic array types used for pictures etc + +#include <memory> +#include <cstddef> +#include <stdexcept> +#include <iostream> +#include <algorithm> +#include <cstring> + +namespace dirac +{ + //! Range type. + /*! + Range type encapsulating a closed range of values [first,last]. + Used to initialies OneDArrays. + */ + class Range + { + public: + //! Constructor + /*! + Constructor taking a start and an end point for the range. + */ + Range(int s, int e): m_fst(s), m_lst(e){} + + //! Returns the start of the range. + int First() const {return m_fst;} + + //! Returns the end point of the range. + int Last() const {return m_lst;} + + private: + int m_fst ,m_lst; + }; + + ////////////////////////////// + //One-Dimensional Array type// + ////////////////////////////// + + //! A template class for one-dimensional arrays. + /*! + A template class for one-D arrays. Can be used wherever built-in + arrays are used, and eliminates the need for explicit memory + (de-)allocation. Also supports arrays not based at zero. + */ + template <class T> class OneDArray + { + public: + //! Default constructor. + /*! + Default constructor produces an empty array. + */ + OneDArray(); + + //! 'Length' constructor. + /*! + Length constructor produces a zero-based array. + */ + OneDArray(const int len); + + //! Range constructor + /*! + Range constructor produces an array with values indexed within the + range parameters. + \param r a range of indexing values. + */ + OneDArray(const Range& r); + + //! Destructor. + /*! + Destructor frees the data allocated in the constructors. + */ + ~OneDArray() + { + FreePtr(); + } + + //! Copy constructor. + /*! + Copy constructor copies both data and metadata. + */ + OneDArray(const OneDArray<T>& cpy); + + //! Assignment= + /*! + Assignment= assigns both data and metadata. + */ + OneDArray<T>& operator=(const OneDArray<T>& rhs); + + //! Resize the array, throwing away the current data. + void Resize(int l); + + //! Element access. + T& operator[](const int pos){return m_ptr[pos-m_first];} + + //! Element access. + const T& operator[](const int pos) const {return m_ptr[pos-m_first];} + + //! Returns the length of the array. + int Length() const {return m_length;} + + //! Returns the index of the first element. + int First() const {return m_first;} + + //! Returns the index of the last element. + int Last() const {return m_last;} + + private: + void Init(const int len); + + void Init(const Range& r); + + void FreePtr(); + + int m_first, m_last; + int m_length; + T* m_ptr; + }; + + //public member functions// + /////////////////////////// + + template <class T> + OneDArray<T>::OneDArray() + { + Init(0); + } + + template <class T> + OneDArray<T>::OneDArray(const int len) + { + Init(len); + } + + template <class T> + OneDArray<T>::OneDArray(const Range& r) + { + Init(r); + } + + template <class T> + OneDArray<T>::OneDArray(const OneDArray<T>& cpy) + { + m_first = cpy.m_first; + m_last = cpy.m_last; + m_length = m_last - m_first + 1; + + if (m_first==0) + Init(m_length); + else + Init(Range(m_first , m_last)); + + memcpy( m_ptr , cpy.m_ptr , m_length * sizeof( T ) ); + } + + template <class T> + OneDArray<T>& OneDArray<T>::operator=(const OneDArray<T>& rhs) + { + if (&rhs != this) + { + FreePtr(); + m_first = rhs.m_first; + m_last = rhs.m_last; + m_length = rhs.m_length; + + if (m_first == 0) + Init(m_length); + else + Init(Range(m_first , m_last)); + + memcpy( m_ptr , rhs.m_ptr , m_length * sizeof( T ) ); + + } + return *this; + } + + template <class T> + void OneDArray<T>::Resize(int l) + { + if (l != m_length) + { + FreePtr(); + Init(l); + } + } + + //private member functions// + //////////////////////////// + + template <class T> + void OneDArray<T>::Init(const int len) + { + Range r(0 , len-1); + + Init(r); + + } + + template <class T> + void OneDArray<T>::Init(const Range& r) + { + + m_first = r.First(); + m_last = r.Last(); + m_length = m_last - m_first + 1; + + if ( m_length>0 ) + { + m_ptr = new T[ m_length ]; + } + else + { + m_length = 0; + m_first = 0; + m_last = -1; + m_ptr = NULL; + } + } + + template <class T> + void OneDArray<T>::FreePtr() + { + if ( m_length>0 ) + delete[] m_ptr; + } + + + ////////////////////////////// + //Two-Dimensional Array type// + ////////////////////////////// + + //! A template class for two-dimensional arrays. + /*! + A template class to do two-d arrays, so that explicit memory + (de-)allocation is not required. Only zero-based arrays are + currently supported so that access is fast. Accessing elements along + a row is therefore much faster than accessing them along a column. + Rows are contiguous in memory, so array[y][x] is equivalent to + array[0][x+y*LengthX()]. + */ + template <class T> class TwoDArray + { + typedef T* element_type; + + public: + + //! Default constructor. + /*! + Default constructor creates an empty array. + */ + TwoDArray(){ Init(0,0); } + + //! Constructor. + /*! + The constructor creates an array of given width height. + */ + TwoDArray( const int height , const int width ){Init(height , width);} + + //! Constructor. + /*! + The constructor creates an array of given width and length height + and initialises it to a value + */ + TwoDArray( const int height , const int width , T val); + + //! Destructor + /*! + Destructor frees the data allocated in the constructor. + */ + virtual ~TwoDArray(){ + FreeData(); + } + + //! Copy constructor. + /*! + Copy constructor copies data and metadata. + */ + TwoDArray(const TwoDArray<T>& Cpy); + + //! Assignment = + /*! + Assignement = assigns both data and metadata. + */ + TwoDArray<T>& operator=(const TwoDArray<T>& rhs); + + //! Copy Contents + /*! + Copy contents of array into output array retaining the dimensions + of the output array. If output array is larger that array then + pad with last true value. + Return true is copy was successful + */ + bool CopyContents(TwoDArray<T>& out) const; + + //! Fill contents + /*! + Initialise the array with the val provided. + */ + void Fill(T val); + + //! Resizes the array, deleting the current data. + void Resize(const int height, const int width); + + //! Element access. + /*! + Accesses the rows of the arrays, which are returned in the form + of pointers to the row data NOT OneDArray objects. + */ + inline element_type& operator[](const int pos){return m_array_of_rows[pos];} + + //! Element access. + /*! + Accesses the rows of the arrays, which are returned in the form of + pointers to the row data NOT OneDArray objects. + */ + inline const element_type& operator[](const int pos) const {return m_array_of_rows[pos];} + + //! Returns the width + int LengthX() const { return m_length_x; } + + //! Returns the height + int LengthY() const { return m_length_y; } + + //! Returns the index of the first element of a row + int FirstX() const { return m_first_x; } + + //! Returns the index of the first element of a column + int FirstY() const { return m_first_y; } + + //! Returns the index of the last element of a row + int LastX() const { return m_last_x; } + + //! Returns the index of the first element of a column + int LastY() const { return m_last_y; } + + private: + //! Initialise the array + void Init(const int height,const int width); + + //! Free all the allocated data + void FreeData(); + + int m_first_x; + int m_first_y; + + int m_last_x; + int m_last_y; + + int m_length_x; + int m_length_y; + + element_type* m_array_of_rows; + }; + + //public member functions// + /////////////////////////// + + template <class T> + TwoDArray<T>::TwoDArray( const int height , const int width , const T val) + { + Init( height , width ); + std::fill_n( m_array_of_rows[0], m_length_x*m_length_y, val); + } + + template <class T> + TwoDArray<T>::TwoDArray(const TwoDArray<T>& Cpy) + { + m_first_x = Cpy.m_first_x; + m_first_y = Cpy.m_first_y; + m_last_x = Cpy.m_last_x; + m_last_y = Cpy.m_last_y; + + m_length_x = m_last_x - m_first_x + 1; + m_length_y = m_last_y - m_first_y + 1; + + if (m_first_x == 0 && m_first_y == 0) + Init(m_length_y , m_length_x); + else{ + //based 2D arrays not yet supported + } + + memcpy( m_array_of_rows[0] , (Cpy.m_array_of_rows)[0] , m_length_x * m_length_y * sizeof( T ) ); + + } + + template <class T> + TwoDArray<T>& TwoDArray<T>::operator=(const TwoDArray<T>& rhs) + { + if (&rhs != this) + { + FreeData(); + + m_first_x = rhs.m_first_x; + m_first_y = rhs.m_first_y; + + m_last_x = rhs.m_last_x; + m_last_y = rhs.m_last_y; + + m_length_x = m_last_x - m_first_x + 1; + m_length_y = m_last_y - m_first_y + 1; + + if (m_first_x == 0 && m_first_y == 0) + Init(m_length_y , m_length_x); + else + { + //based 2D arrays not yet supported + } + + memcpy( m_array_of_rows[0], (rhs.m_array_of_rows)[0], m_length_x * m_length_y * sizeof( T ) ); + + } + + return *this; + + } + + template <class T> + bool TwoDArray<T>::CopyContents(TwoDArray<T>& out) const + { + if (&out != this) + { + int rows = std::min (m_length_y, out.m_length_y); + int cols = std::min (m_length_x, out.m_length_x); + for (int j = 0; j < rows; ++j) + { + memcpy( out.m_array_of_rows[j], m_array_of_rows[j], cols * sizeof( T )) ; + for (int i = cols; i <out.m_length_x; ++i) + out.m_array_of_rows[j][i] = out.m_array_of_rows[j][cols-1]; + } + for (int j = rows; j < out.m_length_y; ++j) + { + memcpy( out.m_array_of_rows[j], out.m_array_of_rows[rows-1], out.m_length_x * sizeof( T )) ; + } + } + return true; + } + + template <class T> + void TwoDArray<T>::Fill( T val) + { + if (m_length_x && m_length_y) + std::fill_n( m_array_of_rows[0], m_length_x*m_length_y, val); + } + + template <class T> + void TwoDArray<T>::Resize(const int height, const int width) + { + if (height != m_length_y || width != m_length_x) + { + FreeData(); + Init(height , width); + } + } + + //private member functions// + //////////////////////////// + + template <class T> + void TwoDArray<T>::Init(const int height , const int width) + { + m_length_x = width; + m_length_y = height; + m_first_x = 0; + m_first_y = 0; + + m_last_x = m_length_x-1; + m_last_y = m_length_y-1; + + if (m_length_y>0) + { + // allocate the array containing ptrs to all the rows + m_array_of_rows = new element_type[ m_length_y ]; + + if ( m_length_x>0 ) + { + // Allocate the whole thing as a single big block + m_array_of_rows[0] = new T[ m_length_x * m_length_y ]; + + // Point the pointers + for (int j=1 ; j<m_length_y ; ++j) + m_array_of_rows[j] = m_array_of_rows[0] + j * m_length_x; + } + else + { + m_length_x = 0; + m_first_x = 0; + m_last_x = -1; + } + } + else + { + m_length_x = 0; + m_length_y = 0; + m_first_x = 0; + m_first_y = 0; + m_last_x = -1; + m_last_y = -1; + m_array_of_rows = NULL; + } + } + + template <class T> + void TwoDArray<T>::FreeData() + { + if (m_length_y>0) + { + if (m_length_x>0) + { + delete[] m_array_of_rows[0]; + } + + m_length_y = m_length_x = 0; + // deallocate the array of rows + delete[] m_array_of_rows; + } + } + + // Related functions + + //! A function for extracting array data + template <class T > + std::ostream & operator<< (std::ostream & stream, TwoDArray<T> & array) + { + for (int j=0 ; j<array.LengthY() ; ++j) + { + for (int i=0 ; i<array.LengthX() ; ++i) + { + stream << array[j][i] << " "; + }// i + stream << std::endl; + }// j + + return stream; + } + + //! A function for inserting array data + template <class T > + std::istream & operator>> (std::istream & stream, TwoDArray<T> & array) + { + for (int j=0 ; j<array.LengthY() ; ++j) + { + for (int i=0 ; i<array.LengthX() ; ++i) + { + stream >> array[j][i]; + }// i + }// j + + return stream; + } + +} //namespace dirac +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec.cpp new file mode 100644 index 000000000..fc0e42312 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec.cpp @@ -0,0 +1,119 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: band_codec.cpp,v 1.53 2009/02/10 01:46:23 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (c) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Steve Bearcroft +* Andrew Kennedy +* Anuradha Suraparaju +* David Schleef +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +// System includes +#include <sstream> + +// Dirac includes +#include <libdirac_common/band_codec.h> +#include <libdirac_byteio/subband_byteio.h> +#include <libdirac_common/dirac_exception.h> +#include <libdirac_common/band_codec_template.h> + +using namespace dirac; + +template +GenericBandCodec<ArithCodec<CoeffArray> >::GenericBandCodec( + SubbandByteIO* subband_byteio, + size_t number_of_contexts, + const SubbandList & band_list, + int band_num, + const bool is_intra); + + +template +GenericIntraDCBandCodec<ArithCodec<CoeffArray> >::GenericIntraDCBandCodec( + SubbandByteIO* subband_byteio, + size_t number_of_contexts, + const SubbandList & band_list); +////////////////////////////////////////////////////////////////////////////////// +//Finally,special class incorporating prediction for the DC band of intra frames// +////////////////////////////////////////////////////////////////////////////////// + +void IntraDCBandCodec::DoWorkCode(CoeffArray& in_data) +{ + // Residues after prediction, quantisation and inverse quantisation + m_dc_pred_res.Resize( m_node.Yl() , m_node.Xl() ); + m_dc_pred_res.Fill( 0 ); + + BandCodec::DoWorkCode(in_data); +} + +void IntraDCBandCodec::CodeCoeff( CoeffArray& in_data, const int xpos, const int ypos) +{ + m_nhood_nonzero = false; + if (ypos > m_node.Yp()) + m_nhood_nonzero |= bool(m_dc_pred_res[ypos-1][xpos]); + if (xpos > m_node.Xp()) + m_nhood_nonzero |= bool(m_dc_pred_res[ypos][xpos-1]); + if (ypos > m_node.Yp() && xpos > m_node.Xp()) + m_nhood_nonzero |= bool(m_dc_pred_res[ypos-1][xpos-1]); + + ValueType prediction = GetPrediction( in_data , xpos , ypos ); + ValueType val = in_data[ypos][xpos] - prediction; + CodeVal( in_data , xpos , ypos , val ); + m_dc_pred_res[ypos][xpos] = in_data[ypos][xpos]; + in_data[ypos][xpos] += prediction; +} + +void IntraDCBandCodec::DoWorkDecode(CoeffArray& out_data) +{ + // Residues after prediction, quantisation and inverse quantisation + m_dc_pred_res.Resize( m_node.Yl() , m_node.Xl() ); + m_dc_pred_res.Fill( 0 ); + + BandCodec::DoWorkDecode(out_data); +} + +void IntraDCBandCodec::DecodeCoeff( CoeffArray& out_data, const int xpos, const int ypos) +{ + m_nhood_nonzero = false; + if (ypos > m_node.Yp()) + m_nhood_nonzero |= bool(m_dc_pred_res[ypos-1][xpos]); + if (xpos > m_node.Xp()) + m_nhood_nonzero |= bool(m_dc_pred_res[ypos][xpos-1]); + if (ypos > m_node.Yp() && xpos > m_node.Xp()) + m_nhood_nonzero |= bool(m_dc_pred_res[ypos-1][xpos-1]); + + DecodeVal( out_data , xpos , ypos ); + m_dc_pred_res[ypos][xpos] = out_data[ypos][xpos]; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec.h new file mode 100644 index 000000000..dfebb2e7f --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec.h @@ -0,0 +1,248 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: band_codec.h,v 1.36 2009/01/21 05:18:09 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Steve Bearcroft +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _BAND_CODEC_H_ +#define _BAND_CODEC_H_ + +#include <libdirac_common/arith_codec.h> +#include <libdirac_common/wavelet_utils.h> + + +namespace dirac +{ + + class SubbandByteIO; + + //Subclasses the arithmetic codec to produce a coding/decoding tool for subbands + + + //! A template class for coding and decoding wavelet subband data. + template<typename EntropyCodec> + class GenericBandCodec: public EntropyCodec + { + public: + + //! Constructor + /*! + Creates a BandCodec object to encode subband data + \param subband_byteio input/output for the encoded bits + \param number_of_contexts the number of contexts used in the encoding process + \param band_list the set of all the subbands + \param band_num the number of the subband being coded + \param is_intra Flag indicating whether the band comes from an intra picture + */ + GenericBandCodec(SubbandByteIO* subband_byteio, + size_t number_of_contexts, + const SubbandList& band_list, + int band_num, + const bool is_intra); + + protected: + //! Code an individual quantised value and perform inverse-quantisation + inline void CodeVal( CoeffArray& in_data , const int xpos , const int ypos , const CoeffType val); + + //! Decode an individual quantised value and perform inverse-quantisation + inline void DecodeVal(CoeffArray& out_data , const int xpos , const int ypos ); + + //! Encode the offset for a code block quantiser + void CodeQuantIndexOffset( const int offset ); + + //! Decode the offset for a code block quantiser + int DecodeQuantIndexOffset(); + + //! Set a code block area to a given value + inline void SetToVal( const CodeBlock& code_block , CoeffArray& coeff_data , const CoeffType val); + + //! Set all block values to 0 + virtual void ClearBlock( const CodeBlock& code_block , CoeffArray& coeff_data); + + protected: + //functions + // Overridden from the base class + virtual void DoWorkCode(CoeffArray& in_data); + // Ditto + virtual void DoWorkDecode(CoeffArray& out_data); + + virtual void CodeCoeffBlock(const CodeBlock& code_block , CoeffArray& in_data); + virtual void DecodeCoeffBlock(const CodeBlock& code_block , CoeffArray& out_data); + + virtual void CodeCoeff(CoeffArray& in_data, const int xpos, const int ypos); + + virtual void DecodeCoeff(CoeffArray& in_data, const int xpos, const int ypos); + //! A function for choosing the context for "follow bits" + inline int ChooseFollowContext( const int bin_number ) const; + + //! A function for choosing the context for "information bits" + inline int ChooseInfoContext() const; + + //! A function for choosing the context for sign bits + inline int ChooseSignContext(const CoeffArray& data , const int xpos , const int ypos ) const; + + private: + //! Private, bodyless copy constructor: class should not be copied + GenericBandCodec(const GenericBandCodec& cpy); + //! Private, bodyless copy operator=: class should not be assigned + GenericBandCodec& operator=(const GenericBandCodec& rhs); + + protected: + + //! Flag indicating whether the band comes from an intra picture + bool m_is_intra; + + //! variables + int m_bnum; + + //! the subband being coded + const Subband m_node; + + //! the quantisation index of the last codeblock + int m_last_qf_idx; + + //! quantisation value + int m_qf; + + //! reconstruction point + CoeffType m_offset; + + //! True if neighbours non-zero + bool m_nhood_nonzero; + + //! the parent subband + Subband m_pnode; + + //! position of the parent coefficient + int m_pxpos, m_pypos; + + //! True if the parent of a coeff is not zero + bool m_parent_notzero; + + }; + + //! A general class for coding and decoding wavelet subband data. + /*! + A general class for coding and decoding wavelet subband data, deriving from the abstract ArithCodec class. + */ + typedef GenericBandCodec<ArithCodec<CoeffArray> > BandCodec; + typedef BandCodec LFBandCodec; + + ////////////////////////////////////////////////////////////////////////////////// + //Finally,special class incorporating prediction for the DC band of intra frames// + ////////////////////////////////////////////////////////////////////////////////// + + //! A template class specially for coding the DC subband of Intra frames + template<typename EntropyCodec> + class GenericIntraDCBandCodec : public GenericBandCodec<EntropyCodec> + { + public: + //! Constructor + /*! + Creates a IntraDCBandCodec object to encode subband data + \param subband_byteio input/output for the encoded bits + \param number_of_contexts the number of contexts used in the encoding process + \param band_list the set of all the subbands + */ + GenericIntraDCBandCodec(SubbandByteIO* subband_byteio, + size_t number_of_contexts, + const SubbandList& band_list) + : GenericBandCodec<EntropyCodec>(subband_byteio,number_of_contexts, + band_list, band_list.Length(), + true){} + + protected: + //! When coding a skipped block, propegate the predicted values for future non skipped blocks + void ClearBlock( const CodeBlock& code_block , CoeffArray& coeff_data); + + //! Prediction of a DC value from its previously coded neighbours + CoeffType GetPrediction(const CoeffArray& data , const int xpos , const int ypos ) const; + + //! Decode codeblock of coefficients and perform DC prediction + void DecodeCoeffBlock(const CodeBlock& code_block , CoeffArray& out_data); + }; + + + //! A class specially for coding the DC subband of Intra frames + /*! + A class specially for coding the DC subband of Intra frames, using + intra-band prediction of coefficients. It uses the abstract ArithCodec + class + */ + class IntraDCBandCodec: public GenericIntraDCBandCodec<ArithCodec<CoeffArray> > + { + public: + //! Constructor + /*! + Creates a IntraDCBandCodec object to encode subband data, based on parameters + \param subband_byteio input/output for the encoded bits + \param number_of_contexts the number of contexts used in the encoding process + \param band_list the set of all the subbands + */ + IntraDCBandCodec(SubbandByteIO* subband_byteio, + size_t number_of_contexts, + const SubbandList& band_list) + : GenericIntraDCBandCodec<ArithCodec<CoeffArray> >(subband_byteio, + number_of_contexts, + band_list){} + + + private: + //! Initialize extra data required for error-feedback DC quantization + void DoWorkCode(CoeffArray& in_data); //overridden from the base class + + //! Ditto + void DoWorkDecode(CoeffArray& out_data); + + //! Encode a single coefficient using error-feedback DC quantization + void CodeCoeff(CoeffArray& in_data, const int xpos, const int ypos); + + //! Decode a single coefficient using error-feedback DC quantization + void DecodeCoeff(CoeffArray& out_data, const int xpos, const int ypos); + + //! Private, bodyless copy constructor: class should not be copied + IntraDCBandCodec(const IntraDCBandCodec& cpy); + + //! Private, bodyless copy operator=: class should not be assigned + IntraDCBandCodec& operator=(const IntraDCBandCodec& rhs); + + private: + CoeffArray m_dc_pred_res; + }; + +}// end namespace dirac +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec_template.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec_template.h new file mode 100644 index 000000000..8ca94d089 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_codec_template.h @@ -0,0 +1,557 @@ +
+#include <libdirac_common/band_codec.h>
+#include <libdirac_byteio/subband_byteio.h>
+
+using namespace dirac;
+
+//! Constructor for encoding.
+template<typename EntropyCodec>
+GenericBandCodec<EntropyCodec>::GenericBandCodec(SubbandByteIO* subband_byteio,
+ size_t number_of_contexts,
+ const SubbandList & band_list,
+ int band_num,
+ const bool is_intra):
+ EntropyCodec(subband_byteio,number_of_contexts),
+ m_is_intra(is_intra),
+ m_bnum(band_num),
+ m_node(band_list(band_num)),
+ m_last_qf_idx(m_node.QuantIndex())
+{
+ if (m_node.Parent()!=0)
+ m_pnode=band_list(m_node.Parent());
+}
+
+
+//encoding function
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::DoWorkCode(CoeffArray& in_data)
+{
+
+ const TwoDArray<CodeBlock>& block_list( m_node.GetCodeBlocks() );
+
+ // coeff blocks can be skipped only if SpatialPartitioning is
+ // enabled i.e. more than one code-block per subband
+ bool code_skip = (block_list.LengthX() > 1 || block_list.LengthY() > 1);
+ // Now loop over the blocks and code
+ for (int j=block_list.FirstY() ; j<=block_list.LastY() ; ++j)
+ {
+ CodeBlock *block = block_list[j];
+ for (int i=block_list.FirstX() ; i<=block_list.LastX() ; ++i)
+ {
+ if (code_skip)
+ EntropyCodec::EncodeSymbol(block[i].Skipped() , BLOCK_SKIP_CTX );
+ if ( !block[i].Skipped() )
+ CodeCoeffBlock( block[i] , in_data );
+ else
+ ClearBlock (block[i] , in_data);
+ }// i
+ }// j
+
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::CodeCoeffBlock( const CodeBlock& code_block , CoeffArray& in_data )
+{
+ //main coding function, using binarisation
+
+ const int xbeg = code_block.Xstart();
+ const int ybeg = code_block.Ystart();
+ const int xend = code_block.Xend();
+ const int yend = code_block.Yend();
+
+ const int qf_idx = code_block.QuantIndex();
+
+ bool has_parent = m_node.Parent() != 0;
+
+ if ( m_node.UsingMultiQuants() )
+ {
+ CodeQuantIndexOffset( qf_idx - m_last_qf_idx);
+ m_last_qf_idx = qf_idx;
+ }
+
+ m_qf = dirac_quantiser_lists.QuantFactor4( qf_idx );
+ if (m_is_intra)
+ m_offset = dirac_quantiser_lists.IntraQuantOffset4( qf_idx );
+ else
+ m_offset = dirac_quantiser_lists.InterQuantOffset4( qf_idx );
+
+ for ( int ypos=ybeg; ypos<yend ;++ypos)
+ {
+ m_pypos=(( ypos-m_node.Yp() )>>1)+m_pnode.Yp();
+ for ( int xpos=xbeg; xpos<xend ;++xpos)
+ {
+ m_pxpos=(( xpos-m_node.Xp() )>>1)+m_pnode.Xp();
+
+ m_nhood_nonzero = false;
+ if (ypos > m_node.Yp())
+ m_nhood_nonzero |= bool(in_data[ypos-1][xpos]);
+ if (xpos > m_node.Xp())
+ m_nhood_nonzero |= bool(in_data[ypos][xpos-1]);
+ if (ypos > m_node.Yp() && xpos > m_node.Xp())
+ m_nhood_nonzero |= bool(in_data[ypos-1][xpos-1]);
+
+ if (has_parent)
+ m_parent_notzero = static_cast<bool> ( in_data[m_pypos][m_pxpos] );
+ else
+ m_parent_notzero = false;
+
+ CodeCoeff( in_data , xpos , ypos );
+
+ }// xpos
+ }// ypos
+
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::CodeCoeff( CoeffArray& in_data, const int xpos, const int ypos)
+{
+ CodeVal( in_data , xpos , ypos , in_data[ypos][xpos] );
+}
+
+
+/*
+Coefficient magnitude value and differential quantiser index magnitude are
+coded using interleaved exp-Golomb coding for binarisation. In this scheme, a
+value N>=0 is coded by writing N+1 in binary form of a 1 followed by K other
+bits: 1bbbbbbb (adding 1 ensures there'll be a leading 1). These K bits ("info
+bits") are interleaved with K zeroes ("follow bits") each of which means
+"another bit coming", followed by a terminating 1:
+
+ 0b0b0b ...0b1
+
+(Conventional exp-Golomb coding has the K zeroes at the beginning, followed
+by the 1 i.e 00...01bb .. b, but interleaving allows the decoder to run a
+single loop and avoid counting the number of zeroes, sparing a register.)
+
+All bits are arithmetically coded. The follow bits have separate contexts
+based on position, and have different contexts from the info bits.
+*/
+
+template<typename EntropyCodec>
+inline void GenericBandCodec<EntropyCodec>::CodeVal( CoeffArray& in_data ,
+ const int xpos ,
+ const int ypos ,
+ const CoeffType val )
+{
+ unsigned int abs_val( std::abs(val) );
+ abs_val <<= 2;
+ abs_val /= m_qf;
+
+ const int N = abs_val+1;
+ int num_follow_zeroes=0;
+
+ while ( N >= (1<<num_follow_zeroes) )
+ ++num_follow_zeroes;
+ --num_follow_zeroes;
+
+ for ( int i=num_follow_zeroes-1, c=1; i>=0; --i, ++c )
+ {
+ EntropyCodec::EncodeSymbol( 0, ChooseFollowContext( c ) );
+ EntropyCodec::EncodeSymbol( N&(1<<i), ChooseInfoContext() );
+ }
+ EntropyCodec::EncodeSymbol( 1, ChooseFollowContext( num_follow_zeroes+1 ) );
+
+ in_data[ypos][xpos] = static_cast<CoeffType>( abs_val );
+
+ if ( abs_val )
+ {
+ // Must code sign bits and reconstruct
+ in_data[ypos][xpos] *= m_qf;
+ in_data[ypos][xpos] += m_offset+2;
+ in_data[ypos][xpos] >>= 2;
+
+ if ( val>0 )
+ {
+ EntropyCodec::EncodeSymbol( 0 , ChooseSignContext( in_data , xpos , ypos ) );
+ }
+ else
+ {
+ EntropyCodec::EncodeSymbol( 1 , ChooseSignContext( in_data , xpos , ypos ) );
+ in_data[ypos][xpos] = -in_data[ypos][xpos];
+ }
+ }
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::CodeQuantIndexOffset( const int offset )
+{
+
+ const int abs_val = std::abs( offset );
+
+ int N = abs_val+1;
+ int num_follow_zeroes=0;
+
+ while ( N>= (1<<num_follow_zeroes) )
+ ++num_follow_zeroes;
+ --num_follow_zeroes;
+
+ for ( int i=num_follow_zeroes-1, c=1; i>=0; --i, ++c )
+ {
+ EntropyCodec::EncodeSymbol( 0 , Q_OFFSET_FOLLOW_CTX );
+ EntropyCodec::EncodeSymbol( N&(1<<i), Q_OFFSET_INFO_CTX );
+ }
+ EntropyCodec::EncodeSymbol( 1 , Q_OFFSET_FOLLOW_CTX );
+
+ if ( abs_val )
+ {
+ if ( offset>0 )
+ EntropyCodec::EncodeSymbol( 0 , Q_OFFSET_SIGN_CTX );
+ else
+ EntropyCodec::EncodeSymbol( 1 , Q_OFFSET_SIGN_CTX );
+ }
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::DoWorkDecode( CoeffArray& out_data )
+{
+ const TwoDArray<CodeBlock>& block_list( m_node.GetCodeBlocks() );
+
+ // coeff blocks can be skipped only if SpatialPartitioning is
+ // enabled i.e. more than one code-block per subband
+ bool decode_skip= (block_list.LengthX() > 1 || block_list.LengthY() > 1);
+ // Now loop over the blocks and decode
+ for (int j=block_list.FirstY() ; j<=block_list.LastY() ; ++j)
+ {
+ CodeBlock *block = block_list[j];
+ for (int i=block_list.FirstX() ; i<=block_list.LastX() ; ++i)
+ {
+ if (decode_skip)
+ block[i].SetSkip( EntropyCodec::DecodeSymbol( BLOCK_SKIP_CTX ) );
+ if ( !block[i].Skipped() )
+ DecodeCoeffBlock( block[i] , out_data );
+ else
+ ClearBlock (block[i] , out_data);
+
+ }// i
+ }// j
+
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::DecodeCoeffBlock( const CodeBlock& code_block , CoeffArray& out_data )
+{
+
+
+ const int xbeg = code_block.Xstart();
+ const int ybeg = code_block.Ystart();
+ const int xend = code_block.Xend();
+ const int yend = code_block.Yend();
+
+ int qf_idx = m_node.QuantIndex();
+
+ bool has_parent = m_node.Parent() != 0;
+
+ if ( m_node.UsingMultiQuants() )
+ {
+ qf_idx = m_last_qf_idx+DecodeQuantIndexOffset();
+ m_last_qf_idx = qf_idx;
+ }
+
+ if (qf_idx > (int)dirac_quantiser_lists.MaxQuantIndex())
+ {
+ std::ostringstream errstr;
+ errstr << "Quantiser index out of range [0.."
+ << (int)dirac_quantiser_lists.MaxQuantIndex() << "]";
+ DIRAC_THROW_EXCEPTION(
+ ERR_UNSUPPORTED_STREAM_DATA,
+ errstr.str(),
+ SEVERITY_PICTURE_ERROR);
+ }
+
+ m_qf = dirac_quantiser_lists.QuantFactor4( qf_idx );
+
+ if (m_is_intra)
+ m_offset = dirac_quantiser_lists.IntraQuantOffset4( qf_idx );
+ else
+ m_offset = dirac_quantiser_lists.InterQuantOffset4( qf_idx );
+
+ //Work
+
+ for ( int ypos=ybeg; ypos<yend ;++ypos)
+ {
+ m_pypos=(( ypos-m_node.Yp() )>>1)+m_pnode.Yp();
+ CoeffType *p_out_data = NULL;
+ if (has_parent)
+ p_out_data = out_data[m_pypos];
+ CoeffType *c_out_data_1 = NULL;
+ if (ypos!=m_node.Yp())
+ c_out_data_1 = out_data[ypos-1];
+ CoeffType *c_out_data_2 = out_data[ypos];
+ for ( int xpos=xbeg; xpos<xend ;++xpos)
+ {
+ m_pxpos=(( xpos-m_node.Xp() )>>1)+m_pnode.Xp();
+
+ m_nhood_nonzero = false;
+ /* c_out_data_1 is the line above the current
+ * c_out_data_2 is the current line */
+ if (ypos > m_node.Yp())
+ m_nhood_nonzero |= bool(c_out_data_1[xpos]);
+ if (xpos > m_node.Xp())
+ m_nhood_nonzero |= bool(c_out_data_2[xpos-1]);
+ if (ypos > m_node.Yp() && xpos > m_node.Xp())
+ m_nhood_nonzero |= bool(c_out_data_1[xpos-1]);
+
+ if (has_parent)
+ m_parent_notzero = ( p_out_data[m_pxpos] != 0 );
+ else
+ m_parent_notzero = false;
+
+ DecodeCoeff( out_data , xpos , ypos );
+
+ }// xpos
+ }// ypos
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::DecodeCoeff( CoeffArray& in_data, const int xpos, const int ypos)
+{
+ DecodeVal( in_data , xpos , ypos );
+}
+
+
+/*
+Coefficient magnitude value and differential quantiser index value is coded
+using interleaved exp-Golomb coding for binarisation. In this scheme, a value
+N>=0 is coded by writing N+1 in binary form of a 1 followed by K other bits:
+1bbbbbbb (adding 1 ensures there'll be a leading 1). These K bits ("info bits")
+are interleaved with K zeroes ("follow bits") each of which means "another bit
+coming", followed by a terminating 1:
+
+ 0b0b0b ...0b1
+
+(Conventional exp-Golomb coding has the K zeroes at the beginning, followed
+by the 1 i.e 00...01bb .. b, but interleaving allows the decoder to run a
+single loop and avoid counting the number of zeroes, sparing a register.)
+
+All bits are arithmetically coded. The follow bits have separate contexts
+based on position, and have different contexts from the info bits.
+*/
+template<typename EntropyCodec>
+inline void GenericBandCodec<EntropyCodec>::DecodeVal( CoeffArray& out_data , const int xpos , const int ypos )
+{
+
+ CoeffType& out_pixel = out_data[ypos][xpos];
+
+ out_pixel = 1;
+ int bit_count=1;
+
+ while ( !EntropyCodec::DecodeSymbol( ChooseFollowContext( bit_count ) ) )
+ {
+ out_pixel <<= 1;
+ out_pixel |= EntropyCodec::DecodeSymbol( ChooseInfoContext() );
+ bit_count++;
+ };
+ --out_pixel;
+
+ if ( out_pixel )
+ {
+ out_pixel *= m_qf;
+ out_pixel += m_offset+2;
+ out_pixel >>= 2;
+
+ if ( EntropyCodec::DecodeSymbol( ChooseSignContext(out_data, xpos, ypos)) )
+ out_pixel = -out_pixel;
+ }
+}
+
+template<typename EntropyCodec>
+inline int GenericBandCodec<EntropyCodec>::ChooseFollowContext( const int bin_number ) const
+{
+ //condition on neighbouring values and parent values
+
+ if (!m_parent_notzero)
+ {
+ switch ( bin_number )
+ {
+ case 1 :
+ if(m_nhood_nonzero == false)
+ return Z_FBIN1z_CTX;
+
+ return Z_FBIN1nz_CTX;
+
+ case 2 :
+ return Z_FBIN2_CTX;
+ case 3 :
+ return Z_FBIN3_CTX;
+ case 4 :
+ return Z_FBIN4_CTX;
+ case 5 :
+ return Z_FBIN5_CTX;
+ default :
+ return Z_FBIN6plus_CTX;
+ }
+ }
+ else
+ {
+ switch ( bin_number )
+ {
+ case 1 :
+ if(m_nhood_nonzero == false)
+ return NZ_FBIN1z_CTX;
+
+ return NZ_FBIN1nz_CTX;
+
+ case 2 :
+ return NZ_FBIN2_CTX;
+ case 3 :
+ return NZ_FBIN3_CTX;
+ case 4 :
+ return NZ_FBIN4_CTX;
+ case 5 :
+ return NZ_FBIN5_CTX;
+ default :
+ return NZ_FBIN6plus_CTX;
+ }
+
+ }
+
+ /* not reachable, but dumb compilers can't spot that */
+ return 0;
+}
+
+template<typename EntropyCodec>
+inline int GenericBandCodec<EntropyCodec>::ChooseInfoContext() const
+{
+ return INFO_CTX;
+}
+
+template<typename EntropyCodec>
+inline int GenericBandCodec<EntropyCodec>::ChooseSignContext( const CoeffArray& data , const int xpos , const int ypos ) const
+{
+ if ( m_node.Yp()==0 && m_node.Xp()!=0 )
+ {
+ //we're in a vertically oriented subband
+ if (ypos == 0)
+ return SIGN0_CTX;
+ else
+ {
+ if (data[ypos-1][xpos]>0)
+ return SIGN_POS_CTX;
+ else if (data[ypos-1][xpos]<0)
+ return SIGN_NEG_CTX;
+ else
+ return SIGN0_CTX;
+ }
+ }
+ else if ( m_node.Xp()==0 && m_node.Yp()!=0 )
+ {
+ //we're in a horizontally oriented subband
+ if (xpos == 0)
+ return SIGN0_CTX;
+ else
+ {
+ if ( data[ypos][xpos-1] > 0 )
+ return SIGN_POS_CTX;
+ else if ( data[ypos][xpos-1] < 0 )
+ return SIGN_NEG_CTX;
+ else
+ return SIGN0_CTX;
+ }
+ }
+ else
+ return SIGN0_CTX;
+}
+
+template<typename EntropyCodec>
+int GenericBandCodec<EntropyCodec>::DecodeQuantIndexOffset()
+{
+ int offset = 1;
+
+ while ( !EntropyCodec::DecodeSymbol( Q_OFFSET_FOLLOW_CTX ) )
+ {
+ offset <<= 1;
+ offset |= EntropyCodec::DecodeSymbol( Q_OFFSET_INFO_CTX );
+ }
+ --offset;
+
+ if ( offset )
+ {
+ if ( EntropyCodec::DecodeSymbol( Q_OFFSET_SIGN_CTX ) )
+ offset = -offset;
+ }
+ return offset;
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::SetToVal( const CodeBlock& code_block , CoeffArray& pic_data , const CoeffType val)
+{
+ for (int j=code_block.Ystart() ; j<code_block.Yend() ; j++)
+ {
+ for (int i=code_block.Xstart() ; i<code_block.Xend() ; i++)
+ {
+ pic_data[j][i] = val;
+ }// i
+ }// j
+}
+
+template<typename EntropyCodec>
+void GenericBandCodec<EntropyCodec>::ClearBlock( const CodeBlock& code_block , CoeffArray& coeff_data)
+{
+ for (int j=code_block.Ystart() ; j<code_block.Yend() ; j++)
+ {
+ CoeffType *pic = &coeff_data[j][code_block.Xstart()];
+ memset (pic, 0, (code_block.Xend()-code_block.Xstart())*sizeof(CoeffType));
+ }// j
+
+}
+
+/* Decode a single coefficient using error-feedback DC quantization */
+template<typename EntropyCodec>
+void GenericIntraDCBandCodec<EntropyCodec>::DecodeCoeffBlock(const CodeBlock& code_block , CoeffArray& out_data)
+{
+ GenericBandCodec<EntropyCodec>::DecodeCoeffBlock(code_block, out_data);
+ /* do prediction for this block */
+ for ( int ypos=code_block.Ystart() ; ypos<code_block.Yend() ; ++ypos)
+ {
+ for ( int xpos=code_block.Xstart() ; xpos<code_block.Xend() ; ++xpos)
+ {
+ out_data[ypos][xpos] += GetPrediction( out_data , xpos , ypos );
+ }
+ }
+}
+
+/* after coding a skipped DC codeblock, reconstruct in_data by predicting the values
+ * and not adding any error term (they were all skipped). This is required to correctly
+ * predict the values in the next codeblock */
+
+template<typename EntropyCodec>
+void GenericIntraDCBandCodec<EntropyCodec>::ClearBlock( const CodeBlock& code_block , CoeffArray& coeff_data)
+{
+ for (int ypos=code_block.Ystart() ; ypos<code_block.Yend() ; ++ypos)
+ {
+ for (int xpos=code_block.Xstart() ; xpos<code_block.Xend() ; ++xpos)
+ {
+ /* NB, it is correct to overwrite the old value */
+ coeff_data[ypos][xpos] = GetPrediction( coeff_data , xpos , ypos );
+ } // i
+ } // j
+}
+
+template<typename EntropyCodec>
+CoeffType GenericIntraDCBandCodec<EntropyCodec>::GetPrediction( const CoeffArray& data , const int xpos , const int ypos ) const
+{
+ /* NB, 4.5.3 integer division
+ * numbers are rounded down towards -ve infinity, differing from
+ * C's convention that rounds towards 0
+ */
+ if (ypos!=0)
+ {
+ if (xpos!=0)
+ {
+ int sum = data[ypos][xpos-1] + data[ypos-1][xpos-1] + data[ypos-1][xpos] + 3/2;
+ if (sum<0)
+ return (sum-2)/3;
+ else
+ return sum/3;
+ }
+ else
+ return data[ypos - 1][0];
+ }
+ else
+ {
+ if(xpos!=0)
+ return data[0][xpos - 1];
+ else
+ return 0;
+ }
+}
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_vlc.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_vlc.cpp new file mode 100644 index 000000000..b6ddf5337 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_vlc.cpp @@ -0,0 +1,101 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: band_vlc.cpp,v 1.8 2009/02/10 01:46:23 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (c) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Anuradha Suraparaju (Original Author)
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+// System includes
+#include <sstream>
+
+// Dirac includes
+#include <libdirac_common/band_vlc.h>
+#include <libdirac_byteio/subband_byteio.h>
+#include <libdirac_common/dirac_exception.h>
+#include <libdirac_common/band_codec_template.h>
+
+using namespace dirac;
+
+ArithCodecToVLCAdapter::ArithCodecToVLCAdapter(
+ SubbandByteIO* subband_byteio,
+ size_t /*number_of_contexts*/):
+ m_byteio(subband_byteio)
+{}
+
+// encoding functions
+int ArithCodecToVLCAdapter::Compress(CoeffArray &in_data)
+{
+ DoWorkCode(in_data);
+ return m_byteio->GetSize();
+}
+
+// decoding functions
+void ArithCodecToVLCAdapter::Decompress(CoeffArray &out_data, int num_bytes)
+{
+ m_byteio->SetBitsLeft(num_bytes * 8);
+ DoWorkDecode(out_data);
+ m_byteio->FlushInputB();
+}
+
+template
+GenericBandCodec<ArithCodecToVLCAdapter>::GenericBandCodec(
+ SubbandByteIO* subband_byteio,
+ size_t number_of_contexts,
+ const SubbandList & band_list,
+ int band_num,
+ const bool is_intra);
+
+template
+GenericIntraDCBandCodec<ArithCodecToVLCAdapter>::GenericIntraDCBandCodec(
+ SubbandByteIO* subband_byteio,
+ size_t number_of_contexts,
+ const SubbandList & band_list);
+
+IntraDCBandVLC::IntraDCBandVLC(SubbandByteIO* subband_byteio,
+ const SubbandList& band_list):
+ GenericIntraDCBandCodec<ArithCodecToVLCAdapter>(subband_byteio, 0, band_list)
+{}
+
+void IntraDCBandVLC::CodeCoeff( CoeffArray& in_data ,
+ const int xpos ,
+ const int ypos )
+{
+ CoeffType val, prediction;
+
+ prediction = GetPrediction( in_data, xpos, ypos );
+ val = in_data[ypos][xpos] - prediction;
+ CodeVal( in_data , xpos , ypos , val );
+ in_data[ypos][xpos] += prediction;
+}
+
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_vlc.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_vlc.h new file mode 100644 index 000000000..597802d26 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/band_vlc.h @@ -0,0 +1,140 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: band_vlc.h,v 1.8 2009/02/09 09:44:56 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Scott R Ladd,
+* Steve Bearcroft
+* Andrew Kennedy
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef _BAND_VLC_H
+#define _BAND_VLC_H
+
+#include <libdirac_common/wavelet_utils.h>
+#include <libdirac_common/band_codec.h>
+
+
+namespace dirac
+{
+
+ class SubbandByteIO;
+ class ByteIO;
+
+ /*! Abstract VLC entropy codec base class */
+ class ArithCodecToVLCAdapter
+ {
+ public:
+ /*! Constructor */
+ ArithCodecToVLCAdapter(SubbandByteIO* subband_byteio, size_t number_of_contexts);
+
+ /*! Virtual Destructor */
+ virtual ~ArithCodecToVLCAdapter(){}
+
+ /* Compresses the input and returns the number of bits written */
+ int Compress (CoeffArray &in_data);
+
+ /* Decompresses the bitstream */
+ void Decompress (CoeffArray& out_data, int num_bytes);
+
+ /* Encodes a symbol and writes to the output */
+ void EncodeSymbol(bool val, int /*context_num*/)
+ {
+ m_byteio->WriteBit(val);
+ }
+
+ /* Decodes a symbol */
+ bool DecodeSymbol(int /*context_num*/)
+ {
+ return m_byteio->ReadBoolB();
+ }
+
+ /*! Purely virtual function that does the actual encoding. Derived classes must define it */
+ virtual void DoWorkCode(CoeffArray &in_data) = 0;
+
+ /*! Purely virtual function that does the actual decoding. Derived classes must define it */
+ virtual void DoWorkDecode(CoeffArray &out_data) = 0;
+
+ protected:
+ /*! Input/output stream for Dirac-format bytes */
+ ByteIO *m_byteio;
+
+ private:
+ //! Private, bodyless copy constructor: class should not be copied
+ ArithCodecToVLCAdapter(const ArithCodecToVLCAdapter& cpy);
+ //! Private, bodyless copy operator=: class should not be assigned
+ ArithCodecToVLCAdapter& operator=(const ArithCodecToVLCAdapter& rhs);
+ };
+
+
+ //! A general class for coding and decoding wavelet subband data using variable length coding.
+ /*!
+ A general class for coding and decoding wavelet subband data using variable length coding,
+ */
+ typedef GenericBandCodec<ArithCodecToVLCAdapter> BandVLC;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ //Finally,special class incorporating prediction for the DC band of intra frames//
+ //////////////////////////////////////////////////////////////////////////////////
+
+ //! A class specially for coding the DC subband of Intra frames
+ /*!
+ A class specially for coding the DC subband of Intra frames, using intra-band prediction
+ of coefficients.
+ */
+ class IntraDCBandVLC: public GenericIntraDCBandCodec<ArithCodecToVLCAdapter>
+ {
+ public:
+ //! Constructor
+ /*!
+ Creates a IntraDCBandVLC object to encode subband data, based on parameters
+ \param subband_byteio input/output for the encoded bits
+ \param band_list the set of all the subbands
+ */
+ IntraDCBandVLC(SubbandByteIO* subband_byteio,
+ const SubbandList& band_list);
+ private:
+ //! Encode a single coefficient using error-feedback DC quantization
+ void CodeCoeff(CoeffArray& in_data, const int xpos, const int ypos);
+
+ private:
+ //! Private, bodyless copy constructor: class should not be copied
+ IntraDCBandVLC (const IntraDCBandVLC& cpy);
+
+ //! Private, bodyless copy operator=: class should not be assigned
+ IntraDCBandVLC& operator=(const IntraDCBandVLC& rhs);
+ };
+
+
+}// end namespace dirac
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/bit_manager.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/bit_manager.cpp new file mode 100644 index 000000000..aed3d145c --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/bit_manager.cpp @@ -0,0 +1,454 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: bit_manager.cpp,v 1.10 2008/01/31 11:25:16 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (original author),
+* Robert Scott Ladd,
+* Tim Borer
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#include <libdirac_common/bit_manager.h>
+#include <libdirac_common/common.h>
+using namespace dirac;
+
+using std::vector;
+
+////////////////
+//Output stuff//
+////////////////
+
+//Constructor
+BasicOutputManager::BasicOutputManager(std::ostream* out_data ):
+ m_num_out_bytes(0),
+ m_op_ptr(out_data)
+{
+ InitOutputStream();
+}
+
+void BasicOutputManager::InitOutputStream()
+{
+ // Set byte pointer to start of buffer
+ m_current_byte = 0;
+ // Set output mask to MSB of byte
+ m_output_mask = 0x80;
+ // Reset the output buffer
+ m_buffer.clear();
+}
+
+void BasicOutputManager::OutputSkipInterpretStartPrefixByte()
+{
+ size_t buf_size = m_buffer.size();
+ if (buf_size >=4 &&
+ m_buffer[buf_size-1] == (char)START_CODE_PREFIX_BYTE3 &&
+ m_buffer[buf_size-2] == (char)START_CODE_PREFIX_BYTE2 &&
+ m_buffer[buf_size-3] == (char)START_CODE_PREFIX_BYTE1 &&
+ m_buffer[buf_size-4] == (char)START_CODE_PREFIX_BYTE0)
+ {
+ m_buffer.push_back((char)NOT_START_CODE);
+ std::cerr << "Wrote ignore code " << std::endl;
+ }
+}
+
+void BasicOutputManager::OutputBit(const bool& bit )
+{
+ m_current_byte |= (bit ? (m_output_mask):0);
+
+ // Shift mask to next bit in the output byte
+ m_output_mask >>= 1;
+
+ if ( m_output_mask == 0 )
+ {
+ // If a whole byte has been written, write out
+ m_output_mask = 0x80;
+ m_buffer.push_back(m_current_byte);
+ OutputSkipInterpretStartPrefixByte();
+ m_current_byte = 0;
+ }
+}
+
+void BasicOutputManager::OutputBit(const bool& bit, int& count)
+{
+ OutputBit(bit);
+ count++;
+}
+
+void BasicOutputManager::OutputByte(const char& byte)
+{
+ FlushOutput();
+ m_buffer.push_back( byte );
+ OutputSkipInterpretStartPrefixByte();
+}
+
+void BasicOutputManager::OutputBytes( char* str_array )
+{
+ FlushOutput();
+ while ( *str_array != 0 )
+ {
+ m_buffer.push_back( *str_array );
+ str_array++;
+ }
+}
+
+void BasicOutputManager::OutputBytes(char* str_array,int num)
+{
+ FlushOutput();
+ for ( int i=0 ; i<num ; ++i )
+ m_buffer.push_back( str_array[i] );
+}
+
+
+void BasicOutputManager::WriteToFile()
+{
+ FlushOutput();
+ for ( vector<char>::iterator it=m_buffer.begin() ; it!=m_buffer.end() ; ++it )
+ {
+ m_op_ptr->write( &( *it ) , 1 );
+ }
+ m_num_out_bytes = m_buffer.size();
+ InitOutputStream();
+}
+
+void BasicOutputManager::FlushOutput()
+{
+ // Flush the current byte to output buffer and reset
+ if ( m_output_mask != 0x80 )
+ {
+ m_buffer.push_back( m_current_byte );
+ m_current_byte = 0;
+ m_output_mask = 0x80;
+ }
+}
+
+size_t BasicOutputManager::Size() const
+{
+ if ( m_output_mask==0x80 )
+ return m_buffer.size();
+ else
+ return m_buffer.size()+1;
+}
+
+// Unit output - a subband or the MV data, for example //
+
+UnitOutputManager::UnitOutputManager(std::ostream* out_data ):
+ m_header(out_data),
+ m_data(out_data),
+ m_unit_bytes(0),
+ m_unit_data_bytes(0),
+ m_unit_head_bytes(0)
+ {}
+
+void UnitOutputManager::WriteToFile()
+{
+ m_header.WriteToFile();
+ m_data.WriteToFile();
+
+ // after writing to file, get the number of unit bytes written
+ m_unit_data_bytes = m_data.GetNumBytes();
+ m_unit_head_bytes = m_header.GetNumBytes();
+ m_unit_bytes = m_unit_data_bytes + m_unit_head_bytes;
+
+}
+
+size_t UnitOutputManager::Size() const
+{
+ return m_data.Size()+m_header.Size();
+}
+
+FrameOutputManager::FrameOutputManager( std::ostream* out_data , int num_bands ) :
+ m_data_array( 3 , num_bands ),
+ m_comp_bytes( 3 ),
+ m_comp_hdr_bytes( 3 ),
+ m_out_stream( out_data )
+{
+ Init( num_bands );
+}
+
+FrameOutputManager::~FrameOutputManager()
+{
+ DeleteAll();
+}
+
+void FrameOutputManager::WriteToFile()
+{
+
+ // Write out the picture header
+ m_frame_header->WriteToFile();
+ m_total_bytes = m_frame_header->GetNumBytes();
+ m_header_bytes = m_frame_header->GetNumBytes();
+
+ // Write out the motion vector data
+ m_mv_data->WriteToFile();
+
+ // after writing to file, get the number of bytes written
+ m_mv_hdr_bytes = m_mv_data->GetUnitHeaderBytes();
+ m_mv_bytes = m_mv_data->GetUnitBytes();
+
+ m_total_bytes += m_mv_bytes;
+ m_header_bytes += m_mv_hdr_bytes;
+
+ // Write out the component data
+ for ( int c=0 ; c<3 ; ++c)
+ {
+
+ m_comp_hdr_bytes[c] = 0;
+ m_comp_bytes[c] = 0;
+
+ for ( int b=m_data_array.LastX() ; b>=0 ; --b)
+ {
+ m_data_array[c][b]->WriteToFile();
+ // after writing to file, get the number of bytes written
+ m_comp_hdr_bytes[c] += m_data_array[c][b]->GetUnitHeaderBytes();
+ m_comp_bytes[c] += m_data_array[c][b]->GetUnitBytes();
+ }// b
+
+ }// c
+
+ for ( int c=0 ; c<m_data_array.LengthY() ; ++c)
+ {
+ m_total_bytes += m_comp_bytes[c];
+ m_header_bytes += m_comp_hdr_bytes[c];
+ }
+}
+
+UnitOutputManager& FrameOutputManager::BandOutput( const int csort , const int band_num)
+{
+ return *( m_data_array[csort][band_num-1] );
+}
+
+const UnitOutputManager& FrameOutputManager::BandOutput( const int csort , const int band_num) const
+{
+ return *( m_data_array[csort][band_num-1] );
+}
+
+// Picture stuff
+
+
+void FrameOutputManager::Init( int num_bands )
+{
+ // Initialise output for the picture header
+ m_frame_header = new BasicOutputManager( m_out_stream );
+
+ // Initialise output for the MV data
+ m_mv_data = new UnitOutputManager( m_out_stream );
+
+ // Initialise subband outputs
+ for ( int c=0 ; c<3 ; ++c)
+ for ( int b=0 ; b<num_bands ; ++b)
+ m_data_array[c][b] = new UnitOutputManager( m_out_stream );
+}
+
+void FrameOutputManager::Reset()
+{
+ const int num_bands = m_data_array.LengthX();
+ DeleteAll();
+ Init( num_bands );
+}
+
+void FrameOutputManager::DeleteAll()
+{
+ // Delete subband outputs
+ for ( int c=0 ; c<3 ; ++c)
+ for ( int b=0 ; b<m_data_array.LengthX() ; ++b )
+ delete m_data_array[c][b];
+
+ // Delete MV data op
+ delete m_mv_data;
+
+ // Delete picture header op
+ delete m_frame_header;
+}
+
+size_t FrameOutputManager::Size() const
+{
+ size_t size = 0;
+
+ size += m_frame_header->Size();
+
+ for ( int c=0 ; c<3 ; ++c)
+ {
+ for ( int b=0 ; b<m_data_array.LengthX() ; ++b )
+ {
+ size += m_data_array[c][b]->Size();
+ }
+ }
+
+ size += m_mv_data->Size();
+
+ return size;
+}
+
+
+// Sequence stuff //
+
+SequenceOutputManager::SequenceOutputManager( std::ostream* out_data ):
+ m_frame_op_mgr( out_data ),
+ m_seq_header( out_data ),
+ m_seq_end( out_data ),
+ m_comp_bytes( 3 ),
+ m_comp_hdr_bytes( 3 ),
+ m_mv_hdr_bytes(0),
+ m_mv_bytes(0),
+ m_total_bytes(0),
+ m_header_bytes(0),
+ m_trailer_bytes(0)
+
+{
+ for (int c=0 ; c<3 ; ++c )
+ {
+ m_comp_hdr_bytes[c] = 0;
+ m_comp_bytes[c] = 0;
+ }
+}
+
+void SequenceOutputManager::WriteFrameData()
+{
+ m_frame_op_mgr.WriteToFile();
+
+ // Keep up with count of component bytes
+ for (int c=0 ; c<m_comp_hdr_bytes.Length(); ++c)
+ {
+ m_comp_hdr_bytes[c] += m_frame_op_mgr.ComponentHeadBytes( c );
+ m_comp_bytes[c] += m_frame_op_mgr.ComponentBytes( c );
+ }// c
+
+ // Keep up with count of MV bytes
+ m_mv_hdr_bytes += m_frame_op_mgr.MVHeadBytes();
+ m_mv_bytes += m_frame_op_mgr.MVBytes();
+
+ // Keep up with overall totals
+ m_header_bytes += m_frame_op_mgr.FrameHeadBytes();
+ m_total_bytes += m_frame_op_mgr.FrameBytes();
+
+}
+
+void SequenceOutputManager::WriteSeqHeaderToFile()
+{
+ m_seq_header.WriteToFile();
+ m_header_bytes += m_seq_header.GetNumBytes();
+ m_total_bytes += m_seq_header.GetNumBytes();
+}
+
+void SequenceOutputManager::WriteSeqTrailerToFile()
+{
+ m_seq_end.WriteToFile();
+ m_trailer_bytes += m_seq_end.GetNumBytes();
+ m_total_bytes += m_seq_end.GetNumBytes();
+}
+
+////////////////
+//Input stuff//
+////////////////
+
+//Constructor
+BitInputManager::BitInputManager(std::istream* in_data ):
+ m_ip_ptr(in_data)
+{
+ InitInputStream();
+}
+
+
+void BitInputManager::InitInputStream()
+{
+ m_shift = 0xffffffff;
+ m_input_bits_left = 0;
+}
+
+bool BitInputManager::InputBit()
+{
+ //assumes mode errors will be caught by iostream class
+
+ if (m_input_bits_left == 0)
+ {
+ m_ip_ptr->read(&m_current_byte,1);
+ m_input_bits_left = 8;
+ if (m_shift == START_CODE_PREFIX && (unsigned char)m_current_byte == NOT_START_CODE)
+ {
+ std::cerr << "Ignoring byte " << std::endl;
+ m_ip_ptr->read(&m_current_byte,1);
+ m_shift = 0xffffffff;
+ }
+ m_shift = (m_shift << 8) | m_current_byte;
+ }
+
+ m_input_bits_left--;
+
+ return bool( ( m_current_byte >> m_input_bits_left ) & 1 );
+
+}
+
+bool BitInputManager::InputBit(int& count)
+{
+ count++;
+ return InputBit();
+}
+
+bool BitInputManager::InputBit(int& count, const int max_count)
+{
+ if ( count<max_count )
+ {
+ count++;
+ return InputBit();
+ }
+ else
+ return false;
+}
+
+char BitInputManager::InputByte()
+{
+ // Forget about what's in the current byte
+ FlushInput();
+
+ char byte;
+ m_ip_ptr->read(&byte,1);
+
+ return byte;
+}
+
+void BitInputManager::InputBytes(char* cptr, int num)
+{
+ // Forget about what's in the current byte
+ FlushInput();
+
+ m_ip_ptr->read(cptr,num);
+}
+
+void BitInputManager::FlushInput()
+{
+ m_input_bits_left = 0;
+}
+
+bool BitInputManager::End() const
+{
+ return m_ip_ptr->eof();
+}
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/bit_manager.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/bit_manager.h new file mode 100644 index 000000000..6f75e8004 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/bit_manager.h @@ -0,0 +1,524 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: bit_manager.h,v 1.16 2008/01/31 11:25:16 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Robert Scott Ladd,
+* Tim Borer
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef _BIT_MANAGER_H_
+#define _BIT_MANAGER_H_
+
+#include <libdirac_common/arrays.h>
+#include <cstring>
+#include <vector>
+#include <iostream>
+
+namespace dirac
+{
+ //! Prefix for all start codes
+ const unsigned int START_CODE_PREFIX = 0x42424344; //BBCD
+ const unsigned int START_CODE_PREFIX_BYTE0 =
+ (START_CODE_PREFIX >> 24) & 0xFF;
+ const unsigned int START_CODE_PREFIX_BYTE1 =
+ (START_CODE_PREFIX >> 16) & 0xFF;
+ const unsigned int START_CODE_PREFIX_BYTE2 =
+ (START_CODE_PREFIX >> 8) & 0xFF;
+ const unsigned int START_CODE_PREFIX_BYTE3 =
+ START_CODE_PREFIX & 0xFF;
+
+ //! Random Access Point (RAP) Intra Picture start Code
+ const unsigned char RAP_START_CODE = 0xD7;
+ //! Non-RAP Intra Picture start code
+ const unsigned char IFRAME_START_CODE = 0xD6;
+ //! L1 Picture start code
+ const unsigned char L1FRAME_START_CODE = 0xD4;
+ //! L2 Picture start code
+ const unsigned char L2FRAME_START_CODE = 0xD5;
+ //! Sequence end code
+ const unsigned char SEQ_END_CODE = 0xD0;
+ //! Not a start code but part of data
+ const unsigned char NOT_START_CODE = 0xFF;
+ //! Bitstream version
+ const unsigned char BITSTREAM_VERSION = 0x05; //0.5
+
+
+ ////////////////////////////////////////////////
+ //--------------Bit output stuff--------------//
+ ////////////////////////////////////////////////
+
+ class UnitOutputManager;
+ class FrameOutputManager;
+ class SequenceOutputManager;
+
+ //! Class for managing bit- and byte-oriented output.
+ /*!
+ A class for managing bit- and byte-oriented output. Wraps around
+ an ostream object but stores data in memory until told told to
+ write out in order to support data re-ordering - for example
+ writing a header once the subsequent data has been obtained.
+ Implementation to be reviewed in future. TJD 13 April 2004.
+ */
+ class BasicOutputManager
+ {
+ // Data cannot be written to file directly, only by other o/p classes
+ friend class UnitOutputManager;
+ friend class FrameOutputManager;
+ friend class SequenceOutputManager;
+
+ public:
+ //! Constructor
+ /*!
+ Constructor requires an ostream object pointer.
+ \param out_data the output stream object pointer
+ */
+ BasicOutputManager(std::ostream* out_data );
+
+ //Copy constructor is default shallow copy
+
+ //Operator= is default shallow=
+
+ //! Destructor
+ ~BasicOutputManager(){}
+
+ //! Write a bit out.
+ /*!
+ Write a bit out to the internal data cache.
+ */
+ void OutputBit(const bool& bit);
+
+ //! Write a bit out and increment count
+ /*!
+ Write a bit out to the internal data cache and increment the
+ count of bits written.
+ */
+ void OutputBit(const bool& bit,int& count);
+
+ //! Write a byte out.
+ /*!
+ Write a byte out to the internal data cache.
+ */
+ void OutputByte(const char& byte);
+
+ //! Write a null-terminated set of bytes out.
+ /*!
+ Write a null-terminated set of bytes out to the internal data cache.
+ */
+ void OutputBytes(char* str_array);
+
+ //! Write a number of bytes out.
+ /*!
+ Write a number of bytes out to the internal data cache.
+ */
+ void OutputBytes(char* str_array,int num);
+
+ //! Return the number of bytes last output to file.
+ /*!
+ Return the number of bytes last output to file.
+ */
+ size_t GetNumBytes() const {return m_num_out_bytes;}
+
+ //! Current size of the internal data cache in bytes.
+ /*!
+ Current size of the internal data cache in bytes.
+ */
+ size_t Size() const;
+
+ private:
+ // Number of output bytes written
+ size_t m_num_out_bytes;
+ std::ostream* m_op_ptr;
+ // Buffer used to store output prior to saving to file
+ std::vector<char> m_buffer;
+ // Char used for temporary storage of op data bits
+ char m_current_byte;
+ // Used to set individual bit within the current header byte
+ int m_output_mask;
+
+ //functions
+
+ //! Write all data to file.
+ /*!
+ Dump the internal data cache to the internal ostream object.
+ */
+ void WriteToFile();
+
+ //Initialise the output stream.
+ void InitOutputStream();
+
+ //Clean out any remaining output bits to the buffer
+ void FlushOutput();
+
+ //! Write an ignore code
+ /*!
+ Write a skip interpret start prefix byte out to the internal data
+ cache.
+ */
+ void OutputSkipInterpretStartPrefixByte();
+ };
+
+ //! A class for handling data output, including headers.
+ /*!
+ A class for handling data output, including headers and reordering.
+ */
+ class UnitOutputManager
+ {
+ // Only the FrameOutputManager can make this class write data to file
+ friend class FrameOutputManager;
+
+ public:
+ //! Constructor.
+ /*!
+ Constructor wraps around a pointer to an ostream object, and
+ initialises two BasicOutputManager objects for header and data
+ */
+ UnitOutputManager(std::ostream* out_data );
+
+ //Copy constructor is default shallow copy
+
+ //Operator= is default shallow=
+
+ //! Destructor
+ ~UnitOutputManager(){}
+
+ //! Handles the header bits.
+ /*!
+ A BasicOutputManager object for handling the header bits.
+ */
+ BasicOutputManager& Header(){return m_header;}
+
+ //! Handles the data bits.
+ /*!
+ A BasicOutputManager object for handling the data bits.
+ */
+ BasicOutputManager& Data(){return m_data;}
+
+ //! Returns the total number of bytes written in the last unit coded.
+ /*!
+ Returns the total number of bytes written in the last unit coded - header + data.
+ */
+ const size_t GetUnitBytes() const {return m_unit_bytes;}
+
+ //! Returns the total number of header bytes written in the last unit coded.
+ const size_t GetUnitHeaderBytes() const {return m_unit_head_bytes;}
+
+ //! Current size of the internal data cache in bytes.
+ /*!
+ Current size of the internal data cache in bytes.
+ */
+ size_t Size() const;
+
+ private:
+ // basic output managers for the header and data
+ BasicOutputManager m_header,m_data;
+
+ // total number of bytes written in the last unit coded
+ size_t m_unit_bytes;
+
+ // number of data bytes for the last unit coded
+ size_t m_unit_data_bytes;
+
+ // number of data bytes for the last unit coded
+ size_t m_unit_head_bytes;
+
+ // functions
+
+ //! Writes the bit caches to file.
+ /*!
+ Writes the header bits to the ostream, followed by the data bits.
+ */
+ void WriteToFile();
+ };
+
+ class FrameOutputManager
+ {
+ public:
+
+ // Only the SequenceOutputManager can make this class write data to file
+ friend class SequenceOutputManager;
+
+ //! Constructor
+ /*
+ Constructs a class which manages output for an entire picture.
+ \param out_data pointer to the output stream
+ \param num_bands the number of subbands per component
+ */
+ FrameOutputManager( std::ostream* out_data , const int num_bands=13 );
+
+ //! Destructor
+ ~FrameOutputManager();
+
+ //! Set the number of bands there will be in a component
+ void SetNumBands( const int num_bands );
+
+ //! Get an output manager for a subband
+ /*!
+ Get an output manager for a subband.
+ \param csort the component (Y, U or V)
+ \param band_num the number of the subband
+ */
+ UnitOutputManager& BandOutput( const int csort , const int band_num );
+
+ //! Get an output manager for a subband
+ /*!
+ Get an output manager for a subband.
+ \param csort the component (Y, U or V)
+ \param band_num the number of the subband
+ */
+ const UnitOutputManager& BandOutput( const int csort , const int band_num ) const;
+
+ //! Get an output manager for MV data
+ /*!
+ Get an output manager for MV data
+ */
+ UnitOutputManager& MVOutput(){ return *m_mv_data; }
+
+ //! Get an output manager for MV data
+ /*!
+ Get an output manager for MV data
+ */
+ const UnitOutputManager& MVOutput() const { return *m_mv_data; }
+
+ //! Get an output manager for the picture header
+ BasicOutputManager& HeaderOutput(){ return *m_frame_header; }
+
+ //! Return the number of bytes used for each component
+ const size_t ComponentBytes( const int comp_num ) const { return m_comp_bytes[comp_num];}
+
+ //! Return the number of header bytes used for each component
+ const size_t ComponentHeadBytes( const int comp_num ) const { return m_comp_hdr_bytes[comp_num];}
+
+ //! Return the number of motion vector bytes used
+ const size_t MVBytes() const { return m_mv_bytes;}
+
+ //! Return the number of motion vector header bytes used
+ const size_t MVHeadBytes() const { return m_mv_hdr_bytes;}
+
+ //! Return the number of bytes used for the whole picture
+ const size_t FrameBytes() const { return m_total_bytes;}
+
+ //! Return the number of header bytes used throughout the picture
+ const size_t FrameHeadBytes() const { return m_header_bytes;}
+
+ //! Current size of the internal data cache in bytes.
+ /*!
+ Current size of the internal data cache in bytes.
+ */
+ size_t Size() const;
+
+ private:
+
+ // Array of subband outputs, 1 for each component and subband
+ TwoDArray< UnitOutputManager* > m_data_array;
+
+ // Motion vector output
+ UnitOutputManager* m_mv_data;
+
+ // Picture header output
+ BasicOutputManager* m_frame_header;
+
+ // The total number of picture bytes
+ size_t m_total_bytes;
+
+ // The total number of header bytes
+ size_t m_header_bytes;
+
+ // The total number of MV header bytes
+ size_t m_mv_hdr_bytes;
+
+ // The total number of MV bytes
+ size_t m_mv_bytes;
+
+ // The total number of bytes in each component
+ OneDArray< size_t > m_comp_bytes;
+
+ // The total number of header bytes in each component
+ OneDArray< size_t > m_comp_hdr_bytes;
+
+ // A copy of a pointer to the output stream
+ std::ostream* m_out_stream;
+
+ // Functions
+
+ //! Initialise the band data
+ void Init( const int num_bands );
+
+ //! Reset all the data
+ void Reset();
+
+ //! Delete all the data
+ void DeleteAll();
+
+ //! Write all the picture data to file
+ void WriteToFile();
+ };
+
+ class SequenceOutputManager
+ {
+ public:
+ //! Constructor
+ SequenceOutputManager( std::ostream* out_data );
+
+ //! Return a reference to the output for a single picture
+ FrameOutputManager& FrameOutput(){ return m_frame_op_mgr; }
+
+ //! Return a reference to the output for the sequence header
+ BasicOutputManager& HeaderOutput(){ return m_seq_header; }
+
+ //! Return a reference to the output for the sequence trailer
+ BasicOutputManager& TrailerOutput(){ return m_seq_end; }
+
+ //! Reset the picture data without outputting
+ void ResetFrame(){ m_frame_op_mgr.Reset(); }
+
+ //! Write the sequence header
+ void WriteSeqHeaderToFile();
+
+ //! Write all the picture data to file
+ void WriteFrameData();
+
+ //! Write the sequence trailer
+ void WriteSeqTrailerToFile();
+
+ //! Return the total number of bytes used for the sequence
+ const size_t SequenceBytes() { return m_total_bytes; }
+
+ //! Return the total number of header bytes used throughout the sequence
+ const size_t SequenceHeadBytes() { return m_header_bytes; }
+
+ //! Return the total number bytes used for MVs
+ const size_t MVBytes() { return m_mv_bytes; }
+
+ //! Return the total number bytes used for a component
+ const size_t ComponentBytes( const int comp_num ) { return m_comp_bytes[comp_num]; }
+
+ //! Reset the picture data
+ void ResetFrameData();
+
+
+ private:
+
+ // The picture output manager
+ FrameOutputManager m_frame_op_mgr;
+
+ // Output manager for the sequence header
+ BasicOutputManager m_seq_header;
+
+ // Output manager for the sequence end
+ BasicOutputManager m_seq_end;
+
+ // The total number of bytes in each component
+ OneDArray< size_t > m_comp_bytes;
+
+ // The total number of header bits in each component
+ OneDArray< size_t > m_comp_hdr_bytes;
+
+ // The number of MV header bytes
+ size_t m_mv_hdr_bytes;
+
+ // The total number of MV bytes
+ size_t m_mv_bytes;
+
+ // The total number of bytes written so far
+ size_t m_total_bytes;
+
+ // The total number of header bytes written so far
+ size_t m_header_bytes;
+
+ // The total number of trailer bytes written so far
+ size_t m_trailer_bytes;
+ };
+
+ ///////////////////////////////////////////////
+ //--------------Bit input stuff--------------//
+ ///////////////////////////////////////////////
+
+ //! A class for managing bit-wise and byte-wise input.
+ class BitInputManager
+ {
+
+ public:
+ //! Constructor.
+ /*!
+ Constructor. Wraps around an istream object.
+ */
+ BitInputManager(std::istream* in_data );
+
+ //Copy constructor is default shallow copy
+
+ //Operator= is default shallow=
+
+ //! Destructor
+ ~BitInputManager(){}
+
+ //input functions
+ //! Obtain the next bit.
+ bool InputBit();
+
+ //! Obtain the next bit, incrementing count.
+ bool InputBit(int& count);
+
+ //! Obtain the next bit, incrementing count, if count<max_count; else return 0 (false).
+ bool InputBit(int& count, const int max_count);
+
+ //! Obtain the next byte.
+ char InputByte();
+
+ //! Obtain a number of bytes.
+ void InputBytes(char* cptr,int num);
+
+ //! Move onto the next byte. Needed if a data unit is not an exact number of bytes.
+ void FlushInput();
+
+ //! Returns true if we're at the end of the input, false otherwise
+ bool End() const ;
+
+ private:
+
+ std::istream* m_ip_ptr;
+ // Char used for temporary storage of ip bits
+ char m_current_byte;
+ // The number of bits left withint the current input byte being decoded
+ int m_input_bits_left;
+
+ //used to check if start code is detected
+ unsigned int m_shift;
+ //functions
+ // Initialise the input stream
+ void InitInputStream();
+ };
+
+} // namespace dirac
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/cmd_line.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/cmd_line.cpp new file mode 100644 index 000000000..82abf66b8 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/cmd_line.cpp @@ -0,0 +1,78 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: cmd_line.cpp,v 1.8 2008/03/14 08:17:36 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Scott R Ladd (Original Author), Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <cstring> +#include "cmd_line.h" +using namespace dirac; + +using namespace std; + +CommandLine::CommandLine(int argc, char * argv[], const set<string> & bool_opts) + : m_options(), + m_inputs(), + m_bool_opts(bool_opts) +{ + bool option_active = false; + vector<option>::iterator active_option; + + for (int i = 1; i < argc; ++i) + { + // is it an option? + if ((strlen(argv[i]) > 1) && (argv[i][0] == '-')) + { + // store new key + string opt_key = string(&argv[i][1]); + m_options.push_back(option(opt_key)); + + // active option is now last in list + active_option = m_options.end(); + --active_option; + + // check option list to see if we're looking for an argument + option_active = (m_bool_opts.find(opt_key) == m_bool_opts.end()); + } + else + { + if (option_active) + active_option->m_value = string(argv[i]); + else + m_inputs.push_back(string(argv[i])); + + option_active = false; + } + } +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/cmd_line.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/cmd_line.h new file mode 100644 index 000000000..0977c8b27 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/cmd_line.h @@ -0,0 +1,92 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: cmd_line.h,v 1.7 2004/11/22 14:05:02 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Scott R Ladd (Original Author), Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#if !defined(LIBDIRAC_CMD_LINE_H) +#define LIBDIRAC_CMD_LINE_H + +// Standard C++ +#include <string> +#include <vector> +#include <set> + +namespace dirac +{ + // structure for defining the nature of options + // a very simple command-line parser + class CommandLine + { + public: + struct option + { + std::string m_name; + std::string m_value; + + option(const std::string & a_name) + : m_name(a_name), m_value("") + { + // nada + } + }; + + //! Constructor + CommandLine(int argc, char * argv[], const std::set<std::string> & bool_opts); + + const std::vector<option> & GetOptions() const + { + return m_options; + } + + const std::vector<std::string> & GetInputs() const + { + return m_inputs; + } + + // convenience property + size_t Count() const + { + return m_options.size(); + } + + private: + std::vector<option> m_options; + std::vector<std::string> m_inputs; + const std::set<std::string> & m_bool_opts; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common.cpp new file mode 100644 index 000000000..35adcc5ef --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common.cpp @@ -0,0 +1,1143 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: common.cpp,v 1.80 2009/01/21 05:21:27 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Tim Borer, +* Anuradha Suraparaju, +* Andrew Kennedy +* Myo Tun (Brunel University, myo.tun@brunel.ac.uk) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <algorithm> +#include <sstream> +#ifndef _MSC_VER +#include <inttypes.h> +#endif +#include <libdirac_common/common.h> +#include <libdirac_common/video_format_defaults.h> +#include <libdirac_common/dirac_exception.h> +using namespace dirac; + + +//const dirac::QuantiserLists dirac::dirac_quantiser_lists; + + +//EntropyCorrector functions + +EntropyCorrector::EntropyCorrector(int depth): + m_Yfctrs( 3 , 3*depth+1 ), + m_Ufctrs( 3 , 3*depth+1 ), + m_Vfctrs( 3 , 3*depth+1 ) +{ + Init(); +} + +float EntropyCorrector::Factor(const int bandnum , const PictureParams& pp , + const CompSort c) const +{ + int idx = pp.PicSort().IsIntra() ? 0 : (pp.IsBPicture() ? 1 : 2); + if (c == U_COMP) + return m_Ufctrs[idx][bandnum-1]; + else if (c == V_COMP) + return m_Vfctrs[idx][bandnum-1]; + else + return m_Yfctrs[idx][bandnum-1]; +} + +void EntropyCorrector::Init() +{ + + //do I-pictures + for (int i=0 ; i<m_Yfctrs.LengthX() ; ++i ) + { + if ( i == m_Yfctrs.LastX() ) + { + // Set factor for Intra pictures + m_Yfctrs[0][i] = 1.0f; + m_Ufctrs[0][i] = 1.0f; + m_Vfctrs[0][i] = 1.0f; + // Set factor for Inter Ref pictures + m_Yfctrs[1][i] = 0.85f; + m_Ufctrs[1][i] = 0.85f; + m_Vfctrs[1][i] = 0.85f; + // Set factor for Inter Non-Ref pictures + m_Yfctrs[2][i] = 0.85f; + m_Ufctrs[2][i] = 0.85f; + m_Vfctrs[2][i] = 0.85f; + } + else if ( i >= m_Yfctrs.LastX()-3 ) + { + // Set factor for Intra pictures + m_Yfctrs[0][i] = 0.85f; + m_Ufctrs[0][i] = 0.85f; + m_Vfctrs[0][i] = 0.85f; + // Set factor for Inter Ref pictures + m_Yfctrs[1][i] = 0.75f; + m_Ufctrs[1][i] = 0.75f; + m_Vfctrs[1][i] = 0.75f; + // Set factor for Inter Non-Ref pictures + m_Yfctrs[2][i] = 0.75f; + m_Ufctrs[2][i] = 0.75f; + m_Vfctrs[2][i] = 0.75f; + } + else + { + // Set factor for Intra pictures + m_Yfctrs[0][i] = 0.75f; + m_Ufctrs[0][i] = 0.75f; + m_Vfctrs[0][i] = 0.75f; + // Set factor for Inter Ref pictures + m_Yfctrs[1][i] = 0.75f; + m_Ufctrs[1][i] = 0.75f; + m_Vfctrs[1][i] = 0.75f; + // Set factor for Inter Non-Ref pictures + m_Yfctrs[2][i] = 0.75f; + m_Ufctrs[2][i] = 0.75f; + m_Vfctrs[2][i] = 0.75f; + } + }//i + +} + +void EntropyCorrector::Update(int bandnum , const PictureParams& pp , + CompSort c ,int est_bits , int actual_bits){ + //updates the factors - note that the estimated bits are assumed to already include the correction factor + + float multiplier; + if (actual_bits != 0 && est_bits != 0) + multiplier = float(actual_bits)/float(est_bits); + else + multiplier=1.0; + + int idx = pp.PicSort().IsIntra() ? 0 : (pp.IsBPicture() ? 1 : 2); + if (c == U_COMP) + m_Ufctrs[idx][bandnum-1] *= multiplier; + else if (c == V_COMP) + m_Vfctrs[idx][bandnum-1] *= multiplier; + else + m_Yfctrs[idx][bandnum-1] *= multiplier; +} + +// Overlapped block parameter functions + +OLBParams::OLBParams(const int xblen, int const yblen, int const xbsep, int const ybsep): + m_xblen(xblen), + m_yblen(yblen), + m_xbsep(xbsep), + m_ybsep(ybsep), + m_xoffset( (xblen-xbsep)/2 ), + m_yoffset( (yblen-ybsep)/2 ) +{} + +bool OLBParams::operator ==(const OLBParams bparams) const +{ + if (bparams.Xblen() != m_xblen || + bparams.Yblen() != m_yblen || + bparams.Xbsep() != m_xbsep || + bparams.Ybsep() != m_ybsep) + + return false; + + return true; +} + +namespace dirac +{ +std::ostream & operator<< (std::ostream & stream, OLBParams & params) +{ + stream << params.Ybsep() << " " << params.Xbsep(); +// stream << " " <<params.Yblen() << " " << params.Xblen(); + + return stream; +} + +std::istream & operator>> (std::istream & stream, OLBParams & params) +{ + int temp; + + stream >> temp; + params.SetYbsep(temp); + + stream >> temp; + params.SetXbsep(temp); + +// stream >> temp; +// params.SetYblen(temp); + +// stream >> temp; +// params.SetXblen(temp); + + return stream; +} + +} + +void PicturePredParams::SetBlockSizes(const OLBParams& olbparams , const ChromaFormat cformat) +{ + //given the raw overlapped block parameters, set the modified internal parameters to + //take account of the chroma sampling format and overlapping requirements, as well + //as the equivalent parameters for sub-SBs and SBs. + //Does NOT set the number of blocks or superblocks, as padding may be required. + + OLBParams tmp_olbparams = olbparams; + // Factors for scaling chroma blocks + int xcfactor,ycfactor; + + if (cformat == format420) + { + xcfactor = 2; + ycfactor = 2; + } + else if (cformat == format422) + { + xcfactor = 2; + ycfactor = 1; + } + else + {// assume 444 + xcfactor = 1; + ycfactor = 1; + } + + + m_lbparams[2] = tmp_olbparams; + + // Check separations are all divisible by 4 + int remainder= m_lbparams[2].Xbsep()%4; + if ( remainder!=0 || m_lbparams[2].Xbsep()==0 ) + { + m_lbparams[2].SetXbsep( m_lbparams[2].Xbsep()+(4-remainder)); + m_lbparams[2].SetXblen( m_lbparams[2].Xbsep()+4 ); + } + remainder= m_lbparams[2].Ybsep()%4; + if ( remainder!=0 || m_lbparams[2].Ybsep()==0 ) + { + m_lbparams[2].SetYbsep( m_lbparams[2].Ybsep()+(4-remainder)); + m_lbparams[2].SetYblen( m_lbparams[2].Ybsep()+4 ); + + } + + // Now check lengths are divisible by 4 + remainder= m_lbparams[2].Xblen()%4; + if ( remainder!=0 ) + { + m_lbparams[2].SetXblen( m_lbparams[2].Xbsep()+4); + } + remainder= m_lbparams[2].Yblen()%4; + if ( remainder!=0 ) + { + m_lbparams[2].SetYblen( m_lbparams[2].Ybsep()+4); + } + + // Check there's non-negative overlap, + // XBLEN >= XBSEP, YBLEN >= YBSEP + if (m_lbparams[2].Xbsep()>m_lbparams[2].Xblen()) + { + m_lbparams[2].SetXblen( m_lbparams[2].Xbsep()+4); + } + if (m_lbparams[2].Ybsep()>m_lbparams[2].Yblen()) + { + m_lbparams[2].SetYblen( m_lbparams[2].Ybsep()+4); + } + + // Check the lengths aren't too big (100% is max roll-off) + // XBLEN <= 2*XBSEP, YBLEN <= 2*YBSEP + if (2*m_lbparams[2].Xbsep()<m_lbparams[2].Xblen()) + { + m_lbparams[2].SetXblen( m_lbparams[2].Xbsep()+4); + } + if (2*m_lbparams[2].Ybsep()<m_lbparams[2].Yblen()) + { + m_lbparams[2].SetYblen( m_lbparams[2].Ybsep()+4); + } + + // Set the chroma values + m_cbparams[2].SetXbsep( m_lbparams[2].Xbsep()/xcfactor ); + m_cbparams[2].SetXblen( m_lbparams[2].Xblen()/xcfactor ); + m_cbparams[2].SetYbsep( m_lbparams[2].Ybsep()/ycfactor ); + m_cbparams[2].SetYblen( m_lbparams[2].Yblen()/ycfactor ); + + + //Now work out the overlaps for splitting levels 1 and 0 + m_lbparams[1].SetXbsep( m_lbparams[2].Xbsep()*2 ); + m_lbparams[1].SetXblen( m_lbparams[2].Xblen() + m_lbparams[2].Xbsep() ); + m_lbparams[1].SetYbsep( m_lbparams[2].Ybsep()*2 ); + m_lbparams[1].SetYblen( m_lbparams[2].Yblen() + m_lbparams[2].Xbsep() ); + + m_lbparams[0].SetXbsep( m_lbparams[1].Xbsep()*2 ); + m_lbparams[0].SetXblen( m_lbparams[1].Xblen() + m_lbparams[1].Xbsep() ); + m_lbparams[0].SetYbsep( m_lbparams[1].Ybsep()*2 ); + m_lbparams[0].SetYblen( m_lbparams[1].Yblen() + m_lbparams[1].Xbsep() ); + + m_cbparams[1].SetXbsep( m_cbparams[2].Xbsep()*2 ); + m_cbparams[1].SetXblen( m_cbparams[2].Xblen() + m_cbparams[2].Xbsep() ); + m_cbparams[1].SetYbsep( m_cbparams[2].Ybsep()*2 ); + m_cbparams[1].SetYblen( m_cbparams[2].Yblen() + m_cbparams[2].Xbsep() ); + + m_cbparams[0].SetXbsep( m_cbparams[1].Xbsep()*2 ); + m_cbparams[0].SetXblen( m_cbparams[1].Xblen() + m_cbparams[1].Xbsep() ); + m_cbparams[0].SetYbsep( m_cbparams[1].Ybsep()*2 ); + m_cbparams[0].SetYblen( m_cbparams[1].Yblen() + m_cbparams[1].Xbsep() ); + + if ( m_lbparams[2].Xbsep()!=olbparams.Xbsep() || + m_lbparams[2].Ybsep()!=olbparams.Ybsep() || + m_lbparams[2].Xblen()!=olbparams.Xblen() || + m_lbparams[2].Yblen()!=olbparams.Yblen() ) + { + std::cout<<std::endl<<"WARNING: block parameters are inconsistent with "; + std::cout<<"specification requirements, which are:"; + std::cout<<std::endl<<"\t 1. Lengths and separations must be positive multiples of 4"; + std::cout<<std::endl<<"\t 2. Length can't be more than twice separations"; + std::cout<<std::endl<<"\t 3. Lengths must be greater than or equal to separations"; + std::cout<<std::endl<<std::endl<<"Instead, using:"; + std::cout<<" xblen="<<m_lbparams[2].Xblen(); + std::cout<<" yblen="<<m_lbparams[2].Yblen(); + std::cout<<" xbsep="<<m_lbparams[2].Xbsep(); + std::cout<<" ybsep="<<m_lbparams[2].Ybsep() << std::endl; + } +} + + +// Codec params functions + +CodecParams::CodecParams(const VideoFormat &vd, PictureType ftype, unsigned int num_refs, bool set_defaults): + m_video_format(vd) +{ + if (set_defaults) + SetDefaultCodecParameters(*this, ftype, num_refs); +} + +WltFilter CodecParams::TransformFilter (unsigned int wf_idx) +{ + if (wf_idx >= filterNK) + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + "Wavelet filter idx out of range [0-7]", + SEVERITY_PICTURE_ERROR); + + if (wf_idx==FIDELITY) + { + std::ostringstream errstr; + errstr << "Wavelet Filter " << wf_idx << " currently not supported"; + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + } + return static_cast<WltFilter>(wf_idx); +} + +void CodecParams::SetTransformFilter(unsigned int wf_idx) +{ + SetTransformFilter(TransformFilter(wf_idx)); +} + +void CodecParams::SetTransformDepth (unsigned int wd) +{ + m_wlt_depth = wd; + // Resize the code block size array. + m_cb.Resize(wd+1); +} + +void CodecParams::SetCodeBlocks (unsigned int level, + unsigned int hblocks, + unsigned int vblocks) +{ + if (level > m_wlt_depth) + { + std::ostringstream errstr; + errstr << "level " << level << " out of range [0-" << m_wlt_depth << "]"; + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + } + + m_cb[level].SetHorizontalCodeBlocks(hblocks); + m_cb[level].SetVerticalCodeBlocks(vblocks); +} + +const CodeBlocks &CodecParams::GetCodeBlocks (unsigned int level) const +{ + if (level > m_wlt_depth) + { + std::ostringstream errstr; + errstr << "level " << level << " out of range [0-" << m_wlt_depth << "]"; + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + } + + return m_cb[level]; +} + +void CodecParams::SetCodeBlockMode (unsigned int cb_mode) +{ + if (cb_mode >= QUANT_UNDEF) + { + std::ostringstream errstr; + errstr << "Code Block mode " << cb_mode << " out of supported range [0-" << QUANT_MULTIPLE << "]"; + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + errstr.str(), + SEVERITY_PICTURE_ERROR); + } + + m_cb_mode = static_cast<CodeBlockMode>(cb_mode); +} + +//EncoderParams functions + +//Default constructor +EncoderParams::EncoderParams(const VideoFormat& video_format, + PictureType ftype, + unsigned int num_refs, + bool set_defaults): + CodecParams(video_format, ftype, num_refs, set_defaults), + m_verbose(false), + m_loc_decode(true), + m_full_search(false), + m_x_range_me(32), + m_y_range_me(32), + m_ufactor(1.0), + m_vfactor(1.0), + m_prefilter(NO_PF), + m_prefilter_strength(0), + m_I_lambda(0.0f), + m_L1_lambda(0.f), + m_L2_lambda(0.0f), + m_L1_me_lambda(0.0f), + m_L2_me_lambda(0.0f), + m_ent_correct(0), + m_target_rate(0) +{ + if(set_defaults) + SetDefaultEncoderParameters(*this); +} + +void EncoderParams::CalcLambdas(const float qf) +{ + if (!m_lossless ) + { + m_I_lambda = std::pow( 10.0 , (12.0-qf )/2.5 )/16.0; + + m_L1_lambda = m_I_lambda*4.0; + m_L2_lambda = m_I_lambda*32.0; + + // Set the lambdas for motion estimation + const double me_ratio = 2.0; + + // Use the same ME lambda for L1 and L2 pictures + m_L1_me_lambda = std::sqrt(m_L1_lambda)*me_ratio; + m_L2_me_lambda = m_L1_me_lambda; + } + else + { + m_I_lambda = 0.0; + m_L1_lambda = 0.0; + m_L2_lambda = 0.0; + + m_L1_me_lambda = 0.0; + m_L2_me_lambda = 0.0; + } +} + +void EncoderParams::SetIntraTransformFilter(unsigned int wf_idx) +{ + SetIntraTransformFilter(TransformFilter(wf_idx)); +} + +void EncoderParams::SetInterTransformFilter(unsigned int wf_idx) +{ + SetInterTransformFilter(TransformFilter(wf_idx)); +} + +void EncoderParams::SetUsualCodeBlocks ( const PictureType &/*ftype*/) +{ + // No subband splitting if spatial partitioning if false + // Since this function is common to encoder and decoder we allow the + // setting of code blocks without checking if DefaultSpatialPartition is + // true. + if (SpatialPartition() == false) + return; + + SetCodeBlocks(0, 1, 1); + int depth = TransformDepth(); + if (depth == 0) + return; + + int xl_pad = (Xl() + (1 << depth)-1) & ~((1 << depth)-1); + int yl_pad = (Yl() + (1 << depth)-1) & ~((1 << depth)-1); + + /* NB, could have different sizes based upon ftype == INTRA_PICTURE */ + /* aim for 12x12 codeblocks in each subband, execpt the DC with 4x4 */ + for (int i = 1; i <= depth; i++) + SetCodeBlocks(depth-i+1, std::max(1,(xl_pad >> i) /12), std::max(1, (yl_pad >> i) /12)); + SetCodeBlocks(0, std::max(1,(xl_pad >> depth) /4), std::max(1,(yl_pad >> depth) /4)); +} + +int EncoderParams::GOPLength() const +{ + if (m_num_L1>0) + return (m_num_L1+1)*m_L1_sep; + + return ((m_num_L1==0) ? 10 : 0); +} + +DecoderParams::DecoderParams(const VideoFormat& video_format, + PictureType ftype, + unsigned int num_refs, + bool set_defaults): + CodecParams(video_format, ftype, num_refs, set_defaults), + m_verbose(false) +{ +} + +// ParseParams functions +// constructor +ParseParams::ParseParams(): + m_major_ver(2), + m_minor_ver(2), + m_profile(8), + m_level(0) +{} + + +//Source functions +//constructor +SourceParams::SourceParams(const VideoFormat& video_format, + bool set_defaults) +{ + // set default parameters + if(set_defaults) + SetDefaultSourceParameters(video_format, *this); +} + +int SourceParams::ChromaWidth() const +{ + switch (m_cformat) + { + case format420: + case format422: + return m_xl/2; + + case format444: + default: + return m_xl; + } +} + +int SourceParams::ChromaHeight() const +{ + switch (m_cformat) + { + case format420: + return m_yl/2; + + case format422: + case format444: + default: + return m_yl; + } +} + + +void SourceParams::SetFrameRate (FrameRateType fr) +{ + m_fr_idx = fr; + switch (fr) + { + case FRAMERATE_23p97_FPS: + m_framerate.m_num = 24000; + m_framerate.m_denom = 1001; + break; + case FRAMERATE_24_FPS: + m_framerate.m_num = 24; + m_framerate.m_denom = 1; + break; + case FRAMERATE_25_FPS: + m_framerate.m_num = 25; + m_framerate.m_denom = 1; + break; + case FRAMERATE_29p97_FPS: + m_framerate.m_num = 30000; + m_framerate.m_denom = 1001; + break; + case FRAMERATE_30_FPS: + m_framerate.m_num = 30; + m_framerate.m_denom = 1; + break; + case FRAMERATE_50_FPS: + m_framerate.m_num = 50; + m_framerate.m_denom = 1; + break; + case FRAMERATE_59p94_FPS: + m_framerate.m_num = 60000; + m_framerate.m_denom = 1001; + break; + case FRAMERATE_60_FPS: + m_framerate.m_num = 60; + m_framerate.m_denom = 1; + break; + case FRAMERATE_14p98_FPS: + m_framerate.m_num = 15000; + m_framerate.m_denom = 1001; + break; + case FRAMERATE_12p5_FPS: + m_framerate.m_num = 25; + m_framerate.m_denom = 2; + break; + default: + m_fr_idx = FRAMERATE_CUSTOM; + m_framerate.m_num = m_framerate.m_denom = 0; + break; + } +} + +void SourceParams::SetPixelAspectRatio (PixelAspectRatioType pix_asr_idx) +{ + m_pix_asr_idx = pix_asr_idx; + + switch (pix_asr_idx) + { + case PIXEL_ASPECT_RATIO_1_1: + m_pixel_aspect_ratio.m_num = m_pixel_aspect_ratio.m_denom = 1; + break; + case PIXEL_ASPECT_RATIO_10_11: + m_pixel_aspect_ratio.m_num = 10; + m_pixel_aspect_ratio.m_denom = 11; + break; + case PIXEL_ASPECT_RATIO_12_11: + m_pixel_aspect_ratio.m_num = 12; + m_pixel_aspect_ratio.m_denom = 11; + break; + case PIXEL_ASPECT_RATIO_40_33: + m_pixel_aspect_ratio.m_num = 40; + m_pixel_aspect_ratio.m_denom = 33; + break; + case PIXEL_ASPECT_RATIO_16_11: + m_pixel_aspect_ratio.m_num = 16; + m_pixel_aspect_ratio.m_denom = 11; + break; + case PIXEL_ASPECT_RATIO_4_3: + m_pixel_aspect_ratio.m_num = 4; + m_pixel_aspect_ratio.m_denom = 3; + break; + default: + m_pix_asr_idx = PIXEL_ASPECT_RATIO_CUSTOM; + m_pixel_aspect_ratio.m_num = m_pixel_aspect_ratio.m_denom = 0; + break; + } +} + +void SourceParams::SetSignalRange (SignalRangeType sr) +{ + m_sr_idx = sr; + switch (sr) + { + case SIGNAL_RANGE_8BIT_FULL: + m_luma_offset = 0; + m_luma_excursion = 255; + m_chroma_offset = 128; + m_chroma_excursion = 255; + break; + case SIGNAL_RANGE_8BIT_VIDEO: + m_luma_offset = 16; + m_luma_excursion = 219; + m_chroma_offset = 128; + m_chroma_excursion = 224; + break; + case SIGNAL_RANGE_10BIT_VIDEO: + m_luma_offset = 64; + m_luma_excursion = 876; + m_chroma_offset = 512; + m_chroma_excursion = 896; + break; + case SIGNAL_RANGE_12BIT_VIDEO: + m_luma_offset = 256; + m_luma_excursion = 3504; + m_chroma_offset = 2048; + m_chroma_excursion = 3584; + break; + default: + m_sr_idx = SIGNAL_RANGE_CUSTOM; + m_luma_offset = 0; + m_luma_excursion = 0; + m_chroma_offset = 0; + m_chroma_excursion = 0; + break; + } +} + +void SourceParams::SetColourSpecification (unsigned int cs_idx) +{ + m_cs_idx = cs_idx; + switch(cs_idx) + { + case 1: + m_col_primary = CP_SDTV_525; + m_col_matrix = CM_SDTV; + m_transfer_func = TF_TV; + break; + case 2: + m_col_primary = CP_SDTV_625; + m_col_matrix = CM_SDTV; + m_transfer_func = TF_TV; + break; + case 3: + m_col_primary = CP_HDTV_COMP_INTERNET; + m_col_matrix = CM_HDTV_COMP_INTERNET; + m_transfer_func = TF_TV; + break; + case 4: + m_col_primary = CP_DCINEMA; + m_col_matrix = CM_HDTV_COMP_INTERNET; + m_transfer_func = TF_DCINEMA; + break; + default: + m_cs_idx = 0; + m_col_primary = CP_HDTV_COMP_INTERNET; + m_col_matrix = CM_HDTV_COMP_INTERNET; + m_transfer_func = TF_TV; + break; + } +} + +void SourceParams::SetColourPrimariesIndex (unsigned int cp) +{ + m_cs_idx = 0; + if (cp >= CP_UNDEF) + { + //TODO: flag a warning + } + m_col_primary = static_cast<ColourPrimaries>(cp); +} + +void SourceParams::SetColourMatrixIndex (unsigned int cm) +{ + m_cs_idx = 0; + if (cm >= CM_UNDEF) + { + //TODO: flag a warning + } + m_col_matrix = static_cast<ColourMatrix>(cm); +} + +void SourceParams::SetTransferFunctionIndex (unsigned int tf) +{ + m_cs_idx = 0; + if (tf >= TF_UNDEF) + { + //TODO: flag a warning + } + m_transfer_func = static_cast<TransferFunction>(tf); +} + + +//PictureParams functions +// Default constructor +PictureParams::PictureParams(): + m_psort(PictureSort::IntraRefPictureSort()), + m_picture_type( INTRA_PICTURE ), + m_reference_type( REFERENCE_PICTURE ), + m_output(false), + m_using_ac(true) +{} + +// Constructor +PictureParams::PictureParams(const ChromaFormat& cf, + int xlen, int ylen, + unsigned int luma_depth, + unsigned int chroma_depth) : + m_cformat(cf), + m_psort(PictureSort::IntraRefPictureSort()), + m_picture_type( INTRA_PICTURE ), + m_reference_type( REFERENCE_PICTURE ), + m_output(false), + m_xl(xlen), + m_yl(ylen), + m_luma_depth(luma_depth), + m_chroma_depth(chroma_depth), + m_using_ac(true) +{ + m_cxl = m_cyl = 0; + if (cf == format420) + { + m_cxl = xlen>>1; + m_cyl = ylen>>1; + } + else if (cf == format422) + { + m_cxl = xlen>>1; + m_cyl = ylen; + } + else if (cf == format444) + { + m_cxl = xlen; + m_cyl = ylen; + } +} + +// Constructor +PictureParams::PictureParams(const ChromaFormat& cf, const PictureSort& ps): + m_cformat(cf), + m_output(false), + m_using_ac(true) +{ + SetPicSort( ps ); +} + +PictureParams::PictureParams(const SourceParams& sparams): + m_cformat(sparams.CFormat()), + m_psort(PictureSort::IntraRefPictureSort()), + m_picture_type( INTRA_PICTURE ), + m_reference_type( REFERENCE_PICTURE ), + m_output(false), + m_xl(sparams.Xl()), + m_yl(sparams.Yl()), + m_cxl(sparams.ChromaWidth()), + m_cyl(sparams.ChromaHeight()), + m_using_ac(true) +{ + if (sparams.SourceSampling() == 1) + { + m_yl = (m_yl>>1); + m_cyl = (m_cyl>>1); + } + m_luma_depth = static_cast<unsigned int> + ( + std::log((double)sparams.LumaExcursion())/std::log(2.0) + 1 + ); + + m_chroma_depth = static_cast<unsigned int> + ( + std::log((double)sparams.ChromaExcursion())/std::log(2.0) + 1 + ); +} + + + +void PictureParams::SetXl(int xlen) +{ + m_xl = xlen; + m_cxl = 0; + if (m_cformat == format420 || m_cformat == format422) + { + m_cxl = m_xl>>1; + } + else if (m_cformat == format444) + { + m_cxl = m_xl; + } +} + +void PictureParams::SetYl(int ylen) +{ + m_yl = ylen; + m_cyl = 0; + if (m_cformat == format420) + { + m_cyl = m_yl>>1; + } + else if (m_cformat == format422 || m_cformat == format444) + { + m_cyl = m_yl; + } +} + +bool PictureParams::IsBPicture() const +{ + bool is_B_picture( false ); + + if ( m_refs.size() == 2 ) + { + if ( m_refs[0] < m_fnum && m_refs[1] > m_fnum ) + is_B_picture = true; + + if ( m_refs[0] > m_fnum && m_refs[1] < m_fnum ) + is_B_picture = true; + } + + return is_B_picture; +} + +void PictureParams::SetPicSort( const PictureSort& ps ) +{ + m_psort=ps; + if ( ps.IsIntra() ) + m_picture_type = INTRA_PICTURE; + else + m_picture_type = INTER_PICTURE; + + if ( ps.IsRef() ) + m_reference_type = REFERENCE_PICTURE; + else + m_reference_type = NON_REFERENCE_PICTURE; + +} + +void PictureParams::SetPictureType(const PictureType ftype) +{ + m_picture_type = ftype; + if (ftype == INTRA_PICTURE ) + m_psort.SetIntra(); + else + m_psort.SetInter(); +} + +void PictureParams::SetReferenceType(const ReferenceType rtype) +{ + m_reference_type = rtype; + if (rtype == REFERENCE_PICTURE ) + m_psort.SetRef(); + else + m_psort.SetNonRef(); +} + + +QuantiserLists::QuantiserLists() +: + // FIXME: hardcode m_max_qindex to 119. In future this will depend on level + // As per spec max qf_idx is 127. But for values of qf_idx > 120 we + // will need more than 32 bits. Hence qf_idx is limited to 119. + m_max_qindex( 119 ), + m_qflist4( m_max_qindex+1 ), + m_intra_offset4( m_max_qindex+1 ), + m_inter_offset4( m_max_qindex+1 ) +{ + m_qflist4[0] = 4; + m_qflist4[1] = 5; + m_intra_offset4[0] = 1; + m_inter_offset4[0] = 1; + m_intra_offset4[1] = 2; + m_inter_offset4[1] = 2; + +#ifdef _MSC_VER + unsigned __int64 base, qfactor; +#else + uint64_t base, qfactor; +#endif //_MSC_VER + + for (unsigned int q=2; q<=m_max_qindex; ++q) + { + base = (1<<(q/4)); + + switch (q%4) + { + case 0: + qfactor = 4*base; + break; + case 1: + qfactor = (503829*base+52958)/105917; + break; + case 2: + qfactor = (665857*base+58854)/117708; + break; + case 3: + qfactor = (440253*base+32722)/65444; + break; + default: //Default case never used + qfactor = 0; + } + + m_qflist4[q] = int( qfactor ); + + m_intra_offset4[q] = (m_qflist4[q]+1)>>1; + m_inter_offset4[q] = (3*m_qflist4[q]+4)>>3; + }// q +} + +namespace dirac +{ +VideoFormat IntToVideoFormat(int video_format) +{ + switch(video_format) + { + case VIDEO_FORMAT_CUSTOM: + return VIDEO_FORMAT_CUSTOM; + case VIDEO_FORMAT_QSIF525: + return VIDEO_FORMAT_QSIF525; + case VIDEO_FORMAT_QCIF: + return VIDEO_FORMAT_QCIF; + case VIDEO_FORMAT_SIF525: + return VIDEO_FORMAT_SIF525; + case VIDEO_FORMAT_CIF: + return VIDEO_FORMAT_CIF; + case VIDEO_FORMAT_4CIF: + return VIDEO_FORMAT_4CIF; + case VIDEO_FORMAT_4SIF525: + return VIDEO_FORMAT_4SIF525; + case VIDEO_FORMAT_SD_480I60: + return VIDEO_FORMAT_SD_480I60; + case VIDEO_FORMAT_SD_576I50: + return VIDEO_FORMAT_SD_576I50; + case VIDEO_FORMAT_HD_720P60: + return VIDEO_FORMAT_HD_720P60; + case VIDEO_FORMAT_HD_720P50: + return VIDEO_FORMAT_HD_720P50; + case VIDEO_FORMAT_HD_1080I60: + return VIDEO_FORMAT_HD_1080I60; + case VIDEO_FORMAT_HD_1080I50: + return VIDEO_FORMAT_HD_1080I50; + case VIDEO_FORMAT_HD_1080P60: + return VIDEO_FORMAT_HD_1080P60; + case VIDEO_FORMAT_HD_1080P50: + return VIDEO_FORMAT_HD_1080P50; + case VIDEO_FORMAT_DIGI_CINEMA_2K24: + return VIDEO_FORMAT_DIGI_CINEMA_2K24; + case VIDEO_FORMAT_DIGI_CINEMA_4K24: + return VIDEO_FORMAT_DIGI_CINEMA_4K24; + case VIDEO_FORMAT_UHDTV_4K60: + return VIDEO_FORMAT_UHDTV_4K60; + case VIDEO_FORMAT_UHDTV_4K50: + return VIDEO_FORMAT_UHDTV_4K50; + case VIDEO_FORMAT_UHDTV_8K60: + return VIDEO_FORMAT_UHDTV_8K60; + case VIDEO_FORMAT_UHDTV_8K50: + return VIDEO_FORMAT_UHDTV_8K50; + default: + return VIDEO_FORMAT_UNDEFINED; + } +} + +ChromaFormat IntToChromaFormat(int chroma_format) +{ + switch(chroma_format) + { + case format444: + return format444; + case format422: + return format422; + case format420: + return format420; + default: + return formatNK; + } +} + +FrameRateType IntToFrameRateType(int frame_rate_idx) +{ + switch(frame_rate_idx) + { + case FRAMERATE_CUSTOM: + return FRAMERATE_CUSTOM; + case FRAMERATE_23p97_FPS: + return FRAMERATE_23p97_FPS; + case FRAMERATE_24_FPS: + return FRAMERATE_24_FPS; + case FRAMERATE_25_FPS: + return FRAMERATE_25_FPS; + case FRAMERATE_29p97_FPS: + return FRAMERATE_29p97_FPS; + case FRAMERATE_30_FPS: + return FRAMERATE_30_FPS; + case FRAMERATE_50_FPS: + return FRAMERATE_30_FPS; + case FRAMERATE_59p94_FPS: + return FRAMERATE_59p94_FPS; + case FRAMERATE_60_FPS: + return FRAMERATE_60_FPS; + case FRAMERATE_14p98_FPS: + return FRAMERATE_14p98_FPS; + case FRAMERATE_12p5_FPS: + return FRAMERATE_12p5_FPS; + default: + return FRAMERATE_UNDEFINED; + } +} + +PixelAspectRatioType IntToPixelAspectRatioType(int pix_asr_idx) +{ + switch(pix_asr_idx) + { + case PIXEL_ASPECT_RATIO_CUSTOM: + return PIXEL_ASPECT_RATIO_CUSTOM; + case PIXEL_ASPECT_RATIO_1_1: + return PIXEL_ASPECT_RATIO_1_1; + case PIXEL_ASPECT_RATIO_10_11: + return PIXEL_ASPECT_RATIO_10_11; + case PIXEL_ASPECT_RATIO_12_11: + return PIXEL_ASPECT_RATIO_12_11; + case PIXEL_ASPECT_RATIO_40_33: + return PIXEL_ASPECT_RATIO_40_33; + case PIXEL_ASPECT_RATIO_16_11: + return PIXEL_ASPECT_RATIO_16_11; + case PIXEL_ASPECT_RATIO_4_3: + return PIXEL_ASPECT_RATIO_4_3; + default: + return PIXEL_ASPECT_RATIO_UNDEFINED; + + } +} + +SignalRangeType IntToSignalRangeType(int signal_range_idx) +{ + switch(signal_range_idx) + { + case SIGNAL_RANGE_CUSTOM: + return SIGNAL_RANGE_CUSTOM; + case SIGNAL_RANGE_8BIT_FULL: + return SIGNAL_RANGE_8BIT_FULL; + case SIGNAL_RANGE_8BIT_VIDEO: + return SIGNAL_RANGE_8BIT_VIDEO; + case SIGNAL_RANGE_10BIT_VIDEO: + return SIGNAL_RANGE_10BIT_VIDEO; + case SIGNAL_RANGE_12BIT_VIDEO: + return SIGNAL_RANGE_12BIT_VIDEO; + default: + return SIGNAL_RANGE_UNDEFINED; + } +} + +MVPrecisionType IntToMVPrecisionType(int mv_prec) +{ + switch(mv_prec) + { + case MV_PRECISION_PIXEL: + return MV_PRECISION_PIXEL; + case MV_PRECISION_HALF_PIXEL: + return MV_PRECISION_HALF_PIXEL; + case MV_PRECISION_QUARTER_PIXEL: + return MV_PRECISION_QUARTER_PIXEL; + case MV_PRECISION_EIGHTH_PIXEL: + return MV_PRECISION_EIGHTH_PIXEL; + default: + return MV_PRECISION_UNDEFINED; + } +} + + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common.h new file mode 100644 index 000000000..0ec2653e3 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common.h @@ -0,0 +1,1613 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: common.h,v 1.79 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Tim Borer, +* Anuradha Suraparaju, +* Andrew Kennedy +* Myo Tun (Brunel University, myo.tun@brunel.ac.uk) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif // _MSC_VER + +#include <libdirac_common/arrays.h> +#include <libdirac_common/common_types.h> +#include <libdirac_common/dirac_assertions.h> +#include <vector> +#include <cmath> +namespace dirac +{ + /*! \file + This file contains common classes used throughout the encoder and + decoder. The main classes are the encoder and decoder parameters for + controlling the encode and decode processes. These are passed + throughout the codec. There are also parameter classes for sequences + and Pictures. + */ + + + //Some basic types used throughout the codec ...// + ////////////////////////////////////////////////////////////// + + //! Type of picture data (including motion compensated residuals) + typedef short ValueType; + +#if !defined(HAVE_MMX) + //! Type of wavelet coefficient data (should be larger than ValueType) + typedef int CoeffType; +#else + //! Type of wavelet coefficient data (should be larger than ValueType) + typedef short CoeffType; +#endif + + //! Type for performing calculations on ValueType and CoeffType. Should be >ValueType, >=CoeffType + typedef int CalcValueType; + + //! Prediction modes for blocks + enum PredMode{ INTRA , REF1_ONLY , REF2_ONLY , REF1AND2, UNDEFINED }; + + //! Types of picture component + enum CompSort{ Y_COMP , U_COMP , V_COMP }; + + //! Addition or subtraction + enum AddOrSub{ ADD , SUBTRACT }; + + //! Forward or backward + enum Direction { FORWARD , BACKWARD }; + + //! Contexts used for coefficient coding + enum CtxAliases + {//used for residual coding + SIGN0_CTX, // -sign, previous symbol is 0 + SIGN_POS_CTX, // -sign, previous symbol is +ve + SIGN_NEG_CTX, // -sign, previous symbol is -ve + + // Follow bit contexts + Z_FBIN1z_CTX, // -bin 1, parent is zero, neighbours zero + Z_FBIN1nz_CTX, // -bin 1, parent is zero, neighbours non-zero + Z_FBIN2_CTX, // -bin 2, parent is zero + Z_FBIN3_CTX, // -bin 3, parent is zero + Z_FBIN4_CTX, // -bin 4, parent is zero + Z_FBIN5_CTX, // -bin 5, parent is zero + Z_FBIN6plus_CTX, // -bins 6 plus, parent is zero + + NZ_FBIN1z_CTX, // -bin 1, parent is non-zero, neighbours zero + NZ_FBIN1nz_CTX, // -bin 1, parent is non-zero, neighbours non-zero + NZ_FBIN2_CTX, // -bin 2, parent is non-zero + NZ_FBIN3_CTX, // -bin 3, parent is non-zero + NZ_FBIN4_CTX, // -bin 4, parent is non-zero + NZ_FBIN5_CTX, // -bin 5, parent is non-zero + NZ_FBIN6plus_CTX, // -bins 6 plus, parent is non-zero + + // Information bit contexts + INFO_CTX, + + BLOCK_SKIP_CTX, // - blocks are skipped + Q_OFFSET_FOLLOW_CTX, // - code block quantiser offset magnitude + Q_OFFSET_INFO_CTX, // - code block quantiser offset info context + Q_OFFSET_SIGN_CTX, // - code block quantiser offset sign + TOTAL_COEFF_CTXS // The total number of coefficient contexts + }; + + //! Contexts used for MV data coding + enum MvCtxAliases + { + // DC value contexts // + /////////////////////// + + DC_FBIN1_CTX, + DC_FBIN2plus_CTX, + DC_INFO_CTX, + DC_SIGN_CTX, + + // Motion vector contexts // + //////////////////////////// + + + MV_FBIN1_CTX, + MV_FBIN2_CTX, + MV_FBIN3_CTX, + MV_FBIN4_CTX, + MV_FBIN5plus_CTX, + + MV_INFO_CTX, + + MV_SIGN_CTX, + + + // Prediction mode contexts + + PMODE_BIT0_CTX, // -bit 0, prediction mode value + PMODE_BIT1_CTX, // -bin 1, prediction mode value + + + // Macroblock contexts + + SB_SPLIT_BIN1_CTX, // bin 1, SB split mode vals + SB_SPLIT_BIN2_CTX, // bin 2, SB split mode vals. Bin 3 not required + + SB_SPLIT_INFO_CTX, // info context for SB split mode + + TOTAL_MV_CTXS // The total number of motion vector contexts + }; + + + /** + * Function to convert an integer to a valid VideoFormat + *@param video_format Integer corresponding to a format + *@return Valid video-format (returns VIDEO_FORMAT_UNDEFINED if no valid format found) + */ + VideoFormat IntToVideoFormat(int video_format); + + /** + * Function to convert an integer to a valid VideoFormat + *@param chroma_format Integer corresponding to a format + *@return Valid chroma-format (returns formatNK if no valid format found) + */ + ChromaFormat IntToChromaFormat(int chroma_format); + + /** + * Function to convert an integer to a valid FrameRate type + *@param frame_rate_idx Integer corresponding to a frame-rate in the spec table + *@return Valid FrameRateType (returns FRAMERATE_UNDEFINED if no valid frame-rate found) + */ + FrameRateType IntToFrameRateType(int frame_rate_idx); + + /** + * Function to convert an integer to a valid PixelAspectRatio type + *@param pix_asr_idx Integer corresponding to a pixel aspect ratio in the spec table + *@return Valid PixelAspectRatioType (returns PIXEL_ASPECT_RATIO_UNDEFINED if no valid pixel aspect ratio found) + */ + PixelAspectRatioType IntToPixelAspectRatioType(int pix_asr_idx); + + /** + * Function to convert an integer to a valid SignalRange type + *@param signal_range_idx Integer corresponding to a signal-range in the spec table + *@return Valid SignalRangeType (returns SIGNAL_RANGE_UNDEFINED if no valid signal-ratio found) + */ + SignalRangeType IntToSignalRangeType(int signal_range_idx); + + /** + * Function to convert an integer to a valid motion-vector precision type + *@param mv_prec Integer corresponding to a valid motion-vector precision + *@return Valid MVPrecisionType (returns SIGNAL_RANGE_UNDEFINED if no valid precision found) + */ + MVPrecisionType IntToMVPrecisionType(int mv_prec); + + //Classes used throughout the codec// + ///////////////////////////////////// + + //! Class defining a rational number + class Rational + { + public: + //! Numerator + unsigned int m_num; + //! Denominator + unsigned int m_denom; + }; + + //! Picture type Class + class PictureSort + { + public: + PictureSort() { fs = 0x00; } // default intra non-ref + + void SetIntra() { fs &= 0xfe; } + void SetInter() { fs |= 0x01; } + void SetNonRef() { fs &= 0xfd; } + void SetRef() { fs |= 0x02; } + + bool IsInter () const { return fs & 0x01; } + bool IsIntra () const { return !IsInter(); } + bool IsRef() const { return fs & 0x02; }; + bool IsNonRef() const { return !IsRef(); } + + void SetIntraNonRef() { SetIntra(); SetNonRef(); } + void SetIntraRef() { SetIntra(); SetRef(); } + void SetInterNonRef() { SetInter(); SetNonRef(); } + void SetInterRef() { SetInter(); SetRef(); } + + bool IsIntraNonRef() const { return (fs & 0x03) == 0x00; } + bool IsIntraRef() const { return (fs & 0x03) == 0x02; } + bool IsInterNonRef() const { return (fs & 0x03) == 0x01; } + bool IsInterRef() const { return (fs & 0x03) == 0x03; } + + void Clear() { fs=0x00; } + + static PictureSort IntraRefPictureSort() + { + PictureSort fs; + fs.SetIntraRef(); + return fs; + } + + static PictureSort InterRefPictureSort() + { + PictureSort fs; + fs.SetInterRef(); + return fs; + } + + static PictureSort IntraNonRefPictureSort() + { + PictureSort fs; + fs.SetIntraNonRef(); + return fs; + } + + static PictureSort InterNonRefPictureSort() + { + PictureSort fs; + fs.SetInterNonRef(); + return fs; + } + + private: + unsigned char fs; + }; + + //! Parameters relating to the source material being encoded/decoded + class SourceParams + { + public: + //! default constructor + SourceParams (const VideoFormat &vf = VIDEO_FORMAT_CUSTOM, + bool set_defaults=true); + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //////////////////////////////////////////////////////////////////// + + // Gets + //! Returns video-format + VideoFormat GetVideoFormat() const { return m_video_format;} + + //! Returns the picture width + unsigned int Xl() const {return m_xl;} + + //! Returns the picture height + unsigned int Yl() const {return m_yl;} + + //! Returns the chroma format of the sequence (420, 422, 444) + ChromaFormat CFormat() const {return m_cformat;} + + //! Returns the chroma width + int ChromaWidth() const; + + //! Returns the chroma height + int ChromaHeight() const; + + //! Returns the source sampling field of the source scan format + unsigned int SourceSampling() const { return m_source_sampling; } + + //! Returns true if top field comes first in time + bool TopFieldFirst() const { return m_topfieldfirst; } + + //! Return the number for frames per second + Rational FrameRate() const { return m_framerate; } + + //! Return the type from the frame rate table + FrameRateType FrameRateIndex() const { return m_fr_idx; } + + //! Return the pixel aspect ratio + Rational PixelAspectRatio() const { return m_pixel_aspect_ratio; } + + //! Return the type from the pixel aspect ratio table + PixelAspectRatioType PixelAspectRatioIndex() const { return m_pix_asr_idx; } + + // Clean area parameters + //! Return the Clean area width + unsigned int CleanWidth() const { return m_clean_width; } + //! Return the Clean area height + unsigned int CleanHeight() const { return m_clean_height; } + //! Return the Clean area left offset + unsigned int LeftOffset() const { return m_left_offset; } + //! Return the Clean area top offset + unsigned int TopOffset() const { return m_top_offset; } + + // Signal Range parameters + + //! Return the type from the signal range table + SignalRangeType SignalRangeIndex() const { return m_sr_idx; } + + //! Return the luma offset + unsigned int LumaOffset() const { return m_luma_offset; } + //! Return the luma excursion + unsigned int LumaExcursion() const { return m_luma_excursion; } + //! Return the chroma offset + unsigned int ChromaOffset() const { return m_chroma_offset; } + //! Return the chroma excursion + unsigned int ChromaExcursion() const { return m_chroma_excursion; } + + //! Return the index into the colour specification table + unsigned int ColourSpecificationIndex() const { return m_cs_idx; } + + //! Return the colour primaries index + ColourPrimaries ColourPrimariesIndex() const { return m_col_primary; } + //! Return the colour matrix index + ColourMatrix ColourMatrixIndex() const { return m_col_matrix; } + //! Return the transfer function index + TransferFunction TransferFunctionIndex() const { return m_transfer_func; } + + // Sets + + //! Sets the picture width + void SetXl(unsigned int xlen) {m_xl = xlen;} + + //! Sets the picture height + void SetYl(unsigned int ylen) {m_yl = ylen;} + + //! Sets the chroma format (Y only, 420, 422 etc) + void SetCFormat(ChromaFormat cf) {m_cformat=cf;} + + //! Set if the source sampling field of the scan format + void SetSourceSampling(unsigned int source_sampling) + { m_source_sampling = source_sampling; } + + //! Set Topfield first. True if top field comes first in time + void SetTopFieldFirst(bool tff) { m_topfieldfirst = tff; } + + //! Sets the video format + void SetVideoFormat(VideoFormat vf){ m_video_format=vf;} + + //! Set the frame rate + void SetFrameRate(const Rational &frate ) + { + m_fr_idx = FRAMERATE_CUSTOM; m_framerate = frate; + } + + //! Set the frame rate + void SetFrameRate(unsigned int fr_num, unsigned int fr_denom ) + { + m_fr_idx = FRAMERATE_CUSTOM; + m_framerate.m_num = fr_num; + m_framerate.m_denom = fr_denom; + } + + //! Set the frame rate + void SetFrameRate(FrameRateType fr); + + //! Set the pixel aspect ratio + void SetPixelAspectRatio(const Rational &pix_asr) + { + m_pix_asr_idx = PIXEL_ASPECT_RATIO_CUSTOM; + m_pixel_aspect_ratio = pix_asr; + } + + //! Set the pixel aspect ratio + void SetPixelAspectRatio(unsigned int pix_as_num, unsigned int pix_as_denom ) + { + m_pix_asr_idx = PIXEL_ASPECT_RATIO_CUSTOM; + m_pixel_aspect_ratio.m_num = pix_as_num; + m_pixel_aspect_ratio.m_denom = pix_as_denom; + } + + //! Set the Pixel Aspect Ratio + void SetPixelAspectRatio(PixelAspectRatioType pixel_aspect_ratio); + + // Clean area parameters + //! Set the Clean area width + void SetCleanWidth(unsigned int clean_width) { m_clean_width = clean_width; } + //! Set the Clean area height + void SetCleanHeight(unsigned int clean_height) { m_clean_height = clean_height; } + //! Set the Clean area left offset + void SetLeftOffset(unsigned int left_offset) { m_left_offset = left_offset; } + //! Set the Clean area top offset + void SetTopOffset(unsigned int top_offset) { m_top_offset = top_offset; } + + // Signal Range parameters + //! Set the Signal Range parameters + void SetSignalRange(SignalRangeType sr); + + //! Set the luma offset + void SetLumaOffset(unsigned int luma_offset) { m_sr_idx = SIGNAL_RANGE_CUSTOM; m_luma_offset = luma_offset; } + //! Set the luma excursion + void SetLumaExcursion(unsigned int luma_exc) { m_sr_idx = SIGNAL_RANGE_CUSTOM; m_luma_excursion = luma_exc; } + //! Set the chroma offset + void SetChromaOffset(unsigned int chroma_off) { m_sr_idx = SIGNAL_RANGE_CUSTOM; m_chroma_offset = chroma_off; } + //! Set the chroma excursion + void SetChromaExcursion(unsigned int chroma_exc) { m_sr_idx = SIGNAL_RANGE_CUSTOM; m_chroma_excursion = chroma_exc; } + + //! Set the Colour specification + void SetColourSpecification(unsigned int cs_idx); + //! Set the colour primaries index + void SetColourPrimariesIndex(unsigned int cp); + //! Set the colour matrix index + void SetColourMatrixIndex(unsigned int cm); + //! Set the transfer function index + void SetTransferFunctionIndex(unsigned int tf); + + private: + //!Video-format + VideoFormat m_video_format; + + //! Width of video + unsigned int m_xl; + + //! Height of video + unsigned int m_yl; + + //! Presence of chroma and/or chroma sampling structure + ChromaFormat m_cformat; + + //! Source sampling field : 0 - progressive, 1 - interlaced + unsigned int m_source_sampling; + + //! If m_source_sampling=1, true if the top field is first in temporal order + bool m_topfieldfirst; + + //! Index into frame rate table + FrameRateType m_fr_idx; + + //! Frame Rate i.e number of frames per second + Rational m_framerate; + + //! Index into pixel aspect ratio table + PixelAspectRatioType m_pix_asr_idx; + + //! Pixel Aspect Ratio + Rational m_pixel_aspect_ratio; + + // Clean area parameters + + //! Clean area width + unsigned int m_clean_width; + + //! Clean area height + unsigned int m_clean_height; + + //! Clean area left offset + unsigned int m_left_offset; + + //! Clean area top offset + unsigned int m_top_offset; + + // signal range parameters + + //! Index into signal range table + SignalRangeType m_sr_idx; + + //! Luma offset + unsigned int m_luma_offset; + //! Luma excursion + unsigned int m_luma_excursion; + //! Chroma offset + unsigned int m_chroma_offset; + //! Chroma excursion + unsigned int m_chroma_excursion; + + //! Index into colour spec table + unsigned int m_cs_idx; + + //! Colour Primaries Index + ColourPrimaries m_col_primary; + + // Colour Matrix index + ColourMatrix m_col_matrix; + + // Transfer function index + TransferFunction m_transfer_func; + }; + + + //! Parameters for initialising picture class objects + class PictureParams + { + + public: + //! Default constructor + PictureParams(); + + //! Constructor + /*! + Picture chroma format is set Picture sort defaults to I picture. + */ + PictureParams(const ChromaFormat& cf, int xlen, int ylen, + unsigned int luma_depth, unsigned int chroma_depth); + + //! Constructor + /*! + Picture chroma format and picture sort are set. + */ + PictureParams(const ChromaFormat& cf, const PictureSort& fs); + + //! Constructor + /*! + Constructor. Parameters are derived from the source parameters + */ + PictureParams(const SourceParams& sparams); + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //////////////////////////////////////////////////////////////////// + + // Gets ... + + //! Returns the chroma format of the picture + const ChromaFormat& CFormat() const{return m_cformat;} + + //! Returns the picture width + int Xl() const {return m_xl;} + + //! Returns the picture height + int Yl() const {return m_yl;} + + //! Returns the chroma width of the picture + int ChromaXl() const{return m_cxl;} + + //! Returns the chroma height of the picture + int ChromaYl() const{return m_cyl;} + + //! Returns the luma depth + unsigned int LumaDepth() const { return m_luma_depth; } + + //! Returns the chroma depth + unsigned int ChromaDepth() const { return m_chroma_depth; } + + //! Returns the type of the picture + const PictureSort& PicSort() const {return m_psort;} + + //! Returns the number of the picture (in time order) + int PictureNum() const {return m_fnum;} + + //! Returns the retired reference picture number + int RetiredPictureNum() const {return m_retd_fnum;} + + //! Returns whether the picture is bi-directionally predicted by checking references + bool IsBPicture() const; + + //! Returns the number of pictures after the current picture number after which the picture can be discarded + int ExpiryTime() const {return m_expiry_time;} + + //! Returns an indication of whether the picture has been output yet + bool Output() const {return m_output;} + + //! Returns a const C++ reference to the set of reference picture numbers (will be empty if the picture is an I picture) + const std::vector<int>& Refs() const {return m_refs;} + + //! Returns non-const C++ referece to the vector of reference pictures, to allow them to be set + std::vector<int>& Refs(){return m_refs;} + + //! Return the number of reference pictures + unsigned int NumRefs()const {return m_refs.size();} + + //! Returns type of picture (see enum) + PictureType GetPictureType () const { return m_picture_type; } + + //! Returns reference picture type (see enum) + ReferenceType GetReferenceType() const { return m_reference_type;} + + //! Returns true is entropy coding using Arithmetic coding + bool UsingAC() const { return m_using_ac; } + + // ... Sets + + //! Sets the type of picture + void SetPicSort( const PictureSort& ps ); + + //! Sets the picture to be Intra/Inter + void SetPictureType(const PictureType ftype); + + //! Sets the picture to be a reference or not + void SetReferenceType(const ReferenceType rtype); + + //! Sets the picture number + void SetPictureNum( const int fn ){ m_fnum=fn; } + + //! Sets how long the picture will stay in the buffer (encoder only) + void SetExpiryTime( const int expt ){ m_expiry_time=expt; } + + //! Sets a flag to indicate that the picture has been output + void SetAsOutput(){m_output=true;} + + //! Sets the chroma format + void SetCFormat(ChromaFormat cf){ m_cformat = cf; } + + //! Sets the picture width + void SetXl(int xlen); + + //! Sets the picture height + void SetYl(int ylen); + + //! Set Luma Depth + void SetLumaDepth(unsigned int luma_depth) { m_luma_depth = luma_depth; } + + //! Set Chroma Depth + void SetChromaDepth(unsigned int chroma_depth) { m_chroma_depth = chroma_depth; } + + //! Sets the retired reference picture number + void SetRetiredPictureNum(int retd_fnum) {m_retd_fnum = retd_fnum;} + + //! Sets the arithmetic coding flag + void SetUsingAC(bool using_ac) { m_using_ac = using_ac; } + + private: + + //! The chroma format + ChromaFormat m_cformat; + + //! The picture sort + PictureSort m_psort; + + //! The set of picture numbers of reference pictures + std::vector<int> m_refs; + + //! The number of pictures, after the current picture number, after the (de)coding of which the picture can be deleted + int m_expiry_time; + + //! The picture number, in temporal order + int m_fnum; + + //! Picture type + PictureType m_picture_type; + + //! Reference type + ReferenceType m_reference_type; + + //! True if the picture has been output, false if not + bool m_output; + + //! The picture number of the retired picture + mutable int m_retd_fnum; + + //! Picture luma width + int m_xl; + + //! Picture luma height + int m_yl; + + //! Picture chroma width + int m_cxl; + + //! Picture chroma height + int m_cyl; + + //! Luma depth - number of bits required for lumz + unsigned int m_luma_depth; + + //! chroma depth - number of bits required for luma + unsigned int m_chroma_depth; + + //! arithmetic coding flag + bool m_using_ac; + }; + + + //! A class for picture component data. + /*! + A class for encapsulating picture data, derived from TwoDArray. + */ + class PicArray: public TwoDArray<ValueType> + { + public: + //! Default constructor + /*! + Default constructor creates an empty array. + */ + PicArray(): TwoDArray<ValueType>(){} + + //! Constructor. + /*! + Contructor creates a two-D array, with specified size and colour + format. + */ + PicArray(int height, int width, CompSort cs=Y_COMP): + TwoDArray<ValueType>(height, width), m_csort(cs){} + + //copy constructor and assignment= derived by inheritance + + //! Destructor + ~PicArray(){} + + //! Return which component is stored + const CompSort& CSort() const {return m_csort;} + + //! Set the type of component being stored + void SetCSort(const CompSort cs){ m_csort = cs; } + + private: + + CompSort m_csort; + }; + + + //! A structure for recording costs, particularly in quantisation. + class CostType + { + public: + //! The error (MSE or 4th power) + double Error; + + //! The entropy in bits per symbol. + double ENTROPY; + + //! The Lagrangian combination of MSE+lambda*entropy + double TOTAL; + }; + + + //! A class used for correcting estimates of entropy. + /*! + A class used by the encoder for correcting estimates of entropy. Used + for selecting quantisers in subband coefficient coding. Factors can be + adjusted in the light of previous experience. + */ + class EntropyCorrector + { + public: + //! Constructor. + /*! + Constructs arrays of correction factors of size. + \param depth the depth of the wavelet transform. + */ + EntropyCorrector(int depth); + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //////////////////////////////////////////////////////////////////// + + //! Returns the correction factor. + /*! + Returns the correction factor for the band given also the type of + picture and component. + */ + float Factor(const int bandnum, const PictureParams& pp, + const CompSort c) const; + + //! Update the correction factors. + /*! + Update the factors for a given subband, component and picture type. + \param bandnum the number of the subband to update + \param pp picture parameters + \param c component type + \param est_bits the number of bits it was estimated would be used + \param actual_bits the number of bits that actually were used + */ + void Update(int bandnum, const PictureParams& pp, + CompSort c,int est_bits,int actual_bits); + + private: + //! Initialises the correction factors + void Init(); + + TwoDArray<float> m_Yfctrs; + TwoDArray<float> m_Ufctrs; + TwoDArray<float> m_Vfctrs; + }; + + //! Parameters for overlapped block motion compensation + class OLBParams + { + + public: + + //! Default constructor does nothing + OLBParams(){} + + //! Constructor + /* + Constructor rationalises proposed parameters to allow suitable + overlap and fit in with chroma format + \param xblen the horizontal block length + \param yblen the vertical block length + \param xblen the horizontal block separation + \param yblen the vertical block separation + + */ + OLBParams(const int xblen, const int yblen, + const int xbsep, const int ybsep); + + // Gets ... + + //! Returns the horizontal block length + int Xblen() const {return m_xblen;} + + //! Returns the vertical block length + int Yblen() const {return m_yblen;} + + //! Returns the horizontal block separation + int Xbsep() const {return m_xbsep;} + + //! Returns the vertical block separation + int Ybsep() const {return m_ybsep;} + + //! The offset in the horizontal start of the block caused by overlap,=(XBLEN-XBSEP)/2 + int Xoffset() const {return m_xoffset;} + + //! The offset in the vertical start of the block caused by overlap,=(YBLEN-YBSEP)/2 + int Yoffset() const {return m_yoffset;} + + // ... and sets + + //! Sets the block width + void SetXblen( int xblen ){ m_xblen = xblen; m_xoffset = (m_xblen-m_xbsep)/2;} + + //! Sets the block height + void SetYblen( int yblen ){ m_yblen = yblen; m_yoffset = (m_yblen-m_ybsep)/2;} + + //! Sets the block horizontal separation + void SetXbsep( int xbsep ){ m_xbsep = xbsep; m_xoffset = (m_xblen-m_xbsep)/2;} + + //! Sets the block vertical separation + void SetYbsep( int ybsep ){ m_ybsep = ybsep; m_yoffset = (m_yblen-m_ybsep)/2;} + + bool operator == (const OLBParams bparams) const; + + // overloaded stream operators + friend std::ostream & operator<< (std::ostream &, OLBParams &); + friend std::istream & operator>> (std::istream &, OLBParams &); + + + private: + + int m_xblen; + int m_yblen; + int m_xbsep; + int m_ybsep; + int m_xoffset; + int m_yoffset; + }; + + //! Parameters relating to the complexity of encoder/decoder + class ParseParams + { + public: + //! Default constructor + ParseParams(); + + // Gets + + //! Get the major version + unsigned int MajorVersion() const { return m_major_ver; } + + //! Get the minor version + unsigned int MinorVersion() const { return m_minor_ver; } + + //! Get the Profile + unsigned int Profile() const { return m_profile; } + + //! Get the Level + unsigned int Level() const { return m_level; } + + // Sets + + //! Set the major version + void SetMajorVersion(unsigned int major_ver) {m_major_ver = major_ver; } + + //! Set the minor version + void SetMinorVersion(unsigned int minor_ver) { m_minor_ver = minor_ver; } + + //! Set the Profile + void SetProfile(unsigned int profile) { m_profile = profile; } + + //! Set the Level + void SetLevel(unsigned int level) { m_level = level; } + + private: + //! Major Version + unsigned int m_major_ver; + //! Minor Version + unsigned int m_minor_ver; + //! Profile + unsigned int m_profile; + //! Level + unsigned int m_level; + }; + + //! Structure to hold code block sizes when spatial partitioning is used + class CodeBlocks + { + public: + //! Default Constructor + CodeBlocks () : m_hblocks(1), m_vblocks(1) + {} + + //! Constructor + CodeBlocks (unsigned int hblocks, unsigned int vblocks) : + m_hblocks(hblocks), + m_vblocks(vblocks) + {} + + // Gets + //! Return the number of horizontal code blocks + unsigned int HorizontalCodeBlocks() const { return m_hblocks; } + //! Return the number of vertical code blocks + unsigned int VerticalCodeBlocks() const { return m_vblocks; } + // Sets + //! Set the number of horizontal code blocks + void SetHorizontalCodeBlocks(unsigned int hblocks) { m_hblocks = hblocks; } + //! Set the number of vertical code blocks + void SetVerticalCodeBlocks(unsigned int vblocks) { m_vblocks = vblocks; } + private: + //! Number of Horizontal code blocks + unsigned int m_hblocks; + //! Number of Vertical code blocks + unsigned int m_vblocks; + }; + + //! Structure to hold motion parameters when motion comp is used + class PicturePredParams + { + public: + PicturePredParams(): + m_lbparams(3), + m_cbparams(3) {} + + //! Return the global motion flag used for encoding/decoding + bool UsingGlobalMotion() const { return m_use_global_motion; } + + //! Return the number of picture weight precision bits + unsigned int PictureWeightsBits() const { return m_picture_weights_bits; } + + //! Return the Ref1 weight + int Ref1Weight() const { return m_ref1_weight; } + + //! Return the Ref2 weight + int Ref2Weight() const { return m_ref2_weight; } + + bool CustomRefWeights() + { + return (m_picture_weights_bits != 1 || + m_ref1_weight != 1 || + m_ref2_weight != 1); + } + + //! Return the number of superblocks horizontally + int XNumSB() const {return m_x_num_sb;} + + //! Return the number of superblocks vertically + int YNumSB() const {return m_y_num_sb;} + + //! Return the number of blocks horizontally + int XNumBlocks() const {return m_x_num_blocks;} + + //! Returns the number of blocks vertically + int YNumBlocks() const {return m_y_num_blocks;} + + //! Return the Luma block parameters for each macroblock splitting level + const OLBParams& LumaBParams(int n) const {return m_lbparams[n];} + + //! Return the Chroma block parameters for each macroblock splitting level + const OLBParams& ChromaBParams(int n) const {return m_cbparams[n];} + + //! Return the number of accuracy bits used for motion vectors + MVPrecisionType MVPrecision() const { return m_mv_precision; } + + //! Set how many SBs there are horizontally + void SetXNumSB(const int xn){m_x_num_sb=xn;} + + //! Set how many SBs there are vertically + void SetYNumSB(const int yn){m_y_num_sb=yn;} + + //! Set how many blocks there are horizontally + void SetXNumBlocks(const int xn){m_x_num_blocks=xn;} + + //! Set how many blocks there are vertically + void SetYNumBlocks(const int yn){m_y_num_blocks=yn;} + + //! Set the block sizes for all SB splitting levels given these prototype block sizes for level=2 + void SetBlockSizes(const OLBParams& olbparams , const ChromaFormat cformat); + + //! Set block level luma params + void SetLumaBlockParams(const OLBParams& olbparams) {m_lbparams[2] = olbparams;} + + //! Set the number of accuracy bits for motion vectors + void SetMVPrecision(const MVPrecisionType p) + { + // Assert in debug mode. Maybe we should throw an exception??? + TESTM((p >=0 && p <=3), "Motion precision value in range 0..3"); + m_mv_precision = p; + } + + void SetMVPrecision(const MVPrecisionType p) const + { + // Assert in debug mode. Maybe we should throw an exception??? + TESTM((p >=0 && p <=3), "Motion precision value in range 0..3"); + m_mv_precision = p; + } + + //! Set the wavelet filter used for picture (de)coding + void SetUsingGlobalMotion(bool gm) { m_use_global_motion=gm; } + + //! Set the picture weight precision bits used for (de)coding + void SetPictureWeightsPrecision(unsigned int wt_prec) { m_picture_weights_bits=wt_prec; } + + //! Set the ref 1 picture weight + void SetRef1Weight(int wt) { m_ref1_weight=wt; } + + //! Set the ref 2 picture weight + void SetRef2Weight(int wt) { m_ref2_weight=wt; } + + private: + + //! The number of superblocks horizontally + int m_x_num_sb; + + //! The number of superblocks verticaly + int m_y_num_sb; + + //! The number of blocks horizontally + int m_x_num_blocks; + + //! The number of blocks vertically + int m_y_num_blocks; + + OneDArray<OLBParams> m_lbparams; + + OneDArray<OLBParams> m_cbparams; + + //! The precision of motion vectors (number of accuracy bits eg 1=half-pel accuracy) + mutable MVPrecisionType m_mv_precision; + + //! picture predicion parameters - precision + unsigned int m_picture_weights_bits; + + //! picture predicion parameters - reference picture 1 weight + int m_ref1_weight; + + //! picture predicion parameters - reference picture 2 weight + int m_ref2_weight; + + //! Global motion fields + bool m_use_global_motion; + + }; + + //! Parameters common to coder and decoder operation + /*! + Parameters used throughout both the encoder and the decoder + */ + class CodecParams + { + public: + + //! Default constructor + CodecParams (const VideoFormat& video_format = VIDEO_FORMAT_CUSTOM, + PictureType ftype = INTRA_PICTURE, + unsigned int num_refs = 0, + bool set_defaults=true); + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //////////////////////////////////////////////////////////////////// + + // Gets ... + + //! Returns the picture coding mode (independent of source format) + /*! Returns the picture coding mode (independent of source format) + * 0 = Frame coding (no quincunx) + * 1 = Field coding (no quincunx) + */ + int PictureCodingMode() const {return m_pic_coding_mode;} + + //! Returns true if the pictures are being coded as fields (mode 1 or 3) + bool FieldCoding() const { return (m_pic_coding_mode==1); } + + //! Returns true if the topmost field comes first in time when coding + bool TopFieldFirst() const {return m_topfieldfirst;} + + //! Return the picture/field luma width + int Xl() const {return m_xl;} + + //! Return the picture/field luma height + int Yl() const {return m_yl;} + + //! Return the picture/field chroma width + int ChromaXl() const {return m_cxl;} + + //! Return the picture/field chroma height + int ChromaYl() const {return m_cyl;} + + //! Returns the luma depth + unsigned int LumaDepth() const { return m_luma_depth; } + + //! Returns the chroma depth + unsigned int ChromaDepth() const { return m_chroma_depth; } + + //! Return zero transform flag being used for picture (de)coding + bool ZeroTransform() const { return m_zero_transform; } + + //! Return the wavelet filter currently being used for picture (de)coding + WltFilter TransformFilter() const { return m_wlt_filter; } + + //! Return the transform depth being used for picture (de)coding + unsigned int TransformDepth() const { return m_wlt_depth; } + + //! Return multiple quantisers flag being used for picture (de)coding + CodeBlockMode GetCodeBlockMode() const { return m_cb_mode; } + + //! Return the spatial partitioning flag being used for picture (de)coding + bool SpatialPartition() const { return m_spatial_partition; } + + //! Return the code blocks for a particular level + const CodeBlocks &GetCodeBlocks(unsigned int level) const; + + //! Return the video format currently being used for picture (de)coding + VideoFormat GetVideoFormat() const { return m_video_format; } + + //! Return the picture prediction params + PicturePredParams& GetPicPredParams(){return m_picpredparams;} + + //! Return the picture prediction params + const PicturePredParams& GetPicPredParams() const {return m_picpredparams;} + + // ... and Sets + //! Sets whether input is coded as fields or quincunxially + void SetPictureCodingMode(int pic_coding){m_pic_coding_mode=pic_coding;} + + //! Sets whether the topmost field comes first in time [NB: TBD since this duplicates metadata in the sequence header] + void SetTopFieldFirst(bool topf){m_topfieldfirst=topf;} + + //! Set the picture/field luma width + void SetXl(const int x){m_xl=x;} + + //! Set the picture/field luma height + void SetYl(const int y){m_yl=y;} + + //! Set the frame/field chroma width + void SetChromaXl(const int x){m_cxl=x;} + + //! Set the frame/field chroma height + void SetChromaYl(const int y){m_cyl=y;} + + //! Set Luma Depth + void SetLumaDepth(unsigned int luma_depth) { m_luma_depth = luma_depth; } + + //! Set Chroma Depth + void SetChromaDepth(unsigned int chroma_depth) { m_chroma_depth = chroma_depth; } + + //! Set the zero transform flag being used for picture (de)coding + void SetZeroTransform(bool zero_transform) { m_zero_transform = zero_transform; } + + //! Set the wavelet filter used for picture (de)coding + void SetTransformFilter(const WltFilter wf) { m_wlt_filter=wf; } + + //! Set the wavelet filter used for picture (de)coding + void SetTransformFilter(unsigned int wf_idx); + + //! Set the transform depth used for picture (de)coding and allocate for the code blocks array + void SetTransformDepth(unsigned int wd); + + //! Set the multiple quantisers flag usedto picture (de)coding + void SetCodeBlockMode(unsigned int cb_mode); + + //! Set the spatial partition flag usedto picture (de)coding + void SetSpatialPartition(bool spatial_partition) { m_spatial_partition=spatial_partition; } + + //! Set the number of code blocks for a particular level + void SetCodeBlocks(unsigned int level, unsigned int hblocks, unsigned int vblocks); + + //! Set the video format used for picture (de)coding + void SetVideoFormat(const VideoFormat vd) { m_video_format=vd; } + + protected: + //! Return the Wavelet filter associated with the wavelet index + WltFilter TransformFilter (unsigned int wf_idx); + private: + + //! The picture prediction parameters + PicturePredParams m_picpredparams; + + //! The picture coding mode + int m_pic_coding_mode; + + //! True if interlaced and top field is first in temporal order + bool m_topfieldfirst; + + //! The frame/field luma width + int m_xl; + + //! The frame/field luma height + int m_yl; + + //! The frame/field chroma width + int m_cxl; + + //! The frame/field chroma height + int m_cyl; + + //! Luma depth - number of bits required for lumz + unsigned int m_luma_depth; + + //! chroma depth - number of bits required for luma + unsigned int m_chroma_depth; + + //! The video format being used + VideoFormat m_video_format; + + //! Zero transform flag + bool m_zero_transform; + + //! The wavelet filter being used + WltFilter m_wlt_filter; + + //! Wavelet depth + unsigned int m_wlt_depth; + + //! Code block mode + CodeBlockMode m_cb_mode; + + //! Spatial partitioning flag + bool m_spatial_partition; + + //! Code block array. Number of entries is m_wlt_depth+1 + OneDArray<CodeBlocks> m_cb; + }; + + //! Parameters for the encoding process + /*! + Parameters for the encoding process, derived from CodecParams. + */ + class EncoderParams: public CodecParams + { + //codec params plus parameters relating solely to the operation of the encoder + + public: + //! Default constructor + EncoderParams(const VideoFormat& video_format, + PictureType ftype = INTER_PICTURE, + unsigned int num_refs = 2, + bool set_defaults=true); + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //This means pointers are copied, not the objects they point to.//// + //////////////////////////////////////////////////////////////////// + + // Gets ... + + + //! Returns true if we're operating verbosely, false otherwise + bool Verbose() const {return m_verbose;} + + //! Returns a flag indicating that we're doing local decoding + bool LocalDecode() const {return m_loc_decode;} + + //! Get whether we're doing lossless coding + bool Lossless() const {return m_lossless;} + + //! Get whether we're doing full-search motion estimation + bool FullSearch() const {return m_full_search; } + + //! Get the horizontal search range for full-search motion estimation + int XRangeME() const {return m_x_range_me;} + + //! Get the vertical search range for full-search motion estimation + int YRangeME() const {return m_y_range_me;} + + //! Get whether we're doing combined component motion estimation + bool CombinedME() const {return m_combined_me; } + + //! Get the quality factor + float Qf() const {return m_qf;} + + //! Return the nominal number of L1 pictures before the next I picture + /*! + Return the nominal number of L1 pictures before the next I picture. Can be + overridden by I-picture insertion + + */ + int NumL1() const {return m_num_L1;} + + //! Return the separation between L1 pictures (and between L1 and I pictures) + int L1Sep() const {return m_L1_sep;} + + //! Return the amount we're weighting noise in the U component + float UFactor() const {return m_ufactor;} + + //! Return the amount we're weighting noise in the V component + float VFactor() const {return m_vfactor;} + + //! Return the number of cycles per degree at the nominal viewing distance for the raster + float CPD() const {return m_cpd;} + + //! Return what prefiltering is in place + PrefilterType Prefilter() const {return m_prefilter;} + + //! Return the prefiltering strength + int PrefilterStrength() const {return m_prefilter_strength;} + + //! Return the Lagrangian parameter to be used for I pictures + float ILambda() const {return m_I_lambda;} + + //! Return the Lagrangian parameter to be used for L1 pictures + float L1Lambda() const {return m_L1_lambda;} + + //! Return the Lagrangian parameter to be used for L2 pictures + float L2Lambda() const {return m_L2_lambda;} + + //! Return the Lagrangian ME parameter to be used for L1 pictures + float L1MELambda() const {return m_L1_me_lambda;} + + //! Return the Lagrangian ME parameter to be used for L2 pictures + float L2MELambda() const {return m_L2_me_lambda;} + + //! Return the size of the GOP + int GOPLength() const; + + //! Return the output path to be used for storing diagnositic data + char * OutputPath() const {return ( char* ) m_output_path.c_str();} + + //! Return a reference to the entropy factors + const EntropyCorrector& EntropyFactors() const {return *m_ent_correct;} + + //! Return a reference to the entropy factors - we need to be able to change the values of the entropy factors in situ + EntropyCorrector& EntropyFactors() {return *m_ent_correct;} + + //! Return the Wavelet filter to be used for intra pictures + WltFilter IntraTransformFilter() { return m_intra_wltfilter; } + + //! Return the Wavelet filter to be used for Inter pictures + WltFilter InterTransformFilter() { return m_inter_wltfilter; } + + //! Return the Target Bit Rate in kbps + int TargetRate() {return m_target_rate;} + + //! Return true if using Arithmetic coding + bool UsingAC() const {return m_using_ac;} + + // ... and Sets + + //! Sets verbosity on or off + void SetVerbose(bool v){m_verbose=v;} + + //! Sets a flag indicating that we're producing a locally decoded o/p + void SetLocalDecode( const bool decode ){m_loc_decode=decode;} + + //! Set whether we're doing lossless coding + void SetLossless(const bool l){m_lossless = l;} + + //! Set whether we're doing full-search motion estimation + void SetFullSearch(const bool fs){m_full_search = fs;} + + //! Set whether we're doing combined component motion estimation + void SetCombinedME(const bool cme){m_combined_me = cme;} + + //! Set the horizontal search range for full-search motion estimation + void SetXRangeME(const int xr){m_x_range_me = xr;} + + //! Set the vertical search range for full-search motion estimation + void SetYRangeME(const int yr){m_y_range_me = yr;} + + //! Set the quality factor + void SetQf(const float qfac){ m_qf=qfac; CalcLambdas(m_qf); } + + //! Set the nominal number of L1 pictures between I pictures + void SetNumL1(const int nl){m_num_L1=nl;} + + //! Set the separation between L1 pictures + void SetL1Sep(const int lsep){m_L1_sep=lsep;} + + //! Set the amount to weight noise in the U component + void SetUFactor(const float uf){m_ufactor=uf;} + + //! Set the amount to weight noise in the V component + void SetVFactor(const float vf){m_vfactor=vf;} + + //! Set the number of cycles per degree at the nominal viewing distance + void SetCPD(const float cpd){m_cpd=cpd;} + + //! Set denoising value - true or false + void SetPrefilter(const PrefilterType pf, const int str){m_prefilter=pf; + m_prefilter_strength=str;} + + //! Set the output path to be used for diagnostic data + void SetOutputPath(const char * op){ m_output_path = op; } + + //! Sets the entropy factors - TBD: set this up in a constructor and pass encoder params around entirely by reference + void SetEntropyFactors(EntropyCorrector* entcorrect){m_ent_correct=entcorrect;} + //! Set the Wavelet filter to be used for intra pictures + void SetIntraTransformFilter(unsigned int wf_idx); + + //! Set the Wavelet filter to be used for inter pictures + void SetInterTransformFilter(unsigned int wf_idx); + + //! Set the Wavelet filter to be used for intra pictures + void SetIntraTransformFilter(WltFilter wf) { m_intra_wltfilter = wf; } + + //! Set the number of code blocks for all levels + void SetUsualCodeBlocks(const PictureType& ftype); + + //! Set the Wavelet filter to be used for inter pictures + void SetInterTransformFilter(WltFilter wf) { m_inter_wltfilter = wf; } + + //! Set the target bit rate + void SetTargetRate(const int rate){m_target_rate = rate;} + + //! Set the arithmetic coding flag + void SetUsingAC(bool using_ac) {m_using_ac = using_ac;} + private: + + //! Calculate the Lagrangian parameters from the quality factor + void CalcLambdas(const float qf); + + private: + + //! Code/decode with commentary if true + bool m_verbose; + + //! Flag indicating we're doing local decoding + bool m_loc_decode; + + //! A flag indicating we're doing lossless coding + bool m_lossless; + + //! A flag indicating whether we're doing full-search block matching + bool m_full_search; + + //! A flag indicating whether we're doing combined component motion estimation + bool m_combined_me; + + //! The horizontal range for full-search block matching + int m_x_range_me; + + //! The vertical range for full-search block matching + int m_y_range_me; + + //! Quality factor + float m_qf; + + //! Number of L1 pictures before next I picture + int m_num_L1; + + //! Separation between L1 pictures + int m_L1_sep; + + //! factor for weighting U component quantisation errors + float m_ufactor; + + //! factor for weighting V component quantisation errors + float m_vfactor; + + //! Cycles per degree assumed for viewing the video + float m_cpd; + + //! Indicator for prefiltering + PrefilterType m_prefilter; + + //! Prefiltering strength + int m_prefilter_strength; + + //! Lagrangian parameter for Intra picture coding + float m_I_lambda; + + //! Lagrangian parameter for L1 picture coding + float m_L1_lambda; + + //! Lagrangian parameter for L2 picture coding + float m_L2_lambda; + + //! Lagrangian param for L1 motion estimation + float m_L1_me_lambda; + + //! Lagrangian param for L2 motion estimation + float m_L2_me_lambda; + + //! Correction factors for quantiser selection + EntropyCorrector* m_ent_correct; + + //! Output file path + std::string m_output_path; + + //! Wavelet filter for Intra pictures + WltFilter m_intra_wltfilter; + + //! Wavelet filter for Inter pictures + WltFilter m_inter_wltfilter; + + //! Target bit rate + int m_target_rate; + + //! Arithmetic coding flag + bool m_using_ac; + + }; + + //! Parameters for the decoding process + /*! + Parameters for the decoding process. Derived from CodecParams. + */ + class DecoderParams: public CodecParams + { + public: + //! Default constructor + DecoderParams(const VideoFormat& video_format = VIDEO_FORMAT_CIF, PictureType ftype=INTRA_PICTURE, unsigned int num_refs = 0, bool set_defaults = false); + + //! Returns true if we're operating verbosely, false otherwise + bool Verbose() const {return m_verbose;} + + //! Sets verbosity on or off + void SetVerbose(bool v){m_verbose=v;} + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //This means pointers are copied, not the objects they point to.//// + //////////////////////////////////////////////////////////////////// + + + private: + + //! Code/decode with commentary if true + bool m_verbose; + + }; + + //! A simple bounds checking function, very useful in a number of places + inline ValueType BChk(const ValueType &num, const ValueType &max) + { + if(num < 0) return 0; + else if(num >= max) return max-1; + else return num; + } + + //! Class for encapsulating quantiser data + class QuantiserLists + { + public: + //! Default constructor + QuantiserLists(); + + //! Returns 4 times the quantisation factor + inline int QuantFactor4( const int index ) const {return m_qflist4[index]; } + + //! Returns the intra Picture quantisation offset for non-zero values + inline int IntraQuantOffset4( const int index ) const {return m_intra_offset4[index]; } + //! Returns the inter Picture quantisation offset for non-zero values + inline int InterQuantOffset4( const int index ) const {return m_inter_offset4[index]; } + + //! Returns the maximum quantiser index supported + inline int MaxQuantIndex() const {return m_max_qindex; } + + + private: + unsigned int m_max_qindex; + OneDArray<int> m_qflist4; + OneDArray<int> m_intra_offset4; + OneDArray<int> m_inter_offset4; + + }; + + //! A constant list of the quantisers being used in Dirac + static const QuantiserLists dirac_quantiser_lists; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common_types.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common_types.h new file mode 100644 index 000000000..ef7d7a4a6 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/common_types.h @@ -0,0 +1,209 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: common_types.h,v 1.21 2008/11/06 04:53:36 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Tim Borer +* Andrew Kennedy, +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _COMMON_TYPES_H_ +#define _COMMON_TYPES_H_ + + +/*! This file contains common enumerated types used throughout the encoder and + the end user interfaces to the encoder and decoder +*/ + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Some basic enumeration types used throughout the codec and by end user ...// +*/ + +/*! Types of chroma formatting (formatNK=format not known) */ +typedef enum { format444, format422, format420, formatNK } ChromaFormat; + +/*! Types of Wavelet filters supported. filterNK - not known) */ +typedef enum +{ + DD9_7=0, /* Deslauriers-Dubuc (9,7) */ + LEGALL5_3, /* LeGall (5,3) */ + DD13_7, /* Deslauriers-Dubuc (13,7) */ + HAAR0, /* Haar, no shift per level*/ + HAAR1, /* Haar, one shift per level*/ + FIDELITY, /* Fidelity wavelet */ + DAUB9_7, /* Integer approximation to Daubechies 97 */ + filterNK +} WltFilter; + +/*! Enumerated type that defines prefiltering types supported by the + encoder. */ +typedef enum +{ + NO_PF = 0, + DIAGLP, + RECTLP, + CWM +} PrefilterType; + +static const int NUM_WLT_FILTERS = 8; + +/*! Types of picture */ +typedef enum { + INTRA_PICTURE=0, + INTER_PICTURE + } PictureType; + +/*! Types of referencing */ +typedef enum { + REFERENCE_PICTURE=0, + NON_REFERENCE_PICTURE +} ReferenceType; + +/*! Types for video-format */ +typedef enum { + VIDEO_FORMAT_CUSTOM=0, + VIDEO_FORMAT_QSIF525, + VIDEO_FORMAT_QCIF, + VIDEO_FORMAT_SIF525, + VIDEO_FORMAT_CIF, + VIDEO_FORMAT_4SIF525, + VIDEO_FORMAT_4CIF, + VIDEO_FORMAT_SD_480I60, + VIDEO_FORMAT_SD_576I50, + VIDEO_FORMAT_HD_720P60, + VIDEO_FORMAT_HD_720P50, + VIDEO_FORMAT_HD_1080I60, + VIDEO_FORMAT_HD_1080I50, + VIDEO_FORMAT_HD_1080P60, + VIDEO_FORMAT_HD_1080P50, + VIDEO_FORMAT_DIGI_CINEMA_2K24, + VIDEO_FORMAT_DIGI_CINEMA_4K24, + VIDEO_FORMAT_UHDTV_4K60, + VIDEO_FORMAT_UHDTV_4K50, + VIDEO_FORMAT_UHDTV_8K60, + VIDEO_FORMAT_UHDTV_8K50, + VIDEO_FORMAT_UNDEFINED +} VideoFormat; + +/*! Types of Colour primaries */ +typedef enum { + CP_HDTV_COMP_INTERNET=0, + CP_SDTV_525, + CP_SDTV_625, + CP_DCINEMA, + CP_UNDEF +}ColourPrimaries; + +/*! Types of Colour Matrices */ +typedef enum { + CM_HDTV_COMP_INTERNET=0, + CM_SDTV, + CM_REVERSIBLE, + CM_UNDEF +}ColourMatrix; + +/*! Types of Transfer functions */ +typedef enum { + TF_TV=0, + TF_EXT_GAMUT, + TF_LINEAR, + TF_DCINEMA, + TF_UNDEF +} TransferFunction; + +/*! Types of Picture-rate */ +typedef enum { + FRAMERATE_CUSTOM=0, + FRAMERATE_23p97_FPS, + FRAMERATE_24_FPS, + FRAMERATE_25_FPS, + FRAMERATE_29p97_FPS, + FRAMERATE_30_FPS, + FRAMERATE_50_FPS, + FRAMERATE_59p94_FPS, + FRAMERATE_60_FPS, + FRAMERATE_14p98_FPS, + FRAMERATE_12p5_FPS, + FRAMERATE_UNDEFINED +} FrameRateType; + +/*! Types of Aspect Ratio */ +typedef enum { + PIXEL_ASPECT_RATIO_CUSTOM=0, + PIXEL_ASPECT_RATIO_1_1, + PIXEL_ASPECT_RATIO_10_11, + PIXEL_ASPECT_RATIO_12_11, + PIXEL_ASPECT_RATIO_40_33, + PIXEL_ASPECT_RATIO_16_11, + PIXEL_ASPECT_RATIO_4_3, + PIXEL_ASPECT_RATIO_UNDEFINED +} PixelAspectRatioType; + + +/*! Types of signal range */ +typedef enum { + SIGNAL_RANGE_CUSTOM=0, + SIGNAL_RANGE_8BIT_FULL, + SIGNAL_RANGE_8BIT_VIDEO, + SIGNAL_RANGE_10BIT_VIDEO, + SIGNAL_RANGE_12BIT_VIDEO, + SIGNAL_RANGE_UNDEFINED +} SignalRangeType; + +/*! Types of motion-vector precision */ +typedef enum { + MV_PRECISION_PIXEL=0, + MV_PRECISION_HALF_PIXEL, + MV_PRECISION_QUARTER_PIXEL, + MV_PRECISION_EIGHTH_PIXEL, + MV_PRECISION_UNDEFINED +} MVPrecisionType; + +/*! Type of quantiser modes when spatial partitioning is enabled */ +typedef enum +{ + QUANT_SINGLE, + QUANT_MULTIPLE, + QUANT_UNDEF +} CodeBlockMode; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_assertions.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_assertions.cpp new file mode 100644 index 000000000..747c64998 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_assertions.cpp @@ -0,0 +1,66 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_assertions.cpp,v 1.2 2004/11/22 13:28:05 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <stdlib.h> +#include <string> +#include <iostream> + +#include "dirac_assertions.h" +using namespace dirac; + +namespace dirac +{ +void dirac_assert( const char *p_fname, int line_number, const char *p_mess ) +{ + dirac_report( p_fname, line_number, p_mess ); + // dump core + abort (); +} + +void dirac_report( const char *p_fname, int line_number, const char *p_mess ) +{ + std::string errMess("Assertion "); + + if ( p_mess ) + errMess = errMess + "^ " + std::string(p_mess) + " ^" +" failed"; + else + errMess += " failure"; + + std::cerr << errMess << " in file " << p_fname << " at line " << line_number << std::endl; +} +} // namespace dirac + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_assertions.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_assertions.h new file mode 100644 index 000000000..209447e84 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_assertions.h @@ -0,0 +1,80 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_assertions.h,v 1.3 2004/11/22 14:05:02 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ +#ifndef DIRAC_ASSERTIONS_H +#define DIRAC_ASSERTIONS_H +namespace dirac +{ + +#undef cmpCOND +#define cmpCOND( exp, trueRes, falseRes ) ( (exp) ? (trueRes) : (falseRes) ) + +#undef ERREXP +#define ERREXP(exp,errfn,text) cmpCOND((exp), ((void)0), errfn(__FILE__,__LINE__,text)) + +#undef ASSERT +#define ASSERT(exp) ERREXP(exp,dirac_assert,NULL) + +#undef ASSERTM +#define ASSERTM(exp,text) ERREXP(exp,dirac_assert,text) + +#undef TEST +#undef TESTM +#undef REPORT +#undef REPORTM + +#ifdef DIRAC_DEBUG +#define TEST(exp) ASSERT(exp) +#define TESTM(exp,text) ASSERTM(exp,text) +#define REPORT(exp) ASSERT(exp) +#define REPORTM(exp,text) ASSERTM(exp,text) +#else +#define TEST(exp) +#define TESTM(exp,text) +#define REPORT(exp) ERREXP(exp,dirac_report,NULL) +#define REPORTM(exp,text) ERREXP(exp,dirac_report,text) +#endif + + +/*! Print a message to standard error and abort if in debug mode */ +void dirac_assert( const char *p_fname, int line_number, const char *p_mess); + +/*! Print a message to standard error */ +void dirac_report( const char *p_fname, int line_number, const char *p_mess); + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_exception.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_exception.cpp new file mode 100644 index 000000000..b42e42748 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_exception.cpp @@ -0,0 +1,100 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_exception.cpp,v 1.2 2007/03/19 16:18:59 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** + * Implementation of class DiracException. + */ +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; +using namespace std; + +///////////////////////////////// PUBLIC ///////////////////////////////////// + + +DiracException::DiracException( + const DiracErrorCode& errorCode, + const string& errorMessage, + const DiracSeverityCode& severityCode) +: mErrorCode(errorCode), + mSeverityCode(severityCode), + mErrorMessage(errorMessage) +{ +} + + +DiracException::DiracException( + const DiracException& src) +: mErrorCode(src.mErrorCode) +, mSeverityCode(src.mSeverityCode) +, mErrorMessage(src.mErrorMessage) +{ + +} + +DiracException::~DiracException() +{ +} + + +//============================== ACCESS ====================================== + +DiracErrorCode DiracException::GetErrorCode() const +{ + return mErrorCode; +} + + DiracSeverityCode DiracException::GetSeverityCode() const +{ + return mSeverityCode; +} + +std::string DiracException::GetErrorMessage() const +{ + return mErrorMessage; +} + + +//========================== GLOBAL OPERATORS ================================ +ostream& operator<<( + ostream& dst, + const DiracException& exception) +{ + // output the error message + dst << exception.GetErrorMessage() << endl; + return dst; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_exception.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_exception.h new file mode 100644 index 000000000..44c54cb0d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_exception.h @@ -0,0 +1,215 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_exception.h,v 1.6 2008/01/31 11:25:16 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** + * Definition of class DiracException. + */ +#ifndef DiracException_h +#define DiracException_h + + +// SYSTEM INCLUDES +// +#include <string> // has a string +#include <iostream> // has an ostringstream + + +namespace dirac { + + /** + * Enumeration of Dirac-defined error codes. + * + * + */ + enum DiracErrorCode { + ERR_UNSUPPORTED_STREAM_DATA=0, + ERR_END_OF_STREAM, + ERR_INVALID_VIDEO_FORMAT, + ERR_INVALID_CHROMA_FORMAT, + ERR_INVALID_PICTURE_RATE, + ERR_INVALID_SIGNAL_RANGE, + ERR_INVALID_PIXEL_ASPECT_RATIO, + ERR_INVALID_VIDEO_DEPTH, + ERR_INVALID_MOTION_VECTOR_PRECISION, + ERR_INVALID_INIT_DATA + + }; + + /** + * Error-severity states + */ + enum DiracSeverityCode { + SEVERITY_NO_ERROR=0, + SEVERITY_WARNING, + SEVERITY_PICTURE_ERROR, + SEVERITY_ACCESSUNIT_ERROR, + SEVERITY_SEQUENCE_ERROR, + SEVERITY_TERMINATE + }; + +/** + * DiracException is the class which should be used for all exceptions + * within Dirac. + */ +class DiracException +{ +public: + + + /** + * Construct from error source ID, error code, and message. + * + * @param errorCode The error code. + * @param errorMessage The error message. + * @param severityCode The error source ID. + */ + DiracException( + const DiracErrorCode& errorCode, + const std::string& errorMessage, + const DiracSeverityCode& severityCode); + + /** + * Copy constructor. + */ + DiracException( + const DiracException& src); + + /** + * Destructor. + */ + virtual ~DiracException(); + + +// OPERATORS + + +// ACCESS + + /** + * Get the error code of this exception. + * + * @return The error code of this exception. + */ + DiracErrorCode GetErrorCode() const; + + /** + * Get the severity level of this exception. + * + * @return The severity level of this exception. + */ + DiracSeverityCode GetSeverityCode() const; + + /** + * Get the error message of this exception. + * + * @return The error message of this exception. + */ + std::string GetErrorMessage() const; + + + +private: + +// ATTRIBUTES + + /** + * The error code of this exception. + */ + DiracErrorCode mErrorCode; + + /** + * Severity of exception + */ + DiracSeverityCode mSeverityCode; + + /** + * The error message. + */ + std::string mErrorMessage; + + + +// UNIMPLEMENTED METHODS + DiracException& operator=(const DiracException&); + +}; // class DiracException + + + + + +// GLOBAL OPERATORS +// +std::ostream& operator<<(std::ostream& dst, const DiracException& exception); + + +// MACROS FOR LOGGING AND THROWING DIRAC EXCEPTIONS +// + + +/** + * Write an exception to the log + */ +#define DIRAC_LOG_EXCEPTION(exception) \ + { \ + if(exception.GetSeverityCode()!=SEVERITY_NO_ERROR) \ + std::cerr << exception.GetErrorMessage(); \ + } + +/** + * Construct an exception from 3 arguments, log it, and throw it. + */ +#define DIRAC_THROW_EXCEPTION(arg1,arg2,arg3) \ + { \ + DiracException exception(arg1,arg2, arg3); \ + DIRAC_LOG_EXCEPTION(exception) \ + throw exception; \ + } + +/** + * Catch a DiracException, log it, and rethrow it. + */ +#define DIRAC_CATCH_AND_RETHROW() \ + catch (const DiracException& e) { \ + DiracException exception(e); \ + DIRAC_LOG_EXCEPTION(exception)\ + throw exception; \ + } + +} // namespace Dirac + +#endif // DiracException_h diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_inttypes.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_inttypes.h new file mode 100644 index 000000000..506c81668 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_inttypes.h @@ -0,0 +1,48 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: dirac_inttypes.h,v 1.1 2008/05/06 09:35:51 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Anuradha Suraparaju (Original Author)
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef DIRAC_INTTYPES_H
+#define DIRAC_INTTYPES_H
+
+#ifndef _MSC_VER
+#include <libdirac_common/dirac-stdint.h>
+#else
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#endif //_MSC_VER
+
+#endif //DIRAC_INTTYPES_H
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_types.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_types.h new file mode 100644 index 000000000..cc7cd7f54 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/dirac_types.h @@ -0,0 +1,198 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_types.h,v 1.12 2008/11/18 23:25:54 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _DIRAC_TYPES_H +#define _DIRAC_TYPES_H + +#include <libdirac_common/common_types.h> + +/*! This file contains common enumerated types used throughout + the end user interfaces to the encoder and decoder +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(WIN32) && defined(_WINDLL) +#define DllExport __declspec( dllexport ) +#else +#define DllExport +#endif + +/* +* Major version corresponds to major version of the software. +* Minor version corresponds to minor version of the software. Bump +* this up by one whenever there are major feature changes to the software. +* Patch version corresponds to changes in the API. It should be +* bumped up by 1 for every committed change to the API +*/ +#define DIRAC_RESEARCH_MAJOR_VERSION 1 /* 0..255 */ +#define DIRAC_RESEARCH_MINOR_VERSION 0 /* 0..255 */ +#define DIRAC_RESEARCH_PATCH_VERSION 2 /* 0..255 */ + +#define DIRAC_RESEARCH_VERSION(X, Y, Z) \ + (((X)<<16) + ((Y)<<8) + (Z)) + +#define DIRAC_RESEARCH_CURVERSION \ + DIRAC_RESEARCH_VERSION(DIRAC_RESEARCH_MAJOR_VERSION, \ + DIRAC_RESEARCH_MINOR_VERSION, \ + DIRAC_RESEARCH_PATCH_VERSION) + +#define DIRAC_RESEARCH_VERSION_ATLEAST(X, Y, Z) \ + (DIRAC_RESEARCH_CURVERSION >= DIRAC_RESEARCH_VERSION(X, Y, Z)) + +/* +* Some basic enumeration types used by end user encoder and decoder ...// +*/ +typedef ChromaFormat dirac_chroma_t; +typedef PictureType dirac_picture_type_t; +typedef ReferenceType dirac_reference_type_t; +typedef WltFilter dirac_wlt_filter_t; + +typedef struct +{ + int numerator; + int denominator; +} dirac_rational_t; + +typedef dirac_rational_t dirac_frame_rate_t; +typedef dirac_rational_t dirac_pix_asr_t; + +/*! Structure that holds the parase parameters */ +typedef struct +{ + //! Major version + unsigned int major_ver; + //! Minor version + unsigned int minor_ver; + //! Profile + unsigned int profile; + //! level + unsigned int level; +} dirac_parseparams_t; + +typedef struct +{ + unsigned int width; + unsigned int height; + unsigned int left_offset; + unsigned int top_offset; +} dirac_clean_area_t; + +typedef struct +{ + unsigned int luma_offset; + unsigned int luma_excursion; + unsigned int chroma_offset; + unsigned int chroma_excursion; +} dirac_signal_range_t; + +typedef struct +{ + float kr; + float kb; +} dirac_col_matrix_t; + +typedef ColourPrimaries dirac_col_primaries_t; +typedef TransferFunction dirac_transfer_func_t; + +typedef struct +{ + dirac_col_primaries_t col_primary; + dirac_col_matrix_t col_matrix; + dirac_transfer_func_t trans_func; +} dirac_colour_spec_t; + +/*! Structure that holds the source parameters */ +typedef struct +{ + /*! numper of pixels per line */ + unsigned int width; + /*! number of lines per frame */ + unsigned int height; + /*! chroma type */ + dirac_chroma_t chroma; + /*! numper of pixels of chroma per line */ + unsigned int chroma_width; + /*! number of lines of chroma per frame */ + unsigned int chroma_height; + /*! source sampling field: 0 - progressive; 1 - interlaced */ + unsigned int source_sampling; + /*! top field comes first : 0 - false; 1 - true. Set by Dirac library. */ + int topfieldfirst; + /*! frame rate */ + dirac_frame_rate_t frame_rate; + /*! pixel aspect ratio */ + dirac_pix_asr_t pix_asr; + /* clean area*/ + dirac_clean_area_t clean_area; + /* signal range*/ + dirac_signal_range_t signal_range; + /* colour specification*/ + dirac_colour_spec_t colour_spec; + +} dirac_sourceparams_t; + +/*! Structure that holds the picture parameters */ +typedef struct +{ + /*! picture type */ + dirac_picture_type_t ptype; + /*! reference type */ + dirac_reference_type_t rtype; + /*! picture number in decoded order */ + int pnum; +} dirac_picparams_t; + + +/*! Structure that holds the frame buffers into which data is written +(NB we have frame-oriented IO even though we code pictures)*/ +typedef struct +{ + /*! buffers to hold the luma and chroma data */ + unsigned char *buf[3]; + /*! user data */ + void *id; +} dirac_framebuf_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp.cpp new file mode 100644 index 000000000..7fe5515c9 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp.cpp @@ -0,0 +1,1239 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mot_comp.cpp,v 1.47 2009/04/21 01:33:04 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Richard Felton (Original Author), +* Thomas Davies, +* Steve Bearcroft +* Mike Ferenduros +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#include <libdirac_common/mot_comp.h> +#if defined(HAVE_MMX) +#include <libdirac_common/mot_comp_mmx.h> +#endif +#include <libdirac_common/motion.h> +#include <libdirac_common/picture_buffer.h> +using namespace dirac; + +using std::vector; + + +#define NUM_USED_BLKS(w,sep,len) ((w+sep+(len-sep)/2-1)/sep) + +//--public member functions--// +/////////////////////////////// + +// Convenience function to perform motion compensation on a picture +// Static function that motion compensates a picture. It uses the +// MV precision value in the PicturePredParams to instantiate the +// appropriate MotionCompensation sub-class. +void MotionCompensator::CompensatePicture(const PicturePredParams &ppp, + const AddOrSub direction , + const MvData& mv_data, + Picture* in_pic , + Picture* refsptr[2]) +{ + switch (ppp.MVPrecision()) + { + case MV_PRECISION_EIGHTH_PIXEL: + { + MotionCompensator_EighthPixel my_comp(ppp); + my_comp.CompensatePicture( direction , mv_data, in_pic, refsptr); + break; + } + case MV_PRECISION_HALF_PIXEL: + { + MotionCompensator_HalfPixel my_comp(ppp); + my_comp.CompensatePicture( direction , mv_data, in_pic, refsptr); + break; + } + case MV_PRECISION_PIXEL: + { + MotionCompensator_Pixel my_comp(ppp); + my_comp.CompensatePicture( direction , mv_data, in_pic, refsptr); + break; + } + case MV_PRECISION_QUARTER_PIXEL: + default: + { + MotionCompensator_QuarterPixel my_comp(ppp); + my_comp.CompensatePicture( direction , mv_data, in_pic, refsptr); + break; + } + } + + return; +} + +// Constructor +// Initialises the lookup tables that is needed for motion +// motion compensation. Creates the necessary arithmetic objects and +// calls ReConfig to create weighting blocks to fit the values within +// m_predparams. +MotionCompensator::MotionCompensator( const PicturePredParams &ppp ): + m_predparams(ppp), + luma_or_chroma(true) +{ + // Allocate for block weights + m_block_weights = new TwoDArray<ValueType>[9]; + // Allocate for superblock weights + m_macro_block_weights = new TwoDArray<ValueType>[9]; + // Allocate for sub superblock weights + m_sub_block_weights = new TwoDArray<ValueType>[9]; + + //Configure weighting blocks for the first time + ReConfig(); +} + +// Destructor +MotionCompensator::~MotionCompensator() +{ + //Tidy up the pointers + delete[] m_block_weights; + delete[] m_macro_block_weights; + delete[] m_sub_block_weights; +} + +//Called to perform motion compensated addition/subtraction on an entire picture. +void MotionCompensator::CompensatePicture( const AddOrSub direction , + const MvData& mv_data, + Picture* my_picture , + Picture* refsptr[2]) +{ + m_add_or_sub = direction; + + const PictureSort& psort=my_picture->GetPparams().PicSort(); + + m_cformat = my_picture->GetPparams().CFormat(); + + if (psort.IsInter()) + {//we can motion compensate + + const std::vector<int>& refs=my_picture->GetPparams().Refs(); + + // Now check that references are marked correctly + if ( !refsptr[0]->GetPparams().PicSort().IsRef() ) + { + std::cout<<std::endl<<"WARNING! Reference picture (number "<<refs[0]; + std::cout<<") being used is not marked as a reference. Incorrect output is likely."; + } + if ( refsptr[0]->GetPparams().PictureNum() != refs[0] ) + { + std::cout<<std::endl<<"WARNING! Reference picture number 0 "; + std::cout<<"does not agree("<<refsptr[0]->GetPparams().PictureNum()<<" and "; + std::cout<<refs[0]<<"). Incorrect output is likely."; + } + + + if ( refs.size()>1 ) + { + if ( !refsptr[1]->GetPparams().PicSort().IsRef() ) + { + std::cout<<std::endl<<"WARNING! Reference picture (number "; + std::cout<<refs[1]<<") being used is not marked as a reference. Incorrect output is likely."; + } + if ( refsptr[1]->GetPparams().PictureNum() != refs[1]) + { + std::cout<<std::endl<<"WARNING! Reference picture number 1 "; + std::cout<<"does not agree("<<refsptr[1]->GetPparams().PictureNum()<<" and "; + std::cout<<refs[1]<<"). Incorrect output is likely."; + } + } + else + refsptr[1] = refsptr[0]; + + luma_or_chroma = true; + //now do all the components + CompensateComponent( my_picture , refsptr, mv_data , Y_COMP ); + + luma_or_chroma = false; + CompensateComponent( my_picture , refsptr, mv_data , U_COMP); + CompensateComponent( my_picture , refsptr, mv_data , V_COMP); + } +} + +//--private member functions--// +//////////////////////////////// + +//Needs to be called if the blocksize changes (and +//on startup). This method creates an array of weighting +//blocks that are used to acheive correctly overlapping +//blocks. +void MotionCompensator::ReConfig() +{ + if (luma_or_chroma) + m_bparams = m_predparams.LumaBParams(2); + else + m_bparams = m_predparams.ChromaBParams(2); + + // Calculate the shift required in horizontal and vertical direction for + // OBMC and the weighting bits for each reference picture. + + // Total shift = shift assuming equal picture weights + + // picture weights precision + int blocks_per_mb_row = m_predparams.XNumBlocks()/m_predparams.XNumSB(); + int blocks_per_sb_row = blocks_per_mb_row>>1; + int mb_xlen = m_bparams.Xblen()*blocks_per_mb_row - (m_bparams.Xblen()-m_bparams.Xbsep())*(blocks_per_mb_row-1); + int mb_ylen = m_bparams.Yblen(); + int mb_xsep = mb_xlen - (m_bparams.Xblen()-m_bparams.Xbsep()); + int mb_ysep = m_bparams.Ybsep(); + int sb_xlen = m_bparams.Xblen()*blocks_per_sb_row - (m_bparams.Xblen()-m_bparams.Xbsep())*(blocks_per_sb_row-1); + int sb_ylen = m_bparams.Yblen(); + int sb_xsep = sb_xlen - (m_bparams.Xblen() - m_bparams.Xbsep()); + int sb_ysep = m_bparams.Ybsep(); + + for(int i = 0; i < 9; i++) + { + m_block_weights[i].Resize( m_bparams.Yblen() , m_bparams.Xblen() ); + m_macro_block_weights[i].Resize( mb_ylen , mb_xlen ); + m_sub_block_weights[i].Resize( sb_ylen , sb_xlen ); + } + + // Firstly calculate the non-weighted Weighting blocks. i,e, assuming that + // the picture_weight for each reference picture is 1. + + // Calculate non-weighted Block Weights + CalculateWeights( m_bparams.Xbsep(), m_bparams.Ybsep(), m_block_weights ); + + // Calculate non-weighted "macro" Block Weights + CalculateWeights( mb_xsep, mb_ysep , m_macro_block_weights ); + + // Calculate non-weighted superblock Weights + CalculateWeights( sb_xsep, sb_ysep , m_sub_block_weights ); +} + +void MotionCompensator::CompensateComponent( Picture* pic , + Picture* refsptr[2] , + const MvData& mv_data , + const CompSort cs ) +{ + // Set up references to pictures and references + PicArray& pic_data_out = pic->Data( cs ); + + // Size of picture component being motion compensated + + const PicArray& ref1up = refsptr[0]->UpData( cs ); + const PicArray& ref2up = refsptr[1]->UpData( cs ); + + // Set up a row of blocks which will contain the MC data, which + // we'll add or subtract to pic_data_out + TwoDArray<ValueType> pic_data(m_bparams.Yblen(), pic_data_out.LengthX(), 0 ); + + // Factors to compensate for subsampling of chroma + int xscale_shift = 0; + int yscale_shift = 0; + if ( cs != Y_COMP ) + { + if (m_cformat == format420) + { + xscale_shift = 1; + yscale_shift = 1; + } + else if (m_cformat == format422) + { + xscale_shift = 1; + yscale_shift = 0; + } + } + + ImageCoords pic_size(pic->GetPparams().Xl(), pic->GetPparams().Yl()); + if ( cs != Y_COMP ) + { + pic_size.x = pic->GetPparams().ChromaXl(); + pic_size.y = pic->GetPparams().ChromaYl(); + } + + + // Reference to the relevant DC array + const TwoDArray<ValueType>& dcarray = mv_data.DC( cs ); + + // Set up references to the vectors + const int num_refs = pic->GetPparams().Refs().size(); + const MvArray* mv_array1; + const MvArray* mv_array2; + mv_array1 = &mv_data.Vectors(1); + if (num_refs ==2 ) + mv_array2 = &mv_data.Vectors(2); + else + mv_array2 = &mv_data.Vectors(1); + + ReConfig();//set all the weighting blocks up + + //Blocks are listed left to right, line by line. + MVector mv1,mv2; + PredMode block_mode; + + //Coords of the top-left corner of a block + ImageCoords pos; + + //Loop for each block in the output image. + //The CompensateBlock function will use the image pointed to by ref1up + //and add the compensated pixels to the image pointed to by pic_data. + size_t wgt_idx; + + int save_from_row = m_bparams.Ybsep()-m_bparams.Yoffset(); + + bool row_overlap = ((m_bparams.Yblen() - m_bparams.Ybsep()) > 0); + + // unpadded picture dimensions + const int x_end_data = pic_data_out.FirstX() + std::min(pic_data_out.LengthX(), pic_size.x ); + const int y_end_data = pic_data_out.FirstY() + std::min(pic_data_out.LengthY(), pic_size.y ); + + const int blocks_per_mb_row = m_predparams.XNumBlocks()/m_predparams.XNumSB(); + const int blocks_per_sb_row = blocks_per_mb_row>>1; + + // The picture does not contain integral number of blocks. So not all + // blocks need to be processed. Compute the relevant blocks to be + // processed + int y_num_blocks = std::min((NUM_USED_BLKS(pic_size.y,m_bparams.Ybsep(),m_bparams.Yblen())), + m_predparams.YNumBlocks()); + int x_num_blocks = std::min((NUM_USED_BLKS(pic_size.x,m_bparams.Xbsep(),m_bparams.Xblen())), + m_predparams.XNumBlocks()); + + //Loop over all the block rows + pos.y = -m_bparams.Yoffset(); + for(int yblock = 0; yblock < y_num_blocks; ++yblock) + { + pos.x = -m_bparams.Xoffset(); + int xincr, xb_incr = 0; + //loop over all the blocks in a row + for(int xblock = 0 ; xblock < x_num_blocks; xblock+=xb_incr) + { + int split_mode = mv_data.SBSplit()[yblock/blocks_per_mb_row][xblock/blocks_per_mb_row]; + + int blk_x, blk_y = 1; + + switch (split_mode) + { + case 0: // processing superblock + blk_x = blocks_per_mb_row; + break; + case 1: // processing sub-superblock + blk_x = blocks_per_sb_row; + break; + case 2: // processing block + default: + blk_x = 1; + break; + } + + //Decide which weights to use. + if (pos.x >=0 && (xblock+blk_x) < x_num_blocks) + { + // block is entirely within picture in x direction + if (pos.y < 0) + wgt_idx = 1; + else if ((yblock+blk_y) < y_num_blocks) + wgt_idx = 4; + else + wgt_idx = 7; + } + else if (pos.x < 0) + { + // left edge of block is outside picture in x direction + if (pos.y < 0) + wgt_idx = 0; + else if ((yblock+blk_y) < y_num_blocks) + wgt_idx = 3; + else + wgt_idx = 6; + } + else + { + // right edge of block is outside picture in x direction + if (pos.y < 0) + wgt_idx = 2; + else if ((yblock+blk_y) < y_num_blocks) + wgt_idx = 5; + else + wgt_idx = 8; + } + + + block_mode = mv_data.Mode()[yblock][xblock]; + + TwoDArray<ValueType> *wt; + + if (split_mode == 0) //Block part of a MacroBlock + { + wt = &m_macro_block_weights[wgt_idx]; + xb_incr = blocks_per_mb_row; + } + else if (split_mode == 1) //Block part of a SubBlock + { + wt = &m_sub_block_weights[wgt_idx]; + xb_incr = blocks_per_sb_row; + } + else + { + wt = &m_block_weights[wgt_idx]; + xb_incr = 1; + } + xincr = m_bparams.Xbsep() * xb_incr; + + mv1 = (*mv_array1)[yblock][xblock]; + mv1.x >>= xscale_shift; + mv1.y >>= yscale_shift; + + mv2 = (*mv_array2)[yblock][xblock]; + mv2.x >>= xscale_shift; + mv2.y >>= yscale_shift; + + CompensateBlock(pic_data, pos, pic_size, block_mode, dcarray[yblock][xblock], ref1up, mv1, ref2up, mv2, *wt); + + //Increment the block horizontal position + pos.x += xincr; + + }//xblock + + // Update the pic data + // Use only the first Ybsep rows since the remaining rows are + // needed for the next row of blocks since we are using overlapped + // blocks motion compensation + if (m_add_or_sub == SUBTRACT) + { + int start_y = std::max(pic_data_out.FirstY() , pos.y) ; + int end_y = std::min (pic_data_out.FirstY() + pos.y + m_bparams.Ybsep() , y_end_data); + + if (yblock == y_num_blocks - 1) + { + end_y = pic_data_out.LengthY(); + if (end_y > y_end_data) + end_y = y_end_data; + + } + + for ( int i = start_y, pos_y = 0; i < end_y; i++, pos_y++) + { + ValueType *pic_row = pic_data[pos_y]; + ValueType *out_row = pic_data_out[i]; + + for ( int j =pic_data_out.FirstX(); j < x_end_data; ++j) + { + out_row[j] -= static_cast<ValueType>( (pic_row[j] + 32) >> 6 ); + } + + // Okay, we've done all the actual blocks. Now if the picture is further padded + // we need to set the padded values to zero beyond the last block in the row, + // for all the picture lines in the block row. Need only do this when we're + // subtracting. + + for (int j=pic_size.x; j<pic_data_out.LengthX() ; ++j ) + { + out_row[pic_data_out.FirstX()+j] = 0; + } + } + } + else // (m_add_or_sub == ADD) + { + int start_y = std::max(pic_data_out.FirstY() , pos.y) ; + int end_y = std::min (pic_data_out.FirstY() + pos.y + m_bparams.Ybsep() , pic_data_out.FirstY() + pic_data_out.LengthY()); + if (yblock == (y_num_blocks - 1)) + { + end_y += (m_bparams.Yblen()-m_bparams.Ybsep()); + if (end_y > pic_size.y) + end_y = pic_size.y; + } +#if defined (HAVE_MMX) + CompensateComponentAddAndShift_mmx (start_y, end_y, 6, pic_size, + pic_data, pic_data_out); +#else + for ( int i = start_y, pic_y = 0; i < end_y; i++, pic_y++) + { + ValueType *pic_row = pic_data[pic_y]; + ValueType *out_row = pic_data_out[i]; + + for ( int j =0; j < pic_size.x; j++) + { + out_row[j] += static_cast<ValueType>( (pic_row[j] + 32) >> 6 ); + } + // Pad the remaining pixels of the row with last truepic pixel val + for ( int j = pic_size.x; j < pic_data.LengthX(); j++) + { + out_row[j] = out_row[pic_size.x-1]; + } + } +#endif + } + //Increment the block vertical position + pos.y += m_bparams.Ybsep(); + + if (row_overlap) + { + // Copy the rows required to motion compensate the next row of + // blocks. This is usually Yblen-Ybsep rows. + memmove (pic_data[0], pic_data[save_from_row], (m_bparams.Yblen() - save_from_row)*pic_data.LengthX()*sizeof(ValueType)); + memset( pic_data[m_bparams.Yblen() - save_from_row], 0, save_from_row*pic_data.LengthX()*sizeof(ValueType) ); + save_from_row = m_bparams.Ybsep(); + } + else + { + // no row overlap. So reset pic_data to 0. + memset( pic_data[0], 0, m_bparams.Yblen()*pic_data.LengthX()*sizeof(ValueType) ); + } + }//yblock + + if ( m_add_or_sub == SUBTRACT) + { + // Finally, now we've done all the blocks, we must set all padded lines + // below the last row equal to 0, if we're subtracting + for ( int y=pic_size.y ; y<pic_data_out.LengthY() ; ++y ) + { + ValueType *out_row = pic_data_out[y]; + for ( int x=0 ; x<pic_data_out.LengthX() ; ++x ) + { + out_row[x] = 0; + } + + } + } + else if ( m_add_or_sub == ADD) + { + // Edge extension + // Finally, now we've done all the blocks, we must set all padded lines + // below the last row equal to same as last row, if we're adding + ValueType *last_row = &pic_data_out[pic_size.y-1][0]; + for ( int y=pic_size.y ; y<pic_data_out.LengthY() ; ++y ) + { + ValueType *out_row = pic_data_out[y]; + for ( int x=0 ; x<pic_data_out.LengthX() ; ++x ) + { + out_row[x] = last_row[x]; + } + + } + } +} + +void MotionCompensator::CompensateBlock( + TwoDArray<ValueType> &pic_data , + const ImageCoords& pos , + const ImageCoords& pic_size , + PredMode block_mode, + ValueType dc, + const PicArray &ref1up_data , + const MVector &mv1 , + const PicArray &ref2up_data , + const MVector &mv2 , + const TwoDArray<ValueType>& wt_array) +{ + //Coordinates in the image being written to. + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + const ImageCoords end_pos( std::min( pos.x + wt_array.LengthX() , pic_size.x ) , + std::min( pos.y + wt_array.LengthY() , pic_size.y ) ); + + // Check if we are within original picture bounds + if (start_pos.x >= end_pos.x || start_pos.y >= end_pos.y) + return; + + TwoDArray<ValueType> val1(end_pos.y - start_pos.y, end_pos.x-start_pos.x); + TwoDArray<ValueType> val2(end_pos.y - start_pos.y, end_pos.x-start_pos.x); + + if(block_mode == REF1_ONLY) + { + BlockPixelPred(val1, pos, pic_size, ref1up_data, mv1); + } + else if (block_mode == REF2_ONLY) + { + BlockPixelPred(val1, pos, pic_size, ref2up_data, mv2); + } + else if(block_mode == REF1AND2) + { + BlockPixelPred(val1, pos, pic_size, ref1up_data, mv1); + BlockPixelPred(val2, pos, pic_size, ref2up_data, mv2); + } + else + {//we have a DC block. + DCBlock(val1, dc); + } + /* + * Multiply the block by reference weights. Return result in val1 + */ + AdjustBlockByRefWeights(val1, val2, block_mode); + + /* + * Multiply the block by OBMC spatial weights. Return result val1 + */ + AdjustBlockBySpatialWeights(val1, pos, wt_array); + +#if !defined (HAVE_MMX) + for (int y = 0, py=0; y < val1.LengthY(); ++y, ++py) + { + for (int x = 0, px=start_pos.x; x < val1.LengthX(); ++x, ++px) + { + pic_data[py][px] += val1[y][x]; + } + } +#else + AddMCBlock_mmx(ImageCoords(start_pos.x, 0), pic_data, val1); +#endif +} + +void MotionCompensator::DCBlock( TwoDArray<ValueType> &block_data , + const ValueType dc) +{ + + //Quick process where we can just copy from the double size image. + ValueType *block_curr = &block_data[0][0]; + for(int y = 0; y < block_data.LengthY(); ++y) + { + for(int x=0; x < block_data.LengthX(); ++x, ++block_curr) + { + *block_curr = dc; + } + } +} + +void MotionCompensator::AdjustBlockByRefWeights ( + TwoDArray<ValueType>& val1_block, + TwoDArray<ValueType>& val2_block, + PredMode block_mode) +{ + // No need to multiply by reference weights if DC block + if (block_mode == INTRA) + return; + + if (m_predparams.CustomRefWeights()) + { + int ref_wt_prec_bias = 1; + for (int i = m_predparams.PictureWeightsBits()-1; i > 0; --i) + { + ref_wt_prec_bias <<= 1; + } + if (block_mode != REF1AND2) + { + for (int y = 0; y < val1_block.LengthY(); ++y) + { + for (int x = 0; x < val1_block.LengthX(); ++x) + { + val1_block[y][x] *= (m_predparams.Ref1Weight() + + m_predparams.Ref2Weight()); + } + } + } + else + { + for (int y = 0; y < val1_block.LengthY(); ++y) + { + for (int x = 0; x < val1_block.LengthX(); ++x) + { + val1_block[y][x] *= m_predparams.Ref1Weight(); + val2_block[y][x] *= m_predparams.Ref2Weight(); + val1_block[y][x] += val2_block[y][x]; + } + } + } + for (int y = 0; y < val1_block.LengthY(); ++y) + { + for (int x = 0; x < val1_block.LengthX(); ++x) + { + val1_block[y][x] = (val1_block[y][x] + ref_wt_prec_bias) >> m_predparams.PictureWeightsBits(); + } + } + } + else + { + // Default weights + if (block_mode == REF1AND2) + { + for (int y = 0; y < val1_block.LengthY(); ++y) + { + for (int x = 0; x < val1_block.LengthX(); ++x) + { + val1_block[y][x] = (val1_block[y][x] + val2_block[y][x] + 1)>>1; + } + } + } + // Nothing to do for other block modes when using default weights + } +} + +#if !defined (HAVE_MMX) +void MotionCompensator::AdjustBlockBySpatialWeights ( + TwoDArray<ValueType>& val_block, + const ImageCoords &pos, + const TwoDArray<ValueType> &wt_array) +{ + ImageCoords start_pos (std::max(0, pos.x), std::max(0, pos.y)); + ImageCoords wt_start (start_pos.x - pos.x, start_pos.y - pos.y); + + for (int y = 0, wt_y=wt_start.y; y < val_block.LengthY(); ++y, ++wt_y) + { + for (int x = 0, wt_x=wt_start.x; x < val_block.LengthX(); ++x, ++wt_x) + { + val_block[y][x] *= wt_array[wt_y][wt_x]; + } + } +} +#endif + +void MotionCompensator::CalculateWeights( int xbsep, int ybsep, + TwoDArray<ValueType>* wts_array) +{ + // Firstly calculate the non-weighted Weighting blocks. i,e, assuming that + // the picture_weight for each reference picture is 1. + // We can create all nine weighting blocks by calculating values + // for four blocks and mirroring them to generate the others. + CreateBlock( xbsep, ybsep, false , false , wts_array[0] ); + CreateBlock( xbsep, ybsep, false , true , wts_array[3] ); + CreateBlock( xbsep, ybsep, true , false , wts_array[1] ); + CreateBlock( xbsep, ybsep, true , true , wts_array[4] ); + + // Note order of flipping is important. + FlipX( wts_array[3] , wts_array[5] ); + FlipX( wts_array[0] , wts_array[2] ); + FlipY( wts_array[0] , wts_array[6] ); + FlipX( wts_array[6] , wts_array[8] ); + FlipY( wts_array[1] , wts_array[7] ); + +} +// Calculates a weighting block. +// bparams defines the block parameters so the relevant weighting arrays can +// be created. +// FullX and FullY refer to whether the weight should be adjusted for the +// edge of an image. +// eg. 1D Weighting shapes in x direction + +// FullX true FullX false +// *** ******** +// * * * +// * * * +//* * * +void MotionCompensator::CreateBlock( int xbsep, int ybsep, + bool FullX , bool FullY , + TwoDArray<ValueType>& WeightArray) +{ + // Create temporary arrays + int xblen = WeightArray.LengthX(); + int yblen = WeightArray.LengthY(); + + OneDArray<ValueType> HWts( xblen ); + OneDArray<ValueType> VWts( yblen ); + + // Window in the x direction + int xoffset = (xblen - xbsep)/2; + if ( xoffset != 1 ) + { + for(int x = 0; x < 2*xoffset; ++x) + { + HWts[x] = 1 + (6*x + xoffset-1)/(2*xoffset-1); + HWts[x+xbsep] = 8 - HWts[x]; + }// x + } + else + { + HWts[0]=HWts[1+xbsep]=3; + HWts[1]=HWts[xbsep]=5; + } + for (int x = 2*xoffset; x < xbsep; ++x) + HWts[x] = 8; + + // Window in the y direction + int yoffset = (yblen - ybsep)/2; + if ( yoffset != 1 ) + { + for(int y = 0; y < 2*yoffset; ++y) + { + VWts[y] = 1 + (6 *y + yoffset-1)/(2*yoffset-1); + VWts[y+ybsep] = 8 - VWts[y]; + }// y + } + else + { + VWts[0]=VWts[1+ybsep]=3; + VWts[1]=VWts[ybsep]=5; + } + for (int y = 2*yoffset; y < ybsep; ++y) + VWts[y] = 8; + + // Now reflect or pad, as appropriate + if (!FullX) + { + for( int x = 0; x < 2*xoffset; ++x) + HWts[x] = 8; + } + + // Reflect or pad, as appropriate + if (!FullY) + { + for( int y = 0 ; y < 2*yoffset; ++y) + VWts[y] = 8; + } + + for(int y = 0; y < yblen; ++y) + { + for(int x = 0; x < xblen; ++x) + { + WeightArray[y][x] = VWts[y] * HWts[x]; + }// x + }// y +} + +// Flips the values in an array in the x direction. +void MotionCompensator::FlipX( const TwoDArray<ValueType>& Original , + TwoDArray<ValueType>& Flipped) +{ + int yblen = Original.LengthY(); + int xblen = Original.LengthX(); + for(int y = 0; y < yblen; ++y) + { + for(int x = 0; x < xblen; ++x) + { + Flipped[y][x] = Original[y][(xblen-1) - x]; + }// y + }// x +} + +// Flips the values in an array in the y direction. +void MotionCompensator::FlipY( const TwoDArray<ValueType>& Original , + TwoDArray<ValueType>& Flipped) +{ + int yblen = Original.LengthY(); + int xblen = Original.LengthX(); + for(int y = 0; y < yblen; ++y) + { + for(int x = 0; x < xblen; ++x) + { + Flipped[y][x] = Original[(yblen-1) - y][x]; + }// y + }// x +} + + +// Concrete Sub-Classes +// Class that implement the BlockPixelPred function based on pixel +// precision values + +// Motion Compesation class that provides pixel precision compensation + +MotionCompensator_Pixel::MotionCompensator_Pixel( const PicturePredParams &ppp ) : + MotionCompensator( ppp ) +{} + +void MotionCompensator_Pixel::BlockPixelPred( + TwoDArray<ValueType> &block_data , + const ImageCoords& pos, + const ImageCoords& pic_size , + const PicArray &refup_data , + const MVector &mv) +{ + //Coordinates in the image being written to. + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + + //Where to start in the upconverted image - scaled since ref is upconverted + const ImageCoords ref_start( (start_pos.x + mv.x)<<1 , (start_pos.y + mv.y)<<1 ); + + //An additional stage to make sure the block to be copied does not fall outside + //the reference image. + const int refXlen = refup_data.LengthX(); + //const int refYlen = refup_data.LengthY(); + const int trueRefXlen = (pic_size.x << 1) - 1; + const int trueRefYlen = (pic_size.y << 1) - 1; + bool do_bounds_checking = false; + + //Check if there are going to be any problems copying the block from + //the upvconverted reference image. + if( ref_start.x < 0 ) + do_bounds_checking = true; + else if( ref_start.x + ((block_data.LengthX() - 1)<<1 ) >= trueRefXlen ) + do_bounds_checking = true; + if( ref_start.y < 0 ) + do_bounds_checking = true; + else if( ref_start.y + ((block_data.LengthY() - 1)<<1 ) >= trueRefYlen) + do_bounds_checking = true; + + ValueType *block_curr = &block_data[0][0]; + if( !do_bounds_checking ) + { + ValueType *refup_curr = &refup_data[ref_start.y][ref_start.x]; + const int refup_next( 2*(refXlen - block_data.LengthX()) ); // - go down a row and back up + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = *refup_curr; + }// x + }// y + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + + for( int y=0, ry=ref_start.y, by=BChk(ry,trueRefYlen); + y < block_data.LengthY(); ++y, ry+=2 , by=BChk(ry,trueRefYlen) ) + { + for( int x=0 , rx=ref_start.x , bx=BChk(rx,trueRefXlen); + x <block_data.LengthX() ; ++x, ++block_curr, rx+=2 , bx=BChk(rx,trueRefXlen) ) + { + *block_curr = refup_data[by][bx]; + }// x + }// y + + } +} + + +// Motion Compesation class that provides half-pixel precision compensation +MotionCompensator_HalfPixel::MotionCompensator_HalfPixel( const PicturePredParams &ppp ) : + MotionCompensator( ppp ) +{} + +#if !defined (HAVE_MMX) +void MotionCompensator_HalfPixel::BlockPixelPred( + TwoDArray<ValueType> &block_data , + const ImageCoords& pos , + const ImageCoords& pic_size , + const PicArray &refup_data , + const MVector &mv) +{ + //Where to start in the upconverted image + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + const ImageCoords ref_start( ( start_pos.x<<1 ) + mv.x ,( start_pos.y<<1 ) + mv.y ); + + //An additional stage to make sure the block to be copied does not fall + //outsidethe reference image. + const int refXlen = refup_data.LengthX(); + //const int refYlen = refup_data.LengthY(); + const int trueRefXlen = (pic_size.x << 1) - 1; + const int trueRefYlen = (pic_size.y << 1) - 1; + + bool do_bounds_checking = false; + + //Check if there are going to be any problems copying the block from + //the upvconverted reference image. + + if( ref_start.x < 0 ) + do_bounds_checking = true; + else if( ref_start.x + ((block_data.LengthX() -1 )<<1 ) >= trueRefXlen ) + do_bounds_checking = true; + if( ref_start.y < 0 ) + do_bounds_checking = true; + else if( ref_start.y + ((block_data.LengthY() - 1 )<<1 ) >= trueRefYlen) + do_bounds_checking = true; + + ValueType *block_curr = &block_data[0][0]; + + if( !do_bounds_checking ) + { + ValueType *refup_curr = &refup_data[ref_start.y][ref_start.x]; + const int refup_next( (refXlen - block_data.LengthX())*2 );// go down 2 rows and back up + + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = refup_curr[0]; + } + } + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=0, ry=ref_start.y, by=BChk(ry,trueRefYlen); + y<block_data.LengthY(); ++y, ry+=2 , by=BChk(ry,trueRefYlen)) + { + for( int x=0 , rx=ref_start.x , bx=BChk(rx,trueRefXlen); + x<block_data.LengthX() ; + ++x, ++block_curr, rx+=2 , bx=BChk(rx,trueRefXlen)) + { + *block_curr = refup_data[by][bx]; + }// x + }// y + } +} +#endif + +// Motion Compesation class that provides quarter-pixel precision compensation +MotionCompensator_QuarterPixel::MotionCompensator_QuarterPixel( const PicturePredParams &ppp ) : + MotionCompensator( ppp ) +{} + +#if !defined (HAVE_MMX) +void MotionCompensator_QuarterPixel::BlockPixelPred( + TwoDArray<ValueType> &block_data , + const ImageCoords& pos , + const ImageCoords& pic_size , + const PicArray &refup_data , + const MVector &mv) +{ + // Set up the start point in the reference image by rounding the motion vector + // to 1/2 pel accuracy.NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>1 , mv.y>>1 ); + + //Get the remainder after rounding. NB rmdr values always 0 or 1 + const MVector rmdr( mv.x & 1 , mv.y & 1 ); + + //Where to start in the upconverted image + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + const ImageCoords ref_start( ( start_pos.x<<1 ) + roundvec.x ,( start_pos.y<<1 ) + roundvec.y ); + + //An additional stage to make sure the block to be copied does not fall outside + //the reference image. + const int refXlen = refup_data.LengthX(); + //const int refYlen = refup_data.LengthY(); + const int trueRefXlen = (pic_size.x<<1) - 1; + const int trueRefYlen = (pic_size.y<<1) - 1; + + ValueType *block_curr = &block_data[0][0]; + + bool do_bounds_checking = false; + //Check if there are going to be any problems copying the block from + //the upvconverted reference image. + if( ref_start.x < 0 ) + do_bounds_checking = true; + else if( ref_start.x + (block_data.LengthX()<<1 ) >= trueRefXlen ) + do_bounds_checking = true; + if( ref_start.y < 0 ) + do_bounds_checking = true; + else if( ref_start.y + (block_data.LengthY()<<1 ) >= trueRefYlen ) + do_bounds_checking = true; + + if( !do_bounds_checking ) + { + ValueType *refup_curr = &refup_data[ref_start.y][ref_start.x]; + const int refup_next( ( refXlen - block_data.LengthX() )*2 ); //go down 2 rows and back to beginning of block line + if( rmdr.x == 0 && rmdr.y == 0 ) + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = refup_curr[0]; + } + } + } + else if( rmdr.y == 0 ) + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = (refup_curr[0] + refup_curr[1] + 1) >> 1; + } + } + } + else if( rmdr.x == 0 ) + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = ( refup_curr[0] + refup_curr[refXlen] + 1 ) >> 1; + } + } + } + else + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = ( refup_curr[0] + refup_curr[1] + + refup_curr[refXlen+0] + + refup_curr[refXlen+1] + 2 ) >> 2; + } + } + } + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + + //weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (2 - rmdr.x) * (2 - rmdr.y), //tl + rmdr.x * (2 - rmdr.y), //tr + (2 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + + for(int c = 0, uY = ref_start.y,BuY=BChk(uY,trueRefYlen),BuY1=BChk(uY+1,trueRefYlen); + c < block_data.LengthY(); ++c, uY += 2,BuY=BChk(uY,trueRefYlen),BuY1=BChk(uY+1,trueRefYlen)) + { + for(int l = 0, uX = ref_start.x,BuX=BChk(uX,trueRefXlen),BuX1=BChk(uX+1,trueRefXlen); + l < block_data.LengthX(); ++l, uX += 2,BuX=BChk(uX,trueRefXlen),BuX1=BChk(uX+1,trueRefXlen)) + { + + block_data[c][l] = ( linear_wts[0] * refup_data[BuY][BuX] + + linear_wts[1] * refup_data[BuY][BuX1] + + linear_wts[2] * refup_data[BuY1][BuX] + + linear_wts[3] * refup_data[BuY1][BuX1] + + 2 + ) >> 2; + }//l + }//c + + } +} +#endif + +// Motion Compesation class that provides one eighth-pixel precision +// compensation +MotionCompensator_EighthPixel::MotionCompensator_EighthPixel( const PicturePredParams &ppp ) : + MotionCompensator( ppp ) +{} + +void MotionCompensator_EighthPixel::BlockPixelPred( + TwoDArray<ValueType> &block_data , + const ImageCoords& pos , + const ImageCoords& pic_size , + const PicArray &refup_data , + const MVector &mv) +{ + + //Set up the start point in the reference image by rounding the motion vector + //NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>2 , mv.y>>2 ); + + //Get the remainder after rounding. NB rmdr values always 0,1,2 or 3 + const MVector rmdr( mv.x & 3 , mv.y & 3 ); + + //Where to start in the upconverted image + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + const ImageCoords ref_start( ( start_pos.x<<1 ) + roundvec.x ,( start_pos.y<<1 ) + roundvec.y ); + + //weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (4 - rmdr.x) * (4 - rmdr.y), //tl + rmdr.x * (4 - rmdr.y), //tr + (4 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + //An additional stage to make sure the block to be copied does not fall outside + //the reference image. + const int refXlen = refup_data.LengthX(); + //const int refYlen = refup_data.LengthY(); + const int trueRefXlen = (pic_size.x << 1) - 1; + const int trueRefYlen = (pic_size.y << 1) - 1; + bool do_bounds_checking = false; + + //Check if there are going to be any problems copying the block from + //the upvconverted reference image. + if( ref_start.x < 0 ) + do_bounds_checking = true; + else if( ref_start.x + (block_data.LengthX()<<1 ) >= trueRefXlen ) + do_bounds_checking = true; + if( ref_start.y < 0 ) + do_bounds_checking = true; + else if( ref_start.y + (block_data.LengthY()<<1 ) >= trueRefYlen) + do_bounds_checking = true; + + + if( !do_bounds_checking ) + { + ValueType *block_curr = &block_data[0][0]; + ValueType *refup_curr = &refup_data[ref_start.y][ref_start.x]; + + const int refup_next = (refup_data.LengthX() - block_data.LengthX() )*2; //go down 2 rows and back up + + if( rmdr.x == 0 && rmdr.y == 0 ) + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = refup_curr[0]; + } + } + } + else if( rmdr.y == 0 ) + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = ( + linear_wts[0] * refup_curr[0] + + linear_wts[1] * refup_curr[1] + + 8 + ) >> 4; + } + } + } + else if( rmdr.x == 0 ) + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = ( + linear_wts[0] * refup_curr[0] + + linear_wts[2] * refup_curr[refXlen+0] + + 8 + ) >> 4; + } + } + } + else + { + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = ( + linear_wts[0] * refup_curr[0] + + linear_wts[1] * refup_curr[1] + + linear_wts[2] * refup_curr[refXlen+0] + + linear_wts[3] * refup_curr[refXlen+1] + + 8 + ) >> 4; + } + } + } + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + + for(int c = 0, uY = ref_start.y,BuY=BChk(uY,trueRefYlen),BuY1=BChk(uY+1,trueRefYlen); + c < block_data.LengthY(); ++c, uY += 2,BuY=BChk(uY,trueRefYlen),BuY1=BChk(uY+1,trueRefYlen)) + { + for(int l = 0, uX = ref_start.x,BuX=BChk(uX,trueRefXlen),BuX1=BChk(uX+1,trueRefXlen); + l < block_data.LengthX(); + ++l, uX += 2,BuX=BChk(uX,trueRefXlen),BuX1=BChk(uX+1,trueRefXlen)) + { + + block_data[c][l] = ( + linear_wts[0] * refup_data[BuY][BuX] + + linear_wts[1] * refup_data[BuY][BuX1] + + linear_wts[2] * refup_data[BuY1][BuX] + + linear_wts[3] * refup_data[BuY1][BuX1] + + 8 + ) >> 4; + }//l + }//c + + } + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp.h new file mode 100644 index 000000000..7974cc1db --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp.h @@ -0,0 +1,301 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mot_comp.h,v 1.22 2008/08/27 00:17:11 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Richard Felton (Original Author), +* Thomas Davies +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +// Motion Compensation routines. +// Supports different sizes of blocks as long as the parameters +// describing them are 'legal'. Blocks overlap the edge of the image +// being written to but blocks in the reference image are forced to +// lie completely within the image bounds. + +#ifndef _INCLUDED_MOT_COMP +#define _INCLUDED_MOT_COMP + +#include <cstdlib> +#include <ctime> +#include <iostream> +#include <vector> +#include <libdirac_common/common.h> +#include <libdirac_common/upconvert.h> +#include <libdirac_common/motion.h> +#include <libdirac_common/picture_buffer.h> + +namespace dirac +{ + class PictureBuffer; + class Picture; + + //! Abstract Motion compensator class. + /*! + Motion compensator class, for doing motion compensation with two + references and overlapped blocks, using raised-cosine roll-off. + This is an abstract class. It must be sub-classed and the + BlockPixelPred must be defined in the sub-classes. + */ + class MotionCompensator + { + + public: + //! Constructor. + /*! + Constructor initialises using codec parameters. + */ + MotionCompensator( const PicturePredParams &ppp ); + //! Destructor + virtual ~MotionCompensator(); + + //! Convenience function to perform motion compensation on a picture + /*! + Static function that motion compensates a picture. It uses the + MV precision value in the PicturePredParams to instantiate the + appropriate MotionCompensation sub-class. + \param ppp Picture prediction parameters + \param direction whether we're subtracting or adding + \param mv_data the motion vector data + \param in_pic Pointer to picture being motion compensated + \param refptr Array of pointers to reference pictures. + */ + static void CompensatePicture ( const PicturePredParams &ppp, + const AddOrSub direction , + const MvData& mv_data, + Picture* in_pic , + Picture* refptr[2]); + + //! Compensate a picture + /*! + Perform motion compensated addition/subtraction on a picture using + parameters + \param direction whether we're subtracting or adding + ` \param mv_data the motion vector data + \param in_pic Pointer to picture being motion compensated + \param refsptr Array of pointers to reference pictures. + */ + void CompensatePicture( const AddOrSub direction , + const MvData& mv_data, + Picture* in_pic , + Picture* refsptr[2] ); + + private: + //private, body-less copy constructor: this class should not be copied + MotionCompensator( const MotionCompensator& cpy ); + //private, body-less assignment=: this class should not be assigned + MotionCompensator& operator=( const MotionCompensator& rhs ); + + //functions + + //! Motion-compensate a component + void CompensateComponent( Picture* pic , + Picture* refsptr[2] , + const MvData& mv_data , const CompSort cs); + + //! Recalculate the weight matrix and store other key block related parameters. + //! DC-compensate an individual block + void DCBlock( TwoDArray<ValueType> &block_data , + const ValueType dc); + void ReConfig(); + + // Calculates a weighting arrays blocks. + void CalculateWeights(int xbsep, int ybsep, TwoDArray<ValueType>* wt_array); + + //! Calculates a weighting block. + /*! + Params defines the block parameters so the relevant weighting + arrays can be created. FullX and FullY refer to whether the + weight should be adjusted for the edge of an image. eg. 1D + Weighting shapes in x direction + FullX true FullX false + *** ******** + * * * + * * * + * * * + */ + void CreateBlock(int xbsep, int ybsep, bool FullX, bool FullY, TwoDArray<ValueType>& WeightArray); + + //! Flips the values in an array in the x direction + void FlipX(const TwoDArray<ValueType>& Original, TwoDArray<ValueType>& Flipped); + + //! Flips the values in an array in the y direction. + void FlipY(const TwoDArray<ValueType>& Original, TwoDArray<ValueType>& Flipped); + + virtual void CompensateBlock( TwoDArray<ValueType>& pic_data , + const ImageCoords& pos , + const ImageCoords &orig_pic_size, + PredMode block_mode, + ValueType dc, + const PicArray& ref1up_data , + const MVector& mv1 , + const PicArray& ref2up_data , + const MVector& mv2 , + const TwoDArray<ValueType>& Weights ); + //! Predict pixels in a block. Pure virtual. SubClasses need to define it + virtual void BlockPixelPred( TwoDArray<ValueType>& block_data , + const ImageCoords& pos, + const ImageCoords &orig_pic_size, + const PicArray& refup_data , + const MVector& mv) = 0; + + // Adjust the block value based on reference weights + /* + * Adjust the block value based on reference weights of each + * reference picture. + * val1_block - Block predicted from a single reference picture + * val2_block - Block predicted from second reference picture + * mode is REF1AND2 + * block_mode - Block prediction mode. + * + * On return, val1_block will contain the weight reference weight + * adjusted block values + */ + void AdjustBlockByRefWeights (TwoDArray<ValueType>& val1_block, + TwoDArray<ValueType>& val2_block, + PredMode block_mode); + + // Adjust the block value based spatial weighting matrix + /* + * Adjust the block value based on spatial weighting matrix + * val_block - Predicted block + * pos - position of top lef corner of block in picture + * wt_array - spatial weighting matrix + * + * On return, val_block will contain the spatial weight adjusted block + * values + */ + void AdjustBlockBySpatialWeights (TwoDArray<ValueType>& val_block, + const ImageCoords &pos, + const TwoDArray<ValueType> &wt_array); + protected: + //variables + + //! The codec parameters + PicturePredParams m_predparams; + + //! The chroma format + ChromaFormat m_cformat; + bool luma_or_chroma; //true if we're doing luma, false if we're coding chroma + + // A marker saying whether we're doing MC addition or subtraction + AddOrSub m_add_or_sub; + + // Block information + OLBParams m_bparams; + // Arrays of block weights + TwoDArray<ValueType>* m_block_weights; + // Arrays of super block weights + TwoDArray<ValueType>* m_macro_block_weights; + // Arrays of sub super block weights + TwoDArray<ValueType>* m_sub_block_weights; + }; + + //! Pixel precision Motion compensator class. + class MotionCompensator_Pixel : public MotionCompensator + { + + public: + //! Constructor. + /*! + Constructor initialises using codec parameters. + */ + MotionCompensator_Pixel (const PicturePredParams &ppp); + + private: + //! Motion-compensate a block. + virtual void BlockPixelPred( TwoDArray<ValueType>& block_data , + const ImageCoords& pos, + const ImageCoords &orig_pic_size, + const PicArray& refup_data , + const MVector& mv); + }; + + //! Half Pixel precision Motion compensator class. + class MotionCompensator_HalfPixel : public MotionCompensator + { + public: + //! Constructor. + /*! + Constructor initialises using codec parameters. + */ + MotionCompensator_HalfPixel (const PicturePredParams &ppp); + private: + //! Motion-compensate a block. + virtual void BlockPixelPred( TwoDArray<ValueType>& block_data , + const ImageCoords& pos, + const ImageCoords &orig_pic_size, + const PicArray& refup_data , + const MVector& mv); + }; + + //! Quarter Pixel precision Motion compensator class. + class MotionCompensator_QuarterPixel : public MotionCompensator + { + public: + //! Constructor. + /*! + Constructor initialises using codec parameters. + */ + MotionCompensator_QuarterPixel (const PicturePredParams &ppp); + private: + //! Motion-compensate a block. + virtual void BlockPixelPred( TwoDArray<ValueType>& block_data , + const ImageCoords& pos, + const ImageCoords &orig_pic_size, + const PicArray& refup_data , + const MVector& mv); + }; + + //! Eighth Pixel precision Motion compensator class. + class MotionCompensator_EighthPixel : public MotionCompensator + { + public: + //! Constructor. + /*! + Constructor initialises using codec parameters. + */ + MotionCompensator_EighthPixel (const PicturePredParams &ppp); + private: + //! Motion-compensate a block. + virtual void BlockPixelPred( TwoDArray<ValueType>& block_data , + const ImageCoords& pos, + const ImageCoords &orig_pic_size, + const PicArray& refup_data , + const MVector& mv); + }; + + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp_mmx.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp_mmx.cpp new file mode 100644 index 000000000..8c1cd0fa7 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp_mmx.cpp @@ -0,0 +1,470 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mot_comp_mmx.cpp,v 1.9 2008/01/09 10:50:23 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#if defined(HAVE_MMX) +#include <mmintrin.h> +#include <libdirac_common/mot_comp.h> +#include <libdirac_common/mot_comp_mmx.h> +#include <libdirac_common/motion.h> +#include <libdirac_common/dirac_assertions.h> +using namespace dirac; + +inline void check_active_columns( + int x, int xmax, ValueType act_cols1[4], + ValueType act_cols2[4], ValueType *row1, ValueType *row2) +{ + // check if we need any clipping + if (x >= 0 && (x+3) < xmax) { + // special case, nothing to do + memcpy(act_cols1, &row1[x], 4 * sizeof(ValueType)); + memcpy(act_cols2, &row2[x], 4 * sizeof(ValueType)); + } + else + { + act_cols1[0] = row1[BChk(x,xmax)]; + act_cols2[0] = row2[BChk(x,xmax)]; + act_cols1[1] = row1[BChk(x+1,xmax)]; + act_cols2[1] = row2[BChk(x+1,xmax)]; + act_cols1[2] = row1[BChk(x+2,xmax)]; + act_cols2[2] = row2[BChk(x+2,xmax)]; + act_cols1[3] = row1[BChk(x+3,xmax)]; + act_cols2[3] = row2[BChk(x+3,xmax)]; + } +} + +void MotionCompensator_QuarterPixel::BlockPixelPred( + TwoDArray<ValueType> &block_data , + const ImageCoords& pos , + const ImageCoords& orig_pic_size , + const PicArray &refup_data , + const MVector &mv) +{ + // Set up the start point in the reference image by rounding the motion vector + // to 1/2 pel accuracy.NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>1 , mv.y>>1 ); + + //Get the remainder after rounding. NB rmdr values always 0 or 1 + const MVector rmdr( mv.x & 1 , mv.y & 1 ); + + //Where to start in the upconverted image + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + // check that we are doing MC within true pic boundaries + if (start_pos.x >= orig_pic_size.x || start_pos.y >= orig_pic_size.y) + return; + const ImageCoords ref_start( ( start_pos.x<<1 ) + roundvec.x ,( start_pos.y<<1 ) + roundvec.y ); + + //An additional stage to make sure the block to be copied does not fall outside + //the reference image. + const int refXlen = refup_data.LengthX(); + const int trueRefXlen = (orig_pic_size.x << 1) - 1; + const int trueRefYlen = (orig_pic_size.y << 1) - 1; + + ValueType *block_curr = &block_data[0][0]; + + bool do_bounds_checking = false; + //Check if there are going to be any problems copying the block from + //the upvconverted reference image. + if( ref_start.x < 0 ) + do_bounds_checking = true; + else if( ref_start.x + (block_data.LengthX()<<1 ) >= trueRefXlen ) + do_bounds_checking = true; + if( ref_start.y < 0 ) + do_bounds_checking = true; + else if( ref_start.y + (block_data.LengthY()<<1 ) >= trueRefYlen) + do_bounds_checking = true; + + if( !do_bounds_checking ) + { + int stopX = (block_data.LengthX()>>2)<<2; + ValueType *refup_curr = &refup_data[ref_start.y][ref_start.x]; + const int refup_next( ( refXlen - block_data.LengthX() )*2 ); //go down 2 rows and back to beginning of block line + if( rmdr.x == 0 && rmdr.y == 0 ) + { + __m64 m1, m2; + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + int x; + for( x=0; x < stopX; x+=4, block_curr+=4, refup_curr+=8 ) + { + m1 = _mm_unpacklo_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + m2 = _mm_unpackhi_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + // *block_curr = refup_curr[0] + *(__m64 *)block_curr = _mm_unpacklo_pi16 (m1, m2); + } + // Mopup the last value + for ( x=stopX ; x < block_data.LengthX(); ++x) + { + *block_curr = *refup_curr; + ++block_curr; + refup_curr+=2; + } + } + _mm_empty(); + } + else if( rmdr.y == 0 ) + { + __m64 round = _mm_set_pi16 (1, 1, 1, 1); + __m64 m1, m2, m3; + + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + int x; + for( x=0; x < stopX; x+=4, block_curr+=4, refup_curr+=8 ) + { + m1 = _mm_unpacklo_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + m3 = _mm_unpackhi_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + m2 = _mm_unpackhi_pi16 (m1, m3); + m1 = _mm_unpacklo_pi16 (m1, m3); + + // (refup_curr[0] + refup_curr[1] + 1)>>1 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_add_pi16 (m1, round); + *(__m64 *)block_curr = _mm_srai_pi16 (m1, 1); + } + + // Mopup the last value + for ( x=stopX; x < block_data.LengthX(); ++x) + { + *block_curr = (( *refup_curr + + *(refup_curr+1) + 1 + ) >> 1); + ++block_curr; + refup_curr+=2; + } + } + _mm_empty(); + } + else if( rmdr.x == 0 ) + { + __m64 round = _mm_set_pi16 (1, 1, 1, 1); + __m64 m1, m2, m3; + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + int x; + for( x = 0; x < stopX; x+=4, block_curr+=4, refup_curr+=8 ) + { + m1 = _mm_unpacklo_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + m2 = _mm_unpackhi_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + // m1 now contains r00 r02 r04 r06 + m1 = _mm_unpacklo_pi16 (m1, m2); + + m3 = _mm_unpacklo_pi16 (*(__m64 *)(refup_curr+refXlen), *(__m64 *)(refup_curr+refXlen+4)); + m2 = _mm_unpackhi_pi16 (*(__m64 *)(refup_curr+refXlen), *(__m64 *)(refup_curr+refXlen+4)); + // m1 now contains r10 r12 r14 r16 + m2 = _mm_unpacklo_pi16 (m3, m2); + + // (refup_curr[0] + (refup_curr+refXlen)[0] + 1)>>1 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_add_pi16 (m1, round); + *(__m64 *)block_curr = _mm_srai_pi16 (m1, 1); + } + for ( x=stopX; x < block_data.LengthX(); ++x) + { + *block_curr = (( *refup_curr + *(refup_curr+refXlen) + + 1 + ) >> 1); + ++block_curr; + refup_curr+=2; + } + } + _mm_empty(); + } + else + { + __m64 round = _mm_set_pi16 (2, 2, 2, 2); + __m64 m1, m2, m3; + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + int x; + for( x = 0; x < stopX; x+=4, block_curr+=4, refup_curr+=8 ) + { + m1 = _mm_add_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+refXlen)); + m2 = _mm_add_pi16 (*(__m64 *)(refup_curr+4), *(__m64 *)(refup_curr+refXlen+4)); + m3 = _mm_unpacklo_pi16 (m1, m2); + m1 = _mm_unpackhi_pi16 (m1, m2); + + m2 = _mm_unpackhi_pi16 (m3, m1); + m1 = _mm_unpacklo_pi16 (m3, m1); + + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_add_pi16 (m1, round); + *(__m64 *)block_curr = _mm_srai_pi16 (m1, 2); + } + for ( x=stopX; x < block_data.LengthX(); ++x) + { + *block_curr = (( *refup_curr + + *(refup_curr+1) + + *(refup_curr+refXlen) + + *(refup_curr+refXlen+1) + + 2 + ) >> 2); + ++block_curr; + refup_curr+=2; + } + } + _mm_empty(); + } + } + else + { + // We're 2doing bounds checking because we'll fall off the edge of the reference otherwise. + + //weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (2 - rmdr.x) * (2 - rmdr.y), //tl + rmdr.x * (2 - rmdr.y), //tr + (2 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + ValueType act_cols1[4], act_cols2[4]; + int uX, uY, c, l; + for(c = 0, uY = ref_start.y; c < block_data.LengthY(); ++c, uY += 2) + { + for(l = 0, uX=ref_start.x; l < block_data.LengthX(); ++l, ++block_curr, uX += 2) + { + check_active_columns(uX, trueRefXlen, act_cols1, act_cols2, refup_data[BChk(uY, trueRefYlen)], refup_data[BChk(uY+1, trueRefYlen)]); + + *block_curr = (( linear_wts[0] * act_cols1[0] + + linear_wts[1] * act_cols1[1] + + linear_wts[2] * act_cols2[0] + + linear_wts[3] * act_cols2[1] + + 2 + ) >> 2); + }//l + }//c + } +} + +void MotionCompensator_HalfPixel::BlockPixelPred( + TwoDArray<ValueType> &block_data , + const ImageCoords& pos , + const ImageCoords& orig_pic_size , + const PicArray &refup_data , + const MVector &mv) +{ + //Where to start in the upconverted image + const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) ); + const ImageCoords ref_start( ( start_pos.x<<1 ) + mv.x ,( start_pos.y<<1 ) + mv.y ); + + //An additional stage to make sure the block to be copied does not fall outside + //the reference image. + const int refXlen = refup_data.LengthX(); + //const int refYlen = refup_data.LengthY(); + const int trueRefXlen = (orig_pic_size.x << 1) - 1; + const int trueRefYlen = (orig_pic_size.y << 1) - 1; + + bool do_bounds_checking = false; + + //Check if there are going to be any problems copying the block from + //the upvconverted reference image. + + if( ref_start.x < 0 ) + do_bounds_checking = true; + else if( ref_start.x + ((block_data.LengthX() - 1 )<<1 ) >= trueRefXlen ) + do_bounds_checking = true; + if( ref_start.y < 0 ) + do_bounds_checking = true; + else if( ref_start.y + ((block_data.LengthY() - 1 )<<1 ) >= trueRefYlen) + do_bounds_checking = true; + + ValueType *block_curr = &block_data[0][0]; + + if( !do_bounds_checking ) + { + ValueType *refup_curr = &refup_data[ref_start.y][ref_start.x]; + const int refup_next( (refXlen - block_data.LengthX())*2 );// go down 2 rows and back up +#if 1 + int stopX = (block_data.LengthX()>>2)<<2; + { + __m64 m1, m2; + + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + int x; + for( x=0; x < stopX; x+=4, block_curr+=4, refup_curr+=8 ) + { + m1 = _mm_unpacklo_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + m2 = _mm_unpackhi_pi16 (*(__m64 *)refup_curr, *(__m64 *)(refup_curr+4)); + *(__m64 *)block_curr = _mm_unpacklo_pi16 (m1, m2); + } + // Mopup the last value + for ( x=stopX ; x < block_data.LengthX(); ++x) + { + *block_curr = *refup_curr; + ++block_curr; + refup_curr+=2; + } + } + _mm_empty(); + } +#else + + for( int y=0; y < block_data.LengthY(); ++y, refup_curr+=refup_next ) + { + for( int x=0; x < block_data.LengthX(); ++x, ++block_curr, refup_curr+=2 ) + { + *block_curr = refup_curr[0]; + } + } +#endif + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=0, ry=ref_start.y, by=BChk(ry,trueRefYlen); + y<block_data.LengthY(); + ++y, ry+=2,by=BChk(ry,trueRefYlen)) + { + for( int x=0 , rx=ref_start.x , bx=BChk(rx,trueRefXlen); + x<block_data.LengthX() ; + ++x, ++block_curr, rx+=2 , bx=BChk(rx,trueRefXlen)) + { + *block_curr = refup_data[by][bx]; + }// x + }// y + } +} + +void MotionCompensator::AdjustBlockBySpatialWeights ( + TwoDArray<ValueType>& val_block, + const ImageCoords &pos, + const TwoDArray<ValueType> &wt_array) +{ + ImageCoords start_pos (std::max(0, pos.x), std::max(0, pos.y)); + ImageCoords wt_start (start_pos.x - pos.x, start_pos.y - pos.y); + + ValueType *val_curr = &val_block[0][0]; + ValueType *wt_curr = &wt_array[wt_start.y][wt_start.x]; + + // go down at row and back to beginning of weights line + const int wt_next = wt_array.LengthX() - val_block.LengthX(); + + const int stopX = (val_block.LengthX()>>2)<<2; + + for ( int j = 0; j < val_block.LengthY(); ++j, wt_curr += wt_next) + { + for ( int i = 0; i < stopX; i+=4, val_curr+=4, wt_curr+=4) + { + /* + * NOTE: Using only the low 16 bits of the result of multiplication + * by weights because the result is supposed to fit in 16 bit + * words. For some weights could result in overflow and errors + */ + __m64 *out = (__m64 *)val_curr; + *out = _mm_mullo_pi16 (*(__m64 *)val_curr, *(__m64 *)wt_curr); + } + for (int i = stopX; i < val_block.LengthX(); ++i, ++val_curr, ++wt_curr) + { + *val_curr = *val_curr * *wt_curr; + } + } + _mm_empty(); +} + +namespace dirac +{ + void CompensateComponentAddAndShift_mmx (int start_y, int end_y, + int weight_bits, + const ImageCoords& orig_pic_size, + TwoDArray<ValueType> &comp_data, + PicArray &pic_data_out) + { + if (start_y >= end_y) + return; + const int round_val = 1<<(weight_bits-1); + int stopX = pic_data_out.FirstX() + ((orig_pic_size.x>>2)<<2); + int x_end_truepic_data = pic_data_out.FirstX() + orig_pic_size.x; + int x_end_data = pic_data_out.FirstX() + pic_data_out.LengthX(); + __m64 mround_val = _mm_set_pi16 (round_val, round_val, round_val, round_val); + ValueType *pic_row = &comp_data[0][comp_data.FirstX()]; + ValueType *out_row = &pic_data_out[start_y][pic_data_out.FirstX()]; + for ( int i = start_y; i < end_y; i++) + { + for ( int j = pic_data_out.FirstX(); j < stopX; j+=4) + { + __m64 in1 = _mm_add_pi16 (*(__m64 *)pic_row, mround_val); + in1 = _mm_srai_pi16 (in1, weight_bits); + __m64 *out = (__m64 *)out_row; + *out = _mm_add_pi16 (in1, *out); + pic_row += 4; + out_row += 4; + } + for ( int j =stopX; j < x_end_truepic_data; j++) + { + *out_row += static_cast<ValueType>( (*pic_row + round_val) >> weight_bits ); + ++out_row; + ++pic_row; + } + // Now pad past the true picture with the last true pic val in + // current row + ValueType last_true_val = *(out_row - 1); + for ( int j = x_end_truepic_data; j < x_end_data; ++j) + { + *out_row = last_true_val; + ++out_row; + ++pic_row; + } + } + _mm_empty(); + } + + void AddMCBlock_mmx (const ImageCoords& start_pos, + TwoDArray<ValueType> &comp_strip, + TwoDArray<ValueType>& block_data) + { + const int stopX = (block_data.LengthX()>>2)<<2; + + const int comp_next = comp_strip.LengthX()-block_data.LengthX(); + ValueType *comp_curr = &comp_strip[start_pos.y][start_pos.x]; + ValueType *block_curr = &block_data[0][0]; + + for (int j = 0; j < block_data.LengthY(); ++j, comp_curr += comp_next) + { + for (int i = 0; i < stopX; i+=4, comp_curr+=4, block_curr+=4) + { + __m64 *out = (__m64 *)comp_curr; + // mc_tmp[y][x] += val + *out = _mm_add_pi16 (*(__m64 *)comp_curr, *(__m64 *)block_curr); + } + for (int i = stopX; i < block_data.LengthX(); ++i, ++comp_curr, ++block_curr) + { + *comp_curr += *block_curr; + } + } + _mm_empty(); + } +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp_mmx.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp_mmx.h new file mode 100644 index 000000000..4be009c61 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mot_comp_mmx.h @@ -0,0 +1,64 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mot_comp_mmx.h,v 1.4 2008/01/09 10:50:23 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author), +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +// Motion Compensation routines. +// Supports different sizes of blocks as long as the parameters +// describing them are 'legal'. Blocks overlap the edge of the image +// being written to but blocks in the reference image are forced to +// lie completely within the image bounds. + +#ifndef _INCLUDED_MOT_COMP_MMX_H +#define _INCLUDED_MOT_COMP_MMX_H + +#if defined (HAVE_MMX) +#include <libdirac_common/common.h> +#include <libdirac_common/motion.h> +namespace dirac +{ + + void CompensateComponentAddAndShift_mmx (int start_y, int end_y, + int weight_bits, + const ImageCoords& orig_pic_size, + TwoDArray<ValueType> &comp_data, + PicArray &pic_data_out); + + void AddMCBlock_mmx (const ImageCoords& start_pos, TwoDArray<ValueType> &comp_strip, TwoDArray<ValueType>& block_data); +} + +#endif // HAVE_MMX + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/motion.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/motion.cpp new file mode 100644 index 000000000..cb48bdbb3 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/motion.cpp @@ -0,0 +1,722 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: motion.cpp,v 1.28 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Chris Bowley, +* Tim Borer +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +//////////////////////////////////////////////////////////////// +//classes and functions for motion estimation and compensation// +//////////////////////////////////////////////////////////////// + +#include <libdirac_common/motion.h> +using namespace dirac; + +#include <cmath> + +using namespace std; + +//Motion vector and Motion Estimation structures// +////////////////////////////////////////////////// + +MvData::MvData( const PicturePredParams& predparams , const int num_refs ): + m_predparams( predparams ), + m_vectors( Range(1 , num_refs) ), + m_gm_vectors( Range(1 , num_refs) ), + m_modes( predparams.YNumBlocks() , predparams.XNumBlocks() ), + m_dc( 3 ), + m_sb_split( predparams.YNumSB() , predparams.XNumSB() ), + m_gm_params( Range(1 , num_refs) )//, +// m_num_refs(num_refs) +{ + InitMvData(); +} + +void MvData::InitMvData() +{ + // Create the arrays of vectors + for ( int i=m_vectors.First() ; i<=m_vectors.Last() ; ++i ){ + m_vectors[i] = new MvArray( Mode().LengthY() , Mode().LengthX() ); + m_gm_vectors[i] = new MvArray( Mode().LengthY() , Mode().LengthX() ); + } + + // create global motion parameter arrays + for ( int i=m_gm_params.First() ; i<=m_gm_params.Last() ; ++i ){ + m_gm_params[i] = new OneDArray<float> ( 8 ); + } + + // Create the arrays of dc values + for ( int i=0 ; i<3 ; ++i ) + m_dc[i] = new TwoDArray<ValueType>( Mode().LengthY() , Mode().LengthX() , 0); +} + +MvData::~MvData() +{ + // Delete the arrays of vectors + for ( int i=m_vectors.First() ; i<=m_vectors.Last() ; ++i ){ + delete m_vectors[i]; + delete m_gm_vectors[i]; + } + + // delete array of global motion parameters + for ( int i=m_gm_params.First() ; i<=m_gm_params.Last() ; ++i ){ + delete m_gm_params[i]; + } + + // Delete the arrays of dc values + for ( int i=0 ; i<3 ; ++i ) + delete m_dc[i]; +} + +MEData::MEData(const PicturePredParams& predparams , const int num_refs ): + MvData( predparams , num_refs ), + m_pred_costs( Range( 1 , num_refs ) ), + m_intra_costs( predparams.YNumBlocks() , predparams.XNumBlocks(), 0 ), + m_bipred_costs( predparams.YNumBlocks() , predparams.XNumBlocks() ), + m_SB_costs( predparams.YNumSB() , predparams.XNumSB() ), + m_lambda_map( predparams.YNumBlocks() , predparams.XNumBlocks() ), + m_inliers( Range( 1 , num_refs ) ), + m_intra_block_ratio(0.0) +{ + InitMEData(); +} + +void MEData::InitMEData() +{ + // Create the arrays of prediction costs + for ( int i=m_pred_costs.First() ; i<=m_pred_costs.Last() ; ++i ) + m_pred_costs[i] = new TwoDArray<MvCostData>( Mode().LengthY() , Mode().LengthX() ); + + // Create the arrays of vectors + for ( int i=m_inliers.First() ; i<=m_inliers.Last() ; ++i ) + m_inliers[i] = new TwoDArray<int>( Mode().LengthY() , Mode().LengthX() ); +} + +void MEData::SetLambdaMap( const int num_refs , const float lambda ) +{ + TwoDArray<bool> transition_map1( Mode().LengthY() , Mode().LengthX() ); + TwoDArray<bool> transition_map2( Mode().LengthY() , Mode().LengthX() ); + + FindTransitions( transition_map1 , 1 ); + + if ( num_refs==1 ) + { + for ( int j=0 ; j<m_lambda_map.LengthY() ; j++) + { + for ( int i=0 ; i<m_lambda_map.LengthX() ; i++) + { + if ( transition_map1[j][i] ) + m_lambda_map[j][i] = 0.0; + else + m_lambda_map[j][i] = lambda; + if ( i<4 || j<4 ) + m_lambda_map[j][i] /= 5.0; + }// i + }// j + } + else if ( num_refs > 1 ) + { + FindTransitions( transition_map2 , 2 ); + + for ( int j=0 ; j<m_lambda_map.LengthY() ; j++) + { + for ( int i=0 ; i<m_lambda_map.LengthX() ; i++) + { + if ( transition_map1[j][i] && transition_map2[j][i] ) + m_lambda_map[j][i] = 0.0; + else if (transition_map1[j][i] || transition_map2[j][i] ) + m_lambda_map[j][i] = lambda/4.0; + else + m_lambda_map[j][i] = lambda; + + if ( i<4 || j<4 ) + m_lambda_map[j][i] /= 5.0; + }// i + }// j + } + +} + +void MEData::SetLambdaMap( const int level , const TwoDArray<float>& l_map , const float wt ) +{ + + const int factor = 1<<(2-level); + int xstart , xend , ystart , yend; + + for (int j = 0 ; j<m_lambda_map.LengthY() ; ++j ) + { + for (int i = 0 ; i<m_lambda_map.LengthX() ; ++i ) + { + xstart = factor * i; + ystart = factor * j; + xend = factor * ( i + 1 ); + yend = factor * ( j + 1 ); + + m_lambda_map[j][i] = l_map[ystart][xstart]; + + for (int q = ystart ; q<yend ; ++q ) + for (int p = xstart ; p<xend ; ++p ) + m_lambda_map[j][i] = std::max( l_map[q][p] , m_lambda_map[j][i] ); + + m_lambda_map[j][i] *= wt; + + }// i + }// j + +} + +void MEData::FindTransitions( TwoDArray<bool>& trans_map , const int ref_num ) +{ + + const MvArray& mv_array = Vectors( ref_num ); + + // Start with a statistical approach - determine thresholds later + + // Compute mean and standard deviation of local SAD variance // + /////////////////////////////////////////////////////////////// + + long double total_cost = 0.0; + long double mean_cost; + long double sd_cost = 0.0; + double diff; + double threshold; + + // first, mean + for ( int j=0 ; j<mv_array.LengthY() ; ++j ) + for ( int i=0 ; i<mv_array.LengthX() ; ++i ) + total_cost += PredCosts( ref_num )[j][i].SAD; + + mean_cost = total_cost / + static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() ); + + // next , Standard Deviation + + for ( int j=0 ; j<mv_array.LengthY() ; ++j ) + { + for ( int i=0 ; i<mv_array.LengthX() ; ++i ) + { + diff = PredCosts( ref_num )[j][i].SAD - mean_cost; + diff *= diff; + sd_cost += diff; + + }// i + }// j + + // Get the variance ... + sd_cost /= static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() ); + + // ... and then the SD + sd_cost = std::sqrt( sd_cost ); + + threshold = mean_cost + 3*sd_cost; + + // now go through and mark those that go above the threshold + for ( int j=0 ; j<mv_array.LengthY() ; ++j ) + for ( int i=0 ; i<mv_array.LengthX() ; ++i ) + trans_map[j][i] = ( PredCosts( ref_num )[j][i].SAD >= threshold )? true : false; + + + // Next look at motion-vector costs + TwoDArray<double> val_array( mv_array.LengthY() , mv_array.LengthX() ); + + // first, mean + total_cost = 0.0; + for ( int i=0 ; i<mv_array.LengthX() ; ++i ) + { + val_array[0][i] = 0.0; + val_array[val_array.LastY()][i] = 0.0; + }// i + + for ( int j=1 ; j<mv_array.LengthY()-1 ; ++j ) + { + val_array[j][0] = 0.0; + val_array[j][val_array.LastX()] = 0.0; + for ( int i=1 ; i<mv_array.LengthX()-1 ; ++i ) + { + val_array[j][i] =0.0; + for (int q=-1 ; q<=1 ; ++q) + for (int p=-1 ; p<=1 ; ++p) + val_array[j][i] = std::max( val_array[j][i] , (double)Norm1( mv_array[j+q][i+p] - mv_array[j][i] ) ); + + total_cost += val_array[j][i]; + + }// i + }// j + + + mean_cost = total_cost / + static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() ); + + // next , Standard Deviation + sd_cost = 0.0; + + for ( int j=1 ; j<mv_array.LengthY()-1 ; ++j ) + { + for ( int i=1 ; i<mv_array.LengthX()-1 ; ++i ) + { + diff = val_array[j][i] - mean_cost; + diff *= diff; + + sd_cost += diff; + + }// i + }// j + + // Get the variance ... + sd_cost /= static_cast<long double>( mv_array.LengthX()*mv_array.LengthY() ); + + // ... and then the SD + sd_cost = std::sqrt( sd_cost ); + + threshold = mean_cost + 3*sd_cost; + + // now go through and mark those that go above the threshold + for ( int j=0 ; j<mv_array.LengthY() ; ++j ) + for ( int i=0 ; i<mv_array.LengthX() ; ++i ) + trans_map[j][i] = ( val_array[j][i] >= threshold )? true : false; + + bool contains_trans; + + for ( int j=0 ; j<mv_array.LengthY()/4 ; ++j ) + { + for ( int i=0 ; i<mv_array.LengthX()/4 ; ++i ) + { + contains_trans = false; + for ( int q=4*j ; q<4*(j+1) ; ++q ) + { + for ( int p=4*i ; p<4*(i+1) ; ++p ) + { + if (trans_map[q][p]) + contains_trans = true; + }// p + }// q + for ( int q=4*j ; q<4*(j+1) ; ++q ) + for ( int p=4*i ; p<4*(i+1) ; ++p ) + trans_map[q][p] = contains_trans; + + }// i + }// j + +} + + +MEData::~MEData() +{ + // Delete the arrays of prediction costs + for ( int i=m_pred_costs.First() ; i<=m_pred_costs.Last() ; ++i ) + delete m_pred_costs[i]; + + for ( int i=m_inliers.First() ; i<=m_inliers.Last() ; ++i ) + delete m_inliers[i]; +} + +void MEData::DropRef( const int rindex ){ + + if (rindex==2){} + else if (rindex==1){ + // Swap data for reference 1 and reference 2 + // so that reference 2 becomes the new reference 1 + + MvArray* ptr = m_vectors[1]; + m_vectors[1] = m_vectors[2]; + m_vectors[2] = ptr; + + ptr = m_gm_vectors[1]; + m_gm_vectors[1] = m_gm_vectors[2]; + m_gm_vectors[2] = ptr; + + OneDArray<float>* ptr2 = m_gm_params[1]; + m_gm_params[1] = m_gm_params[2]; + m_gm_params[2] = ptr2; + + TwoDArray<MvCostData>* ptr3 = m_pred_costs[1]; + m_pred_costs[1] = m_pred_costs[2]; + m_pred_costs[2] = ptr3; + + TwoDArray<int>* ptr4 = m_inliers[1]; + m_inliers[1] = m_inliers[2]; + m_inliers[2] = ptr4; + } +} + +namespace dirac +{ +//! Overloaded operator<< for MvCostData +/*! + Only writes SAD value to stream +*/ +ostream & operator<< (ostream & stream, MvCostData & cost) +{ + stream << cost.SAD << " " << cost.mvcost; + + return stream; +} + +//! Overloaded operator>> for MvCostData +/*! + Only reads SAD value from stream +*/ +istream & operator>> (istream & stream, MvCostData & cost) +{ + stream >> cost.SAD >> cost.mvcost; + + return stream; +} + +//! Overloaded operator>> for PredMode +/*! + No operator<< is specified as enumeration is written as integers + operator>> required to specify PredMode input +*/ +istream & operator>> (istream & stream, PredMode & mode) +{ + int temp; + stream >> temp; + mode = (PredMode)temp; + + return stream; +} + +// Overriden extractor operator for reading MvData data members +istream &operator>> (istream & stream, MEData & me_data) +{ + stream.ignore(1000, '\n'); + + // input reference-independent information + stream >> me_data.SBSplit(); + stream >> me_data.SBCosts(); + stream >> me_data.Mode(); + stream >> me_data.IntraCosts(); + + if (me_data.m_pred_costs.Length() > 1) + stream >> me_data.BiPredCosts(); + + if (me_data.DC().Length() == 1) + { + stream >> me_data.DC( Y_COMP ); + } + else if (me_data.DC().Length() == 3) + { + stream >> me_data.DC( Y_COMP ); + stream >> me_data.DC( U_COMP ); + stream >> me_data.DC( V_COMP ); + } + + // input reference information + for (int i=1; i<=me_data.m_pred_costs.Length(); ++i) + { + stream >> me_data.Vectors(i); + stream >> me_data.PredCosts(i); + //stream >> me_data.GlobalMotionParameters(i); + //stream >> me_data.GlobalMotionVectors(i); + //stream >> me_data.GlobalMotionInliers(i); + } + + return stream; +} + +// Overriden operator for output of MvData member data (to file) +ostream &operator<< (ostream & stream, MEData & me_data) +{ + // output reference-independent information + stream << endl << endl << me_data.SBSplit(); + stream << endl << me_data.SBCosts(); + stream << endl << me_data.Mode(); + stream << endl << me_data.IntraCosts() << endl; + + if (me_data.m_pred_costs.Length() > 1) + stream << me_data.BiPredCosts(); + + // output component DC values + if (me_data.DC().Length() == 1) + { + stream << endl << me_data.DC( Y_COMP ); + } + else if (me_data.DC().Length() == 3) + { + stream << endl << me_data.DC( Y_COMP ); + stream << endl << me_data.DC( U_COMP ); + stream << endl << me_data.DC( V_COMP ); + } + + // output reference information + for (int i=1; i<=me_data.m_pred_costs.Length(); ++i) + { + stream << endl << me_data.Vectors(i); + stream << endl << me_data.PredCosts(i) << endl; + //stream << endl << me_data.GlobalMotionParameters(i) << endl; + //stream << endl << me_data.GlobalMotionVectors(i) << endl; + //stream << endl << me_data.GlobalMotionInliers(i) << endl; + } + + return stream; +} + +int Median( const int val1, const int val2, const int val3) +{ + int tmp; + + tmp=val1; + tmp+=val2; + tmp+=val3; + + tmp -= std::max( std::max( val1 , val2 ) , val3 ); + tmp -= std::min( std::min( val1 , val2 ) , val3 ); + + return tmp; +} + +MVector MvMedian(const MVector& mv1,const MVector& mv2,const MVector& mv3) { + //takes median of each vector component + MVector tmp_mv; + + tmp_mv.x=mv1.x; + tmp_mv.x+=mv2.x; + tmp_mv.x+=mv3.x; + + tmp_mv.x-=std::max(std::max(mv1.x,mv2.x),mv3.x); + tmp_mv.x-=std::min(std::min(mv1.x,mv2.x),mv3.x); + + tmp_mv.y=mv1.y; + tmp_mv.y+=mv2.y; + tmp_mv.y+=mv3.y; + + tmp_mv.y-=std::max(std::max(mv1.y,mv2.y),mv3.y); + tmp_mv.y-=std::min(std::min(mv1.y,mv2.y),mv3.y); + + return tmp_mv; +} + +int Median(const std::vector<int>& val_list) +{ + // take the median of up to 4 elements + + switch (val_list.size() ) + { + case 1 : + + return val_list[0]; + case 2 : // return the mean + return ( ( val_list[0] + val_list[1] + 1 )>>1 ); + case 3 : + return Median(val_list[0], val_list[1], val_list[2] ); + case 4 : + { + int med_val(0); + int max_val(val_list[0]); + int min_val(val_list[0]); + + for (int i=0; i<4; ++i ) + { + med_val += val_list[i]; + max_val = std::max( max_val , val_list[i] ); + min_val = std::min( min_val , val_list[i] ); + + }// i + + med_val -= ( max_val + min_val ); + + return ( (med_val + 1)>>1 ); + } + default : + return 0; + } + +} + +MVector MvMedian(const std::vector<MVector>& vect_list){ + //median of 0-4 vectors + + if ( vect_list.size() == 0 ) + return 0; + else if ( vect_list.size() == 1 ) + return vect_list[0]; + else if ( vect_list.size() == 2 ) + return MvMean( vect_list[0], vect_list[1] ); + else if ( vect_list.size() == 3 ) + return MvMedian(vect_list[0], vect_list[1], vect_list[2] ); + else if ( vect_list.size() == 4 ) + { + MVector tmp_mv(0); + MVector max_mv(vect_list[0]); + MVector min_mv(vect_list[0]); + for (int i=0; i<4; ++i ) + { + tmp_mv.x += vect_list[i].x; + max_mv.x=std::max(max_mv.x, vect_list[i].x); + min_mv.x=std::min(min_mv.x, vect_list[i].x); + + tmp_mv.y += vect_list[i].y; + max_mv.y=std::max(max_mv.y, vect_list[i].y); + min_mv.y=std::min(min_mv.y, vect_list[i].y); + + }// i + + tmp_mv.x -= (max_mv.x+min_mv.x); + tmp_mv.y -= (max_mv.y+min_mv.y); + + tmp_mv.x = (tmp_mv.x+1)>>1; + tmp_mv.y = (tmp_mv.y+1)>>1; + + return tmp_mv; + + } + else + { + MVector median; + int num_vals=int(vect_list.size()); + if (num_vals>0) { + int pos=0; + std::vector<int> ordered_vals(vect_list.size()); + //do x first + ordered_vals[0]=vect_list[0].x; + for (int I=1;I<num_vals;++I){ + for (int K=0;K<I;++K){ + if (vect_list[I].x<ordered_vals[K]){ + pos=K; + break; + } + else + pos=K+1; + }//K + if (pos==I) + ordered_vals[I]=vect_list[I].x; + else{ + for (int K=I-1;K>=pos;--K){ + ordered_vals[K+1]=ordered_vals[K]; + } + ordered_vals[pos]=vect_list[I].x; + } + }//I + if (vect_list.size()%2!=0) + median.x=ordered_vals[(num_vals-1)/2]; + else + median.x=(ordered_vals[(num_vals/2)-1]+ordered_vals[num_vals/2]+1)>>1; + + //now do y + ordered_vals[0]=vect_list[0].y; + for (int I=1;I<num_vals;++I){ + for (int K=0;K<I;++K){ + if (vect_list[I].y<ordered_vals[K]){ + pos=K; + break; + } + else + pos=K+1; + }//K + if (pos==I) + ordered_vals[I]=vect_list[I].y; + else{ + for (int K=I-1;K>=pos;--K){ + ordered_vals[K+1]=ordered_vals[K]; + } + ordered_vals[pos]=vect_list[I].y; + } + }//I + if (num_vals%2!=0) + median.y=ordered_vals[(num_vals-1)/2]; + else + median.y=(ordered_vals[(num_vals/2)-1]+ordered_vals[num_vals/2]+1)>>1; + + } + else{ + median.x=0; + median.y=0; + } + + return median; + } + +} + + +//! Return the unbiased mean of two motion vectors +MVector MvMean(const MVector& mv1, const MVector& mv2) +{ + //takes mean of each vector component + MVector tmp_mv; + + tmp_mv.x = mv1.x; + tmp_mv.x += mv2.x+1; + tmp_mv.x >>= 1; + + tmp_mv.y = mv1.y; + tmp_mv.y += mv2.y+1; + tmp_mv.y >>= 1; + + return tmp_mv; +} + +//! Return the mean of a set of unsigned integer values +unsigned int GetUMean(std::vector<unsigned int>& values) +{ + unsigned int sum=0; + for (unsigned int I=0;I<values.size();++I) + sum+=values[I]; + + sum+=(values.size()>>1); + sum/=values.size(); + + return sum; +} + +//! Return the mean of a set of signed integer values +int GetSMean(std::vector<int>& values) +{ + if (values.size()==0) + return 0; + + int sum=0; + for (unsigned int i=0;i<values.size();++i) + sum+=values[i]; + if ( sum>=0 ) + { + sum+=(values.size()>>1); + sum/=values.size(); + } + else + { + int old_sum = sum; + sum -= values.size()*old_sum; + sum+=(values.size()>>1); + sum/=values.size(); + sum += old_sum; + } + + return sum; +} + +} // namespace dirac diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/motion.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/motion.h new file mode 100644 index 000000000..a985bdbd7 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/motion.h @@ -0,0 +1,448 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: motion.h,v 1.30 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Chris Bowley, +* Tim Borer +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/common.h> +#include <algorithm> +#ifndef _MOTION_H +#define _MOTION_H + +namespace dirac +{ + //////////////////////////////////////////////////////////////// + //classes and functions for motion estimation and compensation// + //////////////////////////////////////////////////////////////// + + //classes + + //! Horizontal or vertical + enum MvElement { HORIZONTAL , VERTICAL }; + + //! Motion vector class - just a pair + template <class T> + class MotionVector + { + public: + + //! Constructor + MotionVector<T>(T a, T b) : x(a), y(b) {}; + //! Default construct - sets components to 0 + MotionVector<T>() : x(0), y(0) {}; + //! Constructor + MotionVector<T>(T a) : x(a), y(a) {}; + + //! Addition + inline MotionVector<T> operator+(const MotionVector<T>& argument) const; + + //! Subtraction + inline MotionVector<T> operator-(const MotionVector<T>& argument) const; + + //! Scalar multiplication + inline MotionVector<T> operator*(const float argument) const; + + //! Scalar multiplication + inline MotionVector<T> operator*(const int argument) const; + + //! Bitshift of each component + inline MotionVector<T> operator<<(const int argument) const; + + //! Bitshift of each component + inline MotionVector<T> operator>>(const int argument) const; + + //! Array-style element access + T& operator[](const int pos){return ( ( pos==0) ? x : y );} + + //! Array-style element access. + const T& operator[](const int pos) const {return ( ( pos==0) ? x : y );} + + + //! x and y components + T x,y; + + }; + + + template <class T> + inline MotionVector<T> MotionVector<T>::operator+(const MotionVector<T>& argument) const + { + MotionVector<T> temp; + temp.x = x + argument.x; + temp.y = y + argument.y; + + return temp; + } + + template <class T> + inline MotionVector<T> MotionVector<T>::operator-(const MotionVector<T>& argument) const + { + MotionVector<T> temp; + temp.x = x-argument.x; + temp.y = y-argument.y; + + return temp; + } + + template <class T> + inline MotionVector<T> MotionVector<T>::operator*(const float argument) const + { + MotionVector<T> temp; + temp.x = x*argument; + temp.y = y*argument; + + return temp; + } + + template <class T> + inline MotionVector<T> MotionVector<T>::operator*(const int argument) const + { + MotionVector<T> temp; + temp.x = x*argument; + temp.y = y*argument; + + return temp; + } + + template <class T> + inline MotionVector<T> MotionVector<T>::operator<<(const int argument) const + { + MotionVector<T> temp; + temp.x = x<<argument; + temp.y = y<<argument; + + return temp; + } + + template <class T> + inline MotionVector<T> MotionVector<T>::operator>>(const int argument) const + { + MotionVector<T> temp; + temp.x = x>>argument; + temp.y = y>>argument; + + return temp; + } + + //! Overloaded operator<< for MotionVector class for output to stream + template <class T> + std::ostream & operator<< (std::ostream & stream, MotionVector<T> & mv) + { + stream << mv.x << " " << mv.y; + + return stream; + } + + //! Overloaded operator>> for MotionVector class for input from stream + template <class T> + std::istream & operator>> (std::istream & stream, MotionVector<T> & mv) + { + stream >> mv.x; + stream >> mv.y; + + return stream; + } + + //! MVector class is a vector of ints + typedef MotionVector<int> MVector; + + //! ImageCoords class is a vector of ints + typedef MotionVector<int> ImageCoords; + + //! MvArray is a two-D array of MVectors + typedef TwoDArray<MVector> MvArray; + + //! An array of float-based motion vectors for doing global motion calcs + typedef TwoDArray< MotionVector<float> > MvFloatArray; + + //! Class for recording costs derived in motion estimation + class MvCostData + { + public: + //! Constructor + MvCostData(): + SAD(0.0), + mvcost(0.0), + total(0.0){} + + void SetTotal( const float lambda ){total = SAD + lambda*mvcost;} + + //! The Sum of Absolute Differences - easier to compute than Sum-Squared Differences + float SAD; + + //! The (Lagrangian-weighted) motion vector cost - the difference of a motion vector from its neighbouring vectors + float mvcost; + + //! Total=SAD+mvcost + float total; + }; + + + //! Class for all the motion vector data + /*! + Motion vector data: the motion vectors themselves, the blocks + and macroblock modes. + */ + class MvData + { + public: + //! Constructor + /*! + Constructor takes: + \param predparams Picture prediction parameters + \param num_refs the number of references being used for the picture + */ + MvData( const PicturePredParams& predparams , const int num_refs); + + //! Destructor + ~MvData(); + + //! Return a reference to the local picture prediction params + PicturePredParams& GetPicPredParams(){return m_predparams;} + + //! Return a reference to the local picture prediction params + const PicturePredParams& GetPicPredParams() const{return m_predparams;} + + //! Get the MVs for a reference + MvArray& Vectors(const int ref_id){return *( m_vectors[ref_id] );} + + //! Get the MVs for a reference + const MvArray& Vectors(const int ref_id) const {return *( m_vectors[ref_id] );} + + //! Get the global MVs for a reference + MvArray& GlobalMotionVectors(const int ref_id){return *( m_gm_vectors[ref_id] );} + + //! Get the global MVs for a reference + const MvArray& GlobalMotionVectors(const int ref_id) const {return *( m_gm_vectors[ref_id] );} + + //! Get the DC values for each component + TwoDArray<ValueType>& DC(CompSort cs){return *( m_dc[cs] );} + + //! Get the DC values for each component + const TwoDArray<ValueType>& DC(CompSort cs) const {return *( m_dc[cs] );} + + //! Get a reference to the vector holding component DC values + const OneDArray< TwoDArray<ValueType>* >& DC() const {return m_dc;} + + //! Get the block prediction modes + TwoDArray<PredMode>& Mode(){return m_modes;} + + //! Get the block prediction modes + const TwoDArray<PredMode>& Mode() const {return m_modes;} + + //! Get the SB split level + TwoDArray<int>& SBSplit(){return m_sb_split;} + + //! Get the SB split level + const TwoDArray<int>& SBSplit() const{return m_sb_split;} + + //! Get the global motion model parameters + OneDArray<float>& GlobalMotionParameters(const int ref_id) { return *( m_gm_params[ref_id] ); } + + //! Get the global motion model parameters + const OneDArray<float>& GlobalMotionParameters(const int ref_id) const { return *( m_gm_params[ref_id] ); } + + protected: + // A local copy of the picture prediction parameters + PicturePredParams m_predparams; + + // Initialises the arrays of data + void InitMvData(); + + // The motion vectors + OneDArray<MvArray*> m_vectors; + + // The global motion vectors + OneDArray<MvArray*> m_gm_vectors; + + // The block modes + TwoDArray<PredMode> m_modes; + + // The DC values + OneDArray< TwoDArray<ValueType>* > m_dc; + + // The SB split levels + TwoDArray<int> m_sb_split; + + // Global motion model parameters + OneDArray< OneDArray<float>* > m_gm_params; + +// // Number of reference frames +// unsigned int m_num_refs; + }; + + //! Class for all the motion estimation data + /*! + Motion estimation data: derived from MvData class, also + incorporates costs for blocks and macroblocks + */ + + class MEData: public MvData + { + public: + + //! Constructor + /*! + Constructor takes: + \param predparams the picture prediction parameters + \param num_refs the number of references being used for the picture + */ + MEData( const PicturePredParams& predparams , const int num_refs = 2); + + //! Destructor + ~MEData(); + + //! drop the data relating to one reference + void DropRef( int ref_index ); + + //! Get the block cost structures for each reference + TwoDArray<MvCostData>& PredCosts(const int ref_id){ return *( m_pred_costs[ref_id] ); } + + //! Get the block cost structures for each reference + const TwoDArray<MvCostData>& PredCosts(const int ref_id) const { return *( m_pred_costs[ref_id] ); } + + //! Get the intra costs + TwoDArray<float>& IntraCosts(){ return m_intra_costs; } + + //! Get the intra costs + const TwoDArray<float>& IntraCosts() const { return m_intra_costs; } + + //! Get the bipred costs + TwoDArray<MvCostData>& BiPredCosts(){ return m_bipred_costs; } + + //! Get the bipred costs + const TwoDArray<MvCostData>& BiPredCosts() const { return m_bipred_costs; } + + //! Get the SB costs + TwoDArray<float>& SBCosts(){ return m_SB_costs; } + + //! Get the SB costs + const TwoDArray<float>& SBCosts() const { return m_SB_costs; } + + //! Get the proportion of intra blocks + float IntraBlockRatio() const {return m_intra_block_ratio; } + + //! Set the intra block ratio + void SetIntraBlockRatio(const float r){ m_intra_block_ratio = r; } + + //! Set up the lambda map by detecting motion discontinuities + void SetLambdaMap( const int num_refs , const float lambda ); + + //! Set up the lambda map by averaging the lambda map from a lower level + void SetLambdaMap( const int level , const TwoDArray<float>& l_map , const float wt ); + + //! Get a lambda value for a given block and level + const TwoDArray<float>& LambdaMap() const { return m_lambda_map; } + + //! Get the inliers for each reference + TwoDArray<int>& GlobalMotionInliers(const int ref_id){ return *( m_inliers[ref_id] ); } + + //! Get the inliers for each reference + const TwoDArray<int>& GlobalMotionInliers(const int ref_id) const { return *( m_inliers[ref_id] ); } + + //! Overloaded operator<< for outputing to (file) stream + friend std::ostream &operator<< (std::ostream & stream, MEData & me_data); + + //! Overloaded operator>> for input of data from (file) stream + friend std::istream &operator>> (std::istream & stream, MEData & me_data); + + private: + // Initialises the arrays of data + void InitMEData(); + + // Finds transitions in the motion vectors + void FindTransitions( TwoDArray<bool>& trans_map , const int ref_num ); + + // The costs of predicting each block, for each reference + OneDArray< TwoDArray<MvCostData>* > m_pred_costs; + + // The costs of predicting each block by DC + TwoDArray<float> m_intra_costs; + + // The costs of predicting each block bidirectionally + TwoDArray<MvCostData> m_bipred_costs; + + // The costs for each macroblock as a whole + TwoDArray<float> m_SB_costs; + + // A map of the lambda values to use + TwoDArray<float> m_lambda_map; + + // Global motion inliers + OneDArray< TwoDArray<int>* > m_inliers; + + // Intra block ratio + float m_intra_block_ratio; + + }; + + //motion estimation and coding stuff + + //! Return the median of 3 integers + int Median( const int val1, const int val2, const int val3); + + //! Return the median of three motion vectors + MVector MvMedian(const MVector& mv1,const MVector& mv2,const MVector& mv3); + + + //! Return the median of a set of integers + int Median(const std::vector<int>& val_list); + + //! Return the median of a set of (up to 4) motion vectors + MVector MvMedian(const std::vector<MVector>& vect_list); + + //! Return the mean of two motion vectors + MVector MvMean(const MVector& mv1, const MVector& mv2); + + //! Return the squared length of a motion vector + inline int Norm2(const MVector& mv){//L^2 norm of a motion vector + return mv.x*mv.x+mv.y*mv.y; + } + + //! Return the sum of the lengths of a motion vector's componets + inline int Norm1(const MVector& mv){//L^1 norm of a motion vector + return abs(mv.x)+abs(mv.y); + } + + //! Return the mean of a set of unsigned integer values + unsigned int GetUMean(std::vector<unsigned int>& values); + + //! Return the mean of a set of signed integer values + int GetSMean(std::vector<int>& values); + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mv_codec.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mv_codec.cpp new file mode 100644 index 000000000..d576d6e12 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mv_codec.cpp @@ -0,0 +1,641 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mv_codec.cpp,v 1.35 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Tim Borer, +* Andrew Kennedy, +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/mv_codec.h> + +using namespace dirac; + +//public functions// +//////////////////// +// Constructor +SplitModeCodec::SplitModeCodec(ByteIO* p_byteio, + size_t number_of_contexts) + : ArithCodec <MvData> (p_byteio,number_of_contexts) +{} + + + +void SplitModeCodec::InitContexts() +{ +} + +// Main code function +void SplitModeCodec::DoWorkCode( MvData& in_data ) +{ + for (m_sb_yp = 0; m_sb_yp < in_data.SBSplit().LengthY(); ++m_sb_yp) + { + for (m_sb_xp = 0; m_sb_xp < in_data.SBSplit().LengthX(); ++m_sb_xp) + { + CodeVal(in_data); + }//m_sb_xp + }//m_sb_yp +} + +// Main decode function +void SplitModeCodec::DoWorkDecode( MvData& out_data) +{ + + for (m_sb_yp = 0; m_sb_yp < out_data.SBSplit().LengthY(); ++m_sb_yp) + { + for (m_sb_xp = 0; m_sb_xp < out_data.SBSplit().LengthX(); ++m_sb_xp) + { + DecodeVal( out_data ); + }//m_sb_xp + }//m_sb_yp +} + +//protected functions// +/////////////////////// + +void SplitModeCodec::ResetAll() +{ +} + +//coding functions// +//////////////////// + +//prediction functions + +unsigned int SplitModeCodec::Prediction(const TwoDArray<int> & split_data ) const +{ + int result = 0; + + std::vector < unsigned int > nbrs; + + if (m_sb_xp > 0 && m_sb_yp > 0) + { + nbrs.push_back( split_data[m_sb_yp-1][m_sb_xp] ); + nbrs.push_back( split_data[m_sb_yp-1][m_sb_xp-1] ); + nbrs.push_back( split_data[m_sb_yp][m_sb_xp-1] ); + + result = GetUMean(nbrs); + } + else if (m_sb_xp > 0 && m_sb_yp == 0) + result = split_data[m_sb_yp][m_sb_xp-1]; + else if (m_sb_xp == 0 && m_sb_yp > 0) + result = split_data[m_sb_yp-1][m_sb_xp]; + + return result; +} + + +void SplitModeCodec::CodeVal(const MvData& in_data) +{ + int val = in_data.SBSplit()[m_sb_yp][m_sb_xp] - Prediction( in_data.SBSplit() ); + + if (val < 0) val+=3; //produce prediction mod 3 + + EncodeUInt(val, SB_SPLIT_BIN1_CTX, SB_SPLIT_BIN2_CTX); +} + +//decoding functions// +////////////////////// + + + +void SplitModeCodec::DecodeVal(MvData& out_data) +{ + out_data.SBSplit()[m_sb_yp][m_sb_xp] = + (DecodeUInt(SB_SPLIT_BIN1_CTX, SB_SPLIT_BIN2_CTX) + + Prediction(out_data.SBSplit())) % 3; +} + +/******************************************************************************/ + +//public functions// +//////////////////// +// Constructor +PredModeCodec::PredModeCodec(ByteIO* p_byteio, + size_t number_of_contexts, + int num_refs) + : ArithCodec <MvData> (p_byteio,number_of_contexts), + m_num_refs(num_refs) +{} + + + +void PredModeCodec::InitContexts() +{ +} + +// Main code function +void PredModeCodec::DoWorkCode( MvData& in_data ) +{ + int step,max; + int split_depth; + + for (m_sb_yp = 0, m_sb_tlb_y = 0; m_sb_yp < in_data.SBSplit().LengthY(); ++m_sb_yp, m_sb_tlb_y += 4) + { + for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < in_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4) + { + split_depth = in_data.SBSplit()[m_sb_yp][m_sb_xp]; + + step = 4 >> (split_depth); + max = (1 << split_depth); + + //now do all the block modes and mvs in the mb + for (m_b_yp = m_sb_tlb_y; m_b_yp < m_sb_tlb_y+4; m_b_yp += step) + { + for (m_b_xp = m_sb_tlb_x; m_b_xp < m_sb_tlb_x+4; m_b_xp += step) + { + CodeVal(in_data); + }//m_b_xp + }//m_b_yp + + }//m_sb_xp + }//m_sb_yp +} + +// Main decode function +void PredModeCodec::DoWorkDecode( MvData& out_data) +{ + int step,max; + int split_depth; + int xstart,ystart; + + // Then the prediction mode + for (m_sb_yp = 0,m_sb_tlb_y = 0; m_sb_yp < out_data.SBSplit().LengthY(); ++m_sb_yp,m_sb_tlb_y += 4) + { + for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < out_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4) + { + split_depth = out_data.SBSplit()[m_sb_yp][m_sb_xp]; + step = 4 >> (split_depth); + max = (1 << split_depth); + + //now do all the block mvs in the mb + for (int j = 0; j < max; ++j) + { + for (int i = 0; i < max; ++i) + { + xstart = m_b_xp = m_sb_tlb_x + i * step; + ystart = m_b_yp = m_sb_tlb_y + j * step; + + DecodeVal(out_data); + + // propagate throughout SB + for (m_b_yp = ystart; m_b_yp < ystart+step; m_b_yp++) + { + for (m_b_xp = xstart; m_b_xp < xstart+step; m_b_xp++) + { + out_data.Mode()[m_b_yp][m_b_xp] = out_data.Mode()[ystart][xstart]; + }//m_b_xp + }//m_b_yp + }//i + }//j + + }//m_sb_xp + }//m_sb_yp +} + +//protected functions// +/////////////////////// + +void PredModeCodec::ResetAll() +{ +} + +//coding functions// +//////////////////// + +//prediction functions + +unsigned int PredModeCodec::Prediction(const TwoDArray < PredMode > & preddata) const +{ + unsigned int result = (unsigned int)(INTRA); + unsigned int num_ref1_nbrs( 0 ); + unsigned int num_ref2_nbrs( 0 ); + + if (m_b_xp > 0 && m_b_yp > 0) + { + num_ref1_nbrs += ((unsigned int)( preddata[m_b_yp-1][m_b_xp] ) ) & 1; + num_ref1_nbrs += ((unsigned int)( preddata[m_b_yp-1][m_b_xp-1] ) ) & 1; + num_ref1_nbrs += ((unsigned int)( preddata[m_b_yp][m_b_xp-1] ) ) & 1; + + result = num_ref1_nbrs>>1; + + if ( m_num_refs==2) + { + num_ref2_nbrs += ((unsigned int)( preddata[m_b_yp-1][m_b_xp] ) ) & 2; + num_ref2_nbrs += ((unsigned int)( preddata[m_b_yp-1][m_b_xp-1] ) ) & 2; + num_ref2_nbrs += ((unsigned int)( preddata[m_b_yp][m_b_xp-1] ) ) & 2; + num_ref2_nbrs >>= 1; + result ^= ( (num_ref2_nbrs>>1)<<1 ); + } + } + else if (m_b_xp > 0 && m_b_yp == 0) + result = (unsigned int)( preddata[0][m_b_xp-1] ); + else if (m_b_xp == 0 && m_b_yp > 0) + result = (unsigned int)( preddata[m_b_yp-1][0] ); + + return result; +} + +void PredModeCodec::CodeVal(const MvData& in_data) +{ + // Xor with the prediction so we predict whether REF1 is used or REF2 is + // used, separately + unsigned int residue = in_data.Mode()[m_b_yp][m_b_xp] ^ + Prediction( in_data.Mode() ); + + // Code REF1 part of the prediction residue (ie the first bit) + EncodeSymbol( residue & 1 , PMODE_BIT0_CTX ); + + // Code REF2 part of the prediction residue (ie the second bit) + if (m_num_refs==2) + { + EncodeSymbol( residue & 2 , PMODE_BIT1_CTX ); + } + +} + +//decoding functions// +////////////////////// + +void PredModeCodec::DecodeVal( MvData& out_data ) +{ + // Xor with the prediction so we predict whether REF1 is used or REF2 is + // used, separately + unsigned int residue; + + // Decode REF1 part of the prediction residue (ie the first bit) + bool bit; + bit = DecodeSymbol( PMODE_BIT0_CTX ); + residue = (unsigned int) bit; + + // Decode REF2 part of the prediction residue (ie the second bit) + if (m_num_refs==2) + { + bit = DecodeSymbol( PMODE_BIT1_CTX ); + residue |= ( (unsigned int) bit ) << 1; + } + + out_data.Mode()[m_b_yp][m_b_xp] = + PredMode( Prediction( out_data.Mode() ) ^ residue ); +} + +/******************************************************************************/ + + +//public functions// +//////////////////// +// Constructor +VectorElementCodec::VectorElementCodec(ByteIO* p_byteio, + int ref_id, + MvElement horvert, + size_t number_of_contexts) + : ArithCodec <MvData> (p_byteio,number_of_contexts), + m_ref(ref_id), + m_hv(horvert) +{} + + + +void VectorElementCodec::InitContexts() +{} + +// Main code function +void VectorElementCodec::DoWorkCode( MvData& in_data ) +{ + int step,max; + int split_depth; + + for (m_sb_yp = 0, m_sb_tlb_y = 0; m_sb_yp < in_data.SBSplit().LengthY(); ++m_sb_yp, m_sb_tlb_y += 4) + { + for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < in_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4) + { + split_depth = in_data.SBSplit()[m_sb_yp][m_sb_xp]; + + step = 4 >> (split_depth); + max = (1 << split_depth); + + //now do all the block modes and mvs in the mb + for (m_b_yp = m_sb_tlb_y; m_b_yp < m_sb_tlb_y+4; m_b_yp += step) + { + for (m_b_xp = m_sb_tlb_x; m_b_xp < m_sb_tlb_x+4; m_b_xp += step) + { + if ( in_data.Mode()[m_b_yp][m_b_xp] & m_ref ) + { + CodeVal(in_data); + } + }//m_b_xp + }//m_b_yp + + }//m_sb_xp + }//m_sb_yp +} + +// Main decode function +void VectorElementCodec::DoWorkDecode( MvData& out_data) +{ + int step,max; + int split_depth; + int xstart,ystart; + + for (m_sb_yp = 0,m_sb_tlb_y = 0; m_sb_yp < out_data.SBSplit().LengthY(); ++m_sb_yp,m_sb_tlb_y += 4) + { + for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < out_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4) + { + split_depth = out_data.SBSplit()[m_sb_yp][m_sb_xp]; + step = 4 >> (split_depth); + max = (1 << split_depth); + + //now do all the block mvs in the mb + for (int j = 0; j < max; ++j) + { + for (int i = 0; i < max; ++i) + { + xstart = m_b_xp = m_sb_tlb_x + i * step; + ystart = m_b_yp = m_sb_tlb_y + j * step; + + if (out_data.Mode()[m_b_yp][m_b_xp] & m_ref) + { + DecodeVal( out_data ); + } + + // propagate throughout SB + for (m_b_yp = ystart; m_b_yp < ystart+step; m_b_yp++) + { + for (m_b_xp = xstart; m_b_xp < xstart+step; m_b_xp++) + { + out_data.Vectors(m_ref)[m_b_yp][m_b_xp][m_hv] = + out_data.Vectors(m_ref)[ystart][xstart][m_hv]; + + }//m_b_xp + }//m_b_yp + }//i + }//j + + }//m_sb_xp + }//m_sb_yp +} + +//protected functions// +/////////////////////// + +void VectorElementCodec::ResetAll() +{ +} + +//coding functions// +//////////////////// + +//prediction functions + +int VectorElementCodec::Prediction(const MvArray& mvarray, + const TwoDArray < PredMode > & preddata) const +{ + std::vector <int> nbrs; + PredMode pmode; + int result( 0 ); + + if (m_b_xp > 0 && m_b_yp > 0) + { + pmode = preddata[m_b_yp-1][m_b_xp]; + if (pmode & m_ref) + nbrs.push_back(mvarray[m_b_yp-1][m_b_xp][m_hv]); + + pmode = preddata[m_b_yp-1][m_b_xp-1]; + if (pmode & m_ref) + nbrs.push_back(mvarray[m_b_yp-1][m_b_xp-1][m_hv]); + + pmode = preddata[m_b_yp][m_b_xp-1]; + if (pmode & m_ref) + nbrs.push_back(mvarray[m_b_yp][m_b_xp-1][m_hv]); + + if (nbrs.size() > 0) + result = Median(nbrs); + } + else if (m_b_xp > 0 && m_b_yp == 0) + { + pmode = preddata[0][m_b_xp-1]; + if (pmode & m_ref) + result = mvarray[0][m_b_xp-1][m_hv]; + } + else if (m_b_xp == 0 && m_b_yp > 0) + { + pmode = preddata[m_b_yp-1][0]; + if (pmode & m_ref) + result = mvarray[m_b_yp-1][0][m_hv]; + } + return result; +} + +void VectorElementCodec::CodeVal(const MvData& in_data ) +{ + const MvArray& mv_array = in_data.Vectors(m_ref); + const int pred = Prediction( mv_array , in_data.Mode() ); + const int val = mv_array[m_b_yp][m_b_xp][m_hv] - pred; + + EncodeSInt(val, MV_FBIN1_CTX, MV_FBIN5plus_CTX); +} + +//decoding functions// +////////////////////// + + +void VectorElementCodec::DecodeVal( MvData& out_data ) +{ + MvArray& mv_array = out_data.Vectors(m_ref); + int pred = Prediction( mv_array , out_data.Mode() ); + mv_array[m_b_yp][m_b_xp][m_hv] = pred + + DecodeSInt(MV_FBIN1_CTX, MV_FBIN5plus_CTX); + +} + +/******************************************************************************/ +//public functions// +//////////////////// +// Constructor +DCCodec::DCCodec(ByteIO* p_byteio, + const CompSort csort, + size_t number_of_contexts): +ArithCodec <MvData> (p_byteio,number_of_contexts), +m_csort( csort ) +{} + + + +void DCCodec::InitContexts() +{ +} + +// Main code function +void DCCodec::DoWorkCode( MvData& in_data ) +{ + int step,max; + int split_depth; + + for (m_sb_yp = 0, m_sb_tlb_y = 0; m_sb_yp < in_data.SBSplit().LengthY(); ++m_sb_yp, m_sb_tlb_y += 4) + { + for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < in_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4) + { + split_depth = in_data.SBSplit()[m_sb_yp][m_sb_xp]; + + step = 4 >> (split_depth); + max = (1 << split_depth); + + //now do all the block modes and mvs in the mb + for (m_b_yp = m_sb_tlb_y; m_b_yp < m_sb_tlb_y+4; m_b_yp += step) + { + for (m_b_xp = m_sb_tlb_x; m_b_xp < m_sb_tlb_x+4; m_b_xp += step) + { + if(in_data.Mode()[m_b_yp][m_b_xp] == INTRA) + { + CodeVal(in_data); + } + }//m_b_xp + }//m_b_yp + + }//m_sb_xp + }//m_sb_yp +} + +// Main decode function +void DCCodec::DoWorkDecode( MvData& out_data) +{ + int step,max; + int split_depth; + int xstart,ystart; + + for (m_sb_yp = 0,m_sb_tlb_y = 0; m_sb_yp < out_data.SBSplit().LengthY(); ++m_sb_yp,m_sb_tlb_y += 4) + { + for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < out_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4) + { + //start with split mode + split_depth = out_data.SBSplit()[m_sb_yp][m_sb_xp]; + step = 4 >> (split_depth); + max = (1 << split_depth); + + //now do all the block mvs in the mb + for (int j = 0; j < max; ++j) + { + for (int i = 0; i < max; ++i) + { + xstart = m_b_xp = m_sb_tlb_x + i * step; + ystart = m_b_yp = m_sb_tlb_y + j * step; + + if(out_data.Mode()[m_b_yp][m_b_xp] == INTRA) + { + DecodeVal( out_data ); + } + + // propagate throughout SB + for (m_b_yp = ystart; m_b_yp < ystart+step; m_b_yp++) + { + for (m_b_xp = xstart; m_b_xp < xstart+step; m_b_xp++) + { + out_data.DC( m_csort )[m_b_yp][m_b_xp] = out_data.DC( m_csort )[ystart][xstart]; + }//m_b_xp + }//m_b_yp + }//i + }//j + + }//m_sb_xp + }//m_sb_yp + +} + +//protected functions// +/////////////////////// + +void DCCodec::ResetAll() +{ +} + +//coding functions// +//////////////////// + +//prediction functions + +ValueType DCCodec::Prediction(const TwoDArray < ValueType > & dcdata, + const TwoDArray < PredMode > & preddata) const +{ + std::vector < int > nbrs; + PredMode pmode; + ValueType result = 0; + + if (m_b_xp > 0 && m_b_yp > 0) + { + pmode = preddata[m_b_yp-1][m_b_xp]; + if (pmode == INTRA) + nbrs.push_back( (int) dcdata[m_b_yp-1][m_b_xp] ); + + pmode = preddata[m_b_yp-1][m_b_xp-1]; + if (pmode == INTRA) + nbrs.push_back((int)dcdata[m_b_yp-1][m_b_xp-1] ); + + pmode = preddata[m_b_yp][m_b_xp-1]; + if (pmode == INTRA) + nbrs.push_back( (int) dcdata[m_b_yp][m_b_xp-1] ); + + if (nbrs.size() > 0) + result = ValueType(GetSMean(nbrs)); + } + else if (m_b_xp > 0 && m_b_yp == 0) + { + pmode = preddata[0][m_b_xp-1]; + if (pmode == INTRA) + result = dcdata[0][m_b_xp-1]; + } + else if (m_b_xp == 0 && m_b_yp > 0) + { + pmode = preddata[m_b_yp-1][0]; + if (pmode == INTRA) + result = dcdata[m_b_yp-1][0]; + } + return result; +} + +void DCCodec::CodeVal(const MvData& in_data) +{ + const int val = in_data.DC( m_csort )[m_b_yp][m_b_xp] - + Prediction( in_data.DC(m_csort) , in_data.Mode() ); + EncodeSInt(val, DC_FBIN1_CTX, DC_FBIN2plus_CTX); +} + +//decoding functions// +////////////////////// + +void DCCodec::DecodeVal( MvData& out_data ) +{ + out_data.DC( m_csort )[m_b_yp][m_b_xp] = DecodeSInt(DC_FBIN1_CTX, DC_FBIN2plus_CTX) + + Prediction(out_data.DC( m_csort ), out_data.Mode()); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mv_codec.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mv_codec.h new file mode 100644 index 000000000..ed76ac92a --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/mv_codec.h @@ -0,0 +1,301 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: mv_codec.h,v 1.25 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Tim Borer, +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _MV_CODEC_H_ +#define _MV_CODEC_H_ + +///////////////////////////////////////////////// +//Class to do motion vector coding and decoding// +//------using adaptive arithmetic coding-------// +///////////////////////////////////////////////// + +#include <libdirac_common/arith_codec.h> +#include <libdirac_common/common.h> +#include <libdirac_common/motion.h> +#include <libdirac_common/wavelet_utils.h> +#include <vector> + +namespace dirac +{ + //! Codes and decodes the split mode + /*! + Derived from the ArithCodec class, this codes and decodes the split mode + */ + class SplitModeCodec: public ArithCodec<MvData> + { + public: + //! Constructor + /*! + Creates a MvDataCodec object to encode MV data, based on parameters + \param p_byteio Input/output for the encoded bits + \param number_of_contexts the number of contexts used + */ + SplitModeCodec(ByteIO* p_byteio, size_t number_of_contexts); + + + + //! Initialises the contexts + void InitContexts(); + + private: + + // Position of current SB + int m_sb_xp, m_sb_yp; + + private: + + // functions + //! Private, bodyless copy constructor: class should not be copied + SplitModeCodec(const SplitModeCodec& cpy); + //! Private, bodyless copy operator=: class should not be assigned + SplitModeCodec& operator=(const SplitModeCodec& rhs); + + // coding functions + // Code the SB splitting mode + void CodeVal(const MvData& in_data); + + // decoding functions + // Decode the SB splitting mode + void DecodeVal( MvData& out_data); + + void DoWorkCode( MvData& in_data ); + void DoWorkDecode(MvData& out_data); + + // Context stuff + void ResetAll(); + + //prediction stuff + unsigned int Prediction(const TwoDArray<int>& mbdata) const; + + }; + +/******************************************************************************/ + + //! Codes and decodes the prediction modes + /*! + Derived from the ArithCodec class, this codes and decodes the prediction mode. + */ + class PredModeCodec: public ArithCodec<MvData> + { + public: + //! Constructor + /*! + Creates a MvDataCodec object to encode MV data, based on parameters + \param p_byteio Input/output for the encoded bits + \param number_of_contexts the number of contexts used + \param num_refs Number of references + */ + PredModeCodec(ByteIO* p_byteio, size_t number_of_contexts, const int num_refs); + + //! Initialises the contexts + void InitContexts(); + + private: + + // Position of current block + int m_b_xp, m_b_yp; + // Position of current SB + int m_sb_xp, m_sb_yp; + // Position of top-left block of current SB + int m_sb_tlb_x, m_sb_tlb_y; + // Number of reference pictures + int m_num_refs; + + private: + + // functions + //! Private, bodyless copy constructor: class should not be copied + PredModeCodec(const PredModeCodec& cpy); + //! Private, bodyless copy operator=: class should not be assigned + PredModeCodec& operator=(const PredModeCodec& rhs); + + // coding functions + // Code the block prediction mode + void CodeVal(const MvData& in_data); + + // decoding functions + // Decode the block prediction mode + void DecodeVal(MvData& out_data); + + void DoWorkCode( MvData& in_data ); + void DoWorkDecode(MvData& out_data); + + // Context stuff + void ResetAll(); + + //prediction stuff + unsigned int Prediction(const TwoDArray<PredMode>& preddata) const; + + }; + +/******************************************************************************/ + + //! Codes and decodes an array of motion vectors + /*! + Derived from the ArithCodec class, this codes and decodes a motion vector + element (vertical or horizontal) + */ + class VectorElementCodec: public ArithCodec<MvData> + { + public: + //! Constructor + /*! + Creates a MvDataCodec object to encode MV data, based on parameters + \param p_byteio Input/output for the encoded bits + \param ref_id The identity of the reference (1 or 2) + \param horvert The identity of the vector element (horizontal or vertical) + \param number_of_contexts the number of contexts used + */ + VectorElementCodec(ByteIO* p_byteio, int ref_id, MvElement horvert, + size_t number_of_contexts); + + + //! Initialises the contexts + void InitContexts(); + + private: + + // Position of current block + int m_b_xp, m_b_yp; + + // Position of current SB + int m_sb_xp, m_sb_yp; + + // Position of top-left block of current SB + int m_sb_tlb_x, m_sb_tlb_y; + + // The identity of the reference (1 or 2) + const int m_ref; + + // Whether it's the vertical or horizontal MV element + const MvElement m_hv; + + private: + + // functions + //! Private, bodyless copy constructor: class should not be copied + VectorElementCodec(const VectorElementCodec& cpy); + //! Private, bodyless copy operator=: class should not be assigned + VectorElementCodec& operator=(const VectorElementCodec& rhs); + + // coding functions + // Code the motion vector element + void CodeVal(const MvData& in_data); + + // decoding functions + // Decode the motion vector element + void DecodeVal( MvData& out_data); + + void DoWorkCode( MvData& in_data ); + void DoWorkDecode(MvData& out_data); + + // Context stuff + void ResetAll(); + + //prediction stuff + int Prediction( const MvArray& mvarray, + const TwoDArray<PredMode>& preddata) const; + + }; + +/******************************************************************************/ + //! Codes and decodes a set of DC values + /*! + Derived from the ArithCodec class, this codes and decodes all the DC + values for a component + */ + class DCCodec: public ArithCodec<MvData> + { + public: + //! Constructor + /*! + Creates a MvDataCodec object to encode MV data, based on parameters + \param p_byteio Input/output for the encoded bits + \param csort The identity of the component (Y, U or V) + \param number_of_contexts the number of contexts used + */ + DCCodec(ByteIO* p_byteio, const CompSort csort, size_t number_of_contexts); + + //! Initialises the contexts + void InitContexts(); + + private: + + // The component being coded + const CompSort m_csort; + // Position of current block + int m_b_xp, m_b_yp; + // Position of current SB + int m_sb_xp, m_sb_yp; + // Position of top-left block of current SB + int m_sb_tlb_x, m_sb_tlb_y; + + private: + + // functions + //! Private, bodyless copy constructor: class should not be copied + DCCodec(const DCCodec& cpy); + //! Private, bodyless copy operator=: class should not be assigned + DCCodec& operator=(const DCCodec& rhs); + + // coding functions + // Code the dc value of intra blocks + void CodeVal(const MvData& in_data); + + // decoding functions + // Decode the dc value of intra blocks + void DecodeVal( MvData& out_data); + + void DoWorkCode( MvData& in_data ); + void DoWorkDecode(MvData& out_data); + + // Context stuff + void ResetAll(); + + //prediction stuff + ValueType Prediction( const TwoDArray<ValueType>& dcdata, + const TwoDArray<PredMode>& preddata) const; + }; + + +}// end namepace dirac + + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/pic_io.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/pic_io.cpp new file mode 100644 index 000000000..b6e56ebc3 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/pic_io.cpp @@ -0,0 +1,672 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: pic_io.cpp,v 1.28 2008/06/19 10:17:17 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott Robert Ladd, +* Stuart Cunningham, +* Tim Borer, +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/pic_io.h> +#include <libdirac_common/dirac_assertions.h> +using namespace dirac; + +/*************************************Output***********************************/ +StreamPicOutput::~StreamPicOutput() +{ +} + +StreamPicOutput::StreamPicOutput (std::ostream *op_ptr, const SourceParams& sp) : + m_sparams(sp), + m_op_pic_ptr(op_ptr) +{ +} + +StreamFrameOutput::StreamFrameOutput(std::ostream *op_str, + const SourceParams& sp) : + StreamPicOutput (op_str, sp) +{} + +StreamFrameOutput::~StreamFrameOutput() +{ +} + +bool StreamFrameOutput::WriteToNextFrame( const Picture& myframe ) +{ + bool ret_val; + + ret_val=WriteFrameComponent(myframe.Data(Y_COMP), Y_COMP ); + ret_val&=WriteFrameComponent( myframe.Data(U_COMP), U_COMP ); + ret_val&=WriteFrameComponent( myframe.Data(V_COMP), V_COMP ); + + return ret_val; +} + +bool StreamFrameOutput::WriteFrameComponent( const PicArray& pic_data , const CompSort& cs) +{ + if (!m_op_pic_ptr) + { + std::cerr<<std::endl<<"Can't open picture data file for writing"; + return false; + } + + //initially set up for 10-bit data input, rounded to 8 bits on file output + //This will throw out any padding to the right and bottom of a frame + + int xl,yl; + if (cs == Y_COMP) + { + xl = m_sparams.Xl(); + yl = m_sparams.Yl(); + } + else + { + xl = m_sparams.ChromaWidth(); + yl = m_sparams.ChromaHeight(); + } + + unsigned char* tempc=new unsigned char[xl]; + + if (m_op_pic_ptr) + { + for (int j=0 ; j<yl ;++j) + { + for (int i=0 ; i<xl ; ++i) + { + tempc[i] = (unsigned char) ( pic_data[j][i] + 128 ); + }//I + + m_op_pic_ptr->write((char*) tempc,xl); + + }//J + } + m_op_pic_ptr->flush(); + + delete[] tempc; + + //exit success + return true; +} + +StreamFieldOutput::StreamFieldOutput(std::ostream *op_str, + const SourceParams& sp) : + StreamPicOutput(op_str, sp), + m_frame_store(NULL) +{ + int frame_size = (m_sparams.Xl() * m_sparams.Yl()) + + 2 * (m_sparams.ChromaWidth() * m_sparams.ChromaHeight()); + m_frame_store = new unsigned char[frame_size]; +} + +StreamFieldOutput::~StreamFieldOutput() +{ + if (m_frame_store) + delete [] m_frame_store; +} + +bool StreamFieldOutput::WriteToNextFrame( const Picture& myfield ) +{ + bool ret_val; + + ret_val=WriteFieldComponent(myfield.Data(Y_COMP) , myfield.GetPparams().PictureNum(), Y_COMP ); + ret_val&=WriteFieldComponent(myfield.Data(U_COMP) , myfield.GetPparams().PictureNum(), U_COMP ); + ret_val&=WriteFieldComponent(myfield.Data(V_COMP) , myfield.GetPparams().PictureNum(), V_COMP ); + + return ret_val; +} + +bool StreamFieldOutput::WriteFieldComponent( const PicArray& pic_data , int field_num, const CompSort& cs) +{ + if (!m_op_pic_ptr) + { + std::cerr<<std::endl<<"Can't open picture data file for writing"; + return false; + } + + unsigned char *comp; + int xl,yl; + if (cs == Y_COMP) + { + xl = m_sparams.Xl(); + yl = m_sparams.Yl(); + comp = m_frame_store; + } + else + { + xl = m_sparams.ChromaWidth(); + yl = m_sparams.ChromaHeight(); + if (cs == U_COMP) + { + comp = m_frame_store + (m_sparams.Xl() * m_sparams.Yl()); + } + else + { + comp = m_frame_store + (m_sparams.Xl() * m_sparams.Yl()) + (xl*yl); + } + } + + // Seek offset before writing field to store + int start = 0; + // Seek offset between writing lines to file + int skip = 0; + // Seek offset after writing field to file + int end = 0; + + bool top_field = m_sparams.TopFieldFirst() ? (!(field_num%2)) : + (field_num%2); + + bool write_to_file = (m_sparams.TopFieldFirst() && !top_field) || + (!m_sparams.TopFieldFirst() && top_field); + + if (m_sparams.TopFieldFirst()) + { + if (top_field) + { + start = 0; + skip = 2 * xl * sizeof(char); + end = -(xl*yl); + } + else + { + start = xl; + skip = 2 * xl * sizeof(char); + end = 0; + } + } + else + { + if (!top_field) // i.e. bottom field + { + start = xl; + skip = 2 * xl * sizeof(char); + end = -(xl*yl); + } + else // top field + { + start = 0; + skip = 2 * xl * sizeof(char); + end = xl; + } + } + + unsigned char *tempc = comp + start; + + int field_yl = yl>>1; + int field_xl = xl; + for (int j=0 ; j<field_yl ;++j) + { + for (int i=0 ; i<field_xl ; ++i) + { + tempc[i] = (unsigned char) (pic_data[j][i]+128); + }//I + tempc += skip; + }//J + tempc += end; + + if (write_to_file) + { + m_op_pic_ptr->write((char*) comp,xl*yl); + m_op_pic_ptr->flush(); + return true; + } + //exit success + return false; +} + +MemoryStreamOutput::MemoryStreamOutput(SourceParams &sp, bool interlace) +{ + //picture input + m_op_pic_ptr = + new std::ostream(&m_membuf); + + if (interlace) + m_op_pic_str = new StreamFieldOutput(m_op_pic_ptr, sp); + else + m_op_pic_str = new StreamFrameOutput(m_op_pic_ptr, sp); +} + +MemoryStreamOutput::~MemoryStreamOutput() +{ + delete m_op_pic_str; + delete m_op_pic_ptr; +} + +void MemoryStreamOutput::SetMembufReference (unsigned char *buf, int buf_size) +{ + m_membuf.SetMembufReference(buf, buf_size); +} + +FileStreamOutput::FileStreamOutput(const char* output_name, + const SourceParams& sp, bool interlace) +{ + //picture output + m_op_pic_ptr = + new std::ofstream(output_name,std::ios::out | std::ios::binary); + + if (!(*m_op_pic_ptr)) + { + std::cerr << std::endl << + "Can't open output picture data file for output: " << + output_name<<std::endl; + return; + + } + if (interlace) + m_op_pic_str = new StreamFieldOutput(m_op_pic_ptr, sp); + else + m_op_pic_str = new StreamFrameOutput(m_op_pic_ptr, sp); +} + +FileStreamOutput::~FileStreamOutput() +{ + if (m_op_pic_ptr && *m_op_pic_ptr) + { + static_cast<std::ofstream *>(m_op_pic_ptr)->close(); + delete m_op_pic_ptr; + } + delete m_op_pic_str; +} + + +/**************************************Input***********************************/ + + +StreamPicInput::StreamPicInput (std::istream *ip_pic_ptr, + const SourceParams &sparams) : + m_sparams(sparams), + m_ip_pic_ptr(ip_pic_ptr) +{} + + +StreamPicInput::~StreamPicInput () +{} + +bool StreamPicInput::End() const +{ + return m_ip_pic_ptr->eof(); +} + +StreamFrameInput::StreamFrameInput (std::istream *ip_pic_ptr, + const SourceParams &sparams) : + StreamPicInput(ip_pic_ptr, sparams) +{} + +StreamFrameInput::~StreamFrameInput () +{} + +void StreamFrameInput::Skip(const int num) +{ + const int num_pels = m_sparams.Xl()*m_sparams.Yl(); + int num_bytes; + + const ChromaFormat cf = m_sparams.CFormat(); + + if ( cf == format420 ) + num_bytes = (num_pels*3)/2; + else if ( cf == format422 ) + num_bytes = num_pels*2; + else + num_bytes = num_pels*3; + + m_ip_pic_ptr->seekg( num*num_bytes , std::ios::cur ); +} + +bool StreamFrameInput::ReadNextPicture(Picture& myframe) +{ + //return value. Failure if one of the components can't be read, + //success otherwise/. + + bool ret_val; + + ret_val=ReadFrameComponent( myframe.Data(Y_COMP) , Y_COMP); + ret_val&=ReadFrameComponent(myframe.Data(U_COMP) , U_COMP); + ret_val&=ReadFrameComponent(myframe.Data(V_COMP) , V_COMP); + + return ret_val; +} + +bool StreamFrameInput::ReadFrameComponent(PicArray& pic_data, const CompSort& cs) +{ + + if (! *m_ip_pic_ptr) + return false; + + int xl,yl; + if (cs == Y_COMP){ + xl = m_sparams.Xl(); + yl = m_sparams.Yl(); + } + else{ + if (m_sparams.CFormat()==format420) + { + xl = m_sparams.Xl()/2; + yl = m_sparams.Yl()/2; + } + else if (m_sparams.CFormat() == format422) + { + xl = m_sparams.Xl()/2; + yl = m_sparams.Yl(); + } + else{ + xl = m_sparams.Xl(); + yl = m_sparams.Yl(); + } + } + + unsigned char * temp = new unsigned char[xl];//array big enough for one line + + for (int j=0 ; j<yl ; ++j) + { + m_ip_pic_ptr->read((char*) temp, xl); + + for (int i=0 ; i<xl ; ++i) + { + pic_data[j][i] = (ValueType) temp[i]; + }//I + for (int i=0 ; i<xl ; ++i) + { + pic_data[j][i] -= 128; + }//I + + + //pad the columns on the rhs using the edge value + for (int i=xl ; i<pic_data.LengthX() ; ++i ){ + pic_data[j][i] = pic_data[j][xl-1]; + }//I + + }//J + + delete [] temp; + + //now do the padded lines, using the last true line + for (int j=yl ; j<pic_data.LengthY() ; ++j ) + { + for (int i=0 ; i<pic_data.LengthX() ; ++i ) + { + pic_data[j][i] = pic_data[yl-1][i]; + }//I + }//J + + return true; +} + +StreamFieldInput::StreamFieldInput (std::istream *ip_pic_ptr, + const SourceParams &sparams) : + StreamPicInput(ip_pic_ptr, sparams) +{} + +StreamFieldInput::~StreamFieldInput () +{} + +void StreamFieldInput::Skip(const int num) +{ + REPORTM (num && false, "StreamFieldInput::Skip - Reached unimplemented function"); +} + +bool StreamFieldInput::ReadNextPicture(Picture& mypic) +{ + // FIXME: this method is BROKEN! + + //return value. Failure if one of the components can't be read, + //success otherwise/. + + bool ret_val; + + bool is_field1 = ((mypic.GetPparams().PictureNum()%2) == 0); + ret_val=ReadFieldComponent( is_field1, mypic.Data(Y_COMP), Y_COMP); + ret_val&=ReadFieldComponent(is_field1, mypic.Data(U_COMP), U_COMP); + ret_val&=ReadFieldComponent(is_field1, mypic.Data(V_COMP), V_COMP); + + int picture_size = m_sparams.Xl()*m_sparams.Yl() + + 2*m_sparams.ChromaWidth()*m_sparams.ChromaHeight(); + if (is_field1) + { + //Seek back to the beginning of frame so that the next field + //from the frame can be read + m_ip_pic_ptr->seekg (-picture_size, std::ios::cur); + } + + return ret_val; +} + +bool StreamFieldInput::ReadNextFrame(Picture& field1, Picture& field2) +{ + //return value. Failure if one of the components can't be read, + //success otherwise/. + + bool ret_val = false; + + ret_val=ReadFieldComponent( field1.Data(Y_COMP), field2.Data(Y_COMP), Y_COMP); + ret_val&=ReadFieldComponent(field1.Data(U_COMP), field2.Data(U_COMP), U_COMP); + ret_val&=ReadFieldComponent(field1.Data(V_COMP), field2.Data(V_COMP), V_COMP); + + return ret_val; +} + +bool StreamFieldInput::ReadFieldComponent(PicArray& pic_data1, + PicArray& pic_data2, + const CompSort& cs) +{ + if (! *m_ip_pic_ptr) + return false; + + //initially set up for 8-bit file input expanded to 10 bits for array output + + int xl,yl; + if (cs == Y_COMP){ + xl = m_sparams.Xl(); + yl = m_sparams.Yl(); + } + else{ + if (m_sparams.CFormat()==format420) + { + xl = m_sparams.Xl()/2; + yl = m_sparams.Yl()/2; + } + else if (m_sparams.CFormat() == format422) + { + xl = m_sparams.Xl()/2; + yl = m_sparams.Yl(); + } + else{ + xl = m_sparams.Xl(); + yl = m_sparams.Yl(); + } + } + + unsigned char * temp = new unsigned char[xl];//array big enough for one line + ValueType *pic; + + for (int j=0 ; j<yl ; j++) + { + m_ip_pic_ptr->read((char*) temp, xl); + if (j % 2 == 0) + { + pic = m_sparams.TopFieldFirst() ? + &pic_data1[j/2][0] : &pic_data2[j/2][0]; + } + else + { + pic = m_sparams.TopFieldFirst() ? + &pic_data2[j/2][0] : &pic_data1[j/2][0]; + } + for (int i=0 ; i<xl ; ++i) + { + pic[i] = (ValueType) temp[i]; + }//I + for (int i=0 ; i<xl ; ++i) + { + pic[i] -= 128; + }//I + + + //pad the columns on the rhs using the edge value + for (int i=xl ; i<pic_data1.LengthX() ; ++i ){ + pic[i] = pic[xl-1]; + }//I + + }//J + + delete [] temp; + + //now do the padded lines, using the last true line + for (int j=yl/2 ; j<pic_data1.LengthY() ; ++j ) + { + for (int i=0 ; i<pic_data1.LengthX() ; ++i ) + { + pic_data1[j][i] = pic_data1[yl/2-1][i]; + pic_data2[j][i] = pic_data2[yl/2-1][i]; + }//I + }//J + + return true; +} + +bool StreamFieldInput::ReadFieldComponent(bool is_field1, + PicArray& pic_data, + const CompSort& cs) +{ + if (! *m_ip_pic_ptr) + return false; + + //initially set up for 8-bit file input expanded to 10 bits for array output + + int xl,yl; + if (cs == Y_COMP){ + xl = m_sparams.Xl(); + yl = m_sparams.Yl()>>1; + } + else{ + xl = m_sparams.ChromaWidth(); + yl = m_sparams.ChromaHeight()>>1; + } + + unsigned char * pic = new unsigned char[2*xl];//array big enough for two lines - one for each field + + int start = 0; + if ((is_field1 && !m_sparams.TopFieldFirst()) || + (!is_field1 && m_sparams.TopFieldFirst())) + { + start = xl; + } + + for (int j=0 ; j<yl ; j++) + { + m_ip_pic_ptr->read((char*) pic, 2*xl); + // skip to the start of the field + unsigned char *field = pic + start; + for (int i=0 ; i<xl ; ++i) + { + pic_data[j][i] = (ValueType) field[i]; + }//I + for (int i=0 ; i<xl ; ++i) + { + pic_data[j][i] -= 128; + } + //pad the columns on the rhs using the edge value + for (int i=xl ; i<pic_data.LengthX() ; ++i ){ + pic_data[j][i] = pic_data[j][xl-1]; + }//I + + }//J + delete [] pic; + + //now do the padded lines, using the last true line + for (int j=yl ; j<pic_data.LengthY() ; ++j ) + { + for (int i=0 ; i<pic_data.LengthX() ; ++i ) + { + pic_data[j][i] = pic_data[yl-1][i]; + }//I + }//J + + return true; +} + +MemoryStreamInput::MemoryStreamInput(SourceParams& sparams, bool field_input) +{ + //picture input + m_ip_pic_ptr = + new std::istream(&m_membuf); + + if (field_input) + m_inp_str = new StreamFieldInput(m_ip_pic_ptr, sparams); + else + m_inp_str = new StreamFrameInput(m_ip_pic_ptr, sparams); +} + +MemoryStreamInput::~MemoryStreamInput() +{ + delete m_ip_pic_ptr; + delete m_inp_str; +} + +void MemoryStreamInput::SetMembufReference (unsigned char *buf, int buf_size) +{ + m_membuf.SetMembufReference(buf, buf_size); +} + +FileStreamInput::FileStreamInput(const char* input_name, + const SourceParams &sparams, + bool interlace) +{ + + char input_name_yuv[FILENAME_MAX]; + + strncpy(input_name_yuv, input_name, sizeof(input_name_yuv)); + //strcat(input_name_yuv, ".yuv"); + + //picture input + m_ip_pic_ptr = + new std::ifstream(input_name_yuv,std::ios::in | std::ios::binary); + + if (!(*m_ip_pic_ptr)) + std::cerr << std::endl<< + "Can't open input picture data file: " << + input_name_yuv << std::endl; + + if (interlace) + m_inp_str = new StreamFieldInput(m_ip_pic_ptr, sparams); + else + m_inp_str = new StreamFrameInput(m_ip_pic_ptr, sparams); + +} + +FileStreamInput::~FileStreamInput() +{ + static_cast<std::ifstream *>(m_ip_pic_ptr)->close(); + delete m_ip_pic_ptr; + delete m_inp_str; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/pic_io.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/pic_io.h new file mode 100644 index 000000000..375b4c033 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/pic_io.h @@ -0,0 +1,528 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: pic_io.h,v 1.19 2008/06/19 10:17:17 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott Robert Ladd, +* Stuart Cunningham, +* Tim Borer, +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _PIC_IO_H_ +#define _PIC_IO_H_ + +#include <iostream> +#include <fstream> +#include <streambuf> + +#include <libdirac_common/common.h> +#include <libdirac_common/picture.h> + +namespace dirac +{ + + ////////////////////////////////////////// + //--------------------------------------// + //- -// + //-Uncompressed picture file IO wrapper-// + //- -// + //--------------------------------------// + ////////////////////////////////////////// + + // Stream classes for writing/reading frames of uncompressed/decoded data + // to stream. Streams currently supported are Memory based streams and + // File based streams. These classes need further restructuring. + // Anu - 19-11-2004 + + // Subclass these to provide functionality for different file formats and + // for streaming. + + + //! Class for outputting pictures + + + /*! + Abstract base class for classes that output frames to stream + */ + class StreamPicOutput + { + public: + //! Constructor + /*! + Constructor, takes + \param op_ptr the output stream object + \param sp the source parameters + */ + StreamPicOutput( std::ostream* op_ptr, const SourceParams& sp); + + //! virtual Destructor + virtual ~StreamPicOutput(); + + //! Write a picture to the next frame to be output + virtual bool WriteToNextFrame(const Picture& myframe) = 0; + + //! Get the source parameters + SourceParams& GetSourceParams() {return m_sparams;} + + protected: + //! Source parameters + SourceParams m_sparams; + //! Output stream + std::ostream* m_op_pic_ptr; + + //! Body-less default Constructor + StreamPicOutput(); + private: + + }; + + class StreamFrameOutput : public StreamPicOutput + { + public: + + /*! + Constructor, takes + \param op_ptr the output stream object + \param sp the source parameters + */ + StreamFrameOutput( std::ostream *op_ptr, const SourceParams& sp); + + //! virtual Destructor + virtual ~StreamFrameOutput(); + + //! Write the next frame to the output + bool WriteToNextFrame(const Picture& myframe); + + protected: + //! Write a frame component to file + bool WriteFrameComponent(const PicArray& pic_data, + const CompSort& cs); + private: + //! Body-less Default Constructor + StreamFrameOutput(); + }; + + class StreamFieldOutput : public StreamPicOutput + { + public: + //! Constructor + /*! + Constructor, takes + \param op_ptr the output stream object + \param sp the source parameters + */ + StreamFieldOutput( std::ostream *op_ptr, const SourceParams& sp); + + //! virtual Destructor + virtual ~StreamFieldOutput(); + + //! Write a field to the next frame to be output + bool WriteToNextFrame(const Picture& myfield); + + protected: + //! Write a field component to file + bool WriteFieldComponent(const PicArray& pic_data, + int field_num, + const CompSort& cs); + + private: + //! Body-less Default Constructor + StreamFieldOutput(); + unsigned char *m_frame_store; + }; + + /*! + Outputs pictures to a memory buffer + */ + class MemoryStreamOutput + { + public: + //! Constructor + MemoryStreamOutput(SourceParams &sparams, bool interlace); + + //! Destructor + ~MemoryStreamOutput(); + + //! Get source parameters + SourceParams& GetSourceParams() + { return m_op_pic_str->GetSourceParams();} + + StreamPicOutput *GetStream() { return m_op_pic_str; } + //! Set the memory buffer to write the data to + void SetMembufReference (unsigned char *buf, int buf_size); + + protected: + //! Body-less default Constructor + MemoryStreamOutput(); + //! Body-less copy constructor + MemoryStreamOutput(const MemoryStreamOutput&); + //! Body-less assignment operator + MemoryStreamOutput & operator =(const MemoryStreamOutput&); + + protected: + + //! local memory buffer + class OutputMemoryBuffer : public std::streambuf + { + public: + //! Memory buffer constructor + OutputMemoryBuffer () : + m_op_buf(0), + m_op_buf_size(0), + m_op_idx(0) + {} + + //! Set the buffer variables + /*! Set the memory buffer variables + \param buffer buffer to write data to + \param buffer_size size of output buffer + */ + void SetMembufReference (unsigned char *buffer, int buffer_size) + { + m_op_buf = buffer; + m_op_buf_size = buffer_size; + m_op_idx = 0; + } + + protected: + //! Memory buffer to write data to + unsigned char *m_op_buf; + //! Memory buffer size + int m_op_buf_size; + //! Index of first available byte in buffer + int m_op_idx; + + //! Write Overflow method to write one char at a time + virtual int overflow (int c) + { + if ( c != EOF) + { + if (m_op_idx == m_op_buf_size) + return EOF; + + m_op_buf[m_op_idx] = (char)c; + m_op_idx++; + } + return c; + } + + //! xsputn method to write one multiple chars at a time to buffer + virtual std::streamsize xsputn (const char *s, + std::streamsize num) + { + std::streamsize bytes_left = m_op_buf_size - m_op_idx; + std::streamsize bytes_written = bytes_left > num + ? num : bytes_left; + memcpy (&m_op_buf[m_op_idx], (unsigned char *)s, + bytes_written); + m_op_idx += bytes_written; + return bytes_written; + } + + private: + //! Body-less copy constructor + OutputMemoryBuffer(const OutputMemoryBuffer&); + //! Body-less assignment operator + OutputMemoryBuffer& operator =(const OutputMemoryBuffer&); + }; + + private: + //! Output stream Memory buffer + OutputMemoryBuffer m_membuf; + //! Physical Output stream + std::ostream* m_op_pic_ptr; + //! Pic output Stream + StreamPicOutput *m_op_pic_str; + }; + + /*! + Outputs pictures to a file + */ + class FileStreamOutput + { + public: + + //! Constructor + /*! + Constructor, takes + \param output_name the name of the output file + \param sp the source parameters + \param interlace the output is interlaced + */ + FileStreamOutput (const char* output_name, + const SourceParams& sp, bool interlace); + + //! Destructor + virtual ~FileStreamOutput (); + + StreamPicOutput *GetStream() { return m_op_pic_str; } + private: + //! Physical Output stream + std::ostream* m_op_pic_ptr; + //! Pic output Stream + StreamPicOutput *m_op_pic_str; + }; + + //! Picture input class + /*! + Abstract Class for reading picture data from a stream. + */ + + class StreamPicInput + { + public: + + //! Default Constructor + StreamPicInput(); + //! Constructor + /*! + Constructor, takes + \param ip_pic_ptr input stream to read from + \param sparams Source parameters + */ + StreamPicInput(std::istream *ip_pic_ptr, const SourceParams& sparams); + + //! Destructor + virtual ~StreamPicInput(); + + //! Skip n frames of input + virtual void Skip( const int n)= 0; + + //! Read the next picture frame/field from the file + virtual bool ReadNextPicture(Picture& mypic) = 0; + + //! Get the source parameters + SourceParams& GetSourceParams() const {return m_sparams;} + + //! Returns true if we're at the end of the input, false otherwise + bool End() const ; + + protected: + + //! Source parameters + mutable SourceParams m_sparams; + + //! Input stream + std::istream* m_ip_pic_ptr; + + }; + + class StreamFrameInput : public StreamPicInput + { + public: + + //! Default Constructor + StreamFrameInput(); + //! Constructor + /*! + Constructor, takes + \param ip_pic_ptr input stream to read from + \param sparams Source parameters + */ + StreamFrameInput(std::istream *ip_pic_ptr, const SourceParams& sparams); + + //! Destructor + virtual ~StreamFrameInput(); + + //! Skip n frames of input + virtual void Skip( const int n); + + //! Read the next frame from the file + virtual bool ReadNextPicture(Picture& myframe); + + private: + + //! Read a Frame component from the file + bool ReadFrameComponent(PicArray& pic_data,const CompSort& cs); + + }; + + class StreamFieldInput : public StreamPicInput + { + public: + + //! Default Constructor + StreamFieldInput(); + //! Constructor + /*! + Constructor, takes + \param ip_pic_ptr input stream to read from + \param sparams Source parameters + */ + StreamFieldInput(std::istream *ip_pic_ptr, const SourceParams& sparams); + + //! Destructor + virtual ~StreamFieldInput(); + + //! Skip n frames of input + virtual void Skip( const int n); + + //! Read the next field from the file + virtual bool ReadNextPicture(Picture& myfield); + + //! Read the next frame from the file + bool ReadNextFrame(Picture& field1, Picture& field2); + + protected: + //! Read both Field components from the file + bool ReadFieldComponent(PicArray& pic_data1, + PicArray& pic_data2, + const CompSort& cs); + + //! Read one Field component from the file + bool ReadFieldComponent(bool is_field1, PicArray& pic_data, + const CompSort& cs); + }; + /*! + Class for reading picture data from memory + */ + class MemoryStreamInput + { + public: + //! Constructor + /*! Create a MemoryStreamInput object + \param sparams Source parameters + \param field_input Treat input as fields, not frames + */ + MemoryStreamInput(SourceParams& sparams, bool field_input); + + //! Destructor + ~MemoryStreamInput(); + + SourceParams& GetSourceParams ( ) + { return m_inp_str->GetSourceParams(); } + + //! Set Memory buffer + /*! Set the input memory buffer variables + \param buf Input Buffer to read data from + \param buf_size Input buffer size + */ + void SetMembufReference (unsigned char *buf, int buf_size); + + //! Return the input stream + StreamPicInput *GetStream() { return m_inp_str; } + protected: + //! Body-less copy constructor + MemoryStreamInput(const MemoryStreamInput&); + //! Body-less assignment operator + MemoryStreamInput & operator =(const MemoryStreamInput&); + + protected: + //! Class that defines the Input Stream Memory Buffer + class InputMemoryBuffer : public std::streambuf + { + public: + //! Constructor + InputMemoryBuffer() : m_buffer(0), m_buffer_size(0) + { + setg ((char *)m_buffer, (char *)m_buffer, (char *)m_buffer); + } + + //! Destructor + ~InputMemoryBuffer(){} + + //! Set Input Memory buffer variables + /*! Initialises the input memory buffer vars + \param buffer Input memory buffer + \param buffer_size Input memory buffer size + */ + void SetMembufReference (unsigned char *buffer, int buffer_size) + { + m_buffer = buffer; + m_buffer_size = buffer_size; + + setg ((char *)m_buffer, (char *)m_buffer, + (char *)(m_buffer + buffer_size)); + } + + private: + //! Body-less copy constructor + InputMemoryBuffer (const InputMemoryBuffer& inbuf); + //! Body-less assignment operator + InputMemoryBuffer& operator = (const InputMemoryBuffer& inbuf); + + //! Input memory buffer + unsigned char *m_buffer; + //! Input memory buffer size + int m_buffer_size; + }; + + private: + //! Input stream buffer + InputMemoryBuffer m_membuf; + + //! Input Stream Object + StreamPicInput *m_inp_str; + + //! Input stream + std::istream* m_ip_pic_ptr; + }; + + //! Picture input class + /*! + Class for reading picture data from a file. + */ + class FileStreamInput + { + public: + + //! Constructor + /*! + Constructor, takes + \param input_name the name of the input picture file + \param sparams the source parameters + \param interlace input is treated as interlaced + */ + FileStreamInput (const char* input_name, const SourceParams &sparams, bool interlace); + + //! Destructor + virtual ~FileStreamInput (); + + SourceParams& GetSourceParams ( ) + { return m_inp_str->GetSourceParams(); } + + //! Return the input stream + StreamPicInput *GetStream() { return m_inp_str; } + + private: + StreamPicInput *m_inp_str; + + //! Input stream + std::istream* m_ip_pic_ptr; + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture.cpp new file mode 100644 index 000000000..ee3da95a3 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture.cpp @@ -0,0 +1,337 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture.cpp,v 1.4 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author)
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+//Implementation of picture classes in picture.h
+
+#include <libdirac_common/picture.h>
+#include <libdirac_common/upconvert.h>
+using namespace dirac;
+
+#include <iostream>
+#if defined(HAVE_MMX)
+#include <mmintrin.h>
+#endif
+
+///////////////
+//---Picture---//
+///////////////
+
+Picture::Picture(const PictureParams& pp):
+ m_pparams(pp)
+{
+ for (int c=0;c<3;++c){
+ m_pic_data[c] = NULL;
+ m_up_pic_data[c] = NULL;
+ }
+
+ Init();
+}
+
+Picture::Picture( const Picture& cpy ):
+ m_pparams(cpy.m_pparams)
+{
+
+ //delete data to be overwritten
+ for (int c=0;c<3;++c){
+ m_pic_data[c] = NULL;
+ m_up_pic_data[c] = NULL;
+ }
+
+ //now copy the data across
+ for (int c=0; c<3; ++c ){
+ m_pic_data[c] = new PicArray( *(cpy.m_pic_data[c]) );
+ if (cpy.m_up_pic_data[c] != NULL)
+ m_up_pic_data[c] = new PicArray( *(cpy.m_up_pic_data[c]) );
+ }
+
+}
+
+
+Picture::~Picture()
+{
+ ClearData();
+}
+
+Picture& Picture::operator=(const Picture& rhs)
+{
+ if ( &rhs != this)
+ {
+ m_pparams=rhs.m_pparams;
+
+ // Delete current data
+ ClearData();
+
+ // Copy the data across
+ for (int c=0; c<3; ++c ){
+ m_pic_data[c] = new PicArray( *(rhs.m_pic_data[c]) );
+
+ if (rhs.m_up_pic_data[c] != NULL)
+ m_up_pic_data[c] = new PicArray( *(rhs.m_up_pic_data[c]) );
+ }
+ }
+
+ return *this;
+
+}
+
+void Picture::Fill(ValueType val)
+{
+ for (int c=0; c<3; ++c ){
+ m_pic_data[c]->Fill(val);
+ if (m_up_pic_data[c] != NULL )
+ delete m_up_pic_data[c];
+ }
+}
+
+//Other functions
+
+void Picture::Init()
+{
+ //const ChromaFormat cformat=m_pparams.CFormat();
+
+ //first delete data if we need to
+ ClearData();
+
+ m_pic_data[0]=new PicArray( m_pparams.Yl() , m_pparams.Xl());
+ m_pic_data[0]->SetCSort( Y_COMP );
+
+ m_pic_data[1] = new PicArray( m_pparams.ChromaYl() ,
+ m_pparams.ChromaXl() );
+ m_pic_data[1]->SetCSort( U_COMP );
+
+ m_pic_data[2] = new PicArray( m_pparams.ChromaYl() ,
+ m_pparams.ChromaXl() );
+ m_pic_data[2]->SetCSort( V_COMP );
+}
+
+PicArray& Picture::UpData(CompSort cs)
+{
+ const int c = (int) cs;
+
+ if (m_up_pic_data[c] != NULL )
+ return *(m_up_pic_data[c]);
+ else
+ {//we have to do the upconversion
+
+ m_up_pic_data[c] = new PicArray( 2*m_pic_data[c]->LengthY(),
+ 2*m_pic_data[c]->LengthX() );
+ UpConverter* myupconv;
+ if (c>0)
+ myupconv = new UpConverter(-(1 << (m_pparams.ChromaDepth()-1)),
+ (1 << (m_pparams.ChromaDepth()-1))-1,
+ m_pparams.ChromaXl(), m_pparams.ChromaYl());
+ else
+ myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
+ (1 << (m_pparams.LumaDepth()-1))-1,
+ m_pparams.Xl(), m_pparams.Yl());
+
+ myupconv->DoUpConverter( *(m_pic_data[c]) , *(m_up_pic_data[c]) );
+
+ delete myupconv;
+
+ return *(m_up_pic_data[c]);
+
+ }
+}
+
+const PicArray& Picture::UpData(CompSort cs) const
+{
+ const int c = (int) cs;
+
+ if (m_up_pic_data[c] != NULL)
+ return *(m_up_pic_data[c]);
+ else
+ {//we have to do the upconversion
+
+ m_up_pic_data[c] = new PicArray( 2*m_pic_data[c]->LengthY(),
+ 2*m_pic_data[c]->LengthX() );
+ UpConverter* myupconv;
+ if (c>0)
+ myupconv = new UpConverter(-(1 << (m_pparams.ChromaDepth()-1)),
+ (1 << (m_pparams.ChromaDepth()-1))-1,
+ m_pparams.ChromaXl(), m_pparams.ChromaYl());
+ else
+ myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
+ (1 << (m_pparams.LumaDepth()-1))-1,
+ m_pparams.Xl(), m_pparams.Yl());
+
+ myupconv->DoUpConverter( *(m_pic_data[c]) , *(m_up_pic_data[c]) );
+
+ delete myupconv;
+
+ return *(m_up_pic_data[c]);
+
+ }
+}
+
+void Picture::InitWltData( const int transform_depth )
+{
+
+ int xpad_len, ypad_len;
+ int tx_mul = 1<<transform_depth;
+
+ for (int c=0; c<3; ++c){
+ xpad_len = m_pic_data[c]->LengthX();
+ ypad_len = m_pic_data[c]->LengthY();
+
+ if ( xpad_len%tx_mul != 0 )
+ xpad_len = ( (xpad_len/tx_mul)+1 ) *tx_mul;
+ if ( ypad_len%tx_mul != 0 )
+ ypad_len = ( (ypad_len/tx_mul)+1 ) * tx_mul;
+
+ m_wlt_data[c].Resize( ypad_len, xpad_len );
+ }
+
+}
+
+void Picture::ClipComponent(PicArray& pic_data, CompSort cs) const
+{
+ ValueType *pic = &(pic_data[pic_data.FirstY()][pic_data.FirstX()]);
+ int count = pic_data.LengthY() * pic_data.LengthX();
+
+ ValueType min_val;
+ ValueType max_val;
+
+ min_val = (cs == Y_COMP) ?
+ -(1 << (m_pparams.LumaDepth()-1) ) :
+ -(1 << (m_pparams.ChromaDepth()-1) );
+
+ max_val = (cs == Y_COMP) ?
+ (1 << (m_pparams.LumaDepth()-1) )-1 :
+ (1 << (m_pparams.ChromaDepth()-1) )-1;
+
+#if defined (HAVE_MMX)
+ {
+ int qcount = count >> 2;
+ count = count & 3;
+
+ //__m64 pack_usmax = _mm_set_pi16 (0xffff, 0xffff, 0xffff, 0xffff);
+ //__m64 pack_smin = _mm_set_pi16 (0x8000, 0x8000, 0x8000, 0x8000);
+ __m64 pack_usmax = _mm_set_pi16 (-1, -1, -1, -1);
+ __m64 pack_smin = _mm_set_pi16 (-32768, -32768, -32768, -32768);
+ __m64 high_val = _mm_set_pi16 (max_val, max_val, max_val, max_val);
+ __m64 lo_val = _mm_set_pi16 (min_val, min_val, min_val, min_val);
+
+ __m64 clip_max = _mm_add_pi16 (pack_smin, high_val);
+ __m64 clip_min = _mm_add_pi16 (pack_smin, lo_val);
+
+ __m64 tmp1 = _mm_subs_pu16 ( pack_usmax, clip_max);
+ __m64 tmp2 = _mm_adds_pu16 ( clip_min, tmp1 );
+
+ while (qcount--)
+ {
+ ValueType *p1 = pic;
+ *(__m64 *)p1 = _mm_add_pi16 (pack_smin, *(__m64 *)p1);
+ *(__m64 *)p1 = _mm_adds_pu16 (*(__m64 *)p1, tmp1);
+ *(__m64 *)p1 = _mm_subs_pu16 (*(__m64 *)p1, tmp2);
+ *(__m64 *)p1 = _mm_add_pi16 (lo_val, *(__m64 *)p1);
+ pic += 4;
+ }
+ //Mop up remaining pixels
+ while( count-- )
+ {
+ *pic = std::max( min_val, std::min( max_val , *pic )
+ );
+ pic++;
+ }
+
+ _mm_empty();
+ return;
+ }
+#endif
+
+ // NOTE: depending on a contigous chunk of memory being allocated
+ while (count--)
+ {
+ *pic = std::max( min_val, std::min( max_val, *pic ));
+ pic++;
+ }
+}
+
+void Picture::Clip()
+{
+ //just clips the straight picture data, not the upconverted data
+
+ for (int c=0; c<3; ++c)
+ ClipComponent( *(m_pic_data[c]), (CompSort) c);
+}
+
+void Picture::ClipUpData()
+{
+ //just clips the upconverted data
+
+ for (int c=0; c<3; ++c){
+ if (m_up_pic_data[c])
+ ClipComponent( *(m_up_pic_data[c]), (CompSort) c );
+ }
+
+}
+
+void Picture::ClearData()
+{
+ for (int c=0;c<3;++c){
+ if (m_pic_data[c] != NULL){
+ delete m_pic_data[c];
+ m_pic_data[c] = NULL;
+ }
+
+ if (m_up_pic_data[c] != NULL){
+ delete m_up_pic_data[c];
+ m_up_pic_data[c] = NULL;
+ }
+ }
+
+}
+
+void Picture::ReconfigPicture(const PictureParams &pp )
+{
+
+ PictureParams old_pp = m_pparams;
+ m_pparams = pp;
+
+ // HAve picture dimensions or Chroma format changed ?
+ if (m_pparams.Xl() == old_pp.Xl() &&
+ m_pparams.Yl() == old_pp.Yl() &&
+ m_pparams.CFormat() == old_pp.CFormat())
+ return;
+
+ // Picture dimensions have changed. Re-initialise
+ Init();
+}
+
+
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture.h new file mode 100644 index 000000000..face2d15d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture.h @@ -0,0 +1,149 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture.h,v 1.4 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author)
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef _PICTURE_H_
+#define _PICTURE_H_
+
+#include <libdirac_common/common.h>
+#include <libdirac_common/wavelet_utils.h>
+
+namespace dirac
+{
+ //! A class for encapsulating all the data relating to a picture.
+ /*!
+ A class for encapsulating all the data relating to a picture - all the
+ component data, including upconverted data.
+ */
+ class Picture
+ {
+
+ public:
+
+ //! Constructor
+ /*!
+ Constructor initialises the picture parameters and the data
+ */
+ Picture( const PictureParams& pp );
+
+ //! Copy constructor. Private as not currently used [may want to implement reference counting later.]
+ Picture(const Picture& cpy);
+
+ //! Destructor
+ virtual ~Picture();
+
+ //! Assignment =. Private as not currently used [may want to implement reference counting later.]
+ Picture& operator=( const Picture& rhs );
+
+ //! Picture Fill
+ /*!
+ Initialise contents of picture with value provided
+ */
+ void Fill(ValueType val );
+
+ //gets and sets
+ //! Gets the picture parameters
+ PictureParams& GetPparams() const {return m_pparams;}
+
+ //! Sets the picture sort
+ void SetPictureSort( const PictureSort ps ){m_pparams.SetPicSort( ps ); }
+
+ //! Sets the picture type
+ void SetPictureType( const PictureType ftype ){m_pparams.SetPictureType( ftype ); }
+
+ //! Sets the picture type
+ void SetReferenceType( const ReferenceType rtype ){m_pparams.SetReferenceType( rtype ); }
+
+ //! Reconfigures to the new parameters.
+ void ReconfigPicture( const PictureParams &pp );
+
+ //! Returns a given component
+ PicArray& Data(CompSort cs){return *m_pic_data[(int) cs];}
+
+ //! Returns a given component
+ const PicArray& Data(CompSort cs) const{return *m_pic_data[(int) cs];}
+
+ //! Returns a given upconverted component
+ PicArray& UpData(CompSort cs);
+
+ //! Returns a given upconverted component
+ const PicArray& UpData(CompSort cs) const;
+
+ //! Returns the wavelet coefficient data
+ const CoeffArray& WltData( CompSort c ) const { return m_wlt_data[(int) c]; }
+
+ //! Returns the wavelet coefficient data
+ CoeffArray& WltData( CompSort c ) { return m_wlt_data[(int) c]; }
+
+ //! Initialises the wavelet coefficient data arrays;
+ void InitWltData( const int transform_depth );
+
+ //! Clip the data to prevent overshoot
+ /*!
+ Clips the data to lie between 0 and (1<<video_depth)-1
+ */
+ void Clip();
+
+ //! Clip the upconverted data to prevent overshoot
+ /*!
+ Clips the upconverted data to lie between 0 and (1<<video_depth)-1
+ */
+ void ClipUpData();
+
+ protected:
+ mutable PictureParams m_pparams;
+ PicArray* m_pic_data[3];//the picture data
+ mutable PicArray* m_up_pic_data[3];//upconverted data. Mutable because we
+ //create them on the fly even in const
+ //functions.
+
+ CoeffArray m_wlt_data[3];// the wavelet coefficient data
+
+ //! Initialises the picture once the picture parameters have been set
+ virtual void Init();
+
+ //! Delete all the data
+ virtual void ClearData();
+
+ //! Clip an individual component
+ void ClipComponent(PicArray& pic_data, CompSort cs) const;
+
+ };
+
+} // namespace dirac
+
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture_buffer.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture_buffer.cpp new file mode 100644 index 000000000..cbd311003 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture_buffer.cpp @@ -0,0 +1,265 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_buffer.cpp,v 1.7 2008/06/19 10:07:03 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Scott R Ladd,
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#include <libdirac_common/picture_buffer.h>
+#include <algorithm>
+using namespace dirac;
+
+//Simple constructor for decoder operation
+PictureBuffer::PictureBuffer(){}
+
+//Copy constructor. Why anyone would need this I don't know.
+PictureBuffer::PictureBuffer(const PictureBuffer& cpy)
+ {
+ // first delete all frames in the current buffer
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ delete m_pic_data[i];
+ }//i
+
+ // next create new arrays, copying from the initialising buffer
+ m_pic_data.resize(cpy.m_pic_data.size());
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i){
+ m_pic_data[i] = new Picture( *(cpy.m_pic_data[i]) );
+ }//i
+
+ // now copy the map
+ m_pnum_map = cpy.m_pnum_map;
+
+// // and the reference count
+// m_ref_count = cpy.m_ref_count;
+
+}
+
+//Assignment=. Not sure why this would be used either.
+PictureBuffer& PictureBuffer::operator=(const PictureBuffer& rhs){
+ if (&rhs!=this)
+ {
+ // delete all the frames in the lhs buffer
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ delete m_pic_data[i];
+ }//i
+
+ // next create new arrays, copying from the rhs
+ m_pic_data.resize(rhs.m_pic_data.size());
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ m_pic_data[i] = new Picture( *(rhs.m_pic_data[i]) );
+ }//i
+
+ // now copy the map
+ m_pnum_map = rhs.m_pnum_map;
+
+// // and the reference count
+// m_ref_count = rhs.m_ref_count;
+
+ }
+ return *this;
+}
+
+//Destructor
+PictureBuffer::~PictureBuffer()
+{
+ for (size_t i=0 ; i<m_pic_data.size() ;++i)
+ delete m_pic_data[i];
+}
+
+Picture& PictureBuffer::GetPicture( const unsigned int pnum )
+{//get picture with a given picture number, NOT with a given position in the buffer.
+ //If the picture number does not occur, the first picture in the buffer is returned.
+
+ std::map<unsigned int,unsigned int>::iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos = 0;
+ if (it != m_pnum_map.end())
+ pos = it->second;
+
+ return *(m_pic_data[pos]);
+}
+
+const Picture& PictureBuffer::GetPicture( const unsigned int pnum ) const
+{ //as above, but const version
+
+ std::map<unsigned int,unsigned int>::const_iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos=0;
+ if (it != m_pnum_map.end())
+ pos = it->second;
+
+ return *(m_pic_data[pos]);
+}
+
+Picture& PictureBuffer::GetPicture( const unsigned int pnum, bool& is_present )
+{//get picture with a given picture number, NOT with a given position in the buffer.
+ //If the picture number does not occur, the first picture in the buffer is returned.
+
+ std::map<unsigned int,unsigned int>::iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos = 0;
+ if (it != m_pnum_map.end())
+ {
+ is_present = true;
+ pos = it->second;
+ }
+ else
+ is_present=false;
+
+ return *(m_pic_data[pos]);
+}
+
+const Picture& PictureBuffer::GetPicture( const unsigned int pnum, bool& is_present ) const
+{ //as above, but const version
+
+ std::map<unsigned int,unsigned int>::const_iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos=0;
+ if (it != m_pnum_map.end())
+ {
+ is_present = true;
+ pos = it->second;
+ }
+ else
+ is_present=false;
+
+ return *(m_pic_data[pos]);
+}
+
+bool PictureBuffer::IsPictureAvail( const unsigned int pnum ) const
+{
+
+ std::map<unsigned int,unsigned int>::const_iterator it = m_pnum_map.find(pnum);
+
+ if (it != m_pnum_map.end())
+ return true;
+ else
+ return false;
+}
+
+std::vector<int> PictureBuffer::Members() const
+{
+ std::vector<int> members( 0 );
+ for (unsigned int i=0; i<m_pic_data.size(); ++i )
+ {
+ const PictureParams& pparams = m_pic_data[i]->GetPparams();
+ members.push_back( pparams.PictureNum() );
+ }// i
+
+ return members;
+}
+
+void PictureBuffer::PushPicture( const PictureParams& pp )
+{// Put a new picture onto the top of the stack
+
+ // if picture is present - return
+ if (IsPictureAvail(pp.PictureNum()))
+ return;
+
+// if ( pp.PicSort().IsRef() )
+// m_ref_count++;
+
+ Picture* pptr = new Picture(pp);
+ // add the picture to the buffer
+ m_pic_data.push_back(pptr);
+
+ // put the picture number into the index table
+ std::pair<unsigned int,unsigned int> temp_pair(pp.PictureNum() , m_pic_data.size()-1 );
+ m_pnum_map.insert(temp_pair);
+}
+
+void PictureBuffer::CopyPicture( const Picture& picture )
+{
+ PushPicture(picture.GetPparams());
+
+ bool is_present;
+
+ Picture & p= GetPicture(picture.GetPparams().PictureNum(), is_present);
+ if(is_present)
+ p = picture;
+}
+
+void PictureBuffer::ClearSlot(const unsigned int pos)
+{
+ // Clear a slot corresponding to position pos to take more data
+
+ std::pair<unsigned int,unsigned int>* tmp_pair;
+
+ if (pos<m_pic_data.size())
+ {
+ delete m_pic_data[pos];
+ m_pic_data.erase( m_pic_data.begin()+pos );
+
+ //make a new map
+ m_pnum_map.clear();
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ tmp_pair = new std::pair<unsigned int,unsigned int>( m_pic_data[i]->GetPparams().PictureNum() , i);
+ m_pnum_map.insert(*tmp_pair);
+ delete tmp_pair;
+ }//i
+ }
+}
+
+
+void PictureBuffer::SetRetiredPictureNum(const int show_pnum, const int current_coded_pnum)
+{
+ if ( IsPictureAvail(current_coded_pnum))
+ {
+ PictureParams &pparams = GetPicture(current_coded_pnum).GetPparams();
+ pparams.SetRetiredPictureNum(-1);
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ if (m_pic_data[i]->GetPparams().PicSort().IsRef() ){
+ if ( (m_pic_data[i]->GetPparams().PictureNum() + m_pic_data[i]->GetPparams().ExpiryTime() ) <= show_pnum){
+ pparams.SetRetiredPictureNum(m_pic_data[i]->GetPparams().PictureNum());
+ break;
+ }
+ }
+ }//i
+ }
+}
+
+void PictureBuffer::Remove(const int pnum)
+{
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i){
+ if ( m_pic_data[i]->GetPparams().PictureNum() == pnum)
+ ClearSlot(i);
+ }//i
+}
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture_buffer.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture_buffer.h new file mode 100644 index 000000000..86613720e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/picture_buffer.h @@ -0,0 +1,198 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_buffer.h,v 1.4 2008/06/19 10:07:03 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef _PICTURE_BUFFER_H_
+#define _PICTURE_BUFFER_H_
+
+#include <vector>
+#include <map>
+#include <libdirac_common/picture.h>
+#include <libdirac_common/common.h>
+
+namespace dirac
+{
+ //! Holds pictures both for reference and to overcome reordering delay
+ /*!
+ The buffer holds pictures in a stack to overcome both reordering due to
+ bi-directional prediction and use as references for subsequence motion
+ estimation. Pictures, and components of pictures, can be accessed by their
+ picture numbers. GOP parameters can be included in the constructors so
+ that pictures can be given types (I picture, L1 picture or L2 picture) on
+ being pushed onto the stack; alternatively, these parameters can be
+ overridden.
+ */
+ class PictureBuffer{
+ public:
+ //! Default Constructor
+ PictureBuffer();
+
+ //! Constructor
+ /*!
+ Creates a PictureBuffer using the chroma format. Suitable for
+ compressing when there are no L2 pictures, or when the temporal
+ prediction structure is to be determined on the fly.
+
+ \param cf the Chroma format of pictures in the buffer
+ \param xlen the luma width of pictures in the buffer
+ \param ylen the luma height of pictures in the buffer
+ \param luma_depth the video depth of the luma comp in the buffer
+ \param chroma_depth the video depth of the chroma comp in the buffer
+ \param using_ac True if using Arithmetic coding to code coefficient data
+
+ */
+ PictureBuffer(ChromaFormat cf,
+ const int xlen,
+ const int ylen,
+ const unsigned int luma_depth,
+ const unsigned int chroma_depth,
+ bool using_ac);
+
+ //! Constructor
+ /*!
+ Creates a PictureBuffer using the chroma format, the number of L1
+ pictures between I pictures and the separation in pictures between L1
+ pictures. Suitable for compressing when there is a full GOP structure
+ or when the temporal prediction structure is to be determined on
+ the fly.
+
+ \param cf the Chroma format of pictures in the buffer
+ \param numL1 the number of Layer 1 pictures before the next I picture. 0 means that there is only one I picture.
+ \param L1sep the number of Layer 2 pictures between Layer 1 pictures
+ \param xlen the luma width of pictures in the buffer
+ \param ylen the luma height of pictures in the buffer
+ \param luma_depth the video depth of the luma comp in the buffer
+ \param chroma_depth the video depth of the chroma comp in the buffer
+ \param interlace Set true if material is being coded in interlaced mode
+ \param using_ac True if using Arithmetic coding to code coefficient data
+ */
+ PictureBuffer(ChromaFormat cf,
+ const int numL1,
+ const int L1sep,
+ const int xlen,
+ const int ylen,
+ const unsigned int luma_depth,
+ const unsigned int chroma_depth,
+ bool interlace,
+ bool using_ac);
+
+ //! Copy constructor
+ /*!
+ Copy constructor. Removes the current contents of the pictureture buffer
+ and copies in the contents of the initialising buffer.
+ */
+ PictureBuffer(const PictureBuffer& cpy);
+
+ //! Operator=.
+ /*!
+ Operator=. Assigns all elements of the rhs to the lhs.
+ */
+ PictureBuffer& operator=(const PictureBuffer& rhs);
+
+ //! Destructor
+ ~PictureBuffer();
+
+ //! Get picture with a given picture number (NOT with a given position in the buffer)
+ Picture& GetPicture(const unsigned int pnum );
+
+ //! Get picture with a given picture number (NOT with a given position in the buffer)
+ const Picture& GetPicture(const unsigned int pnum) const;
+
+ //! Get picture with a given picture number, setting a flag to true if it's there
+ Picture& GetPicture(const unsigned int pnum, bool& is_present);
+
+ //! Get picture with a given picture number, setting a flag to true if it's there
+ const Picture& GetPicture(const unsigned int pnum, bool& is_present) const;
+
+ //! Return true if picture with the particular picture number is available else return false
+ bool IsPictureAvail(const unsigned int pnum) const;
+
+ //! Returns a list of member pictures
+ std::vector<int> Members() const;
+
+ //! Put a new picture into the top of the buffer
+ /*!
+ Put a new picture into the top of the buffer. Picture parameters
+ associated with the picture will be as given by the picture parameter
+ object.
+ */
+ void PushPicture(const PictureParams& pp);
+
+ //! Put a copy of a new picture into the buffer
+ /*!
+ Put a copy of a new picture into the buffer.
+ */
+ void CopyPicture( const Picture& picture );
+
+ //! Sets the reference picture number that will be cleaned
+ /*!
+ Indicate which picture which has been output and which is no longer
+ required for reference. Expiry times are set in each picture's
+ picture parameters.
+ \param show_pnum picture number in display order that can be output
+ \param current_coded_pnum picture number in display order of picture currently being coded
+ */
+ void SetRetiredPictureNum(const int show_pnum, const int current_coded_pnum);
+
+ //! Delete picture
+ /*!
+ Delete picture.
+ \param pnum picture number in display order to be deleted from picture buffer
+ */
+ void Remove(int pnum);
+
+ private:
+ //! Clear internal data slot number pos
+ /*!
+ Clear internal data slot number pos
+ */
+ void ClearSlot(const unsigned int pos);
+
+// //! the count of the number of reference pictures in the buffer
+// int m_ref_count;
+
+ //! the buffer storing all the values
+ std::vector<Picture*> m_pic_data;
+
+ //!the map from picture numbers to position in the buffer
+ std::map<unsigned int,unsigned int> m_pnum_map;
+
+ };
+
+} // namespace dirac
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert.cpp new file mode 100644 index 000000000..5535a66da --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert.cpp @@ -0,0 +1,200 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: upconvert.cpp,v 1.11 2007/11/22 15:19:28 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Richard Felton (Original Author), Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/upconvert.h> +using namespace dirac; + +#include <iostream> + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define CLIP(x,min,max) MAX(MIN(x,max),min) + +UpConverter::UpConverter (int min_val, int max_val, int orig_xlen, int orig_ylen) : + m_min_val(min_val), + m_max_val(max_val), + m_orig_xl(orig_xlen), + m_orig_yl(orig_ylen) +{} + +//Up-convert by a factor of two. +void UpConverter::DoUpConverter(const PicArray& pic_data, PicArray& up_data) +{ + + m_width_old = std::min (pic_data.LengthX(), m_orig_xl); + m_height_old = std::min (pic_data.LengthY(), m_orig_yl); + m_width_new = std::min(2*m_width_old, up_data.LengthX()); + m_height_new = std::min(2*m_height_old, up_data.LengthY()); + + // Filter params + const int filter_size = 4; + const int filter_shift = 5; + const short taps[4] = {21,-7,3,-1}; + + + //Variables that will be used by the filter calculations + ValueType sum; + int ypos(0); + + + //There are three y loops to cope with the leading edge, middle + //and trailing edge of each column. + + for(int y = 0 ; y < filter_size; ++y , ypos += 2) + { + + //We are filtering each column but doing it bit by bit. + //This means our main loop is in the x direction and + //there is a much greater chance the data we need will + //be in the cache. + for(int x = 0 , xpos = 0; x < m_width_old; x++ , xpos+=2 ) + { + // Copy a Pixel from the original image in each even position + up_data[ypos][xpos] = pic_data[y][x]; + + //Work out the next pixel from filtered values. + //Excuse the complicated ternary stuff but it sorts out the edge + sum = 1 << (filter_shift-1); + sum += (pic_data[y][x] + pic_data[y+1][x]) * taps[0]; + sum += (pic_data[(y>=1)?(y-1):0][x] + pic_data[y+2][x]) * taps[1]; + sum += (pic_data[(y>=2)?(y-2):0][x] + pic_data[y+3][x]) * taps[2]; + sum += (pic_data[(y>=3)?(y-3):0][x] + pic_data[y+4][x]) * taps[3]; + + sum >>= filter_shift; + up_data[ypos+1][xpos] = CLIP(sum, m_min_val, m_max_val); + }// x, xpos + + // The row loop. + RowLoop( up_data , ypos, filter_size, filter_shift, taps ); + }// y, ypos + // This loop is like the last one but it deals with the centre + // section of the image and so the ternary operations are dropped + // from the filter section. + for(int y = filter_size; y < m_height_old - filter_size; ++y , ypos += 2) + { + for(int x = 0 , xpos=0; x < m_width_old; x++ , xpos+=2 ) + { + up_data[ypos][xpos] = pic_data[y][x]; + + sum = 1 << (filter_shift-1); + + for (int t=0; t<filter_size; ++t) + sum += (pic_data[y-t][x] + pic_data[y+1+t][x]) * taps[t]; + + sum >>= filter_shift; + up_data[ypos+1][xpos] = CLIP(sum, m_min_val, m_max_val); + }// x,xpos + RowLoop( up_data , ypos, filter_size, filter_shift, taps ); + + }// y, ypos + // Another similar loop! - this time we are dealing with + // the trailing edge so the ternary stuff is back in the + // filter calcs but in the second parameter. + for(int y = m_height_old - filter_size; y < m_height_old; ++y , ypos+=2) + { + for(int x = 0 , xpos=0 ; x < m_width_old; x++ , xpos+=2) + { + up_data[ypos][xpos]=pic_data[y][x]; + + sum = 1 << (filter_shift-1); + sum += (pic_data[y][x] + pic_data[((y+1)<m_height_old)?(y+1):(m_height_old-1)][x]) * taps[0]; + sum += (pic_data[y - 1][x] + pic_data[((y+2)<m_height_old)?(y+2):(m_height_old-1)][x]) * taps[1]; + sum += (pic_data[y - 2][x] + pic_data[((y+3)<m_height_old)?(y+3):(m_height_old-1)][x]) * taps[2]; + sum += (pic_data[y - 3][x] + pic_data[((y+4)<m_height_old)?(y+4):(m_height_old-1)][x]) * taps[3]; + + sum >>= filter_shift; + up_data[ypos+1][xpos] = CLIP(sum, m_min_val, m_max_val); + }//x,xpos + RowLoop( up_data , ypos, filter_size, filter_shift, taps ); + + }//y,ypos +} + +void UpConverter::RowLoop(PicArray&up_data, const int row_num, +const int filter_size, const int filter_shift, const short taps[4] ) +{ + const int dble_size( filter_size<<1 ); + + //Calculation variable + ValueType sum; + int ypos; + + //Leading row Edge + //Note the factor of two difference as we only want to fill in every other + //line as the others have already been created + for(int j = 0; j < 2; ++j) + { + ypos = row_num + j; + + for(int x = 0; x < dble_size ; x+=2) + { + sum = 1 << (filter_shift-1); + sum += (up_data[ypos][x] + up_data[ypos][x+2]) * taps[0]; + sum += (up_data[ypos][(x>=2)?(x-2):0] + up_data[ypos][x+4]) * taps[1]; + sum += (up_data[ypos][(x>=4)?(x-4):0] + up_data[ypos][x+6]) * taps[2]; + sum += (up_data[ypos][(x>=6)?(x-6):0] + up_data[ypos][x+8]) * taps[3]; + + + sum >>= filter_shift; + up_data[ypos][x+1] = CLIP(sum, m_min_val, m_max_val); + }// x + //Middle of row + for(int x = dble_size; x<m_width_new-dble_size ; x+=2 ) + { + sum = 1 << (filter_shift-1); + + for (int t=0; t<filter_size; ++t) + sum += (up_data[ypos][x-2*t] + up_data[ypos][x+2+2*t]) * taps[t]; + + + sum >>= filter_shift; + up_data[ypos][x+1] = CLIP(sum, m_min_val, m_max_val); + }// x + //Trailing row edge + for(int x = m_width_new - dble_size ; x<m_width_new ; x+=2) + { + sum = 1 << (filter_shift-1); + sum += (up_data[ypos][x] + up_data[ypos][(((x+2)<m_width_new)?(x+2):(m_width_new-2))]) * taps[0]; + sum += (up_data[ypos][x-2] + up_data[ypos][(((x+4)<m_width_new)?(x+4):(m_width_new-2))]) * taps[1]; + sum += (up_data[ypos][x-4] + up_data[ypos][(((x+6)<m_width_new)?(x+6):(m_width_new-2))]) * taps[2]; + sum += (up_data[ypos][x-6] + up_data[ypos][(((x+8)<m_width_new)?(x+8):(m_width_new-2))]) * taps[3]; + + sum >>= filter_shift; + up_data[ypos][x+1] = CLIP(sum, m_min_val, m_max_val); + }// x + } +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert.h new file mode 100644 index 000000000..94d81026e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert.h @@ -0,0 +1,98 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: upconvert.h,v 1.13 2007/11/22 15:19:28 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Richard Felton (Original Author), Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _UPCONVERT_H_ +#define _UPCONVERT_H_ + +#include <libdirac_common/common.h> + +namespace dirac +{ + //Optimised upconversion class - no array resizes. + //Uses integer math - no floats! + // + + //! Upconversion class + /*! + Class to upconvert data by a factor of 2 in both dimensions + */ + class UpConverter + { + + public: + + //! Constructor + UpConverter(int min_val, int max_val, int orig_xlen, int orig_ylen); + + //! Destructor + ~UpConverter() {}; + + //! Upconvert the picture data + /*! + Upconvert the picture data, where the parameters are + \param pic_data is the original data + \param up_data is the upconverted data + */ + void DoUpConverter(const PicArray& pic_data, PicArray& up_data); + + private: + //! Private body-less copy constructor: class should not be copied + UpConverter(const UpConverter& cpy); + + //! Private body-less assignment: class should not be assigned + UpConverter& operator=(const UpConverter& rhs); + + //! Applies the filter to a row and its successor + void RowLoop(PicArray& up_data, const int row_num, + const int filter_size, const int filter_shift, const short taps[4] ); + + private: + //Variable to keep the loops in check + int m_width_old, m_height_old; + int m_width_new, m_height_new; + + + const int m_min_val; + const int m_max_val; + + const int m_orig_xl; + const int m_orig_yl; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert_mmx.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert_mmx.cpp new file mode 100644 index 000000000..12f102714 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/upconvert_mmx.cpp @@ -0,0 +1,39 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: upconvert_mmx.cpp,v 1.7 2007/11/22 15:19:28 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Thomas Davies (upconvert.cpp) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +// MMX version deleted - new version TBC // diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/video_format_defaults.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/video_format_defaults.cpp new file mode 100644 index 000000000..683fd3065 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/video_format_defaults.cpp @@ -0,0 +1,534 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: video_format_defaults.cpp,v 1.36 2008/10/20 04:21:45 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author). +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <sstream> +#include <libdirac_common/video_format_defaults.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; + +namespace dirac +{ +void SetDefaultCodecParameters(CodecParams &cparams, + PictureType ptype, + unsigned int num_refs) +{ + std::ostringstream errstr; + // Transform parameters + cparams.SetZeroTransform(false); + cparams.SetTransformDepth(4); + WltFilter wf; + SetDefaultTransformFilter(ptype, cparams.GetVideoFormat(), wf); + cparams.SetTransformFilter(wf); + cparams.SetCodeBlockMode(QUANT_SINGLE); + cparams.SetSpatialPartition(false); + + // Default is set to progressive specified irrespective + // of whether the source material is interlaced or progressive. + // Overridden from command line of encoder or in bytestream for decoder. + cparams.SetPictureCodingMode(0); + cparams.SetTopFieldFirst(true); + switch (cparams.GetVideoFormat()) + { + case VIDEO_FORMAT_QSIF525: + case VIDEO_FORMAT_QCIF: + case VIDEO_FORMAT_CUSTOM: + case VIDEO_FORMAT_SIF525: + case VIDEO_FORMAT_CIF: + case VIDEO_FORMAT_4CIF: + case VIDEO_FORMAT_4SIF525: + case VIDEO_FORMAT_SD_480I60: + case VIDEO_FORMAT_SD_576I50: + case VIDEO_FORMAT_HD_720P60: + case VIDEO_FORMAT_HD_720P50: + case VIDEO_FORMAT_HD_1080I60: + case VIDEO_FORMAT_HD_1080I50: + case VIDEO_FORMAT_HD_1080P60: + case VIDEO_FORMAT_HD_1080P50: + case VIDEO_FORMAT_DIGI_CINEMA_2K24: + case VIDEO_FORMAT_DIGI_CINEMA_4K24: + case VIDEO_FORMAT_UHDTV_4K60: + case VIDEO_FORMAT_UHDTV_4K50: + case VIDEO_FORMAT_UHDTV_8K60: + case VIDEO_FORMAT_UHDTV_8K50: + cparams.SetSpatialPartition(true); + break; + default: + errstr << "Unsupported video format " << cparams.GetVideoFormat() + << std::endl; + DIRAC_THROW_EXCEPTION( + ERR_INVALID_VIDEO_FORMAT, + errstr.str(), + SEVERITY_PICTURE_ERROR); + break; + } + + if (ptype == INTER_PICTURE) + { + ASSERTM (num_refs > 0 && num_refs < 3, "Number of reference frames should be 1 or 2 fo INTER frames" ); + OLBParams bparams; + PicturePredParams& predparams = cparams.GetPicPredParams(); + predparams.SetUsingGlobalMotion(false); + SetDefaultBlockParameters(bparams, cparams.GetVideoFormat()); + predparams.SetLumaBlockParams(bparams); + predparams.SetMVPrecision(MV_PRECISION_HALF_PIXEL); + // NOTE: FIXME - need to add global motion params here + predparams.SetPictureWeightsPrecision(1); + predparams.SetRef1Weight(1); + predparams.SetRef2Weight(1); + cparams.SetPictureCodingMode(0); + } +} + +void SetDefaultSourceParameters(const VideoFormat &vf, SourceParams& sparams) +{ + std::ostringstream errstr; + sparams.SetVideoFormat(vf); + sparams.SetCFormat(format420); + sparams.SetSourceSampling(0); + sparams.SetTopFieldFirst(true); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_1_1); + sparams.SetSignalRange(SIGNAL_RANGE_8BIT_FULL); + sparams.SetLeftOffset(0); + sparams.SetTopOffset(0); + sparams.SetColourSpecification(1); + + switch (vf) + { + case VIDEO_FORMAT_CUSTOM: + sparams.SetXl(640); + sparams.SetYl(480); + sparams.SetTopFieldFirst(false); + sparams.SetFrameRate(FRAMERATE_23p97_FPS); + sparams.SetCleanWidth(640); + sparams.SetCleanHeight(480); + sparams.SetColourSpecification(0); + break; + case VIDEO_FORMAT_QSIF525: + sparams.SetXl(176); + sparams.SetYl(120); + sparams.SetTopFieldFirst(false); + sparams.SetFrameRate(FRAMERATE_14p98_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_10_11); + sparams.SetCleanWidth(176); + sparams.SetCleanHeight(120); + sparams.SetColourSpecification(1); + break; + case VIDEO_FORMAT_QCIF: + sparams.SetXl(176); + sparams.SetYl(144); + sparams.SetFrameRate(FRAMERATE_12p5_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_12_11); + sparams.SetCleanWidth(176); + sparams.SetCleanHeight(144); + sparams.SetColourSpecification(2); + break; + case VIDEO_FORMAT_SIF525: + sparams.SetXl(352); + sparams.SetYl(240); + sparams.SetTopFieldFirst(false); + sparams.SetFrameRate(FRAMERATE_14p98_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_10_11); + sparams.SetCleanWidth(352); + sparams.SetCleanHeight(240); + sparams.SetColourSpecification(1); + break; + case VIDEO_FORMAT_CIF: + sparams.SetXl(352); + sparams.SetYl(288); + sparams.SetFrameRate(FRAMERATE_12p5_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_12_11); + sparams.SetCleanWidth(352); + sparams.SetCleanHeight(288); + sparams.SetColourSpecification(2); + break; + case VIDEO_FORMAT_4SIF525: + sparams.SetXl(704); + sparams.SetYl(480); + sparams.SetTopFieldFirst(false); + sparams.SetFrameRate(FRAMERATE_14p98_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_10_11); + sparams.SetCleanWidth(704); + sparams.SetCleanHeight(480); + sparams.SetColourSpecification(1); + break; + case VIDEO_FORMAT_4CIF: + sparams.SetXl(704); + sparams.SetYl(576); + sparams.SetFrameRate(FRAMERATE_12p5_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_12_11); + sparams.SetCleanWidth(704); + sparams.SetCleanHeight(576); + sparams.SetColourSpecification(2); + break; + case VIDEO_FORMAT_SD_480I60: + sparams.SetXl(720); + sparams.SetYl(480); + sparams.SetCFormat(format422); + sparams.SetSourceSampling(1); + sparams.SetTopFieldFirst(false); + sparams.SetFrameRate(FRAMERATE_29p97_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_10_11); + sparams.SetCleanWidth(704); + sparams.SetCleanHeight(480); + sparams.SetLeftOffset(8); + sparams.SetSignalRange(SIGNAL_RANGE_10BIT_VIDEO); + sparams.SetColourSpecification(1); + break; + case VIDEO_FORMAT_SD_576I50: + sparams.SetXl(720); + sparams.SetYl(576); + sparams.SetCFormat(format422); + sparams.SetSourceSampling(1); + sparams.SetFrameRate(FRAMERATE_25_FPS); + sparams.SetPixelAspectRatio(PIXEL_ASPECT_RATIO_12_11); + sparams.SetCleanWidth(704); + sparams.SetCleanHeight(576); + sparams.SetLeftOffset(8); + sparams.SetSignalRange(SIGNAL_RANGE_10BIT_VIDEO); + sparams.SetColourSpecification(2); + break; + case VIDEO_FORMAT_HD_720P50: + case VIDEO_FORMAT_HD_720P60: + sparams.SetXl(1280); + sparams.SetYl(720); + sparams.SetCFormat(format422); + if (vf == VIDEO_FORMAT_HD_720P50) + sparams.SetFrameRate(FRAMERATE_50_FPS); + else + sparams.SetFrameRate(FRAMERATE_59p94_FPS); + sparams.SetCleanWidth(1280); + sparams.SetCleanHeight(720); + sparams.SetSignalRange(SIGNAL_RANGE_10BIT_VIDEO); + sparams.SetColourSpecification(3); + break; + case VIDEO_FORMAT_HD_1080I60: + case VIDEO_FORMAT_HD_1080I50: + case VIDEO_FORMAT_HD_1080P60: + case VIDEO_FORMAT_HD_1080P50: + sparams.SetXl(1920); + sparams.SetYl(1080); + sparams.SetCFormat(format422); + switch (vf) + { + case VIDEO_FORMAT_HD_1080I60: + sparams.SetSourceSampling(1); + sparams.SetFrameRate(FRAMERATE_29p97_FPS); + break; + case VIDEO_FORMAT_HD_1080I50: + sparams.SetSourceSampling(1); + sparams.SetFrameRate(FRAMERATE_25_FPS); + break; + case VIDEO_FORMAT_HD_1080P60: + sparams.SetFrameRate(FRAMERATE_59p94_FPS); + break; + case VIDEO_FORMAT_HD_1080P50: + sparams.SetFrameRate(FRAMERATE_50_FPS); + break; + default: + break; + } + sparams.SetSignalRange(SIGNAL_RANGE_10BIT_VIDEO); + sparams.SetCleanWidth(1920); + sparams.SetCleanHeight(1080); + sparams.SetColourSpecification(3); + break; + case VIDEO_FORMAT_DIGI_CINEMA_2K24: + sparams.SetXl(2048); + sparams.SetYl(1080); + sparams.SetCFormat(format444); + sparams.SetFrameRate(FRAMERATE_24_FPS); + sparams.SetCleanWidth(2048); + sparams.SetCleanHeight(1080); + sparams.SetSignalRange(SIGNAL_RANGE_12BIT_VIDEO); + sparams.SetColourSpecification(4); + break; + case VIDEO_FORMAT_DIGI_CINEMA_4K24: + sparams.SetXl(4096); + sparams.SetYl(2160); + sparams.SetCFormat(format444); + sparams.SetFrameRate(FRAMERATE_24_FPS); + sparams.SetCleanWidth(4096); + sparams.SetCleanHeight(2160); + sparams.SetSignalRange(SIGNAL_RANGE_12BIT_VIDEO); + sparams.SetColourSpecification(4); + break; + case VIDEO_FORMAT_UHDTV_4K60: + case VIDEO_FORMAT_UHDTV_4K50: + sparams.SetXl(3840); + sparams.SetYl(2160); + sparams.SetCFormat(format422); + sparams.SetSourceSampling(0); + switch (vf) + { + case VIDEO_FORMAT_UHDTV_4K60: + sparams.SetFrameRate(FRAMERATE_59p94_FPS); + break; + case VIDEO_FORMAT_UHDTV_4K50: + sparams.SetFrameRate(FRAMERATE_50_FPS); + break; + default: + break; + } + sparams.SetSignalRange(SIGNAL_RANGE_10BIT_VIDEO); + sparams.SetCleanWidth(3840); + sparams.SetCleanHeight(2160); + sparams.SetColourSpecification(3); + break; + case VIDEO_FORMAT_UHDTV_8K60: + case VIDEO_FORMAT_UHDTV_8K50: + sparams.SetXl(7680); + sparams.SetYl(4320); + sparams.SetCFormat(format422); + sparams.SetSourceSampling(0); + switch (vf) + { + case VIDEO_FORMAT_UHDTV_8K60: + sparams.SetFrameRate(FRAMERATE_59p94_FPS); + break; + case VIDEO_FORMAT_UHDTV_8K50: + sparams.SetFrameRate(FRAMERATE_50_FPS); + break; + default: + break; + } + sparams.SetSignalRange(SIGNAL_RANGE_10BIT_VIDEO); + sparams.SetCleanWidth(7680); + sparams.SetCleanHeight(4320); + sparams.SetColourSpecification(3); + break; + default: + errstr << "Unsupported video format " << sparams.GetVideoFormat() + << std::endl; + DIRAC_THROW_EXCEPTION( + ERR_INVALID_VIDEO_FORMAT, + errstr.str(), + SEVERITY_PICTURE_ERROR); + break; + } +} + +void SetDefaultEncoderParameters(EncoderParams& encparams) +{ + encparams.SetLossless(false); + encparams.SetQf(5.5f); + encparams.GetPicPredParams().SetMVPrecision(MV_PRECISION_HALF_PIXEL); + encparams.SetUsingAC(true); + + switch (encparams.GetVideoFormat()) + { + case VIDEO_FORMAT_4SIF525: + case VIDEO_FORMAT_4CIF: + case VIDEO_FORMAT_SD_480I60: + case VIDEO_FORMAT_SD_576I50: + encparams.SetL1Sep(3); + encparams.SetNumL1(7); + encparams.SetCPD(32.0f); + break; + + case VIDEO_FORMAT_HD_720P60: + case VIDEO_FORMAT_HD_720P50: + encparams.SetL1Sep(3); + encparams.SetNumL1(15); + encparams.SetCPD(20.0f); + break; + + case VIDEO_FORMAT_HD_1080I60: + case VIDEO_FORMAT_HD_1080I50: + case VIDEO_FORMAT_HD_1080P60: + case VIDEO_FORMAT_HD_1080P50: + encparams.SetL1Sep(3); + encparams.SetNumL1(7); + encparams.SetCPD(32.0f); + break; + case VIDEO_FORMAT_UHDTV_4K60: + case VIDEO_FORMAT_UHDTV_4K50: + case VIDEO_FORMAT_UHDTV_8K60: + case VIDEO_FORMAT_UHDTV_8K50: + encparams.SetL1Sep(6); + encparams.SetNumL1(7); + encparams.SetCPD(48.0f); + break; + case VIDEO_FORMAT_CIF: + default: + encparams.SetL1Sep(3); + encparams.SetNumL1(19); + encparams.SetCPD(20.0f); + break; + } + +} + +void SetDefaultBlockParameters(OLBParams& bparams, + const VideoFormat& video_format) +{ + switch (video_format) + { + case VIDEO_FORMAT_QCIF: + case VIDEO_FORMAT_QSIF525: + case VIDEO_FORMAT_CUSTOM: + case VIDEO_FORMAT_SIF525: + case VIDEO_FORMAT_CIF: + case VIDEO_FORMAT_4SIF525: + case VIDEO_FORMAT_4CIF: + case VIDEO_FORMAT_SD_480I60: + case VIDEO_FORMAT_SD_576I50: + bparams.SetXblen(12); + bparams.SetYblen(12); + bparams.SetXbsep(8); + bparams.SetYbsep(8); + break; + + case VIDEO_FORMAT_HD_720P60: + case VIDEO_FORMAT_HD_720P50: + bparams.SetXblen(16); + bparams.SetYblen(16); + bparams.SetXbsep(12); + bparams.SetYbsep(12); + break; + + case VIDEO_FORMAT_HD_1080I60: + case VIDEO_FORMAT_HD_1080I50: + case VIDEO_FORMAT_HD_1080P60: + case VIDEO_FORMAT_HD_1080P50: + case VIDEO_FORMAT_DIGI_CINEMA_2K24: + case VIDEO_FORMAT_DIGI_CINEMA_4K24: + bparams.SetXblen(24); + bparams.SetYblen(24); + bparams.SetXbsep(16); + bparams.SetYbsep(16); + break; + case VIDEO_FORMAT_UHDTV_4K60: + case VIDEO_FORMAT_UHDTV_4K50: + case VIDEO_FORMAT_UHDTV_8K60: + case VIDEO_FORMAT_UHDTV_8K50: + bparams.SetXblen(36); + bparams.SetYblen(36); + bparams.SetXbsep(24); + bparams.SetYbsep(24); + break; + default: + bparams.SetXblen(12); + bparams.SetYblen(12); + bparams.SetXbsep(8); + bparams.SetYbsep(8); + break; + } +} + +void SetDefaultBlockParameters(OLBParams& bparams, int pidx) +{ + switch (pidx) + { + case 0: // custom - so undefined values + return; + case 1: + bparams = OLBParams(8, 8, 4, 4); + break; + case 2: + bparams = OLBParams(12, 12, 8, 8); + break; + case 3: + bparams = OLBParams(16, 16, 12, 12); + break; + case 4: + bparams = OLBParams(24, 24, 16, 16); + break; + default: + DIRAC_THROW_EXCEPTION( + ERR_UNSUPPORTED_STREAM_DATA, + "Block params index out of range [0-4]", + SEVERITY_PICTURE_ERROR); + break; + } +} + +unsigned int BlockParametersIndex (const OLBParams& bparams) +{ + OLBParams bparams_1(8, 8, 4, 4); + OLBParams bparams_2(12, 12, 8, 8); + OLBParams bparams_3(16, 16, 12, 12); + OLBParams bparams_4(24, 24, 16, 16); + + if (bparams == bparams_1) + return 1; + else if (bparams == bparams_2) + return 2; + else if (bparams == bparams_3) + return 3; + else if (bparams == bparams_4) + return 4; + else + return 0; +} + +void SetDefaultTransformFilter(const PictureType ptype, const VideoFormat video_format, + WltFilter &wf) +{ + switch (video_format) + { + case VIDEO_FORMAT_QCIF: + case VIDEO_FORMAT_QSIF525: + case VIDEO_FORMAT_CUSTOM: + case VIDEO_FORMAT_SIF525: + case VIDEO_FORMAT_CIF: + case VIDEO_FORMAT_4SIF525: + case VIDEO_FORMAT_4CIF: + case VIDEO_FORMAT_SD_480I60: + case VIDEO_FORMAT_SD_576I50: + case VIDEO_FORMAT_HD_720P60: + case VIDEO_FORMAT_HD_720P50: + case VIDEO_FORMAT_HD_1080I60: + case VIDEO_FORMAT_HD_1080I50: + case VIDEO_FORMAT_HD_1080P60: + case VIDEO_FORMAT_HD_1080P50: + case VIDEO_FORMAT_DIGI_CINEMA_2K24: + case VIDEO_FORMAT_DIGI_CINEMA_4K24: + case VIDEO_FORMAT_UHDTV_4K60: + case VIDEO_FORMAT_UHDTV_4K50: + case VIDEO_FORMAT_UHDTV_8K60: + case VIDEO_FORMAT_UHDTV_8K50: + default: + if (ptype == INTRA_PICTURE) + wf = DD13_7; + else + wf = DD13_7; + break; + } +} +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/video_format_defaults.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/video_format_defaults.h new file mode 100644 index 000000000..97426a833 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/video_format_defaults.h @@ -0,0 +1,102 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: video_format_defaults.h,v 1.7 2008/10/01 00:26:20 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Andrew Kennedy (Original Author), +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/** +* Returns structures containing default parameter values for different video-formats +*/ +#ifndef video_format_defaults_h +#define video_format_defaults_h + +//LOCAL INCLUDES +#include <libdirac_common/common.h> // SeqParams + +namespace dirac +{ + /** + * Sets default codec parameters - common to encoder and decoder + *@param cparams Codec Params objects for setting defaults + *@param ptype Picture type i,e, INTRA or INTER + *@param num_refs Number of reference frames + */ + void SetDefaultCodecParameters (CodecParams &cparams, PictureType ptype, unsigned int num_refs); + + /** + * Sets default encoder parameters + *@param encparams Params objects for setting defaults + */ + void SetDefaultEncoderParameters(EncoderParams& encparams); + + /** + * Sets default Source parameters + *@param vf Video Format + *@param sparams Params object for setting defaults + */ + void SetDefaultSourceParameters(const VideoFormat &vf, SourceParams& sparams); + + /** + * Sets default block parameters + *@param bparams Params object for setting defaults + *@param video_format Video format + */ + void SetDefaultBlockParameters(OLBParams& bparams, + const VideoFormat& video_format); + + /** + * Sets default block parameters + *@param bparams Params object for setting defaults + *@param pidx Index into Block Parameters table + */ + void SetDefaultBlockParameters(OLBParams& bparams, + int pidx); + /** + * Returns index of block parameters in Defaults table + *@param bparams Params object for getting index + */ + unsigned int BlockParametersIndex(const OLBParams& bparams); + + /** + * Sets the default Transform filter depending on picture type + *@param ptype Picture type i.e. intra or inter + *@param video_format The video format + *@param wf WltFilter object for getting the default wavelet filter + */ + void SetDefaultTransformFilter( const PictureType ptype, const VideoFormat video_format, + WltFilter &wf); +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils.cpp new file mode 100644 index 000000000..43f95e787 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils.cpp @@ -0,0 +1,1570 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: wavelet_utils.cpp,v 1.44 2008/10/20 04:21:02 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/wavelet_utils.h> +#include <libdirac_common/common.h> +#include <cstdlib> + +using namespace dirac; + +// Default constructor +CodeBlock::CodeBlock() +: + m_skipped( false ){ + Init( 0 , 0 , 0 , 0 ); +} + +// Constructor +CodeBlock::CodeBlock( const int xstart , + const int ystart , + const int xend , + const int yend) +: + m_skipped( false ) +{ + Init( xstart , ystart , xend , yend ); +} + +// Initialises the code block +void CodeBlock::Init( const int xstart , + const int ystart , + const int xend , + const int yend ){ + m_xstart = xstart; + m_xend = xend; + m_ystart = ystart; + m_yend= yend; + + m_xl = xend - xstart; + m_yl = yend - ystart; +} + + +// Default constructor +Subband::Subband(){ + // this space intentionally left blank +} + +// Constructor +Subband::Subband(int xpos,int ypos, int xlen, int ylen): + m_xp( xpos ), + m_yp( ypos ), + m_xl( xlen ), + m_yl( ylen ), + m_wt( 1.0 ), + m_code_block_array(), + m_skipped( false ){ + SetNumBlocks( 1 , 1 ); +} + +// Constructor +Subband::Subband(int xpos,int ypos, int xlen, int ylen, int d) + : + m_xp( xpos ), + m_yp( ypos ), + m_xl( xlen ), + m_yl( ylen ), + m_wt( 1.0 ), + m_depth( d ), + m_code_block_array(), + m_skipped( false ) +{ + SetNumBlocks( 1 , 1 ); +} + +void Subband::SetWt( const float w ) +{ + m_wt = w; +} + +void Subband::SetNumBlocks( const int ynum , const int xnum){ + m_code_block_array.Resize( ynum , xnum ); + + OneDArray<int> xbounds( xnum + 1 ); + OneDArray<int> ybounds( ynum + 1 ); + + for (int i=0; i<=xnum ; ++i) + { + xbounds[i] = ( i * m_xl )/xnum + m_xp; + }// i + + for (int j=0; j<=ynum ; ++j) + { + ybounds[j] = ( j * m_yl )/ynum + m_yp; + }// j + + for (int j=0; j<m_code_block_array.LengthY() ; ++j) + for (int i=0; i<m_code_block_array.LengthX() ; ++i) + m_code_block_array[j][i].Init( xbounds[i] , ybounds[j] , + xbounds[i+1] , ybounds[j+1] ); + +} + +//! Destructor +Subband::~Subband(){} + +//subband list methods + +void SubbandList::Init(const int depth,const int xlen,const int ylen){ + int xl=xlen; + int yl=ylen; + + Clear(); + Subband* tmp; + + for (int level = 1; level <= depth; ++level){ + xl/=2; + yl/=2; + /* HH */ + tmp=new Subband( xl , yl , xl , yl , level); + AddBand( *tmp ); + delete tmp; + + /* LH */ + tmp=new Subband( 0 , yl , xl , yl , level); + AddBand( *tmp ); + delete tmp; + + /* HL */ + tmp=new Subband(xl , 0 , xl , yl , level); + AddBand( *tmp ); + delete tmp; + + if (level == depth){ + /* LL */ + tmp=new Subband( 0 , 0 , xl , yl , level); + AddBand( *tmp ); + delete tmp; + } + } + //now set the parent-child relationships + int len = bands.size(); + (*this)(len).SetParent(0); + (*this)(len-3).SetParent(0); + (*this)(len-2).SetParent(0); + (*this)(len-1).SetParent(0); + + for (int level = 2; level <= depth; ++level){ + //do parent-child relationship for other bands + (*this)( len-3*(level) ).SetParent( len-3*(level-1) ); + (*this)(len-3*(level)+1).SetParent(len-3*(level-1)+1); + (*this)(len-3*(level)+2).SetParent(len-3*(level-1)+2); + }// level + +} + +void CoeffArray::SetBandWeights (const EncoderParams& encparams, + const PictureParams& pparams, + const CompSort csort, + const float cpd_scale_factor) +{ + const WltFilter wltfilter = encparams.TransformFilter(); + const bool field_coding = encparams.FieldCoding(); + const ChromaFormat cformat = pparams.CFormat(); + const float cpd = encparams.CPD()*cpd_scale_factor; + const PictureSort psort = pparams.PicSort(); + + int xlen, ylen, xl, yl, xp, yp; + float xfreq, yfreq; + float temp(0.0); + + // Compensate for chroma subsampling + float chroma_xfac(1.0); + float chroma_yfac(1.0); + + if( csort != Y_COMP) + { + if( cformat == format422) + { + chroma_xfac = 2.0; + chroma_yfac = 1.0; + } + else if( cformat == format420 ) + { + chroma_xfac = 2.0; + chroma_yfac = 2.0; + } + + } + + xlen = 2 * m_band_list(1).Xl(); + ylen = 2 * m_band_list(1).Yl(); + + if (cpd != 0.0) + { + for( int i = 1; i<=m_band_list.Length() ; i++ ) + { + xp = m_band_list(i).Xp(); + yp = m_band_list(i).Yp(); + xl = m_band_list(i).Xl(); + yl = m_band_list(i).Yl(); + + + xfreq = cpd * ( float(xp) + (float(xl)/2.0) ) / float(xlen); + yfreq = cpd * ( float(yp) + (float(yl)/2.0) ) / float(ylen); + + if(field_coding) + yfreq/=2.0; + + temp = PerceptualWeight( xfreq/chroma_xfac , yfreq/chroma_yfac , csort ); + + m_band_list(i).SetWt(temp); + }// i + + // Make sure dc is always the lowest weight + float min_weight=m_band_list(m_band_list.Length()).Wt(); + + for( int b=1 ; b<=m_band_list.Length()-1 ; b++ ) + min_weight = ((min_weight>m_band_list(b).Wt()) ? m_band_list(b).Wt() : min_weight); + + m_band_list( m_band_list.Length() ).SetWt( min_weight ); + + // Now normalize weights so that white noise is always weighted the same + + // Overall factor to ensure that white noise ends up with the same RMS, whatever the weight + double overall_factor=0.0; + //fraction of the total number of samples belonging to each subband + double subband_fraction; + + for( int i=1 ; i<=m_band_list.Length() ; i++ ) + { + subband_fraction = 1.0/((double) m_band_list(i).Scale() * m_band_list(i).Scale()); + overall_factor += subband_fraction/( m_band_list(i).Wt() * m_band_list(i).Wt() ); + } + overall_factor = std::sqrt( overall_factor ); + + //go through and normalise + + for( int i=m_band_list.Length() ; i>0 ; i-- ) + m_band_list(i).SetWt( m_band_list(i).Wt() * overall_factor ); + } + else + {//cpd=0 so set all weights to 1 + + for( int i=1 ; i<=m_band_list.Length() ; i++ ) + m_band_list(i).SetWt( 1.0 ); + + } + + //Finally, adjust to compensate for the absence of scaling in the transform + //Factor used to compensate: + double lfac; + double hfac; + int filt_shift; + + switch (wltfilter){ + case DD9_7 : + lfac = 1.218660804;; + hfac = 0.780720058; + filt_shift = 1; + + break; + + case LEGALL5_3 : + lfac = 1.179535649; + hfac = 0.81649658; + filt_shift = 1; + + break; + + case DD13_7 : + lfac = 1.235705971; + hfac = 0.780719354; + filt_shift = 1; + + break; + + case HAAR0 : + lfac = 1.414213562; + hfac = 0.707106781; + filt_shift = 0; + + break; + + case HAAR1 : + lfac = 1.414213562; + hfac = 0.707106781; + filt_shift = 1; + + break; + + case DAUB9_7 : + lfac = 1.149604398; + hfac = 0.869864452; + filt_shift = 1; + + break; + + default: + lfac = 1.0; + hfac = 1.0; + filt_shift = 0; + + } + + + int idx; + int shift; + int depth = (m_band_list.Length()-1)/3; + + // Do the DC subband + idx = m_band_list.Length(); + double cf = (1<<(depth*filt_shift)) / std::pow(lfac,2*depth ) ; + + m_band_list(idx).SetWt( m_band_list(idx).Wt()*cf); + + // Do the non-DC subbands + for (int level=1; level<=depth; level++) + { + shift = (depth-level+1)*filt_shift; + for ( int orient=3;orient>=1; --orient ) + { + idx = 3*(depth-level)+orient; + + // index into the subband list + idx = 3*(depth-level)+orient; + + // Divide through by the weight for the LF subband that was decomposed + // to create this level + cf = 1.0/ std::pow(lfac,2*(depth-level) ); + + if ( m_band_list(idx).Xp() != 0 && m_band_list(idx).Yp() != 0) + // HH subband + cf /= (hfac * hfac); + else + // LH or HL subband + cf /= (lfac * hfac); + + cf *= double(1<<shift); + + m_band_list(idx).SetWt( m_band_list(idx).Wt()*cf ); + + }// orient + }//level + + +} + +// Returns a perceptual noise weighting based on extending CCIR 959 values +// assuming a two-d isotropic response. Also has a fudge factor of 20% for chroma +float CoeffArray::PerceptualWeight( const float xf , + const float yf , + const CompSort cs ) +{ + double freq_sqd( xf*xf + yf*yf ); + + if ( cs != Y_COMP ) + freq_sqd *= 1.2; + + return 0.255 * std::pow( 1.0 + 0.2561*freq_sqd , 0.75) ; + +} + + + +//wavelet transform methods +/////////////////////////// + +//public methods + +WaveletTransform::WaveletTransform(int d, WltFilter f) + : m_depth(d), + m_filt_sort(f) +{ + switch( m_filt_sort ){ + + case DD9_7 : + m_vhfilter = new VHFilterDD9_7; + break; + + case LEGALL5_3 : + m_vhfilter = new VHFilterLEGALL5_3; + break; + + case DD13_7 : + m_vhfilter = new VHFilterDD13_7; + break; + + case HAAR0 : + m_vhfilter = new VHFilterHAAR0; + break; + + case HAAR1 : + m_vhfilter = new VHFilterHAAR1; + break; + + default : + m_vhfilter = new VHFilterDAUB9_7; + } +} + +//! Destructor +WaveletTransform::~WaveletTransform(){ delete m_vhfilter; } + +void WaveletTransform::Transform(const Direction d, PicArray& pic_data, CoeffArray& coeff_data) { + + int xl,yl; + + SubbandList& bands = coeff_data.BandList(); + + if (d == FORWARD){ + xl=coeff_data.LengthX(); + yl=coeff_data.LengthY(); + + // First copy picture data into coeff_data and pad + for ( int j=0; j<pic_data.LengthY(); ++j){ + for ( int i=0; i<pic_data.LengthX(); ++i) + coeff_data[j][i] = CoeffType( pic_data[j][i] ); + for ( int i=pic_data.LengthX(); i<coeff_data.LengthX(); ++i) + coeff_data[j][i] = coeff_data[j][pic_data.LastX()]; + }// j + for ( int j=pic_data.LengthY(); j<coeff_data.LengthY(); ++j){ + for ( int i=0; i<coeff_data.LengthX(); ++i) + coeff_data[j][i] = coeff_data[pic_data.LastY()][i]; + } + + for (int l = 1; l <= m_depth; ++l , xl>>=1 , yl>>=1){ + m_vhfilter->Split(0,0,xl,yl,coeff_data); + } + + bands.Init( m_depth , coeff_data.LengthX() , coeff_data.LengthY() ); + } + else{ + xl = coeff_data.LengthX()/(1<<(m_depth-1)); + yl = coeff_data.LengthY()/(1<<(m_depth-1)); + + for (int l = 1; l <= m_depth; ++l, xl<<=1 , yl<<=1 ) + m_vhfilter->Synth(0,0,xl,yl,coeff_data); + + //band list now inaccurate, so clear + bands.Clear(); + + // Lastly, copy coeff_data back into picture data + for ( int j=0; j<pic_data.LengthY(); ++j){ + for ( int i=0; i<pic_data.LengthX(); ++i){ + pic_data[j][i] = ValueType( coeff_data[j][i] ); + }// i + }// j + } +} + +// Private functions // +/////////////////////// +// NOTEL MMX version is defined in wavelet_utils_mmx.cpp +// the corresponding changes are made in wavelet_utils_mmx.cpp as well +void VHFilter::Interleave( const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + TwoDArray<CoeffType> temp_data( yl , xl ); + const int xl2( xl>>1); + const int yl2( yl>>1); + const int yend( yp + yl ); + + // Make a temporary copy of the subband + for (int j = yp; j<yend ; j++ ) + memcpy( temp_data[j-yp] , coeff_data[j]+xp , xl * sizeof( CoeffType ) ); + + // Re-order to interleave + for (int j = 0, s=yp; j<yl2 ; j++, s+=2) + { + for (int i = 0 , r=xp ; i<xl2 ; i++ , r += 2) + coeff_data[s][r] = temp_data[j][i]; + for (int i = xl2, r=xp+1; i<xl ; i++ , r += 2) + coeff_data[s][r] = temp_data[j][i]; + }// j + + for (int j = yl2, s=yp+1 ; j<yl ; j++ , s += 2) + { + for (int i = 0 , r=xp ; i<xl2 ; i++ , r += 2) + coeff_data[s][r] = temp_data[j][i]; + for (int i = xl2, r=xp+1; i<xl ; i++ , r += 2) + coeff_data[s][r] = temp_data[j][i]; + }// j + +} + +#if !defined(HAVE_MMX) +void VHFilter::ShiftRowLeft(CoeffType *row, int length, int shift) +{ + for (int i = 0; i < length; ++i) + row[i] <<= shift; +} + +void VHFilter::ShiftRowRight(CoeffType *row, int length, int shift) +{ + const CoeffType halfway( 1<<(shift-1) ); + for (int i = 0; i < length; ++i) + row[i] = ((row[i]+halfway)>>shift); +} +#endif + +void VHFilter::DeInterleave( const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + TwoDArray<CoeffType> temp_data( yl , xl ); + const int xl2( xl>>1); + const int yl2( yl>>1); + const int xend( xp + xl ); + const int yend( yp + yl ); + + // Make a temporary copy of the subband + for (int j = yp; j<yend ; j++ ) + memcpy( temp_data[j-yp] , coeff_data[j]+xp , xl * sizeof( CoeffType ) ); + + // Re-order to de-interleave + for (int j = yp, s=0; j<yp+yl2 ; j++, s+=2) + { + for (int i = xp , r=0 ; i<xp+xl2 ; i++ , r += 2) + coeff_data[j][i] = temp_data[s][r]; + for (int i = xp+xl2, r=1; i<xend ; i++ , r += 2) + coeff_data[j][i] = temp_data[s][r]; + }// j + + for (int j = yp+yl2, s=1 ; j<yend ; j++ , s += 2) + { + for (int i = xp , r=0 ; i<xp+xl2 ; i++ , r += 2) + coeff_data[j][i] = temp_data[s][r]; + for (int i = xp+xl2, r=1; i<xend ; i++ , r += 2) + coeff_data[j][i] = temp_data[s][r]; + }// j + +} + +void VHFilterDAUB9_7::Split (const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + + const int xend=xp+xl; + const int yend=yp+yl; + + CoeffType* line_data; + + // Positional variables + int i,j,k; + + // Objects to do lifting stages + // (in revese order and type from synthesis) + const PredictStep97< 6497 > predictA; + const PredictStep97< 217 > predictB; + const UpdateStep97< 3616 > updateA; + const UpdateStep97< 1817 > updateB; + + //first do horizontal + + for (j = yp; j < yend; ++j) + { + // First lifting stage + line_data = coeff_data[j]; + // Shift left by one bit to give us more accuracy + ShiftRowLeft(line_data, xl, 1); + + predictA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] ); + predictB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] ); + + for ( k = xp+3; k < xend-1; k+=2) + { + predictA.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + predictB.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + }// i + + predictA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] ); + predictB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] ); + + + //second lifting stage + + updateA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] ); + updateB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] ); + + for ( k = xp+3; k < xend-1; k+=2) + { + updateA.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + updateB.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + }// i + + updateA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] ); + updateB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] ); + + }// j + + // next do vertical + + // First lifting stage + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + predictA.Filter( coeff_data[yp+1][i] , coeff_data[yp+2][i] , coeff_data[yp][i] ); + predictB.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + }// i + + // middle bit + for ( k = yp+3 ; k<yend-1 ; k+=2) + { + for ( i = xp ; i<xend ; ++ i) + { + predictA.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + predictB.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + }// i + }// j + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + predictA.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + predictB.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + }// i + + // Second lifting stage + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + updateA.Filter( coeff_data[yp+1][i] , coeff_data[yp+2][i] , coeff_data[yp][i] ); + updateB.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + }// i + + // middle bit + for ( k = yp+3 ; k<yend-1 ; k+=2) + { + for ( i = xp ; i<xend ; ++ i) + { + updateA.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + updateB.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + }// i + }// j + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + updateA.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + updateB.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + }// i + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp ,yp ,xl ,yl , coeff_data ); + +} + +void VHFilterDAUB9_7::Synth (const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + + int i,j,k; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + const PredictStep97< 1817 > predictB; + const PredictStep97< 3616 > predictA; + const UpdateStep97< 217 > updateB; + const UpdateStep97< 6497 > updateA; + + CoeffType* line_data; + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl , yl , coeff_data ); + + // Next, do the vertical synthesis + // First lifting stage + + // Begin with the bottom edge + for ( i = xend-1 ; i>=xp ; --i) + { + predictB.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + predictA.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + }// i + // Next, do the middle bit + for ( k = yend-3 ; k>yp+1 ; k-=2) + { + for ( i = xend-1 ; i>=xp ; --i) + { + predictB.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + predictA.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + }// i + }// j + // Then do the top edge + for ( i = xend-1 ; i>=xp ; --i) + { + predictB.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + predictA.Filter( coeff_data[yp+1][i] , coeff_data[yp+2][i] , coeff_data[yp][i] ); + }// i + + // Second lifting stage + + // Begin with the bottom edge + for ( i = xend-1 ; i>=xp ; --i) + { + updateB.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + updateA.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + }// i + // Next, do the middle bit + for ( k = yend-3 ; k>yp+1 ; k-=2) + { + for ( i = xend-1 ; i>=xp ; --i) + { + updateB.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + updateA.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + }// i + }// j + // Then do the top edge + for ( i = xend-1 ; i>=xp ; --i) + { + updateB.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + updateA.Filter( coeff_data[yp+1][i] , coeff_data[yp+2][i] , coeff_data[yp][i] ); + }// i + + + // Next do the horizontal synthesis + for (j = yend-1; j >= yp ; --j) + { + // First lifting stage + line_data = coeff_data[j]; + + predictB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] ); + predictA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] ); + + for ( k = xend-3; k > xp+1; k-=2) + { + predictB.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + predictA.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + }// i + + predictB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] ); + predictA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] ); + + // Second lifting stage + + updateB.Filter( line_data[xend-2] , line_data[xend-3] , line_data[xend-1] ); + updateA.Filter( line_data[xend-1] , line_data[xend-2] , line_data[xend-2] ); + + for ( k = xend-3; k > xp+1; k-=2) + { + updateB.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + updateA.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + }// i + + updateB.Filter( line_data[xp] , line_data[xp+1] , line_data[xp+1] ); + updateA.Filter( line_data[xp+1] , line_data[xp+2] , line_data[xp] ); + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + + } + +} + +#if !defined HAVE_MMX +// NOTE: MMX version is defined in wavelet_utils_mmx.cpp +// the corresponding changes are made in wavelet_utils_mmx.cpp as well +void VHFilterLEGALL5_3::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + + const int xend=xp+xl; + const int yend=yp+yl; + + CoeffType* line_data; + + // Positional variables + int i,j,k; + + // Objects to do lifting stages + // (in revese order and type from synthesis) + const PredictStepShift< 1 > predict; + const UpdateStepShift< 2 > update; + + //first do horizontal + + for (j = yp; j < yend; ++j) + { + // First lifting stage + line_data = &coeff_data[j][xp]; + // Shift left by one bit to give us more accuracy + ShiftRowLeft(line_data, xl, 1); + + predict.Filter( line_data[1] , line_data[2] , line_data[0] ); + update.Filter( line_data[0] , line_data[1] , line_data[1] ); + + for (k = 3; k < xl-1; k+=2) + { + predict.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + update.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + }// i + + predict.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] ); + update.Filter( line_data[xl-2] , line_data[xl-3] , line_data[xl-1] ); + + }// j + + // next do vertical + + // First lifting stage + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+1][i] , coeff_data[yp+2][i] , coeff_data[yp][i] ); + update.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + }// i + + // middle bit + for (k = yp+3 ; k<yend-1 ; k+=2) + { + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + update.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + }// i + }// j + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + update.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + }// i + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp , yp , xl , yl , coeff_data ); +} + + +// NOTE: MMX version is defined in wavelet_utils_mmx.cpp +// the corresponding changes are made in wavelet_utils_mmx.cpp as well +void VHFilterLEGALL5_3::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + int i,j,k; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + const PredictStepShift< 2 > predict; + const UpdateStepShift< 1 > update; + + CoeffType* line_data; + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl , yl , coeff_data ); + + // Next, do the vertical synthesis + // First lifting stage + + // Begin with the bottom edge + for ( i = xend-1 ; i>=xp ; --i) + { + predict.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + update.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + }// i + // Next, do the middle bit + for ( k = yend-3 ; k>yp+1 ; k-=2) + { + for ( i = xend-1 ; i>=xp ; --i) + { + predict.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + update.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + }// i + }// j + // Then do the top edge + for ( i = xend-1 ; i>=xp ; --i) + { + predict.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + update.Filter( coeff_data[yp+1][i] , coeff_data[yp+2][i] , coeff_data[yp][i] ); + }// i + + // Next do the horizontal synthesis + for (j = yend-1; j >= yp ; --j) + { + // First lifting stage + line_data = &coeff_data[j][xp]; + + predict.Filter( line_data[xl-2] , line_data[xl-3] , line_data[xl-1] ); + update.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] ); + + for ( k = xl-3; k > 1; k-=2) + { + predict.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + update.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + }// i + + predict.Filter( line_data[0] , line_data[1] , line_data[1] ); + update.Filter( line_data[1] , line_data[2] , line_data[0] ); + + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + + } + +} +#endif + +void VHFilterDD9_7::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + + const int xend=xp+xl; + const int yend=yp+yl; + + CoeffType* line_data; + + // Positional variables + int i,j,k; + + PredictStepFourTap< 4 , 9 , -1 > predict; + UpdateStepShift< 2 > update; + + //first do horizontal + + for (j = yp; j < yend; ++j) + { + line_data = &coeff_data[j][xp]; + // Shift left by one bit to give us more accuracy + ShiftRowLeft(line_data, xl, 1); + + // First lifting stage + predict.Filter( line_data[1] , line_data[0] , line_data[2] , line_data[0] , line_data[4] ); + for (k=3 ; k<xl-3 ; k+=2) + { + predict.Filter( line_data[k] , line_data[k-1] , line_data[k+1] , line_data[k-3] , line_data[k+3] ); + }// i + predict.Filter( line_data[xl-3] , line_data[xl-4] , line_data[xl-2] , line_data[xl-6] , line_data[xl-2] ); + predict.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] , line_data[xl-4] , line_data[xl-2] ); + + //Second lifting stage + + update.Filter( line_data[0] , line_data[1] , line_data[1] ); + for (i=2 ; i<xl-1 ; i+=2 ) + { + update.Filter( line_data[i] , line_data[i-1] , line_data[i+1] ); + }// i + + }// j + + // next do vertical + + // First lifting stage + // top line + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+1][i] , coeff_data[yp][i] , coeff_data[yp+2][i] , coeff_data[yp][i] , coeff_data[yp+4][i] ); + }// i + + // middle bit + for ( k = yp+3 ; k<yend-3 ; k+=2) + { + for ( i = xp ; i<xend ; ++i) + { + predict.Filter( coeff_data[k][i] , coeff_data[k-1][i] , coeff_data[k+1][i] , coeff_data[k-3][i] , coeff_data[k+3][i] ); + }// i + }// j + + // bottom lines + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yend-3][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] , coeff_data[yend-6][i] , coeff_data[yend-2][i] ); + predict.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] ); + }// i + + //Second lifting stage + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + + }// i + // middle bit + for ( j = yp+2 ; j<yend-1 ; j+=2 , k+=2) + { + for ( i = xp ; i<xend ; ++i) + { + update.Filter( coeff_data[j][i] , coeff_data[j-1][i] , coeff_data[j+1][i] ); + }// i + }// j + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp , yp , xl , yl , coeff_data ); + + + +} + +#if !defined(HAVE_MMX) +// NOTE: MMX version is defined in wavelet_utils_mmx.cpp +// the corresponding changes are made in wavelet_utils_mmx.cpp as well +void VHFilterDD9_7::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + int i,j; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + PredictStepShift<2> predict; + UpdateStepFourTap< 4 , 9 , -1> update; + + CoeffType* line_data; + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl ,yl , coeff_data ); + + // First, do the vertical synthesis + + // First lifting stage + // Middle bit + for ( j=yend-2 ; j>=yp+2 ; j-=2 ) + { + for ( i = xend-1 ; i>=xp ; --i) + { + predict.Filter( coeff_data[j][i] , coeff_data[j-1][i] , coeff_data[j+1][i] ); + }// i + }// j + + // top line + for ( i = xend-1 ; i>=xp ; --i) + { + predict.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + }// i + + + // Second lifting stage + for ( i = xend-1 ; i>=xp ; --i) + { + + update.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] ); + update.Filter( coeff_data[yend-3][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] , coeff_data[yend-6][i] , coeff_data[yend-2][i] ); + }// i + + // middle bit + for ( j=yend-5 ; j>=yp+3 ; j-=2) + { + for ( i = xend-1 ; i>=xp ; --i) + { + update.Filter( coeff_data[j][i] , coeff_data[j-1][i] , coeff_data[j+1][i] , coeff_data[j-3][i] , coeff_data[j+3][i] ); + }// i + }// k + + for ( i = xend-1 ; i>=xp ; --i) + { + update.Filter( coeff_data[yp+1][i] , coeff_data[yp][i] , coeff_data[yp+2][i] , coeff_data[yp][i] , coeff_data[yp+4][i] ); + }// i + + // Next do the horizontal synthesis + for (j = yend-1; j >= yp; --j) + { + line_data = &coeff_data[j][xp]; + + // First lifting stage + for (i=xl-2 ; i>=2 ; i-=2) + { + predict.Filter( line_data[i] , line_data[i-1] , line_data[i+1] ); + }// i + predict.Filter( line_data[0] , line_data[1] , line_data[1] ); + + // Second lifting stage + update.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] , line_data[xl-4] , line_data[xl-2] ); + update.Filter( line_data[xl-3] , line_data[xl-4] , line_data[xl-2] , line_data[xl-6] , line_data[xl-2] ); + for (i=xl-5 ; i>=3 ; i-=2) + { + update.Filter( line_data[i] , line_data[i-1] , line_data[i+1] , line_data[i-3] , line_data[i+3] ); + }// i + update.Filter( line_data[1] , line_data[0] , line_data[2] , line_data[0] , line_data[4] ); + + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + + }// j + +} +#endif + +void VHFilterDD13_7::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + + const int xend=xp+xl; + const int yend=yp+yl; + + PredictStepFourTap< 4 , 9 , -1 > predict; + UpdateStepFourTap< 5 , 9 , -1> update; + + CoeffType* line_data; + + // Positional variables + int i,j,k; + + //first do horizontal + + for (j = yp; j < yend; ++j) + { + line_data = &coeff_data[j][xp]; + // Shift left by one bit to give us more accuracy + ShiftRowLeft(line_data, xl, 1); + + // First lifting stage + predict.Filter( line_data[1] , line_data[0] ,line_data[2] , line_data[0] , line_data[4] ); + for (k=3 ; k<xl-3 ; k+=2) + { + predict.Filter( line_data[k] , line_data[k-1] , line_data[k+1] , line_data[k-3] , line_data[k+3] ); + }// i + + predict.Filter( line_data[xl-3] , line_data[xl-4] , line_data[xl-2] , line_data[xl-6] , line_data[xl-2] ); + predict.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] , line_data[xl-4] , line_data[xl-2] ); + + //second lifting stage + update.Filter( line_data[0] , line_data[1] , line_data[1] , line_data[3] , line_data[1] ); + update.Filter( line_data[2] , line_data[1] , line_data[3] , line_data[5] , line_data[1] ); + for (k=4 ; k<xl-3 ; k+=2) + { + update.Filter( line_data[k] , line_data[k-1] , line_data[k+1] , line_data[k-3] , line_data[k+3] ); + }// i + + update.Filter( line_data[xl-2] , line_data[xl-3] , line_data[xl-1] , line_data[xl-5] , line_data[xl-1] ); + }// j + + // next do vertical + + // First lifting stage + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+1][i] , coeff_data[yp][i] , coeff_data[yp+2][i] , coeff_data[yp][i] , coeff_data[yp+4][i] ); + }// i + + // middle bit + for ( k = yp+3 ; k<yend-3 ; k+=2) + { + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[k][i] , coeff_data[k-1][i] , coeff_data[k+1][i] , coeff_data[k-3][i] , coeff_data[k+3][i] ); + }// i + }// j + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yend-3][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] , coeff_data[yend-6][i] , coeff_data[yend-2][i] ); + predict.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] ); + }// i + + // Second lifting stage + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] , coeff_data[yp+3][i] , coeff_data[yp+1][i] ); + update.Filter( coeff_data[yp+2][i] , coeff_data[yp+1][i] , coeff_data[yp+3][i] , coeff_data[yp+5][i] , coeff_data[yp+1][i] ); + }// i + + // middle bit + for ( k = yp+4 ; k<yend-3 ; k+=2) + { + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[k][i] , coeff_data[k-1][i] , coeff_data[k+1][i] , coeff_data[k-3][i] , coeff_data[k+3][i] ); + }// i + }// j + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] , coeff_data[yend-5][i] , coeff_data[yend-1][i] ); + }// i + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp , yp , xl , yl , coeff_data ); +} + +#if !defined(HAVE_MMX) +// NOTE: MMX version is defined in wavelet_utils_mmx.cpp +// the corresponding changes are made in wavelet_utils_mmx.cpp as well +void VHFilterDD13_7::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + int i,j,k; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + PredictStepFourTap< 5 , 9 , -1 > predict; + UpdateStepFourTap< 4 , 9 , -1> update; + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl , yl , coeff_data ); + + // Next, do the vertical synthesis + + // First lifting stage + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] , coeff_data[yend-5][i] , coeff_data[yend-1][i] ); + }// i + + // middle bit + for ( k = yend-4 ; k>=yp+4 ; k-=2) + { + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[k][i] , coeff_data[k-1][i] , coeff_data[k+1][i] , coeff_data[k-3][i] , coeff_data[k+3][i] ); + }// i + }// j + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+2][i] , coeff_data[yp+1][i] , coeff_data[yp+3][i] , coeff_data[yp+5][i] , coeff_data[yp+1][i] ); + predict.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] , coeff_data[yp+3][i] , coeff_data[yp+1][i] ); + + }// i + + // Second lifting stage + // bottom edge + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] ); + update.Filter( coeff_data[yend-3][i] , coeff_data[yend-4][i] , coeff_data[yend-2][i] , coeff_data[yend-6][i] , coeff_data[yend-2][i] ); + + }// i + + // middle bit + for ( k = yend-5 ; k>=yp+3 ; k-=2) + { + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[k][i] , coeff_data[k-1][i] , coeff_data[k+1][i] , coeff_data[k-3][i] , coeff_data[k+3][i] ); + }// i + }// j + + // top edge - j=xp + for ( i = xp ; i<xend ; ++ i) + { + update.Filter( coeff_data[yp+1][i] , coeff_data[yp][i] , coeff_data[yp+2][i] , coeff_data[yp][i] , coeff_data[yp+4][i] ); + }// i + + // Next do the horizontal synthesis + + CoeffType* line_data; + + for (j = yend-1; j >= yp ; --j) + { + line_data = &coeff_data[j][xp]; + + // First lifting stage + + predict.Filter( line_data[xl-2] , line_data[xl-3] , line_data[xl-1] , line_data[xl-5] , line_data[xl-1] ); + + for (k=xl-4 ; k>=4 ; k-=2) + { + predict.Filter( line_data[k] , line_data[k-1] , line_data[k+1] , line_data[k-3] , line_data[k+3] ); + + }// i + predict.Filter( line_data[2] , line_data[1] , line_data[3] , line_data[5] , line_data[1] ); + predict.Filter( line_data[0] , line_data[1] , line_data[1] , line_data[3] , line_data[1] ); + + //second lifting stage + update.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] , line_data[xl-4] , line_data[xl-2] ); + update.Filter( line_data[xl-3] , line_data[xl-4] , line_data[xl-2] , line_data[xl-6] , line_data[xl-2] ); + + for (k=xl-5 ; k>=3 ; k-=2) + { + update.Filter( line_data[k] , line_data[k-1] , line_data[k+1] , line_data[k-3] , line_data[k+3] ); + }// i + + update.Filter( line_data[1] , line_data[0] , line_data[2] , line_data[0] , line_data[4] ); + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + + }// j +} +#endif + +void VHFilterHAAR0::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + + const int xend=xp+xl; + const int yend=yp+yl; + + // first do Horizontal + for (int j = yp; j < yend; ++j) + { + for (int i = xp+1; i < xend; i+=2) + { + // odd sample + // x(2n+1) -= x(2n) + coeff_data[j][i] -= coeff_data[j][i-1]; + // even sample + // x(2n) += x(2n+1)/2 + coeff_data[j][i-1] += ((coeff_data[j][i]+1)>>1); + } + } + + // next do vertical + for (int j = yp+1; j < yend; j+=2) + { + for (int i = xp; i < xend; ++i) + { + coeff_data[j][i] -= coeff_data[j-1][i]; + coeff_data[j-1][i] += ((coeff_data[j][i]+1)>>1); + } + } + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp , yp , xl , yl , coeff_data ); +} + +void VHFilterHAAR0::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xend( xp+xl ); + const int yend( yp+yl ); + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl , yl , coeff_data ); + + // First do the vertical + for (int j = yp+1; j < yend; j+=2) + { + for (int i = xp; i < xend; ++i) + { + coeff_data[j-1][i] -= ((coeff_data[j][i]+1)>>1); + coeff_data[j][i] += coeff_data[j-1][i]; + } + } + + // Next do the horizontal + for (int j = yp; j < yend; ++j) + { + for (int i = xp+1; i < xend; i+=2) + { + coeff_data[j][i-1] -= ((coeff_data[j][i]+1)>>1); + coeff_data[j][i] += coeff_data[j][i-1]; + } + } +} + +void VHFilterHAAR1::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xend=xp+xl; + const int yend=yp+yl; + + CoeffType* line_data; + + // first do Horizontal + for (int j = yp; j < yend; ++j) + { + line_data = &(coeff_data[j][xp]); + ShiftRowLeft(line_data, xl, 1); + for (int i = xp+1; i < xend; i+=2) + { + // odd sample + // x(2n+1) -= x(2n) + coeff_data[j][i] -= coeff_data[j][i-1]; + // even sample + // x(2n) += x(2n+1)/2 + coeff_data[j][i-1] += ((coeff_data[j][i]+1)>>1); + } + } + + // next do vertical + for (int j = yp+1; j < yend; j+=2) + { + for (int i = xp; i < xend; ++i) + { + coeff_data[j][i] -= coeff_data[j-1][i]; + coeff_data[j-1][i] += ((coeff_data[j][i]+1)>>1); + } + } + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp , yp , xl , yl , coeff_data ); +} + +void VHFilterHAAR1::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xend( xp+xl ); + const int yend( yp+yl ); + + CoeffType* line_data; + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl , yl , coeff_data ); + + // First do the vertical + for (int j = yp+1; j < yend; j+=2) + { + for (int i = xp; i < xend; ++i) + { + coeff_data[j-1][i] -= ((coeff_data[j][i]+1)>>1); + coeff_data[j][i] += coeff_data[j-1][i]; + } + } + + // Next do the horizontal + for (int j = yp; j < yend; ++j) + { + for (int i = xp+1; i < xend; i+=2) + { + coeff_data[j][i-1] -= ((coeff_data[j][i]+1)>>1); + coeff_data[j][i] += coeff_data[j][i-1]; + } + line_data = &coeff_data[j][xp]; + ShiftRowRight(line_data, xl, 1); + } +} + +void VHFilterHAAR2::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xend=xp+xl; + const int yend=yp+yl; + + CoeffType* line_data; + + // first do Horizontal + for (int j = yp; j < yend; ++j) + { + line_data = &coeff_data[j][xp]; + ShiftRowLeft(line_data, xl, 2); + for (int i = xp+1; i < xend; i+=2) + { + // odd sample + // x(2n+1) -= x(2n) + coeff_data[j][i] -= coeff_data[j][i-1]; + // even sample + // x(2n) += x(2n+1)/2 + coeff_data[j][i-1] += ((coeff_data[j][i]+1)>>1); + } + } + + // next do vertical + for (int j = yp+1; j < yend; j+=2) + { + for (int i = xp; i < xend; ++i) + { + coeff_data[j][i] -= coeff_data[j-1][i]; + coeff_data[j-1][i] += ((coeff_data[j][i]+1)>>1); + } + } + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave( xp , yp , xl , yl , coeff_data ); +} + +void VHFilterHAAR2::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xend( xp+xl ); + const int yend( yp+yl ); + + CoeffType* line_data; + + // Firstly reorder to interleave subbands, so that subsequent calculations can be in-place + Interleave( xp , yp , xl , yl , coeff_data ); + + // First do the vertical + for (int j = yp+1; j < yend; j+=2) + { + for (int i = xp; i < xend; ++i) + { + coeff_data[j-1][i] -= ((coeff_data[j][i]+1)>>1); + coeff_data[j][i] += coeff_data[j-1][i]; + } + } + + // Next do the horizontal + for (int j = yp; j < yend; ++j) + { + for (int i = xp+1; i < xend; i+=2) + { + coeff_data[j][i-1] -= ((coeff_data[j][i]+1)>>1); + coeff_data[j][i] += coeff_data[j][i-1]; + } + line_data = &coeff_data[j][xp]; + ShiftRowRight(line_data, xl, 2); + } +} + + + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils.h new file mode 100644 index 000000000..2ca565f3b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils.h @@ -0,0 +1,731 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: wavelet_utils.h,v 1.32 2008/10/20 04:21:02 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _WAVELET_UTILS_H_ +#define _WAVELET_UTILS_H_ + +#include <libdirac_common/arrays.h> +#include <libdirac_common/common.h> +#include <vector> +#include <cmath> +#include <iostream> + +//utilities for subband and wavelet transforms +//Includes fast transform using lifting + +namespace dirac +{ + + class PicArray; + class Subband; + + //! Class for encapsulating metadata concerning a block of coefficients in a subband + class CodeBlock + { + + friend class Subband; + + public: + //! Constructor + /* + Default constructor - sets all dimensions to zero + */ + CodeBlock(); + + //! Constructor + /* + Initialise the code block + \param xstart the x-coord of the first coefficient in the block + \param xend one past the last coefficient, horizontally + \param ystart the y-coord of the first coefficient in the block + \param yend one past the last coefficient, vertically + */ + CodeBlock( const int xstart , const int ystart , const int xend , const int yend); + + //! Returns the horizontal start of the block + int Xstart() const { return m_xstart; } + + //! Returns the vertical start of the block + int Ystart() const { return m_ystart; } + + //! Returns one past the last coefficient coord, horizontally + int Xend() const { return m_xend; } + + //! Returns one past the last coefficient coord, vertically + int Yend() const { return m_yend; } + + //! Returns the width of the code block + int Xl() const { return m_xl; } + + //! Returns the height of the code block + int Yl() const { return m_yl; } + + //! Returns the quantisation index associated to the code block + int QuantIndex() const{ return m_quantindex; } + + //! Returns true if the code-block is skipped, false if not + bool Skipped() const { return m_skipped; } + + //! Sets the quantisation index + void SetQuantIndex( const int quantindex ){ m_quantindex = quantindex; } + + //! Sets whether the code block is skipped or not + void SetSkip( bool skip ){ m_skipped = skip; } + + private: + + //! Initialise the code block + /* + Initialise the code block + \param xstart the x-coord of the first coefficient in the block + \param xend one past the last coefficient, horizontally + \param ystart the y-coord of the first coefficient in the block + \param yend one past the last coefficient, vertically + */ + void Init( const int xstart , const int ystart , const int xend , const int yend ); + + private: + + int m_xstart; + int m_ystart; + int m_xend; + int m_yend; + int m_xl; + int m_yl; + + int m_quantindex; + + bool m_skipped; + }; + + + //! Class encapsulating all the metadata relating to a wavelet subband + class Subband + { + public: + + //! Default constructor + Subband(); + + //! Constructor + /*! + The constructor parameters are + \param xpos the xposition of the subband when packed into a + big array with all the others + \param ypos the xposition of the subband + \param xlen the width of the subband + \param ylen the height of the subband + */ + Subband(int xpos, int ypos, int xlen, int ylen); + + //! Constructor + /*! + The constructor parameters are + \param xpos the xposition of the subband when packed into a + big array with all the others + \param ypos the xposition of the subband + \param xlen the width of the subband + \param ylen the height of the subband + \param d the depth of the subband in the wavelet transform + */ + Subband(int xpos, int ypos, int xlen, int ylen, int d); + + //! Destructor + ~Subband(); + + //Default (shallow) copy constructor and operator= used + + //! Return the width of the subband + int Xl() const {return m_xl;} + + //! Return the horizontal position of the subband + int Xp() const {return m_xp;} + + //! Return the height of the subband + int Yl() const {return m_yl;} + + //! Return the vertical position of the subband + int Yp() const {return m_yp;} + + //! Return the index of the maximum bit of the largest coefficient + int Max() const {return m_max_bit;} + + //! Return the subband perceptual weight + double Wt() const {return m_wt;} + + //! Return the depth of the subband in the transform + int Depth() const {return m_depth;} + + //! Return the scale of the subband, viewed as a subsampled version of the picture + int Scale() const {return ( 1<<m_depth );} + + //! Return a quantisation index + int QuantIndex() const {return m_qindex;} + + //! Return a flag indicating whether we have separate quantisers for each code block + bool UsingMultiQuants() const {return m_multi_quants; } + + //! Return the index of the parent subband + int Parent() const {return m_parent;} + + //! Return the indices of any child subbands + const std::vector<int>& Children() const {return m_children;} + + //! Return the index of a specific child band + int Child(const int n) const {return m_children[n];} + + //! Return the code blocks + TwoDArray<CodeBlock>& GetCodeBlocks(){ return m_code_block_array; } + + //! Return the code blocks + const TwoDArray<CodeBlock>& GetCodeBlocks() const { return m_code_block_array; } + + //! Returns true if subband is skipped, false if not + bool Skipped() const { return m_skipped; } + + //! Set the perceptual weight + void SetWt( const float w ); + + //! Set the parent index + void SetParent( const int p ){ m_parent=p; } + + //! Set the subband depth + void SetDepth( const int d ){ m_depth=d;} + + //! Set the index of the maximum bit of the largest coefficient + void SetMax( const int m ){ m_max_bit=m; }; + + //! Set the number of (spatial) quantisers in the subband. Creates code block structure + void SetNumBlocks( const int ynum , const int xnum ); + + //! Set the quantisation index + void SetQuantIndex( const int idx){ m_qindex = idx; } + + //! Set the number of (spatial) quantisers in the subband. Creates code block structure + void SetUsingMultiQuants( const bool multi){ m_multi_quants = multi; } + + //! Set whether the subband is skipped or not + void SetSkip(const bool skip ){ m_skipped = skip; } + + private: + // subband bounds + int m_xp , m_yp , m_xl , m_yl; + + // perceptual weight for quantisation + double m_wt; + + // depth in the transform + int m_depth; + + // quantiser index + int m_qindex; + + // position of parent in a subband list + int m_parent; + + // positions of children in the subband list + std::vector<int> m_children; + + // position of the MSB of the largest absolute value + int m_max_bit; + + // The code blocks + TwoDArray<CodeBlock> m_code_block_array; + + // A flag indicating whether we're using one qf for each code block + bool m_multi_quants; + + // Whether the subband is skipped or not + bool m_skipped; + }; + + //! A class encapulating all the subbands produced by a transform + class SubbandList + { + public: + //! Constructor + SubbandList(){} + + //! Destructor + ~SubbandList(){} + + //Default (shallow) copy constructor and operator= used + //! Initialise the list + void Init(const int depth,const int xlen,const int ylen); + + //! Return the length of the subband list + int Length() const {return bands.size();} + + //! Return the subband at position n (1<=n<=length) + Subband& operator()(const int n){return bands[n-1];} + + //! Return the subband at position n (1<=n<=length) + const Subband& operator()(const int n) const {return bands[n-1];} + + //! Add a band to the list + void AddBand(const Subband& b){bands.push_back(b);} + + //! Remove all the bands from the list + void Clear(){bands.clear();} + + private: + + //! Given x and y spatial frequencies in cycles per degree, returns a weighting value + float PerceptualWeight( const float xf , const float yf , const CompSort cs); + + private: + std::vector<Subband> bands; + }; + + class CoeffArray; + //! A virtual parent class to do vertical and horizontal splitting with wavelet filters + class VHFilter + { + + public: + + VHFilter(){} + + virtual ~VHFilter(){} + + //! Split a subband into 4 + virtual void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data)=0; + + //! Create a single band from 4 quadrant bands + virtual void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data)=0; + + //! Return the value of the additional bitshift + virtual int GetShift() const =0; + + protected: + + //! Interleave data from separate subbands into even and odd positions for in-place calculation - called by Synth + inline void Interleave( const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data ); + + + //! De-interleave data even and odd positions into separate subbands - called by Split + inline void DeInterleave( const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data ); + + //! Shift all vals in Row by 'shift' bits to the left to increase accuracy by 'shift' bits. Used in Analysis stage of filter + void ShiftRowLeft(CoeffType *row, int length, int shift); + + //! Shift all vals in Row by 'shift' bits to the right to counter the shift in the Analysis stage. This function is used in the Synthesis stage + void ShiftRowRight(CoeffType *row, int length, int shift); + }; + + //! Class to do Daubechies (9,7) filtering operations + class VHFilterDAUB9_7 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return the value of the additional bitshift + int GetShift() const {return 1;} + + + }; + + //! Class to do (5,3) wavelet filtering operations + class VHFilterLEGALL5_3 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return the value of the additional bitshift + int GetShift() const {return 1;} + + +#ifdef HAVE_MMX + inline void HorizSynth (int xp, int xl, int ystart, int yend, CoeffArray &coeff_data); +#endif + + }; + + //! A short filter that's actually close to Daubechies (9,7) but with just two lifting steps + class VHFilterDD9_7 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return the value of the additional bitshift + int GetShift() const {return 1;} + }; + + + //! An extension of DD9_7, with a better low-pass filter but more computation + class VHFilterDD13_7 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return the value of the additional bitshift + int GetShift() const {return 1;} + + }; + + //! Class to do Haar wavelet filtering operations + class VHFilterHAAR0 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return the value of the additional bitshift + int GetShift() const {return 0;} + + + }; + + //! Class to do Haar wavelet filtering operations with a single shift per level + class VHFilterHAAR1 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return the value of the additional bitshift + int GetShift() const {return 1;} + + }; + + + //! Class to do Haar wavelet filtering operations with a double shift per level + class VHFilterHAAR2 : public VHFilter + { + + public: + + //! Split a subband into 4 + void Split(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Create a single band from 4 quadrant bands + void Synth(const int xp, const int yp, const int xl, const int yl, CoeffArray& coeff_data); + + //! Return a correction factor to compensate for non-unity power gain of low-pass filter + double GetLowFactor() const { return 1.414213562;} + + //! Return a correction factor to compensate for non-unity power gain of high-pass filter + double GetHighFactor() const { return 0.707106781;} + + //! Return the value of the additional bitshift + int GetShift() const {return 2;} + + }; + + + + // Lifting steps used in the filters + + //! Class to do two-tap prediction lifting step + template<int shift> + class PredictStepShift + { + + public: + + //! Constructor + PredictStepShift(){} + + // Assume default copy constructor, assignment= and destructor // + + //! Do the filtering + /* + Do the filtering. + \param in_val the value being predicted + \param val1 the first value being used for prediction + \param val2 the second value being used for prediction + */ + inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const + { + in_val -= (( val1 + val2 + (1<<(shift-1)) ) >>shift ); + } + + }; + + //! Class to do two-tap updating lifting step + template<int shift> + class UpdateStepShift + { + + public: + //! Constructor + UpdateStepShift(){} + + //! Do the filtering + /* + Do the filtering. + \param in_val the value being updated + \param val1 the first value being used for updating + \param val2 the second value being used for updating + */ + inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const + { + in_val += ( ( val1 + val2 + (1<<(shift-1)) ) >>shift ); + } + + }; + + //! Class to do symmetric four-tap prediction lifting step + template <int shift , int tap1, int tap2> + class PredictStepFourTap + { + public: + + //! Constructor + PredictStepFourTap(){} + + // Assume default copy constructor, assignment= and destructor // + + //! Do the filtering + inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2 , + const CoeffType& val3, const CoeffType& val4 ) const + { + in_val -= ( tap1*( val1 + val2 ) + tap2*( val3 + val4 ) + (1<<(shift-1)))>>shift; + } + }; + + //! Class to do symmetric four-tap update lifting step + template <int shift , int tap1 , int tap2> + class UpdateStepFourTap + { + + public: + //! Constructor + UpdateStepFourTap(){} + + //! Do the filtering + inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2 , + const CoeffType& val3, const CoeffType& val4 ) const + { + in_val += ( tap1*( val1 + val2 ) + tap2*( val3 + val4 ) + (1<<(shift-1)) )>>shift; + } + }; + + //! Class to do two-tap prediction lifting step for Daubechies (9,7) + template <int gain> class PredictStep97 + { + public: + + //! Constructor + PredictStep97(){} + + // Assume default copy constructor, assignment= and destructor // + + //! Do the filtering + /* + Do the filtering. + \param in_val the value being predicted + \param val1 the first value being used for prediction + \param val2 the second value being used for prediction + */ + inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const + { + in_val -= static_cast< CoeffType >( (gain * static_cast< int >( val1 + val2 )) >>12 ); + } + }; + + //! Class to do two-tap update lifting step for Daubechies (9,7) + template <int gain> class UpdateStep97 + { + + public: + //! Constructor + UpdateStep97(){} + + //! Do the filtering + /* + Do the filtering. + \param in_val the value being updated + \param val1 the first value being used for updating + \param val2 the second value being used for updating + */ + inline void Filter(CoeffType& in_val, const CoeffType& val1, const CoeffType& val2) const + { + in_val += static_cast< CoeffType >( (gain * static_cast< int >( val1 + val2 )) >>12 ); + } + }; + + //! A class for wavelet coefficient data. + /*! + A class for encapsulating coefficient data, derived from TwoDArray.. + */ + class CoeffArray: public TwoDArray<CoeffType> + { + public: + //! Default constructor + /*! + Default constructor creates an empty array. + */ + CoeffArray(): TwoDArray<CoeffType>(){} + + //! Constructor. + /*! + Contructor creates a two-D array, with specified size and colour + format. + */ + CoeffArray(int height, int width, CompSort cs=Y_COMP): + TwoDArray<CoeffType>(height, width), m_csort(cs){} + + //copy constructor and assignment= derived by inheritance + + //! Destructor + ~CoeffArray(){} + + //! Return which component is stored + const CompSort& CSort() const {return m_csort;} + + //! Set the type of component being stored + void SetCSort(const CompSort cs){ m_csort = cs; } + + //! Returns the set of subbands + SubbandList& BandList(){return m_band_list;} + + //! Returns the set of subbands + const SubbandList& BandList() const {return m_band_list;} + + //! Sets the subband weights + /*! + Sets perceptual weights for the subbands. Takes into account both perceptual factors + (weight noise less at higher spatial frequencies) and the scaling needed for the + wavelet transform. + */ + void SetBandWeights (const EncoderParams& encparams, + const PictureParams& pparams, + const CompSort csort, + const float cpd_scale_factor); + + private: + + CompSort m_csort; + + // The subband list to be used for conventional transform apps + SubbandList m_band_list; + + private: + + //! Given x and y spatial frequencies in cycles per degree, returns a weighting value + float PerceptualWeight(float xf,float yf,CompSort cs); + + }; + + //! A class to do wavelet transforms + /*! + A class to do forward and backward wavelet transforms by iteratively splitting or merging the + lowest frequency band. + */ + class WaveletTransform + { + public: + //! Constructor + WaveletTransform(int d = 4, WltFilter f = DAUB9_7); + + //! Destructor + virtual ~WaveletTransform(); + + //! Transforms the data to and from the wavelet domain + /*! + Transforms the data to and from the wavelet domain. + \param d the direction of the transform + \param pic_data the data to be transformed + \param coeff_data array that holds the transform coefficient data + */ + void Transform(const Direction d, PicArray& pic_data, CoeffArray& coeff_data); + + private: + + + private: + + // Private variables + + //! Depth of the transform + int m_depth; + + //! The (vertical and horizontal) wavelet filter set to be used + WltFilter m_filt_sort; + + //! A class to do the vertical and horizontal filtering required + VHFilter* m_vhfilter; + + private: + // Private functions + //! Private, bodyless copy constructor: class should not be copied + WaveletTransform(const WaveletTransform& cpy); + + //! Private, bodyless copy operator=: class should not be assigned + WaveletTransform& operator=(const WaveletTransform& rhs); + + }; +}// end namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils_mmx.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils_mmx.cpp new file mode 100644 index 000000000..0a8953f8d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_common/wavelet_utils_mmx.cpp @@ -0,0 +1,1625 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: wavelet_utils_mmx.cpp,v 1.13 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author), +* Thomas Davies (wavelet_utils.cpp) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/*! + * MMX version of wavelet transform routines. Note that these routines + * assume that wavelet coefficients, of type CoeffType, are in fact + * shorts. This is set in libdirac_common/common.h. Turning MMX on + * reduces the supported wavelet depth to a maximum of 4 or 5 + * (depending on the filter) by the use of only 16 bits for coefficients. + */ + + +#ifdef HAVE_MMX +#include <libdirac_common/wavelet_utils.h> +#include <cstdlib> +#include <mmintrin.h> +using namespace dirac; + +static TwoDArray<CoeffType> t_temp_data; + +#if 0 +//Attempt1 +inline void Interleave_mmx( const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xl2( xl>>1); + const int yl2( yl>>1); + const int yend( yp + yl ); + + if (coeff_data.LengthX() > t_temp_data.LengthX() || + coeff_data.LengthY() > t_temp_data.LengthY()) + { + t_temp_data.Resize(coeff_data.LengthY(), coeff_data.LengthX()); + } + + // Make a temporary copy of the subband + for (int j = yp; j<yend ; j++ ) + memcpy( t_temp_data[j-yp] , coeff_data[j]+xp , xl * sizeof( CoeffType ) ); + + int stopx = (xl2>>2)<<2; + // Re-order to interleave + for (int j = 0, s=yp; j<yl2 ; j++, s+=2) + { + CoeffType *tmp1 = &t_temp_data[j][0]; + CoeffType *out = &coeff_data[s][xp]; + for (int i = 0 , t = xp ; i<xp+stopx ; i+=4 , t+=8) + { + __m64 m1 = *(__m64 *)tmp1; + __m64 m2 = *(__m64 *)(tmp1+xl2); + *(__m64 *)out = _mm_unpacklo_pi16 (m1, m2); + out+=4; + *(__m64 *)out = _mm_unpackhi_pi16 (m1, m2); + out+=4; + tmp1 += 4; + } + for (int i = xp+stopx , r=2*(xp+stopx) ; i<xl2 ; i++ , r += 2) + { + *out = *tmp1; + ++out; + *out = *(tmp1+xl2); + ++out; + ++tmp1; + } + }// j + + for (int j = yl2, s=yp+1 ; j<yl ; j++ , s += 2) + { + CoeffType *tmp1 = &t_temp_data[j][0]; + //CoeffType *tmp2 = &t_temp_data[j][xl2]; + CoeffType *out = &coeff_data[s][xp]; + for (int i = 0 , t=xp; i<stopx ; i+=4 , t += 8) + { + __m64 m1 = *(__m64 *)tmp1; + __m64 m2 = *(__m64 *)(tmp1+xl2); + *(__m64 *)out = _mm_unpacklo_pi16 (m1, m2); + out+=4; + *(__m64 *)out = _mm_unpackhi_pi16 (m1, m2); + out+=4; + tmp1 += 4; + } + for (int i = stopx , r=2*(xp+stopx) ; i<xl2 ; i++ , r += 2) + { + *out = *tmp1; + ++out; + *out = *(tmp1+xl2); + ++out; + ++tmp1; + } + }// j + + _mm_empty(); +} +#endif + +void VHFilter::ShiftRowLeft(CoeffType *row, int length, int shift) +{ + int xstop = length/4*4; + CoeffType *shift_row = row; + for (int i = 0; i < xstop; i+=4, shift_row+=4) + *(__m64 *)shift_row = _mm_slli_pi16 (*(__m64 *)shift_row, shift); + + // mopup + for (int i = xstop; i < length; ++i) + row[i] <<= shift; + + _mm_empty(); +} + +void VHFilter::ShiftRowRight(CoeffType *row, int length, int shift) +{ + CoeffType *shift_row = row; + int round_val = 1<<(shift-1); + __m64 mmx_round = _mm_set_pi16( round_val, round_val, round_val, round_val); + + int xstop = length/4*4; + for (int i = 0; i < xstop; i+=4, shift_row+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)shift_row, mmx_round); + *(__m64 *)shift_row = _mm_srai_pi16(tmp, shift); + } + // mopup + for (int i = xstop; i < length; ++i) + row[i] = ((row[i]+round_val)>>shift); + _mm_empty(); +} + +inline void Interleave_mmx( const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + const int xl2( xl>>1); + const int yl2( yl>>1); + const int yend( yp + yl ); + + if (coeff_data.LengthX() > t_temp_data.LengthX() || + coeff_data.LengthY() > t_temp_data.LengthY()) + { + t_temp_data.Resize(coeff_data.LengthY(), coeff_data.LengthX()); + } + + // Make a temporary copy of the subband. We are doing a vertical + // interleave while copying + for (int j = yp, s=0; j<yp+yl2 ; j++, s+=2 ) + memcpy( t_temp_data[s] , coeff_data[j]+xp , xl * sizeof( CoeffType ) ); + for (int j = yp+yl2, s=1; j<yend ; j++, s+=2 ) + memcpy( t_temp_data[s] , coeff_data[j]+xp , xl * sizeof( CoeffType ) ); + + int stopx = (xl2>>2)<<2; + // Re-order to horizontally interleave + for (int j = 0, s=yp; j<yl ; j++, ++s) + { + CoeffType *tmp1 = &t_temp_data[j][0]; + CoeffType *out = &coeff_data[s][xp]; + for (int i = 0 , t = xp ; i<xp+stopx ; i+=4 , t+=8) + { + __m64 m1 = *(__m64 *)tmp1; + __m64 m2 = *(__m64 *)(tmp1+xl2); + *(__m64 *)out = _mm_unpacklo_pi16 (m1, m2); + out+=4; + *(__m64 *)out = _mm_unpackhi_pi16 (m1, m2); + out+=4; + tmp1 += 4; + } + for (int i = xp+stopx , r=2*(xp+stopx) ; i<xl2 ; i++ , r += 2) + { + *out = *tmp1; + ++out; + *out = *(tmp1+xl2); + ++out; + ++tmp1; + } + }// j + + _mm_empty(); +} + +void VHFilterDD9_7::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + int i, j; + const int xend( xp+xl ); + const int yend( yp+yl ); + const int ymid = yp+yl/2; + + PredictStepShift<2> predict; + __m64 pred_round = _mm_set_pi16 (1<<(2-1), 1<<(2-1), 1<<(2-1), 1<<(2-1)); + + int xstop = xp + ((xl>>2)<<2); + + // First lifting stage + // Top edge + CoeffType *in1 = coeff_data[ymid]; + CoeffType *in2 = coeff_data[ymid]; + CoeffType *out = coeff_data[yp]; + for ( i = xp ; i < xstop ; i+=4 ) + { + // tmp = val + val2 + __m64 tmp = _mm_add_pi16 (*(__m64 *)in1, *(__m64 *)in2); + // unbiased rounding tmp = (tmp + 1<<(shift-1))>>shift + tmp = _mm_add_pi16(tmp, pred_round); + tmp = _mm_srai_pi16(tmp, 2); + // in_val -= tmp; + *(__m64 *)out = _mm_sub_pi16 (*(__m64*)out, tmp); + out += 4; + in1 += 4; + in2 += 4; + } + + // Middle bit + for ( j=1 ; j < yl/2 ; ++j ) + { + in1 = coeff_data[ymid+j-1]; + in2 = coeff_data[ymid+j]; + out = coeff_data[yp+j]; + for ( i = xp ; i < xstop ; i+=4 ) + { + // tmp = val + val2 + __m64 tmp = _mm_add_pi16 (*(__m64 *)in1, *(__m64 *)in2); + // unbiased rounding tmp = (tmp + 1<<(shift-1))>>shift + tmp = _mm_add_pi16(tmp, pred_round); + tmp = _mm_srai_pi16(tmp, 2); + // in_val -= tmp; + *(__m64 *)out = _mm_sub_pi16 (*(__m64*)out, tmp); + out += 4; + in1 += 4; + in2 += 4; + } + } + + // Mopup + if (xstop != xend) + { + for ( i = xstop ; i < xend ; i++) + { + predict.Filter( coeff_data[yp][i] , coeff_data[ymid][i] , coeff_data[ymid][i] ); + }// i + + for ( j=1 ; j < yl/2 ; ++j ) + { + for ( i = xstop ; i < xend ; i++) + { + predict.Filter( coeff_data[yp+j][i] , coeff_data[ymid+j-1][i] , coeff_data[ymid+j][i] ); + }// i + }// j + } + + // Second lifting stage + UpdateStepFourTap< 4 , 9 , -1> update; + // rounding factor for update step + __m64 update_round = _mm_set_pi32 (1<<(4-1), 1<<(4-1)); + // top edge + in1 = coeff_data[yp]; + in2 = coeff_data[yp+1]; + CoeffType *in3 = coeff_data[yp]; + CoeffType *in4 = coeff_data[yp+2]; + out = coeff_data[ymid]; + __m64 tap1 = _mm_set_pi16 (9, 9, 9, 9); + __m64 tap2 = _mm_set_pi16 (-1, -1, -1, -1); + + for ( i = xp ; i < xstop ; i+=4 ) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + } + + // middle bit + for ( j=1 ; j < yl/2 - 2 ; ++j) + { + in1 = coeff_data[yp+j]; + in2 = coeff_data[yp+j+1]; + in3 = coeff_data[yp+j-1]; + in4 = coeff_data[yp+j+2]; + out = coeff_data[ymid+j]; + for ( i = xp ; i < xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + }// k + + // bottom edge + in1 = coeff_data[ymid-2]; + in2 = coeff_data[ymid-1]; + in3 = coeff_data[ymid-3]; + in4 = coeff_data[ymid-1]; + out = coeff_data[yend-2]; + for ( i = xp ; i < xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + } + + in1 = coeff_data[ymid-1]; + in2 = coeff_data[ymid-1]; + in3 = coeff_data[ymid-2]; + in4 = coeff_data[ymid-1]; + out = coeff_data[yend-1]; + for ( i = xp ; i < xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + } + + if (xstop != xend) + { + for ( i = xstop ; i < xend ; i++) + { + update.Filter( coeff_data[ymid][i] , coeff_data[yp][i], coeff_data[yp+1][i], coeff_data[yp][i],coeff_data[yp+2][i]); + }// i + + // middle bit + for ( j=1 ; j < yl/2 - 2 ; ++j) + { + for ( i = xstop ; i < xend ; i++) + { + update.Filter( coeff_data[ymid+j][i] , coeff_data[yp+j][i], coeff_data[yp+j+1][i], coeff_data[yp+j-1][i],coeff_data[yp+j+2][i]); + }// i + }// k + + for ( i = xstop ; i < xend ; i++) + { + update.Filter( coeff_data[yend - 2][i] , coeff_data[ymid-2][i], coeff_data[ymid-1][i], coeff_data[ymid-3][i],coeff_data[ymid-1][i]); + update.Filter( coeff_data[yend - 1][i] , coeff_data[ymid-1][i], coeff_data[ymid-1][i], coeff_data[ymid-2][i],coeff_data[ymid-1][i]); + }// i + } + + + // Horizontal sythesis + + const int xmid = xl/2; + xstop = xmid %4 ? ((xmid>>2)<<2) + 1 : xmid -3; + + for (j = yp; j < yend; ++j) + { + CoeffType *line_data = &coeff_data[j][xp]; + + // First lifting stage acts on even samples i.e. the low pass ones + predict.Filter( line_data[0] , line_data[xmid] , line_data[xmid] ); + for (i=1 ; i < xmid ; ++i) + { + predict.Filter( line_data[i] , line_data[xmid+i-1] , line_data[xmid+i] ); + } + + // Second lifting stage + update.Filter( line_data[xmid] , line_data[0] , line_data[1] , line_data[0] , line_data[2] ); + + for (i=1 ; i < xmid - 2; ++i) + { + update.Filter( line_data[xmid+i] , line_data[i] , line_data[i+1] , line_data[i-1] , line_data[i+2] ); + }// i + update.Filter( line_data[xl-2] , line_data[xmid-2] , line_data[xmid-1] , line_data[xmid-3] , line_data[xmid-1] ); + update.Filter( line_data[xl-1] , line_data[xmid-1] , line_data[xmid-1] , line_data[xmid-2] , line_data[xmid-1] ); + + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + + }// j + _mm_empty(); + Interleave_mmx( xp , yp , xl ,yl , coeff_data ); +} + +void VHFilterDD13_7::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + int i,j,k; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + PredictStepFourTap< 5 , 9 , -1 > predict; + __m64 pred_round = _mm_set_pi32 (1<<(5-1), 1<<(5-1)); + UpdateStepFourTap< 4 , 9 , -1> update; + __m64 update_round = _mm_set_pi32 (1<<(4-1), 1<<(4-1)); + + // Next, do the vertical synthesis + int ymid = yp + yl/2; + + int xstop = xp + ((xl>>2)<<2); + // First lifting stage - odd samples + // bottom edge + CoeffType *out = coeff_data[ymid-1]; + CoeffType *in1 = coeff_data[yend-2]; + CoeffType *in2 = coeff_data[yend-1]; + CoeffType *in3 = coeff_data[yend-3]; + CoeffType *in4 = coeff_data[yend-1]; + + __m64 tap1 = _mm_set_pi16 (9, 9, 9, 9); + __m64 tap2 = _mm_set_pi16 (-1, -1, -1, -1); + for ( i = xp ; i<xstop; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, pred_round); + val3 = _mm_add_pi32 (val3, pred_round); + val1 = _mm_srai_pi32(val1, 5); + val3 = _mm_srai_pi32(val3, 5); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_sub_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + + // middle bit + for ( j = 2 ; j < yl/2 -1 ; ++j) + { + out = coeff_data[yp+j]; + in1 = coeff_data[ymid+j-1]; + in2 = coeff_data[ymid+j]; + in3 = coeff_data[ymid+j-2]; + in4 = coeff_data[ymid+j+1]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, pred_round); + val3 = _mm_add_pi32 (val3, pred_round); + val1 = _mm_srai_pi32(val1, 5); + val3 = _mm_srai_pi32(val3, 5); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_sub_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + }// j + + // top edge - j=xp + out = coeff_data[yp+1]; + in1 = coeff_data[ymid]; + in2 = coeff_data[ymid+1]; + in3 = coeff_data[ymid+2]; + in4 = coeff_data[ymid]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, pred_round); + val3 = _mm_add_pi32 (val3, pred_round); + val1 = _mm_srai_pi32(val1, 5); + val3 = _mm_srai_pi32(val3, 5); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_sub_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + } + + out = coeff_data[yp]; + in1 = coeff_data[ymid]; + in2 = coeff_data[ymid]; + in3 = coeff_data[ymid+1]; + in4 = coeff_data[ymid]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, pred_round); + val3 = _mm_add_pi32 (val3, pred_round); + val1 = _mm_srai_pi32(val1, 5); + val3 = _mm_srai_pi32(val3, 5); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_sub_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + } + + // Mopup + if ( xstop != xend) + { + // Mopup bottom edge + for ( i = xstop ; i<xend ; ++ i) + { + predict.Filter( coeff_data[ymid-1][i] , coeff_data[yend-2][i] , coeff_data[yend-1][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + }// i + + // Mopup middle bit + for ( k = 2 ; k < yl/2 - 1 ; ++k) + { + for ( i = xstop ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+k][i] , coeff_data[ymid+k-1][i] , coeff_data[ymid+k][i] , coeff_data[ymid+k-2][i] , coeff_data[ymid+k+1][i] ); + }// i + }// k + + //Mopup top edge + for ( i = xstop ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+1][i] , coeff_data[ymid][i] , coeff_data[ymid+1][i] , coeff_data[ymid+2][i] , coeff_data[ymid][i] ); + predict.Filter( coeff_data[yp][i] , coeff_data[ymid][i] , coeff_data[ymid][i] , coeff_data[ymid+1][i] , coeff_data[ymid][i] ); + + }// i + + } + + // Second lifting stage + // top edge - j=xp + out = coeff_data[ymid]; + in1 = coeff_data[yp]; + in2 = coeff_data[yp+1]; + in3 = coeff_data[yp]; + in4 = coeff_data[yp+2]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + + + // middle bit + for ( k = 1 ; k < yl/2 - 2 ; ++k) + { + out = coeff_data[ymid+k]; + in1 = coeff_data[k]; + in2 = coeff_data[k+1]; + in3 = coeff_data[k-1]; + in4 = coeff_data[k+2]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + }// k + + // bottom edge + out = coeff_data[yend-2]; + in1 = coeff_data[ymid-2]; + in2 = coeff_data[ymid-1]; + in3 = coeff_data[ymid-3]; + in4 = coeff_data[ymid-1]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + + out = coeff_data[yend-1]; + in1 = coeff_data[ymid-1]; + in2 = coeff_data[ymid-1]; + in3 = coeff_data[ymid-2]; + in4 = coeff_data[ymid-1]; + for ( i = xp ; i<xstop ; i+=4) + { + __m64 val1, val2, val3, val4, tmp1, tmp2; + + val1 = _mm_add_pi16(*(__m64*)in1, *(__m64*)in2); + tmp1 = _mm_mullo_pi16 (val1, tap1); + tmp2 = _mm_mulhi_pi16 (val1, tap1); + val3 = _mm_unpackhi_pi16 (tmp1, tmp2); + val1 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val2 = _mm_add_pi16(*(__m64*)in3, *(__m64*)in4); + tmp1 = _mm_mullo_pi16 (val2, tap2); + tmp2 = _mm_mulhi_pi16 (val2, tap2); + val4 = _mm_unpackhi_pi16 (tmp1, tmp2); + val2 = _mm_unpacklo_pi16 (tmp1, tmp2); + + val1 = _mm_add_pi32 (val1, val2); + val3 = _mm_add_pi32 (val3, val4); + val1 = _mm_add_pi32 (val1, update_round); + val3 = _mm_add_pi32 (val3, update_round); + val1 = _mm_srai_pi32(val1, 4); + val3 = _mm_srai_pi32(val3, 4); + val1 = _mm_packs_pi32 (val1, val3); + + *(__m64*)out = _mm_add_pi16 (*(__m64*)out,val1); + in1 +=4; + in2 +=4; + in3 +=4; + in4 +=4; + out +=4; + }// i + + + // Mopup + if ( xstop != xend) + { + // bottom edge + for ( i = xstop ; i<xend ; ++ i) + { + update.Filter( coeff_data[yend-1][i] , coeff_data[ymid-1][i] , coeff_data[ymid-1][i] , coeff_data[ymid-2][i] , coeff_data[ymid-1][i] ); + update.Filter( coeff_data[yend-2][i] , coeff_data[ymid-2][i] , coeff_data[ymid-1][i] , coeff_data[ymid-3][i] , coeff_data[ymid-1][i] ); + + }// i + + // middle bit + for ( k = 1 ; k < yl/2 - 2 ; ++k) + { + for ( i = xstop ; i<xend ; ++ i) + { + update.Filter( coeff_data[ymid+k][i] , coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] , coeff_data[k+2][i] ); + }// i + }// j + + // top edge - j=xp + for ( i = xstop ; i<xend ; ++ i) + { + update.Filter( coeff_data[ymid][i] , coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp][i] , coeff_data[yp+2][i] ); + }// i + } + + // Next do the horizontal synthesis + + CoeffType* line_data; + int xmid = xl/2; + + for (j = yp; j < yend ; ++j) + { + line_data = &coeff_data[j][xp]; + + // First lifting stage + + predict.Filter( line_data[0] , line_data[xmid] , line_data[xmid] , line_data[xmid+1] , line_data[xmid] ); + predict.Filter( line_data[1] , line_data[xmid] , line_data[xmid+1] , line_data[xmid+2] , line_data[xmid] ); + + for (k=2 ; k < xmid-1 ; ++k) + { + predict.Filter( line_data[k] , line_data[xmid+k-1] , line_data[xmid+k] , line_data[xmid+k-2] , line_data[xmid+k+1] ); + + }// i + predict.Filter( line_data[xmid-1] , line_data[xl-2] , line_data[xl-1] , line_data[xl-3] , line_data[xl-1] ); + + //second lifting stage + + update.Filter( line_data[xmid] , line_data[0] , line_data[1] , line_data[0] , line_data[2] ); + for (k=1 ; k<xmid-2 ; ++k) + { + update.Filter( line_data[xmid+k] , line_data[k] , line_data[k+1] , line_data[k-1] , line_data[k+2] ); + }// i + update.Filter( line_data[xl-2] , line_data[xmid-2] , line_data[xmid-1] , line_data[xmid-3] , line_data[xmid-1] ); + update.Filter( line_data[xl-1] , line_data[xmid-1] , line_data[xmid-1] , line_data[xmid-2] , line_data[xmid-1] ); + + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + + }// j + + _mm_empty(); + // Interleave subbands + Interleave_mmx( xp , yp , xl , yl , coeff_data ); +} + +#if 0 +//Opts - Attempt1 +void VHFilterLEGALL5_3::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + int i,j,k; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + const PredictStepShift< 2 > predict; + const UpdateStepShift< 1 > update; + + CoeffType* line_data; + + // Firstly reorder to interleave subbands, so that subsequent calculations + // can be in-place + Interleave_mmx( xp , yp , xl , yl , coeff_data ); + + // Next, do the vertical synthesis + // First lifting stage + int xstop = (xend>>2)<<2; + + // Begin the top edge + CoeffType *row1, *row2, *row3, *row4; + + row1 = &coeff_data[yp][xp]; + row2 = &coeff_data[yp+1][xp]; + for ( i = xp ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row2); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row1 = _mm_sub_pi16 (*(__m64*)row1, tmp); + + row1 += 4; + row2 += 4; + } + // Mopup + for ( i = xstop ; i < xend ; ++i) + { + predict.Filter( coeff_data[yp][i] , coeff_data[yp+1][i] , coeff_data[yp+1][i] ); + }// i + + + // Next, do the middle bit + for ( k = yp+2 ; k < yend-2 ; k+=2) + { + CoeffType *row1 = &coeff_data[k-2][xp]; + CoeffType *row2 = &coeff_data[k-1][xp]; + CoeffType *row3 = &coeff_data[k][xp]; + CoeffType *row4 = &coeff_data[k+1][xp]; + + for ( i = xp ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row4, *(__m64 *)row2); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row3 = _mm_sub_pi16 (*(__m64*)row3, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row1, *(__m64 *)row3); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row2 = _mm_add_pi16 (*(__m64*)row2, tmp); + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + + //Mopup + for ( i = xstop ; i < xend ; ++i) + { + predict.Filter( coeff_data[k][i] , coeff_data[k+1][i] , coeff_data[k-1][i] ); + update.Filter( coeff_data[k-1][i] , coeff_data[k-2][i] , coeff_data[k][i] ); + }// i + }// j + + // Finally with the bottom edge + row1 = &coeff_data[yend-4][xp]; + row2 = &coeff_data[yend-3][xp]; + row3 = &coeff_data[yend-2][xp]; + row4 = &coeff_data[yend-1][xp]; + + for ( i = xp ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row4); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row3 = _mm_sub_pi16 (*(__m64*)row3, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row3, *(__m64 *)row1); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row2 = _mm_add_pi16 (*(__m64*)row2, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row3, *(__m64 *)row3); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row4 = _mm_add_pi16 (*(__m64*)row4, tmp); + + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + // mopup + for ( i = xstop ; i < xend ; ++i) + { + predict.Filter( coeff_data[yend-2][i] , coeff_data[yend-3][i] , coeff_data[yend-1][i] ); + update.Filter( coeff_data[yend-3][i] , coeff_data[yend-2][i] , coeff_data[yend-4][i] ); + update.Filter( coeff_data[yend-1][i] , coeff_data[yend-2][i] , coeff_data[yend-2][i] ); + }// i + + + // Next do the horizontal synthesis + for (j = yp; j < yend ; ++j) + { + // First lifting stage + line_data = &coeff_data[j][xp]; + + predict.Filter( line_data[0] , line_data[1] , line_data[1] ); + + for ( k = 2; k < xl -2; k+=2) + { + predict.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + update.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + }// i + + predict.Filter( line_data[xl-2] , line_data[xl-3] , line_data[xl-1] ); + update.Filter( line_data[xl-3] , line_data[xl-2] , line_data[xl-4] ); + update.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] ); + + } + _mm_empty(); +} +#endif + +#if 0 +//Opts Attempt 2 +void VHFilterLEGALL5_3::Synth(const int xp , + const int yp , + const int xl , + const int yl , + PicArray& coeff_data) +{ + int i,j,k; + const int yend( yp+yl ); + + const int xl2 (xl>>1); + const int ymid (yp + (yl>>1)); + const PredictStepShift< 2 > predict; + const UpdateStepShift< 1 > update; + + CoeffType* line_data; + + + // Next, do the vertical synthesis + // First lifting stage + + int xstop = (xl>>2)<<2; + + CoeffType *row1, *row2, *row3, *row4; + // First do the top edge + row1 = &coeff_data[yp][xp]; + row2 = &coeff_data[ymid][xp]; + for ( i = 0 ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row2); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row1 = _mm_sub_pi16 (*(__m64*)row1, tmp); + row1+=4; + row2+=4; + }// i + + //mopup + for ( i = xstop ; i < xl ; ++i) + { + predict.Filter( *row1 , *row2 , *row2); + ++row1; + ++row2; + }// i + + // Next, do the middle bit + for ( k = 1 ; k < ymid-1 ; ++k) + { + row1 = &coeff_data[k-1][xp]; + row2 = &coeff_data[k][xp]; + row3 = &coeff_data[ymid+k-1][xp]; + row4 = &coeff_data[ymid+k][xp]; + + for ( i = 0 ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row3, *(__m64 *)row4); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row2 = _mm_sub_pi16 (*(__m64*)row2, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row1); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row3 = _mm_add_pi16 (*(__m64*)row3, tmp); + + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + + for ( i = xstop ; i < xl ; ++i) + { + predict.Filter( *row2 , *row4 , *row3 ); + update.Filter( *row3 , *row2 , *row1 ); + ++row1; + ++row2; + ++row3; + ++row4; + }// i + }// j + + + // Finally with the bottom edge + row1 = &coeff_data[ymid-2][xp]; + row2 = &coeff_data[ymid-1][xp]; + row3 = &coeff_data[yend-2][xp]; + row4 = &coeff_data[yend-1][xp]; + for ( i = xp ; i< xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row3, *(__m64 *)row4); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row2 = _mm_sub_pi16 (*(__m64*)row2, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row1); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row3 = _mm_add_pi16 (*(__m64*)row3, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row2); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row4 = _mm_add_pi16 (*(__m64*)row4, tmp); + + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + // mopup + for ( i = xstop ; i< xl ; ++i) + { + predict.Filter( *row2 , *row3 , *row4 ); + update.Filter( *row3 , *row1 , *row2 ); + update.Filter( *row4 , *row2 , *row2 ); + ++row1; + ++row2; + ++row3; + ++row4; + }// i + + // Next do the horizontal synthesis + xstop = (((xl2 - 2)>>2)<<2) + 1; + //xstop = 1; + for (j = yp; j < yend ; ++j) + { + // First lifting stage + line_data = &coeff_data[j][xp]; + predict.Filter( line_data[0] , line_data[xl2] , line_data[xl2] ); + + for ( k = 1; k < xstop; k+=4) + { + //predict.Filter( line_data[k] , line_data[xl2+k] , line_data[xl2+k-1] ); + __m64 m1 = _mm_add_pi16 (*(__m64 *)(line_data+xl2+k), *(__m64 *)(line_data+xl2+k-1)); + m1 = _mm_srai_pi16 (m1, 2); + *(__m64 *)(line_data+k) = _mm_sub_pi16 (*(__m64 *)(line_data+k), m1); + + //update.Filter( line_data[xl2+k-1] , line_data[k] , line_data[k-1] ); + m1 = _mm_add_pi16 (*(__m64 *)(line_data+k), *(__m64 *)(line_data+k-1)); + m1 = _mm_srai_pi16(m1, 1); + *(__m64 *)(line_data+xl2+k-1) = _mm_add_pi16 (*(__m64*)(line_data+xl2+k-1), m1); + + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + + + for ( k = xstop; k < xl2-1; ++k) + { + predict.Filter( line_data[k] , line_data[xl2+k] , line_data[xl2+k-1] ); + update.Filter( line_data[xl2+k-1] , line_data[k] , line_data[k-1] ); + }// i + + predict.Filter( line_data[xl2-1] , line_data[xl-2] , line_data[xl-1] ); + update.Filter( line_data[xl-2] , line_data[xl2-2] , line_data[xl2-1] ); + update.Filter( line_data[xl-1] , line_data[xl2-1] , line_data[xl2-1] ); + } + _mm_empty(); + + // Finally interleave subbands + Interleave_mmx( xp , yp , xl , yl , coeff_data ); +} +#endif + +//Attempt 3 + +inline void VHFilterLEGALL5_3::HorizSynth (int xp, int xl, int ystart, int yend, CoeffArray &coeff_data) +{ + static const PredictStepShift< 2 > predict; + static const UpdateStepShift< 1 > update; + int j, k; + // Next do the horizontal synthesis + for (j = ystart; j <= yend ; ++j) + { + // First lifting stage + CoeffType *line_data = &coeff_data[j][xp]; + + predict.Filter( line_data[0] , line_data[1] , line_data[1] ); + + for ( k = 2; k < xl -2; k+=2) + { + predict.Filter( line_data[k] , line_data[k+1] , line_data[k-1] ); + update.Filter( line_data[k-1] , line_data[k-2] , line_data[k] ); + }// i + + predict.Filter( line_data[xl-2] , line_data[xl-3] , line_data[xl-1] ); + update.Filter( line_data[xl-3] , line_data[xl-2] , line_data[xl-4] ); + update.Filter( line_data[xl-1] , line_data[xl-2] , line_data[xl-2] ); + // Shift right by one bit to counter the shift in the analysis stage + ShiftRowRight(line_data, xl, 1); + } +} + +void VHFilterLEGALL5_3::Synth(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray &coeff_data) +{ + int i, k; + + const int xend( xp+xl ); + const int yend( yp+yl ); + + const PredictStepShift< 2 > predict; + __m64 pred_round = _mm_set_pi16 (1<<(2-1), 1<<(2-1), 1<<(2-1), 1<<(2-1)); + const UpdateStepShift< 1 > update; + __m64 update_round = _mm_set_pi16 (1, 1, 1, 1); + + int horiz_start = 0; + int horiz_end = 0; + + // Firstly reorder to interleave subbands, so that subsequent calculations + // can be in-place + Interleave_mmx( xp , yp , xl , yl , coeff_data ); + + // Next, do the vertical synthesis + // First lifting stage + int xstop = (xend>>2)<<2; + + // Begin the top edge + CoeffType *row1, *row2, *row3, *row4; + + row1 = &coeff_data[yp][xp]; + row2 = &coeff_data[yp+1][xp]; + for ( i = xp ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row2); + tmp = _mm_add_pi16 (tmp, pred_round); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row1 = _mm_sub_pi16 (*(__m64*)row1, tmp); + + row1 += 4; + row2 += 4; + } + // Mopup + for ( i = xstop ; i < xend ; ++i) + { + predict.Filter( *row1, *row2, *row2 ); + ++row1; + ++row2; + }// i + + + // Next, do the middle bit + for ( k = yp+2 ; k < yend-2 ; k+=2) + { + CoeffType *row1 = &coeff_data[k-2][xp]; + CoeffType *row2 = &coeff_data[k-1][xp]; + CoeffType *row3 = &coeff_data[k][xp]; + CoeffType *row4 = &coeff_data[k+1][xp]; + + for ( i = xp ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row4, *(__m64 *)row2); + tmp = _mm_add_pi16 (tmp, pred_round); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row3 = _mm_sub_pi16 (*(__m64*)row3, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row1, *(__m64 *)row3); + tmp = _mm_add_pi16 (tmp, update_round); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row2 = _mm_add_pi16 (*(__m64*)row2, tmp); + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + + //Mopup + for ( i = xstop ; i < xend ; ++i) + { + predict.Filter( *row3, *row2, *row4 ); + update.Filter( *row2, *row1, *row3 ); + ++row1; + ++row2; + ++row3; + ++row4; + }// i + horiz_end = k - 2; + // Do the horizontal synthesis + HorizSynth (xp, xl, horiz_start, horiz_end, coeff_data); + horiz_start = horiz_end + 1; + }// j + + // Finally with the bottom edge + row1 = &coeff_data[yend-4][xp]; + row2 = &coeff_data[yend-3][xp]; + row3 = &coeff_data[yend-2][xp]; + row4 = &coeff_data[yend-1][xp]; + + for ( i = xp ; i < xstop ; i+=4) + { + __m64 tmp = _mm_add_pi16 (*(__m64 *)row2, *(__m64 *)row4); + tmp = _mm_add_pi16 (tmp, pred_round); + tmp = _mm_srai_pi16(tmp, 2); + *(__m64 *)row3 = _mm_sub_pi16 (*(__m64*)row3, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row3, *(__m64 *)row1); + tmp = _mm_add_pi16 (tmp, update_round); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row2 = _mm_add_pi16 (*(__m64*)row2, tmp); + + tmp = _mm_add_pi16 (*(__m64 *)row3, *(__m64 *)row3); + tmp = _mm_add_pi16 (tmp, update_round); + tmp = _mm_srai_pi16(tmp, 1); + *(__m64 *)row4 = _mm_add_pi16 (*(__m64*)row4, tmp); + + row1 += 4; + row2 += 4; + row3 += 4; + row4 += 4; + }// i + // mopup + for ( i = xstop ; i < xend ; ++i) + { + predict.Filter( *row3, *row2, *row4 ); + update.Filter( *row2, *row1, *row3 ); + update.Filter( *row4, *row3, *row3 ); + ++row1; + ++row2; + ++row3; + ++row4; + }// i + + _mm_empty(); + // Last lines of horizontal synthesis + HorizSynth (xp, xl, horiz_start, yend-1, coeff_data); +} + + +void DeInterleave_mmx( const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray &coeff_data) +{ + const int xl2( xl>>1); + const int yl2( yl>>1); + const int yend( yp + yl ); + + if (coeff_data.LengthX() > t_temp_data.LengthX() || + coeff_data.LengthY() > t_temp_data.LengthY()) + { + t_temp_data.Resize(coeff_data.LengthY(), coeff_data.LengthX()); + } + + // Make a temporary copy of the subband + for (int j = yp; j<yend ; j++ ) + memcpy( t_temp_data[j-yp] , coeff_data[j]+xp , xl * sizeof( CoeffType ) ); + + int stopx = (xl2>>2)<<2; + + for (int j = yp, s=0; j<(yp+yl2) ; j++, s+=2) + { + CoeffType *tmp1 = &t_temp_data[s][0]; + CoeffType *out1 = &coeff_data[j][xp]; + CoeffType *out2 = &coeff_data[j][xl2]; + int r = xp; + for (int i = 0; i<xp+stopx ; i+=4 , r+=8) + { + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)tmp1, *(__m64 *)(tmp1+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)tmp1, *(__m64 *)(tmp1+4)); + *(__m64 *)out1 = _mm_unpacklo_pi16 (m1, m2); + *(__m64 *)out2 = _mm_unpackhi_pi16 (m1, m2); + out1 += 4; + out2 += 4; + tmp1+=8; + } + //mopup + for (int i = xp+stopx; i < xp+xl2; ++i, r+=2) + { + coeff_data[j][i] = t_temp_data[s][r]; + coeff_data[j][i+xl2] = t_temp_data[s][r+1]; + } + }// j + + for (int j = yl2, s=1; j< yend ; j++, s+=2) + { + CoeffType *tmp1 = &t_temp_data[s][0]; + CoeffType *out1 = &coeff_data[j][xp]; + CoeffType *out2 = &coeff_data[j][xl2]; + int r = xp; + for (int i = 0; i<xp+stopx ; i+=4 , r+=8) + { + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)tmp1, *(__m64 *)(tmp1+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)tmp1, *(__m64 *)(tmp1+4)); + *(__m64 *)out1 = _mm_unpacklo_pi16 (m1, m2); + *(__m64 *)out2 = _mm_unpackhi_pi16 (m1, m2); + out1 += 4; + out2 += 4; + tmp1+=8; + } + //mopup + for (int i = xp+stopx; i < xp+xl2; ++i, r+=2) + { + coeff_data[j][i] = t_temp_data[s][r]; + coeff_data[j][i+xl2] = t_temp_data[s][r+1]; + } + }// j + _mm_empty(); +} + +void VHFilterLEGALL5_3::Split(const int xp , + const int yp , + const int xl , + const int yl , + CoeffArray& coeff_data) +{ + //version based on integer-like types + //using edge-extension rather than reflection + + const int xend=xp+xl; + const int yend=yp+yl; + const int xl2 = xl>>1; + const int yl2 = yl>>1; + + CoeffType* line_data; + + // Positional variables + int i,j,k; + + // Objects to do lifting stages + // (in revese order and type from synthesis) + const PredictStepShift< 1 > predict; + __m64 pred_round = _mm_set_pi16 (1, 1, 1, 1); + const UpdateStepShift< 2 > update; + __m64 update_round = _mm_set_pi16 (1<<(2-1), 1<<(2-1), 1<<(2-1), 1<<(2-1)); + + // Lastly, have to reorder so that subbands are no longer interleaved + DeInterleave_mmx( xp , yp , xl , yl , coeff_data ); + //first do horizontal + + for (j = yp; j < yend; ++j) + { + // First lifting stage + line_data = &coeff_data[j][xp]; + // Shift left by one bit to give us more accuracy + ShiftRowLeft(line_data, xl, 1); + + predict.Filter( line_data[xp+xl2] , line_data[1] , line_data[0] ); + update.Filter( line_data[0] , line_data[xp+xl2] , line_data[xp+xl2] ); + + for (k = 1; k < xp+xl2-1; k+=1) + { + predict.Filter( line_data[xp+xl2+k] , line_data[k+1] , line_data[k] ); + update.Filter( line_data[k] , line_data[xp+xl2+k-1] , line_data[xp+xl2+k] ); + }// i + + predict.Filter( line_data[xl-1] , line_data[xp+xl2-1] , line_data[xp+xl2-1] ); + update.Filter( line_data[xp+xl2-1] , line_data[xl-2] , line_data[xl-1] ); + + }// j + + // next do vertical + + // First lifting stage + + // top edge - j=xp + int stopX = (xl>>2)<<2; + CoeffType *in_val = &coeff_data[yp+yl2][xp]; + CoeffType *val1 = &coeff_data[1][xp]; + CoeffType *val2 = &coeff_data[0][xp]; + for ( i = xp ; i<(xp+stopX); i+=4) + { + //predict.Filter( coeff_data[yp+yl2][i] , coeff_data[1][i] , coeff_data[0][i] ); + __m64 m1 = _mm_add_pi16 (*(__m64 *)val1, *(__m64 *)val2); + m1 = _mm_add_pi16 (m1, pred_round); + m1 = _mm_srai_pi16(m1, 1); + *(__m64 *)in_val = _mm_sub_pi16 (*(__m64 *)in_val, m1); + + //update.Filter( coeff_data[0][i] , coeff_data[yp+yl2][i] , coeff_data[yp+yl2][i] ); + m1 = _mm_add_pi16 (*(__m64 *)in_val, *(__m64 *)in_val); + m1 = _mm_add_pi16 (m1, update_round); + m1 = _mm_srai_pi16(m1, 2); + *(__m64 *)val2 = _mm_add_pi16 (*(__m64 *)val2, m1); + in_val += 4; + val1 += 4; + val2 += 4; + }// i + // mopup + for ( i = xp+stopX ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+yl2][i] , coeff_data[1][i] , coeff_data[0][i] ); + update.Filter( coeff_data[0][i] , coeff_data[yp+yl2][i] , coeff_data[yp+yl2][i] ); + }// i + + // middle bit + for (k = 1 ; k<yp+yl2-1 ; k+=1) + { + CoeffType *in_val = &coeff_data[yp+yl2+k][xp]; + CoeffType *in_val2 = &coeff_data[yp+yl2+k-1][xp]; + CoeffType *val1 = &coeff_data[k+1][xp]; + CoeffType *val2 = &coeff_data[k][xp]; + for ( i = xp ; i<xp+stopX ; i+=4) + { + //predict.Filter( coeff_data[yp+yl2+k][i] , coeff_data[k+1][i] , coeff_data[k][i] ); + __m64 m1 = _mm_add_pi16 (*(__m64 *)val1, *(__m64 *)val2); + m1 = _mm_add_pi16 (m1, pred_round); + m1 = _mm_srai_pi16(m1, 1); + *(__m64 *)in_val = _mm_sub_pi16 (*(__m64 *)in_val, m1); + + //update.Filter( coeff_data[k][i] , coeff_data[yp+yl2+k-1][i] , coeff_data[yp+yl2+k][i] ); + m1 = _mm_add_pi16 (*(__m64 *)in_val, *(__m64 *)in_val2); + m1 = _mm_add_pi16 (m1, update_round); + m1 = _mm_srai_pi16(m1, 2); + *(__m64 *)val2 = _mm_add_pi16 (*(__m64 *)val2, m1); + + in_val += 4; + in_val2 += 4; + val1 += 4; + val2 += 4; + }// i + + //mopup + for ( i = xp+stopX ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yp+yl2+k][i] , coeff_data[k+1][i] , coeff_data[k][i] ); + update.Filter( coeff_data[k][i] , coeff_data[yp+yl2+k-1][i] , coeff_data[yp+yl2+k][i] ); + }// i + }// j + + in_val = &coeff_data[yend-1][xp]; + val2 = &coeff_data[yp+yl2-1][xp]; + CoeffType *in_val2 = &coeff_data[yend-2][xp]; + // bottom edge + for ( i = xp ; i<xp+stopX ; i+=4) + { + //predict.Filter( coeff_data[yend-1][i] , coeff_data[yp+yl2-1][i] , coeff_data[yp+yl2-1][i] ); + __m64 m1 = _mm_add_pi16 (*(__m64 *)val2, *(__m64 *)val2); + m1 = _mm_add_pi16 (m1, pred_round); + m1 = _mm_srai_pi16(m1, 1); + *(__m64 *)in_val = _mm_sub_pi16 (*(__m64 *)in_val, m1); + + //update.Filter( coeff_data[yp+yl2-1][i] , coeff_data[yend-2][i] , coeff_data[yend-1][i] ); + m1 = _mm_add_pi16 (*(__m64 *)in_val2, *(__m64 *)in_val); + m1 = _mm_add_pi16 (m1, update_round); + m1 = _mm_srai_pi16(m1, 2); + *(__m64 *)val2 = _mm_add_pi16 (*(__m64 *)val2, m1); + + in_val += 4; + in_val2 += 4; + val2 += 4; + }// i + // mopup + for ( i = xp+stopX ; i<xend ; ++ i) + { + predict.Filter( coeff_data[yend-1][i] , coeff_data[yp+yl2-1][i] , coeff_data[yp+yl2-1][i] ); + update.Filter( coeff_data[yp+yl2-1][i] , coeff_data[yend-2][i] , coeff_data[yend-1][i] ); + }// i + _mm_empty(); +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/comp_decompress.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/comp_decompress.cpp new file mode 100644 index 000000000..3067c241e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/comp_decompress.cpp @@ -0,0 +1,163 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: comp_decompress.cpp,v 1.32 2009/01/21 05:18:09 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Anuradha Suraparaju, +* Andrew Kennedy, +* Tim Borer +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#include <libdirac_decoder/comp_decompress.h> +#include <libdirac_common/wavelet_utils.h> +#include <libdirac_common/band_codec.h> +#include <libdirac_common/band_vlc.h> +using namespace dirac; + +#include <vector> + +#include <ctime> + +using std::vector; + +//Constructor +CompDecompressor::CompDecompressor( DecoderParams& decp, const PictureParams& pp) +: + m_decparams(decp), + m_pparams(pp), + m_psort( pp.PicSort() ) +{} + + +void CompDecompressor::Decompress(ComponentByteIO* p_component_byteio, + CoeffArray& coeff_data, + SubbandList& bands) +{ + + // Set up the code blocks + SetupCodeBlocks( bands ); + + for ( int b=bands.Length() ; b>=1 ; --b ){ + // Multiple quantiser are used only if + // a. The global code_block_mode is QUANT_MULTIPLE + // and + // b. More than one code block is present in the subband. + bands(b).SetUsingMultiQuants( + m_decparams.SpatialPartition() && + m_decparams.GetCodeBlockMode() == QUANT_MULTIPLE && + (bands(b).GetCodeBlocks().LengthX() > 1 || + bands(b).GetCodeBlocks().LengthY() > 1) + ); + + // Read the header data first + SubbandByteIO subband_byteio(bands(b), *p_component_byteio); + subband_byteio.Input(); + + if ( !bands(b).Skipped() ){ + if (m_pparams.UsingAC()){ + // A pointer to the object(s) we'll be using for coding the bands + BandCodec* bdecoder; + + if ( b>=bands.Length()-3){ + if ( m_psort.IsIntra() && b==bands.Length() ) + bdecoder=new IntraDCBandCodec(&subband_byteio, + TOTAL_COEFF_CTXS ,bands); + else + bdecoder=new LFBandCodec(&subband_byteio , + TOTAL_COEFF_CTXS, bands , + b, m_psort.IsIntra()); + } + else + bdecoder=new BandCodec( &subband_byteio , TOTAL_COEFF_CTXS , + bands , b, m_psort.IsIntra()); + + bdecoder->Decompress(coeff_data , subband_byteio.GetBandDataLength()); + delete bdecoder; + } + else{ + // A pointer to the object(s) we'll be using for coding the bands + BandVLC* bdecoder; + + if ( m_psort.IsIntra() && b==bands.Length() ) + bdecoder=new IntraDCBandVLC(&subband_byteio, bands); + else + bdecoder=new BandVLC( &subband_byteio , 0, bands , + b, m_psort.IsIntra()); + + bdecoder->Decompress(coeff_data , subband_byteio.GetBandDataLength()); + delete bdecoder; + } + } + else{ + SetToVal( coeff_data , bands(b) , 0 ); + } + } +} + +void CompDecompressor::SetupCodeBlocks( SubbandList& bands ) +{ + int xregions; + int yregions; + + for (int band_num = 1; band_num<=bands.Length() ; ++band_num) + { + if (m_decparams.SpatialPartition()) + { + int level = m_decparams.TransformDepth() - (band_num-1)/3; + const CodeBlocks &cb = m_decparams.GetCodeBlocks(level); + xregions = cb.HorizontalCodeBlocks(); + yregions = cb.VerticalCodeBlocks(); + } + else + { + xregions = 1; + yregions = 1; + } + + bands( band_num ).SetNumBlocks( yregions ,xregions ); + + }// band_num +} + +void CompDecompressor::SetToVal( CoeffArray& coeff_data , + const Subband& node , + CoeffType val ) +{ + + for (int j=node.Yp() ; j<node.Yp()+node.Yl() ; ++j) + for (int i=node.Xp() ; i<node.Xp()+node.Xl() ; ++i) + coeff_data[j][i]=val; + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/comp_decompress.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/comp_decompress.h new file mode 100644 index 000000000..6468c4ba7 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/comp_decompress.h @@ -0,0 +1,129 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: comp_decompress.h,v 1.14 2008/06/19 10:33:24 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), Scott R Ladd +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + + +#ifndef _COMP_DECOMPRESS_H_ +#define _COMP_DECOMPRESS_H_ + +#include <libdirac_common/arrays.h> +#include <libdirac_common/wavelet_utils.h> +#include <libdirac_common/common.h> +#include <libdirac_byteio/component_byteio.h> + +namespace dirac +{ + //! Decompress a picture component + /*! + This class decompresses one of the three components (Y, U, or V) of a + picture according to a given set or parameters. CompDecompressor is used + by PictureCompressor.. + */ + class CompDecompressor + { + public: + //! Constructor + /*! + Create and initialize a component decompressor with the given + characteristics. + \param decp decoding parameters + \param fp picture parameters + */ + CompDecompressor( DecoderParams& decp, const PictureParams& fp); + + //! Decompress a picture component + /*! + Decompress a PicArray containing a picture component (Y, U, or V). + + \param p_component_byteio Bytestream of component data + \param coeff_data contains the component data to be decompressed + \param bands the subband metadata + */ + void Decompress(ComponentByteIO *p_component_byteio, + CoeffArray& coeff_data, + SubbandList& bands); + + private: + //! Copy constructor is private and body-less + /*! + Copy constructor is private and body-less. This class should not + be copied. + + */ + CompDecompressor(const CompDecompressor& cpy); + + //! Assignment = is private and body-less + /*! + Assignment = is private and body-less. This class should not be + assigned. + + */ + CompDecompressor& operator=(const CompDecompressor& rhs); + + //! Sets the data of a specific subband node to a given value + /*! + Sets the data of a specific subband node to a given value + + \param pic_data contains the component data + \param node subband node + \param val the value to set + */ + void SetToVal(CoeffArray& pic_data,const Subband& node,CoeffType val); + + //! Set up the code block structures for each subband + /*! + Set up the code block structures for each subband + \param bands the set of all the subbands + */ + void SetupCodeBlocks( SubbandList& bands ); + + //! Copy of the decompression parameters provided to the constructor + DecoderParams& m_decparams; + + //! Reference to the picture parameters provided to the constructor + const PictureParams& m_pparams; + + //! Reference to the picture sort + const PictureSort& m_psort; + + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/decoder_types.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/decoder_types.h new file mode 100644 index 000000000..0f04c19be --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/decoder_types.h @@ -0,0 +1,61 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: decoder_types.h,v 1.2 2008/02/13 03:36:11 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + + +#ifndef DECODER_TYPES_H +#define DECODER_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif +/* +* Different states the parser is in +*/ +typedef enum { + STATE_BUFFER, /* need more data input */ + STATE_SEQUENCE, /* start of sequence detected */ + STATE_PICTURE_AVAIL, /* decoded frame available */ + STATE_SEQUENCE_END, /* end of sequence detected */ + STATE_INVALID /* invalid state. Stop further processing */ + } DecoderState; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_cppparser.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_cppparser.cpp new file mode 100644 index 000000000..3940b35fe --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_cppparser.cpp @@ -0,0 +1,287 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_cppparser.cpp,v 1.13 2008/05/02 06:05:04 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author), +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <sstream> +#include <cstdio> +#include <cstring> +#include <libdirac_common/dirac_assertions.h> +#include <libdirac_decoder/dirac_cppparser.h> +#include <libdirac_decoder/seq_decompress.h> +#include <libdirac_common/picture.h> +#include <libdirac_byteio/parseunit_byteio.h> +#include <sstream> +using namespace dirac; + + +InputStreamBuffer::InputStreamBuffer() +{ + m_chunk_buffer = new char[m_buffer_size]; + + setg (m_chunk_buffer, //beginning of read area + m_chunk_buffer, //read position + m_chunk_buffer); //end position +} + +std::ios::pos_type InputStreamBuffer::Rewind() +{ + return Seek(0, std::ios::beg); +} + +std::ios::pos_type InputStreamBuffer::Tell() +{ + return gptr() - eback(); +} + +std::ios::pos_type InputStreamBuffer::Seek(std::ios::pos_type bytes, std::ios::seekdir dir) +{ + char *new_pos; + + switch (dir) + { + case std::ios::beg: + new_pos = eback() + bytes; + break; + case std::ios::end: + new_pos = egptr() + bytes; + break; + default: + new_pos = gptr() + bytes; + break; + } + if (new_pos > egptr() || new_pos < eback()) + return -1; + + setg(eback(), //start of read + new_pos, //current read position + egptr()); //end of stream positon + + return 0; +} + +void InputStreamBuffer::Copy(char *start, int bytes) +{ + //std::cerr << "eback=" << m_chunk_buffer - eback() + // << "gptr=" << gptr() -m_chunk_buffer + // << "egptr=" << egptr() - m_chunk_buffer << endl; + + int bytes_left = m_buffer_size - (egptr() - m_chunk_buffer); + if (bytes_left < bytes) + { + char *temp = new char [m_buffer_size + bytes]; + memcpy (temp, m_chunk_buffer, m_buffer_size); + setg (temp, temp+(gptr()-m_chunk_buffer), temp + (egptr() - m_chunk_buffer)); + delete [] m_chunk_buffer; + m_chunk_buffer = temp; + } + //std::cerr << "eback=" << m_chunk_buffer - eback() + // << "gptr=" << gptr() -m_chunk_buffer + // << "egptr=" << egptr() - m_chunk_buffer << endl; + + memcpy (egptr(), start, bytes); + setg(m_chunk_buffer, gptr(), egptr()+bytes); + + //std::cerr << "eback=" << m_chunk_buffer - eback() + // << "gptr=" << gptr() -m_chunk_buffer + // << "egptr=" << egptr() - m_chunk_buffer << endl; +} + +void InputStreamBuffer::PurgeProcessedData() +{ + //std::cerr << "eback=" << m_chunk_buffer - eback() + // << "gptr=" << gptr() -m_chunk_buffer + // << "egptr=" << egptr() - m_chunk_buffer << endl; + + if (gptr() != m_chunk_buffer) + { + memmove (m_chunk_buffer, gptr(), egptr() - gptr()); + setg(m_chunk_buffer, m_chunk_buffer, m_chunk_buffer+(egptr() - gptr())); + } + //std::cerr << "eback=" << m_chunk_buffer - eback() + // << "gptr=" << gptr() -m_chunk_buffer + // << "egptr=" << egptr() - m_chunk_buffer << endl; +} + +InputStreamBuffer::~InputStreamBuffer() +{ + delete [] m_chunk_buffer; +} + + +DiracParser::DiracParser(bool verbose) : + m_state(STATE_BUFFER), + m_next_state(STATE_SEQUENCE), + m_show_pnum(-1), + m_decomp(0), + m_verbose(verbose) +{ + + + +} + +DiracParser::~DiracParser() +{ + delete m_decomp; +} + +void DiracParser::SetBuffer (char *start, char *end) +{ + TEST (end > start); + m_dirac_byte_stream.AddBytes(start, end-start); +} + +DecoderState DiracParser::Parse() +{ + while(true) + { + ParseUnitByteIO *p_parse_unit=NULL; + ParseUnitType pu_type=PU_UNDEFINED; + + // look for end-of-sequence flag + if(m_next_state==STATE_SEQUENCE_END) + { + if (!m_decomp) + return STATE_BUFFER; + + // look to see if all pictures have been processed + if(m_decomp->Finished()) + { + // if so....delete + delete m_decomp; + m_decomp=NULL; + m_next_state = STATE_BUFFER; + return STATE_SEQUENCE_END; + } + else + // otherwise....get remaining pictures from buffer + pu_type = PU_CORE_PICTURE; + } + + // get next parse unit from stream + if(m_next_state!=STATE_SEQUENCE_END) + { + p_parse_unit=m_dirac_byte_stream.GetNextParseUnit(); + if(p_parse_unit==NULL) + return STATE_BUFFER; + pu_type=p_parse_unit->GetType(); + } + + switch(pu_type) + { + case PU_SEQ_HEADER: + + if(!m_decomp) + { + m_decomp = new SequenceDecompressor (*p_parse_unit, m_verbose); + m_next_state=STATE_BUFFER; + return STATE_SEQUENCE; + } + + m_decomp->NewAccessUnit(*p_parse_unit); + break; + + case PU_CORE_PICTURE: + { + if (!m_decomp) + continue; + + const Picture *my_picture = m_decomp->DecompressNextPicture(p_parse_unit); + if (my_picture) + { + int picturenum_decoded = my_picture->GetPparams().PictureNum(); + if (picturenum_decoded != m_show_pnum) + { + m_show_pnum = my_picture->GetPparams().PictureNum(); + if (m_verbose) + { + std::cout << std::endl; + std::cout << "Picture "; + std::cout<< m_show_pnum << " available"; + } + m_state = STATE_PICTURE_AVAIL; + return m_state; + } + } + break; + } + case PU_END_OF_SEQUENCE: + m_next_state = STATE_SEQUENCE_END; + break; + + case PU_AUXILIARY_DATA: + case PU_PADDING_DATA: + if (m_verbose) + std::cerr << "Ignoring Auxiliary/Padding data" << std::endl; + // Ignore auxiliary and padding data and continue parsing + break; + case PU_LOW_DELAY_PICTURE: + if (m_verbose) + std::cerr << "Low delay picture decoding not yet supported" << std::endl; + return STATE_INVALID; + + default: + return STATE_INVALID; + } + + } +} + +const SourceParams& DiracParser::GetSourceParams() const +{ + return m_decomp->GetSourceParams(); +} + +const DecoderParams& DiracParser::GetDecoderParams() const +{ + return m_decomp->GetDecoderParams(); +} + +const ParseParams& DiracParser::GetParseParams() const +{ + return m_decomp->GetParseParams(); +} + +const PictureParams* DiracParser::GetNextPictureParams() const +{ + return m_decomp->GetNextPictureParams(); +} + +const Picture* DiracParser::GetNextPicture() const +{ + return m_decomp->GetNextPicture(); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_cppparser.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_cppparser.h new file mode 100644 index 000000000..1634dd390 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_cppparser.h @@ -0,0 +1,190 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_cppparser.h,v 1.8 2008/05/02 06:05:04 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + + +#ifndef DIRAC_CPPPARSER_H +#define DIRAC_CPPPARSER_H + +#include <istream> +#include <streambuf> +#include <libdirac_decoder/decoder_types.h> //for DecoderState +#include <libdirac_common/common.h> +#include <libdirac_byteio/dirac_byte_stream.h> + +namespace dirac +{ + class SequenceDecompressor; + class Picture; + + //! Input Stream Buffer Class. + class InputStreamBuffer : public std::streambuf + { + public: + //! Constructor + InputStreamBuffer (); + + //! Destructor + ~InputStreamBuffer(); + + //! Rewind buffer to start of data + std::ios::pos_type Rewind(); + + //! Seek to position specified by bytes offset from pos + /*! + Seek takes + \param bytes offset in bytes + \param pos the position from which the offset is applied + */ + std::ios::pos_type Seek(std::ios::pos_type bytes, + std::ios::seekdir pos = std::ios::cur); + + //! Return the current read position in the buffer + std::ios::pos_type Tell(); + + //! Copy data into buffer + /*! + Copy take + \param start memory area start + \param bytes number of bytes to copy starting from start + */ + void Copy(char *start, int bytes); + + //! Delete all processed data from buffer + void PurgeProcessedData(); + + private: + + //! Private body-less copy constructor + InputStreamBuffer (const InputStreamBuffer& inbuf); + + //! Private body-less assignment operator + InputStreamBuffer& operator = (const InputStreamBuffer& inbuf); + + //! Buffer size + static const int m_buffer_size = 1232896; + + //! Buffere + char *m_chunk_buffer; + }; + + //! Dirac Stream Parser Class + /*! + This class is a wrapper around the SequenceDecompressor class. The + Sequence Decompressor class needs a full picture of data to be available + to decompress a picture successfully. So, the DiracParser class uses + the InputStreamBuffer class to store data until a chunk is available + to be processed and then invokes the SequenceDecompressor functions to + process data. A chunk of data can be a start of sequence, a picture or + end of sequence data. The istream used to instantiate the + SequenceDecompressor object is created using an InputStreamBuffer + object which is manipulated the DiracParser. This ensures that data is + always available for processing by the SequenceDecompressor object. + */ + class DiracParser + { + public: + //! Constructor + /*! + Constructor takes + \param verbose boolean flag. Set to true for verbose output + */ + DiracParser(bool verbose = false ); + + //! Destructor + ~DiracParser(); + + //! Adds bytes to encoder + /*! SetBuffer takes + \param start Start of input buffer + \param end End of input buffer + */ + void SetBuffer (char *start, char *end); + + //! Parse the data in internal buffer + /*! + Parses the data in the input buffer. This function returns one + of the following values + \n STATE_BUFFER : Not enough data in internal buffer to process + \n STATE_SEQUENCE : Start of sequence detected + \n STATE_PICTURE_AVAIL : Decoded picture available + \n STATE_SEQUENCE_END : End of sequence detected + \n STATE_INVALID : Invalid stream. Stop further processing + */ + DecoderState Parse(); + + //! Return the parse parameters of the current sequence + const ParseParams& GetParseParams() const; + + //! Return the source parameters of the current sequence + const SourceParams& GetSourceParams() const; + + //! Return the picture parameters of the next picture to be decoded + const PictureParams* GetNextPictureParams() const; + + //! Return the decoded picture + const Picture* GetNextPicture() const; + + //! Return the coding parameters of the current sequence + const DecoderParams& GetDecoderParams() const; + + private: + + private: + + //! private body-less copy constructor + DiracParser (const DiracParser &dp); + //! private body-less assignement constructor + DiracParser& operator = (const DiracParser &dp); + //! Current state of parser + DecoderState m_state; + //! Next state the parser will enter + DecoderState m_next_state; + //! picture number of last picture decoded in display order + int m_show_pnum; + //! Sequence decompressor object + SequenceDecompressor *m_decomp; + //! verbose flag + bool m_verbose; + //! Byte Stream Buffer + DiracByteStream m_dirac_byte_stream; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_parser.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_parser.cpp new file mode 100644 index 000000000..629746634 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_parser.cpp @@ -0,0 +1,409 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_parser.cpp,v 1.22 2008/06/19 10:33:24 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <cstring> +#include <libdirac_common/dirac_assertions.h> +#include <libdirac_decoder/dirac_cppparser.h> +#include <libdirac_decoder/dirac_parser.h> +#include <libdirac_common/dirac_exception.h> +#include <libdirac_common/picture.h> +#if defined (HAVE_MMX) +#include <mmintrin.h> + +#endif +using namespace dirac; + +#ifdef __cplusplus +extern "C" { +#endif + +extern DllExport dirac_decoder_t *dirac_decoder_init(int verbose) +{ + dirac_decoder_t* decoder = new dirac_decoder_t; + memset (decoder, 0, sizeof(dirac_decoder_t)); + + bool verbosity = verbose > 0 ? true : false; + DiracParser *parser = new DiracParser(verbosity); + decoder->parser = static_cast<void *>(parser); + + decoder->fbuf = new dirac_framebuf_t; + decoder->fbuf->id = NULL; + decoder->fbuf->buf[0] = decoder->fbuf->buf[1] = decoder->fbuf->buf[2] = NULL; + return decoder; +} + +extern DllExport void dirac_decoder_close(dirac_decoder_t *decoder) +{ + TEST (decoder != NULL); + TEST (decoder->parser != NULL); + DiracParser *parser = static_cast<DiracParser *>(decoder->parser); + + delete parser; + + delete decoder->fbuf; + + delete decoder; + + decoder = NULL; +} + +extern DllExport void dirac_buffer (dirac_decoder_t *decoder, unsigned char *start, unsigned char *end) +{ + TEST (decoder != NULL); + TEST (decoder->parser != NULL); + DiracParser *parser = static_cast<DiracParser *>(decoder->parser); + + parser->SetBuffer((char *)start, (char *)end); +} + +static void set_sequence_params (const DiracParser * const parser, dirac_decoder_t *decoder) +{ + TEST (parser != NULL); + TEST (decoder != NULL); + + dirac_sourceparams_t *src_params = &decoder->src_params; + dirac_parseparams_t *parse_params = &decoder->parse_params; + const SourceParams& srcparams = parser->GetSourceParams(); + const ParseParams& pparams = parser->GetParseParams(); + + parse_params->major_ver = pparams.MajorVersion(); + parse_params->minor_ver = pparams.MinorVersion(); + parse_params->profile = pparams.Profile(); + parse_params->level = pparams.Level(); + + src_params->width = srcparams.Xl(); + src_params->height = srcparams.Yl(); + + src_params->chroma = (dirac_chroma_t)srcparams.CFormat(); + src_params->chroma_width = srcparams.ChromaWidth(); + src_params->chroma_height = srcparams.ChromaHeight(); + + // set the source parmeters + src_params->source_sampling = srcparams.SourceSampling(); + src_params->topfieldfirst = srcparams.TopFieldFirst() ? 1 : 0; + + src_params->frame_rate.numerator = srcparams.FrameRate().m_num; + src_params->frame_rate.denominator = srcparams.FrameRate().m_denom; + + src_params->pix_asr.numerator = srcparams.PixelAspectRatio().m_num; + src_params->pix_asr.denominator = srcparams.PixelAspectRatio().m_denom; + + // clean area + src_params->clean_area.width = srcparams.CleanWidth(); + src_params->clean_area.height = srcparams.CleanHeight(); + src_params->clean_area.left_offset = srcparams.LeftOffset(); + src_params->clean_area.top_offset = srcparams.TopOffset(); + + // signal range + src_params->signal_range.luma_offset = srcparams.LumaOffset(); + src_params->signal_range.luma_excursion = srcparams.LumaExcursion(); + src_params->signal_range.chroma_offset = srcparams.ChromaOffset(); + src_params->signal_range.chroma_excursion = srcparams.ChromaExcursion(); + + // Colour specfication + src_params->colour_spec.col_primary = srcparams.ColourPrimariesIndex(); + src_params->colour_spec.trans_func = srcparams.TransferFunctionIndex(); + switch(srcparams.ColourMatrixIndex()) + { + case CM_SDTV: + src_params->colour_spec.col_matrix.kr = 0.299f; + src_params->colour_spec.col_matrix.kb = 0.114f; + break; + case CM_REVERSIBLE: + src_params->colour_spec.col_matrix.kr = 0.25f; + src_params->colour_spec.col_matrix.kb = 0.25f; + break; + case CM_HDTV_COMP_INTERNET: + default: + src_params->colour_spec.col_matrix.kr = 0.2126f; + src_params->colour_spec.col_matrix.kb = 0.0722f; + break; + } +} + +static void set_frame_component (const PicArray& pic_data, const CompSort cs, dirac_decoder_t *decoder) +{ + TEST (decoder->fbuf != NULL); + int xl, yl; + + unsigned char *buf; + + switch (cs) + { + case U_COMP: + xl = decoder->src_params.chroma_width; + yl = decoder->src_params.chroma_height; + buf = decoder->fbuf->buf[1]; + break; + case V_COMP: + xl = decoder->src_params.chroma_width; + yl = decoder->src_params.chroma_height; + buf = decoder->fbuf->buf[2]; + break; + + case Y_COMP: + default: + xl = decoder->src_params.width; + yl = decoder->src_params.height; + buf = decoder->fbuf->buf[0]; + break; + } + + TEST (buf != NULL); + +#if defined HAVE_MMX + int last_idx = (xl>>3)<<3; + __m64 tmp = _mm_set_pi16(128, 128, 128, 128); + for (int j=0 ; j<yl ;++j) + { + for (int i=0 ; i<last_idx ; i+=8 ) + { + __m64 pic1 = *(__m64 *)&pic_data[j][i]; + pic1 = _mm_add_pi16 (pic1, tmp); + __m64 pic2 = *(__m64 *)(&pic_data[j][i+4]); + pic2 = _mm_add_pi16 (pic2, tmp); + __m64 *tmp = (__m64 *)&buf[j*xl+i]; + *tmp = _mm_packs_pu16 (pic1, pic2); + }//i + }//j + _mm_empty(); + + // mop up remaining pixels + for (int j=0 ; j<yl ;++j) + { + for (int i=last_idx ; i<xl ; i++ ) + { + buf[j*xl+i]=(unsigned char) (pic_data[j][i]+128); + }//i + }//j + return; +#else + + for (int j=0 ; j<yl ;++j) + { + for (int i=0 ; i<xl ; ++i) + { + buf[j*xl+i]=(unsigned char) (pic_data[j][i]+128); + }//i + }//j + +#endif +} + +static void set_field_component (const PicArray& pic_data, const CompSort cs, dirac_decoder_t *decoder, unsigned int pic_num) +{ + TEST (decoder->fbuf != NULL); + int xl, yl; + + unsigned char *buf; + + switch (cs) + { + case U_COMP: + xl = decoder->src_params.chroma_width; + yl = decoder->src_params.chroma_height; + buf = decoder->fbuf->buf[1]; + break; + case V_COMP: + xl = decoder->src_params.chroma_width; + yl = decoder->src_params.chroma_height; + buf = decoder->fbuf->buf[2]; + break; + + case Y_COMP: + default: + xl = decoder->src_params.width; + yl = decoder->src_params.height; + buf = decoder->fbuf->buf[0]; + break; + } + + TEST (buf != NULL); + + // Seek offset before writing field to store + int start = 0; + // Seek offset between writing fields to store + int skip = 0; + + + bool top_field = decoder->src_params.topfieldfirst ? (!(pic_num%2)) : + (pic_num%2); + + if (top_field) // i.e. top field + { + start = 0; + skip = 2 * xl * sizeof(char); + } + else // else bottom field + { + start = xl; + skip = 2 * xl * sizeof(char); + } + + unsigned char *tempc = buf + start; + + int field_yl = yl>>1; + int field_xl = xl; + + for (int j=0 ; j<field_yl ;++j) + { + for (int i=0 ; i<field_xl ; ++i) + { + tempc[i] = (unsigned char) (pic_data[j][i]+128); + }//I + tempc += skip; + } +} + +static void set_frame_data (const DiracParser * const parser, dirac_decoder_t *decoder) +{ + TEST (parser != NULL); + TEST (decoder != NULL); + TEST (decoder->fbuf != NULL); + TEST (decoder->state == STATE_PICTURE_AVAIL); + + const Picture* my_picture = parser->GetNextPicture(); + + if (my_picture) + { + int pic_num = my_picture->GetPparams().PictureNum(); + + if (!parser->GetDecoderParams().FieldCoding()) + { + set_frame_component (my_picture->Data(Y_COMP), Y_COMP, decoder); + set_frame_component (my_picture->Data(U_COMP), U_COMP, decoder); + set_frame_component (my_picture->Data(V_COMP), V_COMP, decoder); + } + else + { + set_field_component (my_picture->Data(Y_COMP), Y_COMP, decoder, pic_num); + set_field_component (my_picture->Data(U_COMP), U_COMP, decoder, pic_num); + set_field_component (my_picture->Data(V_COMP), V_COMP, decoder, pic_num); + } + } + return; +} + +extern DllExport dirac_decoder_state_t dirac_parse (dirac_decoder_t *decoder) +{ + TEST (decoder != NULL); + TEST (decoder->parser != NULL); + DiracParser *parser = static_cast<DiracParser *>(decoder->parser); + + unsigned int pic_num; + + while(true) + { + try + { + decoder->state = parser->Parse(); + + switch (decoder->state) + { + case STATE_BUFFER: + return decoder->state; + break; + + case STATE_SEQUENCE: + set_sequence_params(parser, decoder); + decoder->frame_avail = 0; + return decoder->state; + break; + + case STATE_PICTURE_AVAIL: + { + const Picture *my_picture = parser->GetNextPicture(); + if (my_picture) + { + pic_num = parser->GetNextPicture()->GetPparams().PictureNum(); + decoder->frame_num = pic_num; + set_frame_data (parser, decoder); + + /* A full frame is only available if we're doing + * progressive coding or have decoded the second field. + * Will only return when a full frame is available + */ + if (!parser->GetDecoderParams().FieldCoding() || + pic_num%2) + { + /* Frame number currently available for display */ + decoder->frame_num = pic_num; + if (parser->GetDecoderParams().FieldCoding()) + decoder->frame_num = pic_num>>1; + decoder->frame_avail = 1; + return decoder->state; + } + } + break; + } + + case STATE_INVALID: + return decoder->state; + break; + + case STATE_SEQUENCE_END: + return decoder->state; + break; + + default: + break; + } + }//try + catch (const DiracException& e) + { + return STATE_INVALID; + } + } + + return decoder->state; +} + +extern DllExport void dirac_set_buf (dirac_decoder_t *decoder, unsigned char *buf[3], void *id) +{ + TEST (decoder != NULL); + TEST (decoder->fbuf != NULL); + + decoder->fbuf->buf[0] = buf[0]; + decoder->fbuf->buf[1] = buf[1]; + decoder->fbuf->buf[2] = buf[2]; + decoder->fbuf->id = id; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_parser.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_parser.h new file mode 100644 index 000000000..75bdcc7c2 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/dirac_parser.h @@ -0,0 +1,183 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_parser.h,v 1.8 2008/02/13 03:36:11 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef DIRAC_PARSER_H +#define DIRAC_PARSER_H + +#include <libdirac_common/dirac_types.h> +#include <libdirac_decoder/decoder_types.h> + +/*! \file +\brief C interface to Dirac decoder. + + A set of 'C' functions that define the public interface to the Dirac decoder. + Refer to the the reference decoder source code, decoder/decmain.cpp for + an example of how to use the "C" interface. The pseudocode below gives + a brief description of the "C" interface usage. + +\verbatim + #include <libdirac_decoder/dirac_parser.h>/n + Initialise the decoder + + dirac_decoder_t *decoder_handle = dirac_decoder_init(); + do + { + dirac_decoder_state_t state = dirac_parse (decoder_handle); + switch (state) + { + case STATE_BUFFER: + read more data. + Pass data to the decoder. + dirac_buffer (decoder_handle, data_start, data_end) + break; + + case STATE_SEQUENCE: + handle start of sequence. + The decoder returns the sequence parameters in the + seq_params member of the decoder handle. + Allocate space for the frame data buffers and pass + this to the decoder. + dirac_set_buf (decoder_handle, buf, NULL); + break; + + case STATE_SEQUENCE_END: + Deallocate frame data buffers + break; + + case STATE_PICTURE_AVAIL: + Handle picture data. + The decoder sets the fbuf member in the decoder + handle to the frame decoded. + break; + + case STATE_INVALID: + Unrecoverable error. Stop all processing + break; + } + } while (data available && decoder state != STATE_INVALID + + Free the decoder resources + dirac_decoder_close(decoder_handle) + \endverbatim +*/ +#ifdef __cplusplus +extern "C" { +#endif + +typedef DecoderState dirac_decoder_state_t; + +/*! Structure that holds the information returned by the parser */ +typedef struct +{ + /*! parser state */ + dirac_decoder_state_t state; + /*! parse parameters */ + dirac_parseparams_t parse_params; + /*! source parameters */ + dirac_sourceparams_t src_params; + /*! frame (NOT picture) number */ + unsigned int frame_num; + /*! void pointer to internal parser */ + void *parser; + /*! frame (NOT picture) buffer to hold luma and chroma data */ + dirac_framebuf_t *fbuf; + /*! boolean flag that indicates if a decoded frame (NOT picture) is available */ + int frame_avail; + /*! verbose output */ + int verbose; + +} dirac_decoder_t; + +/*! + Decoder Init + Initialise the decoder. + \param verbose boolean flag to set verbose output + \return decoder handle +*/ +extern DllExport dirac_decoder_t *dirac_decoder_init(int verbose); + +/*! + Release the decoder resources + \param decoder Decoder object +*/ +extern DllExport void dirac_decoder_close(dirac_decoder_t *decoder); + +/*! + Parses the data in the input buffer. This function returns the + following values. + \n STATE_BUFFER: Not enough data in internal buffer to process + \n STATE_SEQUENCE: Start of sequence detected. The seq_params member + in the decoder object is set to the details of the + next sequence to be processed. + \n STATE_PICTURE_START: Start of picture detected. The frame_params member + of the decoder object is set to the details of the + next frame to be processed. + \n STATE_PICTURE_AVAIL: Decoded picture available. The frame_aprams member + of the decoder object is set the the details of + the decoded frame available. The fbuf member of + the decoder object has the luma and chroma data of + the decompressed frame. + \n STATE_SEQUENCE_END: End of sequence detected. + \n STATE_INVALID: Invalid stream. Stop further processing. + + \param decoder Decoder object + \return Decoder state + +*/ +extern DllExport dirac_decoder_state_t dirac_parse (dirac_decoder_t *decoder); + +/*! + Copy data into internal buffer + \param decoder Decoder object + \param start Start of data + \param end End of data +*/ +extern DllExport void dirac_buffer (dirac_decoder_t *decoder, unsigned char *start, unsigned char *end); + +/*! + Set the output buffer into which the decoder copies the decoded data + \param decoder Decoder object + \param buf Array of char buffers to hold luma and chroma data + \param id User data +*/ +extern DllExport void dirac_set_buf (dirac_decoder_t *decoder, unsigned char *buf[3], void *id); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/picture_decompress.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/picture_decompress.cpp new file mode 100644 index 000000000..fe413551f --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/picture_decompress.cpp @@ -0,0 +1,372 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_decompress.cpp,v 1.9 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Scott R Ladd,
+* Anuradha Suraparaju,
+* Andrew Kennedy,
+* Tim Borer
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+
+//Decompression of pictures
+/////////////////////////
+
+#include <libdirac_common/dirac_assertions.h>
+#include <libdirac_decoder/picture_decompress.h>
+#include <libdirac_decoder/comp_decompress.h>
+#include <libdirac_common/mot_comp.h>
+#include <libdirac_common/mv_codec.h>
+#include <libdirac_byteio/picture_byteio.h>
+#include <libdirac_common/dirac_exception.h>
+using namespace dirac;
+
+#include <iostream>
+#include <memory>
+
+using std::vector;
+using std::auto_ptr;
+
+PictureDecompressor::PictureDecompressor(DecoderParams& decp, ChromaFormat cf)
+:
+m_decparams(decp),
+m_cformat(cf)
+{
+}
+
+PictureDecompressor::~PictureDecompressor()
+{
+}
+
+
+bool PictureDecompressor::Decompress(ParseUnitByteIO& parseunit_byteio,
+ PictureBuffer& my_buffer)
+{
+ // get current byte position
+ //int start_pos = parseunit_byteio.GetReadBytePosition();
+ try {
+
+ // read picture data
+ PictureByteIO picture_byteio(m_pparams,
+ parseunit_byteio);
+
+ picture_byteio.Input();
+
+ PictureSort fs;
+
+ if (m_pparams.GetPictureType() == INTRA_PICTURE)
+ fs.SetIntra();
+ else
+ fs.SetInter();
+
+ if (m_pparams.GetReferenceType() == REFERENCE_PICTURE)
+ fs.SetRef();
+ else
+ fs.SetNonRef();
+
+ m_pparams.SetPicSort(fs);
+
+ if (m_pparams.GetReferenceType() == REFERENCE_PICTURE)
+ // Now clean the reference pictures from the buffer
+ CleanReferencePictures( my_buffer );
+
+ // Check if the picture can be decoded
+ if (m_pparams.PicSort().IsInter()){
+ const std::vector<int>& refs = m_pparams.Refs();
+
+ for (unsigned int i = 0; i < refs.size(); ++i)
+ if ( !my_buffer.IsPictureAvail(refs[i]) )
+ return false;
+ }
+
+ // decode the rest of the picture
+
+ if ( m_decparams.Verbose() ){
+ std::cout<<std::endl<<"Decoding picture "<<m_pparams.PictureNum()<<" in display order";
+ if ( m_pparams.PicSort().IsInter() ){
+ std::cout<<std::endl<<"References: "<<m_pparams.Refs()[0];
+ if ( m_pparams.Refs().size()>1 )
+ std::cout<<" and "<<m_pparams.Refs()[1];
+ }
+ }
+
+ PictureSort psort = m_pparams.PicSort();
+ auto_ptr<MvData> mv_data;
+
+ if ( psort.IsInter() )
+ //do all the MV stuff
+ DecompressMVData( mv_data, picture_byteio );
+
+ // Read the transform header
+ TransformByteIO transform_byteio(picture_byteio, m_pparams, m_decparams);
+ transform_byteio.Input();
+
+ if (m_pparams.PicSort().IsIntra() && m_decparams.ZeroTransform()){
+ DIRAC_THROW_EXCEPTION(
+ ERR_UNSUPPORTED_STREAM_DATA,
+ "Intra pictures cannot have Zero-Residual",
+ SEVERITY_PICTURE_ERROR);
+ }
+
+ // Add a picture to the buffer to decode into
+ PushPicture(my_buffer);
+
+ //Reference to the picture being decoded
+ Picture& my_picture = my_buffer.GetPicture(m_pparams.PictureNum());
+
+ if (!m_decparams.ZeroTransform()){
+ //decode components
+ Picture& pic = my_buffer.GetPicture( m_pparams.PictureNum() );
+
+ CompDecompressor my_compdecoder( m_decparams , pic.GetPparams() );
+
+ PicArray* comp_data[3];
+ CoeffArray* coeff_data[3];
+
+ const int depth( m_decparams.TransformDepth() );
+ WaveletTransform wtransform( depth, m_decparams.TransformFilter() );
+
+ pic.InitWltData( depth );
+
+ for (int c=0; c<3; ++c){
+ ComponentByteIO component_byteio((CompSort) c, transform_byteio);
+ comp_data[c] = &pic.Data((CompSort) c);
+ coeff_data[c] = &pic.WltData((CompSort) c);
+
+ SubbandList& bands = coeff_data[c]->BandList();
+
+ bands.Init(depth , coeff_data[c]->LengthX() , coeff_data[c]->LengthY());
+ my_compdecoder.Decompress(&component_byteio, *(coeff_data[c]), bands );
+
+ wtransform.Transform(BACKWARD,*(comp_data[c]), *(coeff_data[c]));
+ }
+ }
+ else
+ my_picture.Fill(0);
+
+ if ( psort.IsInter() ){
+ Picture* my_pic = &my_buffer.GetPicture( m_pparams.PictureNum() );
+
+ const std::vector<int>& refs = m_pparams.Refs();
+ Picture* ref_pics[2];
+
+ ref_pics[0] = &my_buffer.GetPicture( refs[0] );
+ if (refs.size()>1)
+ ref_pics[1] = &my_buffer.GetPicture( refs[1] );
+ else
+ ref_pics[1] = ref_pics[0];
+
+ //motion compensate to add the data back in if we don't have an I picture
+ MotionCompensator::CompensatePicture( m_decparams.GetPicPredParams() , ADD , *(mv_data.get()) ,
+ my_pic, ref_pics );
+ }
+
+ my_picture.Clip();
+
+ if (m_decparams.Verbose())
+ std::cout<<std::endl;
+
+
+ //exit success
+ return true;
+
+ }// try
+ catch (const DiracException& e) {
+ // skip picture
+ throw e;
+ }
+
+ //exit failure
+ return false;
+}
+
+void PictureDecompressor::CleanReferencePictures( PictureBuffer& my_buffer )
+{
+ if ( m_decparams.Verbose() )
+ std::cout<<std::endl<<"Cleaning reference buffer: ";
+ // Do picture buffer cleaning
+ int retd_pnum = m_pparams.RetiredPictureNum();
+
+ if ( retd_pnum >= 0 && my_buffer.IsPictureAvail(retd_pnum) && my_buffer.GetPicture(retd_pnum).GetPparams().PicSort().IsRef() )
+ {
+ my_buffer.Remove(retd_pnum);
+ if ( m_decparams.Verbose() )
+ std::cout<<retd_pnum<<" ";
+ }
+}
+
+void PictureDecompressor::SetMVBlocks()
+{
+ PicturePredParams& predparams = m_decparams.GetPicPredParams();
+ OLBParams olb_params = predparams.LumaBParams(2);
+ predparams.SetBlockSizes(olb_params, m_cformat);
+
+ // Calculate the number of macro blocks
+ int xnum_sb = (m_decparams.Xl()+predparams.LumaBParams(0).Xbsep()-1)/
+ predparams.LumaBParams(0).Xbsep();
+ int ynum_sb = (m_decparams.Yl()+predparams.LumaBParams(0).Ybsep()-1)/
+ predparams.LumaBParams(0).Ybsep();
+
+ predparams.SetXNumSB(xnum_sb);
+ predparams.SetYNumSB(ynum_sb);
+
+ // Set the number of blocks
+ predparams.SetXNumBlocks(4*xnum_sb);
+ predparams.SetYNumBlocks(4*ynum_sb);
+
+ // Note that we do not have an integral number of superblocks in a picture
+ // So it is possible that part of a superblock and some blocks can fall
+ // of the edge of the true picture. We need to take this into
+ // consideration while doing Motion Compensation
+}
+
+void PictureDecompressor::PushPicture(PictureBuffer &my_buffer)
+{
+ m_pparams.SetCFormat(m_cformat);
+
+ m_pparams.SetXl(m_decparams.Xl());
+ m_pparams.SetYl(m_decparams.Yl());
+
+ m_pparams.SetLumaDepth(m_decparams.LumaDepth());
+ m_pparams.SetChromaDepth(m_decparams.ChromaDepth());
+
+ my_buffer.PushPicture(m_pparams);
+}
+
+void PictureDecompressor::DecompressMVData( std::auto_ptr<MvData>& mv_data,
+ PictureByteIO& picture_byteio )
+{
+ PicturePredParams& predparams = m_decparams.GetPicPredParams();
+ MvDataByteIO mvdata_byteio (picture_byteio, m_pparams, predparams);
+
+ // Read in the picture prediction parameters
+ mvdata_byteio.Input();
+
+ SetMVBlocks();
+ mv_data.reset(new MvData( predparams, m_pparams.NumRefs() ));
+
+ // decode mv data
+ if (m_decparams.Verbose())
+ std::cout<<std::endl<<"Decoding motion data ...";
+
+ int num_bits;
+
+ // Read in the split mode data header
+ mvdata_byteio.SplitModeData()->Input();
+ // Read the mode data
+ num_bits = mvdata_byteio.SplitModeData()->DataBlockSize();
+ SplitModeCodec smode_decoder( mvdata_byteio.SplitModeData()->DataBlock(), TOTAL_MV_CTXS);
+ smode_decoder.Decompress( *(mv_data.get()) , num_bits);
+
+ // Read in the prediction mode data header
+ mvdata_byteio.PredModeData()->Input();
+ // Read the mode data
+ num_bits = mvdata_byteio.PredModeData()->DataBlockSize();
+ PredModeCodec pmode_decoder( mvdata_byteio.PredModeData()->DataBlock(), TOTAL_MV_CTXS, m_pparams.NumRefs());
+ pmode_decoder.Decompress( *(mv_data.get()) , num_bits);
+
+ // Read in the MV1 horizontal data header
+ mvdata_byteio.MV1HorizData()->Input();
+ // Read the MV1 horizontal data
+ num_bits = mvdata_byteio.MV1HorizData()->DataBlockSize();
+ VectorElementCodec vdecoder1h( mvdata_byteio.MV1HorizData()->DataBlock(), 1,
+ HORIZONTAL, TOTAL_MV_CTXS);
+ vdecoder1h.Decompress( *(mv_data.get()) , num_bits);
+
+ // Read in the MV1 vertical data header
+ mvdata_byteio.MV1VertData()->Input();
+ // Read the MV1 data
+ num_bits = mvdata_byteio.MV1VertData()->DataBlockSize();
+ VectorElementCodec vdecoder1v( mvdata_byteio.MV1VertData()->DataBlock(), 1,
+ VERTICAL, TOTAL_MV_CTXS);
+ vdecoder1v.Decompress( *(mv_data.get()) , num_bits);
+
+ if ( m_pparams.NumRefs()>1 )
+ {
+ // Read in the MV2 horizontal data header
+ mvdata_byteio.MV2HorizData()->Input();
+ // Read the MV2 horizontal data
+ num_bits = mvdata_byteio.MV2HorizData()->DataBlockSize();
+ VectorElementCodec vdecoder2h( mvdata_byteio.MV2HorizData()->DataBlock(), 2,
+ HORIZONTAL, TOTAL_MV_CTXS);
+ vdecoder2h.Decompress( *(mv_data.get()) , num_bits);
+
+ // Read in the MV2 vertical data header
+ mvdata_byteio.MV2VertData()->Input();
+ // Read the MV2 vertical data
+ num_bits = mvdata_byteio.MV2VertData()->DataBlockSize();
+ VectorElementCodec vdecoder2v( mvdata_byteio.MV2VertData()->DataBlock(), 2,
+ VERTICAL, TOTAL_MV_CTXS);
+ vdecoder2v.Decompress( *(mv_data.get()) , num_bits);
+ }
+
+ // Read in the Y DC data header
+ mvdata_byteio.YDCData()->Input();
+ // Read the Y DC data
+ num_bits = mvdata_byteio.YDCData()->DataBlockSize();
+ DCCodec ydc_decoder( mvdata_byteio.YDCData()->DataBlock(), Y_COMP, TOTAL_MV_CTXS);
+ ydc_decoder.Decompress( *(mv_data.get()) , num_bits);
+
+ // Read in the U DC data header
+ mvdata_byteio.UDCData()->Input();
+ // Read the U DC data
+ num_bits = mvdata_byteio.UDCData()->DataBlockSize();
+ DCCodec udc_decoder( mvdata_byteio.YDCData()->DataBlock(), U_COMP, TOTAL_MV_CTXS);
+ udc_decoder.Decompress( *(mv_data.get()) , num_bits);
+
+ // Read in the Y DC data header
+ mvdata_byteio.YDCData()->Input();
+ // Read the Y DC data
+ num_bits = mvdata_byteio.YDCData()->DataBlockSize();
+ DCCodec vdc_decoder( mvdata_byteio.VDCData()->DataBlock(), V_COMP, TOTAL_MV_CTXS);
+ vdc_decoder.Decompress( *(mv_data.get()) , num_bits);
+}
+
+void PictureDecompressor::InitCoeffData( CoeffArray& coeff_data, const int xl, const int yl ){
+
+ // First set the dimensions up //
+ int xpad_len = xl;
+ int ypad_len = yl;
+
+ // The pic dimensions must be a multiple of 2^(transform depth)
+ int tx_mul = (1<<m_decparams.TransformDepth());
+
+ if ( xpad_len%tx_mul != 0 )
+ xpad_len = ( (xpad_len/tx_mul)+1 ) *tx_mul;
+ if ( ypad_len%tx_mul != 0 )
+ ypad_len = ( (ypad_len/tx_mul)+1 ) * tx_mul;
+
+ coeff_data.Resize( ypad_len, xpad_len );
+}
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/picture_decompress.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/picture_decompress.h new file mode 100644 index 000000000..31efbe5db --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/picture_decompress.h @@ -0,0 +1,156 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_decompress.h,v 1.2 2008/04/29 08:51:52 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Scott R Ladd,
+* Anuradha Suraparaju
+* Andrew Kennedy
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+
+
+#ifndef _PICTURE_DECOMPRESS_H_
+#define _PICTURE_DECOMPRESS_H_
+
+#include <libdirac_common/picture_buffer.h>
+#include <libdirac_common/common.h>
+#include <libdirac_byteio/picture_byteio.h>
+#include <libdirac_byteio/transform_byteio.h>
+
+namespace dirac
+{
+ class MvData;
+
+ //! Compress a single image picture
+ /*!
+ This class decompresses a single picture at a time, using parameters
+ supplied at its construction. PictureDecompressor is used by
+ SequenceDecompressor.
+ */
+ class PictureDecompressor{
+ public:
+ //! Constructor
+ /*!
+ Creates a PictureDecompressor with specific set of parameters the
+ control the decompression process. It decodes motion data before
+ decoding each component of the picture.
+
+ \param decp decoder parameters
+ \param cf the chroma format of the picture being decompressed
+ */
+ PictureDecompressor(DecoderParams& decp, ChromaFormat cf);
+
+ //! Destructor
+ /*!
+ Releases resources.
+ */
+ ~PictureDecompressor();
+
+ //! Decompress the next picture into the buffer
+ /*!
+ Decompresses the next picture from the stream and place at the end
+ of a picture buffer.
+ Returns true if able to decode successfully, false otherwise
+
+ \param parseunit_byteio Picture info in Dirac-stream format
+ \param my_buffer picture buffer into which the picture is placed
+ */
+ bool Decompress(ParseUnitByteIO& parseunit_byteio,
+ PictureBuffer& my_buffer);
+
+ //! Returns the picture parameters of the current picture being decoded
+ const PictureParams& GetPicParams() const{ return m_pparams; }
+
+ private:
+ //! Copy constructor is private and body-less
+ /*!
+ Copy constructor is private and body-less. This class should not be copied.
+
+ */
+ PictureDecompressor(const PictureDecompressor& cpy);
+
+ //! Assignment = is private and body-less
+ /*!
+ Assignment = is private and body-less. This class should not be
+ assigned.
+ */
+ PictureDecompressor& operator=(const PictureDecompressor& rhs);
+
+ //! Initialise the padded coefficient data for the IDWT and subband decoding
+ void InitCoeffData( CoeffArray& coeff_data, const int xl, const int yl );
+
+ //! Removes all the reference pictures in the retired list
+ void CleanReferencePictures( PictureBuffer& my_buffer );
+
+ //! Decodes component data
+ void CompDecompress(TransformByteIO *p_transform_byteio,
+ PictureBuffer& my_buffer,int pnum, CompSort cs);
+
+ //! Decodes the motion data
+ void DecompressMVData( std::auto_ptr<MvData>& mv_data, PictureByteIO& picture_byteio );
+
+
+ //! Set the number of superblocks and blocks
+ void SetMVBlocks();
+
+ //! Add a picture to the picture buffer
+ void PushPicture(PictureBuffer &my_buffer);
+
+ //Member variables
+
+ //! Parameters for the decompression, as provided in constructor
+ DecoderParams& m_decparams;
+
+ //! Chroma format of the picture being decompressed
+ ChromaFormat m_cformat;
+
+ //! An indicator which is true if the picture has been skipped, false otherwise
+ bool m_skipped;
+
+ //! An indicator that is true if we use global motion vectors, false otherwise
+ bool m_use_global;
+
+ //! An indicator that is true if we use block motion vectors, false otherwise
+ bool m_use_block_mv;
+
+ //! Prediction mode to use if we only have global motion vectors
+ PredMode m_global_pred_mode;
+
+ //! Current Picture Parameters
+ PictureParams m_pparams;
+ };
+
+} // namespace dirac
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/seq_decompress.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/seq_decompress.cpp new file mode 100644 index 000000000..09421e934 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/seq_decompress.cpp @@ -0,0 +1,170 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: seq_decompress.cpp,v 1.25 2008/08/14 00:51:08 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Anuradha Suraparaju, +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +/////////////////////////////////////////// +//---------------------------------------// +//Class to manage decompressing sequences// +//---------------------------------------// +/////////////////////////////////////////// + +#include <libdirac_common/video_format_defaults.h> +#include <libdirac_common/dirac_assertions.h> +#include <libdirac_decoder/seq_decompress.h> +#include <libdirac_common/common.h> +#include <libdirac_common/picture_buffer.h> +#include <libdirac_decoder/picture_decompress.h> +#include <libdirac_byteio/accessunit_byteio.h> +using namespace dirac; + +SequenceDecompressor::SequenceDecompressor(ParseUnitByteIO& parseunit,bool verbosity) +: +m_all_done(false), +m_current_code_pnum(0), +m_delay(1), +m_show_pnum(-1), +m_highest_pnum(0) +{ + // read unit + NewAccessUnit(parseunit); + + if ( m_decparams.FieldCoding() ) + m_delay = 2; + + m_decparams.SetVerbose( verbosity ); + + m_pbuffer= new PictureBuffer( ); + + m_pdecoder = new PictureDecompressor (m_decparams , m_srcparams.CFormat()); + +} + +SequenceDecompressor::~SequenceDecompressor() +{ + delete m_pbuffer; + delete m_pdecoder; +} + +const PictureParams* SequenceDecompressor::GetNextPictureParams() const +{ + return &m_pdecoder->GetPicParams(); +} + +void SequenceDecompressor::NewAccessUnit(ParseUnitByteIO& parseunit_byteio) +{ + // read sequence header + SequenceHeaderByteIO seqheader_byteio(parseunit_byteio,m_parse_params, m_srcparams, m_decparams); + seqheader_byteio.Input(); + +} + +const Picture* SequenceDecompressor::DecompressNextPicture(ParseUnitByteIO* p_parseunit_byteio) +{ + //this function decodes the next picture in coding order and returns the next picture in display order + //In general these will differ, and because of re-ordering there is a m_delay which needs to be imposed. + //This creates problems at the start and at the end of the sequence which must be dealt with. + //At the start we just keep outputting picture 0. At the end you will need to loop for longer to get all + //the pictures out. It's up to the calling function to do something with the decoded pictures as they + //come out - write them to screen or to file, as required. + + TEST (m_pdecoder != NULL); + + // Remove the last displayed picture from the buffer if it wasn't a reference + if ( m_show_pnum>0 ) + { + if ( m_decparams.Verbose() ) + std::cout<<std::endl<<"Cleaning display buffer: "; + if ( m_pbuffer->IsPictureAvail(m_show_pnum-1) && + m_pbuffer->GetPicture(m_show_pnum-1).GetPparams().PicSort().IsNonRef() ) + { + m_pbuffer->Remove(m_show_pnum-1); + if ( m_decparams.Verbose() ) + std::cout<<(m_show_pnum-1)<<" "; + } + } + + bool new_picture_to_display=false; + + if (p_parseunit_byteio) + { + if (m_decparams.Verbose()) + std::cout<<std::endl<<"Calling picture decompression function"; + new_picture_to_display = m_pdecoder->Decompress(*p_parseunit_byteio, + *m_pbuffer); + } + + if (m_show_pnum < 0 && new_picture_to_display == false) + return NULL; + + if (m_pbuffer->IsPictureAvail(m_show_pnum+1 )) + ++m_show_pnum; + else if (new_picture_to_display && m_pdecoder->GetPicParams().PicSort().IsNonRef()) + { + // if a decoded future non reference frame is available it implies + // that some frames have been skipped because of possible truncation + // errors + m_show_pnum = m_pdecoder->GetPicParams().PictureNum(); + } + + m_highest_pnum = std::max(m_pdecoder->GetPicParams().PictureNum(), m_highest_pnum); + + if (m_pbuffer->IsPictureAvail(m_show_pnum)) + return &m_pbuffer->GetPicture(m_show_pnum); + else + return NULL; +} + +const Picture* SequenceDecompressor::GetNextPicture() +{ + if (m_pbuffer->IsPictureAvail(m_show_pnum)) + return &m_pbuffer->GetPicture(m_show_pnum); + else + return NULL; +} + +bool SequenceDecompressor::Finished() +{ + if (m_show_pnum>=m_highest_pnum) + return true; + + if (!m_pbuffer->IsPictureAvail(m_show_pnum+1 )) + ++m_show_pnum; + + return false; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/seq_decompress.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/seq_decompress.h new file mode 100644 index 000000000..008ffc11d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_decoder/seq_decompress.h @@ -0,0 +1,190 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: seq_decompress.h,v 1.13 2008/05/02 06:05:04 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Anuradha Suraparaju +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#ifndef _SEQ_DECOMPRESS_H_ +#define _SEQ_DECOMPRESS_H_ + +/////////////////////////////////////////// +//---------------------------------------// +//Class to manage decompressing sequences// +//---------------------------------------// +/////////////////////////////////////////// + +#include "libdirac_common/common.h" +#include "libdirac_byteio/parseunit_byteio.h" +#include <iostream> + +namespace dirac +{ + class PictureBuffer; + class Picture; + class PictureDecompressor; + + //! Decompresses a sequence of pictures from a stream. + /*! + This class decompresses a sequence of frames, picture by picture. + */ + class SequenceDecompressor{ + public: + + //! Constructor + /*! + Initializes the decompressor with an input stream and level of + output detail. + \param parseunit First access-unit of new sequence + \param verbosity when true, increases the amount of information displayed during decompression + */ + SequenceDecompressor(ParseUnitByteIO& parseunit, bool verbosity); + + //! Destructor + /*! + Closes files and releases resources. + */ + ~SequenceDecompressor(); + + //! Marks beginning of a new AccessUnit + /*! + \param parseunit_byteio AccessUnit info in Dirac-stream format + */ + void NewAccessUnit(ParseUnitByteIO& parseunit_byteio); + + + //! Decompress the next picture in sequence + /*! + This function decodes the next picture in coding order and returns + the next picture in display order. In general these will differ, and + because of re-ordering there is a delay which needs to be imposed. + This creates problems at the start and at the end of the sequence + which must be dealt with. At the start we just keep outputting + picture 0. At the end you will need to loop for longer to get all + the pictures out. It's up to the calling function to do something + with the decoded pictures as they come out -- write them to screen + or to file, as required. + + \param p_parseunit_byteio Picture information in Dirac-stream format + \return reference to the next locally decoded picture available for display + */ + const Picture* DecompressNextPicture(ParseUnitByteIO* p_parseunit_byteio); + + //! Get the next picture available for display + const Picture* GetNextPicture(); + + //! Get the next picture parameters + const PictureParams* GetNextPictureParams() const; + //! Determine if decompression is complete. + /*! + Indicates whether or not the last picture in the sequence has been + decompressed. + \return true if last picture has been compressed; false if not + */ + bool Finished(); + //! Interrogates for parse parameters. + /*! + Returns the parse parameters used for this decompression run. + + \return parse parameters. + */ + ParseParams & GetParseParams() { return m_parse_params; } + + + //! Interrogates for source parameters. + /*! + Returns the source parameters used for this decompression run. + + \return source parameters. + */ + SourceParams & GetSourceParams() { return m_srcparams; } + + + //! Interrogates for coding parameters. + /*! + Returns the decoder parameters used for this decompression run. + + \return decoder parameters. + */ + DecoderParams & GetDecoderParams() { return m_decparams; } + private: + //! Copy constructor is private and body-less + /*! + Copy constructor is private and body-less. This class should not + be copied. + + */ + SequenceDecompressor(const SequenceDecompressor& cpy); + + //! Assignment = is private and body-less + /*! + Assignment = is private and body-less. This class should not be + assigned. + + */ + SequenceDecompressor& operator=(const SequenceDecompressor& rhs); + + + //Member variables + + //! Completion flag, returned via the Finished method + bool m_all_done; + //! Parameters for the decompression, as provided in constructor + DecoderParams m_decparams; + //! The parse parameters obtained from the stream header + ParseParams m_parse_params; + //! The source parameters obtained from the stream header + SourceParams m_srcparams; + //! A picture buffer used for local storage of pictures whilst pending re-ordering or being used for reference. + PictureBuffer* m_pbuffer; + //! Number of the picture in coded order which is to be decoded + int m_current_code_pnum; + //! A delay so that we don't display what we haven't decoded + int m_delay; + //! Index, in display order, of the last picture read + int m_last_picture_read; + //! Index, in display order of the picture to be displayed next - computed from delay and current_code_pnum + int m_show_pnum; + //! Picture decompressor object + PictureDecompressor *m_pdecoder; + //! Highest picture-num processed - for tracking end-of-sequence + int m_highest_pnum; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/comp_compress.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/comp_compress.cpp new file mode 100644 index 000000000..07762d7ec --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/comp_compress.cpp @@ -0,0 +1,156 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: comp_compress.cpp,v 1.49 2009/01/21 05:18:09 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Anuradha Suraparaju +* Andrew Kennedy +* Tim Borer +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +//Compression of an individual component, +//after motion compensation if appropriate +////////////////////////////////////////// + +#include <libdirac_encoder/comp_compress.h> +#include <libdirac_common/band_codec.h> +#include <libdirac_common/band_vlc.h> +#include <libdirac_common/motion.h> + +using namespace dirac; + +#include <ctime> +#include <vector> +#include <iostream> + +CompCompressor::CompCompressor( EncoderParams& encp,const PictureParams& pp) +: m_encparams(encp), + m_pparams(pp), + m_psort( m_pparams.PicSort() ), + m_cformat( m_pparams.CFormat() ) +{} + +ComponentByteIO* CompCompressor::Compress( CoeffArray& coeff_data , + SubbandList& bands, + CompSort csort, + const OneDArray<unsigned int>& estimated_bits) +{ + // Need to transform, select quantisers for each band, + // and then compress each component in turn + + unsigned int num_band_bytes( 0 ); + + // create byte output + ComponentByteIO *p_component_byteio = new ComponentByteIO(csort); + + // Loop over all the bands (from DC to HF) quantising and coding them + for (int b=bands.Length() ; b>=1 ; --b ) + { + + // create subband byte io + SubbandByteIO subband_byteio(bands(b)); + + if ( !bands(b).Skipped() ) + { // If not skipped ... + if (m_pparams.UsingAC()) + { + // A pointer to an object for coding the subband data + BandCodec* bcoder; + + + // Pick the right codec according to the picture type and subband + if (b >= bands.Length()-3) + { + if ( m_psort.IsIntra() && b == bands.Length() ) + bcoder=new IntraDCBandCodec(&subband_byteio, + TOTAL_COEFF_CTXS , bands ); + else + bcoder=new LFBandCodec(&subband_byteio ,TOTAL_COEFF_CTXS, + bands , b, m_psort.IsIntra()); + } + else + bcoder=new BandCodec(&subband_byteio , TOTAL_COEFF_CTXS , + bands , b, m_psort.IsIntra() ); + + num_band_bytes = bcoder->Compress(coeff_data); + + + delete bcoder; + } + else + { + // A pointer to an object for coding the subband data + BandVLC* bcoder; + + if ( m_psort.IsIntra() && b == bands.Length() ) + bcoder=new IntraDCBandVLC(&subband_byteio, bands ); + else + bcoder=new BandVLC(&subband_byteio , 0, bands , b, + m_psort.IsIntra() ); + + num_band_bytes = bcoder->Compress(coeff_data); + + delete bcoder; + } + // Update the entropy correction factors + m_encparams.EntropyFactors().Update(b , m_pparams , csort , + estimated_bits[b] , 8*num_band_bytes); + } + else + { // ... skipped + SetToVal( coeff_data , bands(b) , 0 ); + } + + // output sub-band data + p_component_byteio->AddSubband(&subband_byteio); + + + }//b + + return p_component_byteio; +} + +void CompCompressor::SetToVal(CoeffArray& coeff_data,const Subband& node,ValueType val) +{ + + for (int j=node.Yp() ; j<node.Yp() + node.Yl() ; ++j) + { + for (int i=node.Xp(); i<node.Xp() + node.Xl() ; ++i) + { + coeff_data[j][i] = val; + }// i + }// j + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/comp_compress.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/comp_compress.h new file mode 100644 index 000000000..e21150904 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/comp_compress.h @@ -0,0 +1,114 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: comp_compress.h,v 1.19 2008/05/07 05:47:00 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), Scott R Ladd +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#ifndef _COMP_COMPRESS_H_ +#define _COMP_COMPRESS_H_ + +#include <libdirac_common/arrays.h> +#include <libdirac_common/wavelet_utils.h> +#include <libdirac_common/common.h> +#include <libdirac_byteio/component_byteio.h> + +namespace dirac +{ + class MEData; + + //! Compress a picture component + /*! + This class compresses one of the three components (Y, U, or V) of a + picture according to a given set or parameters. CompCompressor is used + by PictureCompressor. + */ + class CompCompressor + { + public: + //! Constructor + /*! + Create and initialize a component compressor with the given + characteristics. + \param encp encoding parameters + \param fp picture parameters + */ + CompCompressor( EncoderParams & encp, const PictureParams& fp); + + //! Compress a picture component + /*! + Compress a PicArray containing a picture component (Y, U, or V). + \param coeff_data the component data to be compressed + \param bands Subbands list + \param csort Chroma format + \param estimated_bits the list of estimated number of bits in each subband + \return Picture-component in Dirac-bytestream format + */ + ComponentByteIO* Compress( CoeffArray& coeff_data , + SubbandList& bands, + CompSort csort, + const OneDArray<unsigned int>& estimated_bits); + + private: + //! Copy constructor is private and body-less. This class should not be copied. + CompCompressor(const CompCompressor& cpy); + + //! Assignment = is private and body-less. This class should not be assigned. + CompCompressor& operator=(const CompCompressor& rhs); + + //! Set a subband to a constant value + void SetToVal(CoeffArray& coeff_data,const Subband& node,ValueType val); + + + private: + + // member variables + EncoderParams& m_encparams; + + const PictureParams& m_pparams; + + const PictureSort& m_psort; + + const ChromaFormat& m_cformat; + + float m_lambda; + + }; + +} // namespace dirac + + + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/dirac_encoder.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/dirac_encoder.cpp new file mode 100644 index 000000000..09ba3f570 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/dirac_encoder.cpp @@ -0,0 +1,1179 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_encoder.cpp,v 1.57 2008/11/18 23:25:54 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author), +* Andrew Kennedy +* Thomas Davies +* Myo Tun (Brunel University) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <cstring> +#include <sstream> +#include <fstream> +#include <queue> +#include <string> +#include <libdirac_common/dirac_assertions.h> +#include <libdirac_common/common.h> +#include <libdirac_common/picture.h> +#include <libdirac_common/pic_io.h> +#include <libdirac_encoder/dirac_encoder.h> +#include <libdirac_encoder/seq_compress.h> +#include <libdirac_byteio/dirac_byte_stream.h> +#include <libdirac_common/video_format_defaults.h> +#include <libdirac_common/dirac_exception.h> + +using namespace dirac; +using namespace std; + +template <class T, class S > +void copy_2dArray (const TwoDArray<T> & in, S *out) +{ + for (int j=0 ; j<in.LengthY() ; ++j) + { + for (int i=0 ; i<in.LengthX() ; ++i) + { + // out[j*in.LengthX() + i] = in[j][i]; + *out++ = S( in[j][i] ); + }// i + }// j +} + +void copy_2dArray (const TwoDArray<PredMode> & in, int *out) +{ + for (int j=0 ; j<in.LengthY() ; ++j) + { + for (int i=0 ; i<in.LengthX() ; ++i) + { + // out[j*in.LengthX() + i] = in[j][i]; + *out++ = in[j][i]; + }// i + }// j +} + +void copy_2dArray (const TwoDArray<bool> & in, int *out) +{ + for (int j=0 ; j<in.LengthY() ; ++j) + { + for (int i=0 ; i<in.LengthX() ; ++i) + { + // out[j*in.LengthX() + i] = in[j][i]; + *out++ = in[j][i]; + }// i + }// j +} + +void copy_mv ( const MvArray& mv, dirac_mv_t *dmv) +{ + for (int j=0 ; j<mv.LengthY() ; ++j) + { + for (int i=0 ; i<mv.LengthX() ; ++i) + { + //dmv[j*mv.LengthX() + i].x = mv[j][i].x; + //dmv[j*mv.LengthX() + i].y = mv[j][i].y; + (*dmv).x = mv[j][i].x; + (*dmv).y = mv[j][i].y; + dmv++; + }// i + }// j +} + +void copy_mv_cost (const TwoDArray<MvCostData> &pc, dirac_mv_cost_t *dpc) +{ + for (int j=0 ; j<pc.LengthY() ; ++j) + { + for (int i=0 ; i<pc.LengthX() ; ++i) + { + //dpc[j*pc.LengthX() + i].SAD = pc[j][i].SAD; + //dpc[j*pc.LengthX() + i].mvcost = pc[j][i].mvcost; + (*dpc).SAD = pc[j][i].SAD; + (*dpc).mvcost = pc[j][i].mvcost; + dpc++; + }// i + }// j +} + +/* + Function that allocates the locally managed instrumentation data +*/ +void alloc_instr_data(dirac_instr_t *instr) +{ + instr->sb_split_mode = new int [instr->sb_ylen*instr->sb_xlen]; + memset (instr->sb_split_mode, 0, sizeof(int)*instr->sb_ylen*instr->sb_xlen); + + instr->sb_costs = new float [instr->sb_ylen*instr->sb_xlen]; + memset (instr->sb_costs, 0, sizeof(float)*instr->sb_ylen*instr->sb_xlen); + + instr->pred_mode = new int [instr->mv_ylen * instr->mv_xlen]; + memset (instr->pred_mode, 0, sizeof(int)*instr->mv_ylen*instr->mv_xlen); + + instr->intra_costs = new float [instr->mv_ylen * instr->mv_xlen]; + memset (instr->intra_costs, 0, sizeof(float)*instr->mv_ylen*instr->mv_xlen); + + instr->bipred_costs = new dirac_mv_cost_t [instr->mv_ylen * instr->mv_xlen]; + memset (instr->bipred_costs, 0, sizeof(dirac_mv_cost_t)*instr->mv_ylen*instr->mv_xlen); + + instr->dc_ycomp = new short [instr->mv_ylen * instr->mv_xlen]; + memset (instr->dc_ycomp, 0, sizeof(short)*instr->mv_ylen*instr->mv_xlen); + + instr->dc_ucomp = new short [instr->mv_ylen * instr->mv_xlen]; + memset (instr->dc_ucomp, 0, sizeof(short)*instr->mv_ylen*instr->mv_xlen); + + instr->dc_vcomp = new short [instr->mv_ylen * instr->mv_xlen]; + memset (instr->dc_vcomp, 0, sizeof(short)*instr->mv_ylen*instr->mv_xlen); + + for (int i = 0; i < 2; i++) + { + instr->mv[i] = new dirac_mv_t[instr->mv_ylen * instr->mv_xlen]; + memset (instr->mv[i], 0, + sizeof(dirac_mv_t)*instr->mv_ylen*instr->mv_xlen); + } + + for (int i = 0; i < 2; i++) + { + instr->pred_costs[i] = new dirac_mv_cost_t[instr->mv_ylen * instr->mv_xlen]; + memset (instr->pred_costs[i], 0, + sizeof(dirac_mv_cost_t)*instr->mv_ylen*instr->mv_xlen); + } +} + +/* + Function that frees the locally managed instrumentation data +*/ +void dealloc_instr_data(dirac_instr_t *instr) +{ + if (instr->sb_split_mode) + delete [] instr->sb_split_mode; + + if (instr->sb_costs) + delete [] instr->sb_costs; + + if (instr->pred_mode) + delete [] instr->pred_mode; + + if (instr->intra_costs) + delete [] instr->intra_costs; + + if (instr->bipred_costs) + delete [] instr->bipred_costs; + + if (instr->dc_ycomp) + delete [] instr->dc_ycomp; + + if (instr->dc_ucomp) + delete [] instr->dc_ucomp; + + if (instr->dc_vcomp) + delete [] instr->dc_vcomp; + + for (int i = 0; i < 2; i++) + { + if (instr->mv[i]) + delete [] instr->mv[i]; + } + for (int i = 0; i < 2; i++) + { + if (instr->pred_costs[i]) + delete [] instr->pred_costs[i]; + } +} + +/* + Wrapper class around the SequenceCompressor Class. This class is used + by the "C" encoder interface +*/ +class DiracEncoder +{ +public: + // constructor + DiracEncoder(const dirac_encoder_context_t *enc_ctx, bool verbose); + // destructor + ~DiracEncoder(); + + // Load the next frame of uncompressed data into the SequenceCompressor + bool LoadNextFrame(unsigned char *data, int size); + // Compress the next picture (frame/field) of data + int CompressNextPicture(); + + // Set the encode frame in encoder to the encoded frame data + int GetEncodedData(dirac_encoder_t *encoder); + + // Set the locally decoded frame data in encoder + int GetDecodedData (dirac_encoder_t *encoder); + + // Set the instrumentation data in encoder + void GetInstrumentationData (dirac_encoder_t *encoder); + + // Set the end of sequence infomration in encoder + int GetSequenceEnd(dirac_encoder_t *encoder); + + // Set the buffer to hold the locally decoded frame + void SetDecodeBuffer (unsigned char *buffer, int buffer_size); + + // Return the encoder parameters + const EncoderParams& GetEncParams() const { return m_encparams; } + + // Return the source parameters + const SourceParams& GetSrcParams() const { return m_srcparams; } + + // Return the pts offset + int GetPTSOffset() const { return m_seqcomp->PTSOffset(); } + + // Signal End of Sequence + void SignalEOS() { m_eos_signalled = true; m_seqcomp->SignalEOS(); } + + // End of Sequence + bool EOS() { return m_eos_signalled == true; } + +private: + + // Set the encoder parameters + void SetEncoderParams (const dirac_encoder_context_t *enc_ctx); + + // Set the source parameters + void SetSourceParams (const dirac_encoder_context_t *enc_ctx); + + // Get the picture statistics + void GetPictureStats(dirac_encoder_t *encoder); + + // Get the seuqence statistics + void GetSequenceStats(dirac_encoder_t *encoder, + const DiracByteStats& dirac_seq_stats); + +private: + // sequence compressor + SequenceCompressor *m_seqcomp; + // Source parameters + SourceParams m_srcparams; + // encoder parameters + EncoderParams m_encparams; + // locally encoded picture in coded order + const EncPicture *m_enc_picture; + // locally encoded frame ME data + const MEData *m_enc_medata; + // locally decoded picture number in display order + int m_decpnum; + //locally decoded picture type + PictureSort m_decpsort; + // locally decoded picture number in display order + int m_show_pnum; + // total number of frames/fields loaded so far + int m_num_loaded_pictures; + // total number of frames/fields encoded so far + int m_num_coded_pictures; + // verbose flag + bool m_verbose; + // input stream for uncompressed input pictures + MemoryStreamInput *m_inp_ptr; + // output stream for locally decoded pictures + MemoryStreamOutput *m_out_ptr; + // buffer to hold locally decoded frame. Set by SetDecodeBuffer + unsigned char *m_dec_buf; + // size of buffer to hold locally decoded data. Set by SetDecodeBuffer + int m_dec_bufsize; + // Flag that determines if locally decoded pictures are to be returned. Set + // in Constructor + bool m_return_decoded_pictures; + // Flag that determines if instrumentation data is to be returned. Set + // in Constructor + bool m_return_instr_data; + + // Output destination for compressed data in bitstream format + DiracByteStream m_dirac_byte_stream; + + //Rate Control parameters + // Total Number of bits for a GOP + int m_gop_bits; + + // Total Number GOPs in the input sequence + int m_gop_count; + + // To count the number of pictures for calculating the GOP bit rate + int m_picture_count; + + // field 1 stats if interlaced + dirac_enc_picstats_t m_field1_stats; + + // End of sequence flag. Set to true when user app signals end of + // sequence + bool m_eos_signalled; + +}; + +/* + Instrumentation callback. This function is passed as a parameter to the + SequenceCompressor constructor. It is called by the + FrameCompressor::Compress function once the frame is successfully compressed +*/ +void DiracEncoder::GetInstrumentationData (dirac_encoder_t *encoder) +{ + ASSERT (encoder != NULL); + dirac_instr_t *instr = &encoder->instr; + dirac_instr_t old_instr = *instr; + + if (!m_return_instr_data || m_enc_picture == NULL) + return; + + const PictureParams& pparams = m_enc_picture->GetPparams(); + const PictureSort psort = pparams.PicSort(); + + instr->pnum = pparams.PictureNum(); + instr->ptype = psort.IsIntra() ? INTRA_PICTURE : INTER_PICTURE; + instr->rtype = psort.IsRef() ? REFERENCE_PICTURE : NON_REFERENCE_PICTURE; + instr->num_refs = 0; + encoder->instr_data_avail = 1; + + if (psort.IsIntra()) + { + // no MV data for Intra coded data + return; + } + + TESTM (m_enc_medata != NULL, "ME data available"); + + // Reference info + instr->num_refs = pparams.Refs().size(); + ASSERTM (instr->num_refs <= 2, "Max # reference frames is 2"); + + for (int i=0; i<instr->num_refs; ++i) + instr->refs[i] = pparams.Refs()[i]; + + // Block separation params + instr->ybsep = m_encparams.GetPicPredParams().LumaBParams(2).Ybsep(); + instr->xbsep = m_encparams.GetPicPredParams().LumaBParams(2).Xbsep(); + + // Num superblocks + instr->sb_ylen = m_enc_medata->SBSplit().LengthY(); + instr->sb_xlen = m_enc_medata->SBSplit().LengthX(); + + // Motion vector array dimensions + instr->mv_ylen = m_enc_medata->Vectors(1).LengthY(); + instr->mv_xlen = m_enc_medata->Vectors(1).LengthX(); + + if (old_instr.sb_ylen != instr->sb_ylen || + old_instr.sb_xlen != instr->sb_xlen || + old_instr.mv_ylen != instr->mv_ylen || + old_instr.mv_xlen != instr->mv_xlen) + { + dealloc_instr_data(instr); + alloc_instr_data(instr); + } + + copy_2dArray (m_enc_medata->SBSplit(), instr->sb_split_mode); + copy_2dArray (m_enc_medata->SBCosts(), instr->sb_costs); + copy_2dArray (m_enc_medata->Mode(), instr->pred_mode); + copy_2dArray (m_enc_medata->IntraCosts(), instr->intra_costs); + + if (instr->num_refs > 1) + { + copy_mv_cost (m_enc_medata->BiPredCosts(), instr->bipred_costs); + } + + copy_2dArray (m_enc_medata->DC( Y_COMP ), instr->dc_ycomp); + if (m_enc_medata->DC().Length() == 3) + { + copy_2dArray (m_enc_medata->DC( U_COMP ), instr->dc_ucomp); + copy_2dArray (m_enc_medata->DC( V_COMP ), instr->dc_vcomp); + } + + for (int i=1; i<=instr->num_refs; ++i) + { + copy_mv (m_enc_medata->Vectors(i), instr->mv[i-1]); + copy_mv_cost (m_enc_medata->PredCosts(i), instr->pred_costs[i-1]); + } +} + +DiracEncoder::DiracEncoder(const dirac_encoder_context_t *enc_ctx, + bool verbose) : + m_srcparams(static_cast<VideoFormat>(enc_ctx->enc_params.video_format), true), + m_encparams(static_cast<VideoFormat>(enc_ctx->enc_params.video_format), INTER_PICTURE, 2, true), + m_show_pnum(-1), + m_num_loaded_pictures(0), + m_num_coded_pictures(0), + m_verbose(verbose), + m_dec_buf(0), + m_dec_bufsize(0), + m_return_decoded_pictures(enc_ctx->decode_flag > 0), + m_return_instr_data(enc_ctx->instr_flag > 0), + m_gop_bits(0), + m_gop_count(0), + m_picture_count(0), + m_eos_signalled(false) +{ + // Setup source parameters + SetSourceParams (enc_ctx); + // Setup encoder parameters + m_encparams.SetVerbose( verbose ); + SetEncoderParams (enc_ctx); + + // Set up the input data stream (uncompressed data) + m_inp_ptr = new MemoryStreamInput(m_srcparams, m_encparams.FieldCoding()); + // Set up the output data stream (locally decoded frame) + m_out_ptr = new MemoryStreamOutput(m_srcparams, m_encparams.FieldCoding()); + + // initialise the sequence compressor + if (!m_encparams.FieldCoding()) + { + m_seqcomp = new FrameSequenceCompressor (m_inp_ptr->GetStream(), m_encparams, m_dirac_byte_stream); + } + else + { + m_seqcomp = new FieldSequenceCompressor (m_inp_ptr->GetStream(), m_encparams, m_dirac_byte_stream); + } +} + +void DiracEncoder::SetDecodeBuffer (unsigned char *buffer, int buffer_size) +{ + m_dec_buf = buffer; + m_dec_bufsize = buffer_size; + m_return_decoded_pictures = true; +} + +DiracEncoder::~DiracEncoder() +{ + delete m_seqcomp; + delete m_inp_ptr; + delete m_out_ptr; +} + +void DiracEncoder::SetSourceParams (const dirac_encoder_context_t *enc_ctx) +{ + m_srcparams.SetCFormat( enc_ctx->src_params.chroma ); + m_srcparams.SetXl( enc_ctx->src_params.width ); + m_srcparams.SetYl( enc_ctx->src_params.height ); + + m_srcparams.SetCleanWidth( m_srcparams.Xl() ); + m_srcparams.SetCleanHeight( m_srcparams.Yl() ); + m_srcparams.SetLeftOffset( 0 ); + m_srcparams.SetTopOffset( 0 ); + + m_srcparams.SetSourceSampling( enc_ctx->src_params.source_sampling ); + if (m_srcparams.FrameRate().m_num != (unsigned int)enc_ctx->src_params.frame_rate.numerator || + m_srcparams.FrameRate().m_denom != (unsigned int)enc_ctx->src_params.frame_rate.denominator) + { + m_srcparams.SetFrameRate( enc_ctx->src_params.frame_rate.numerator, + enc_ctx->src_params.frame_rate.denominator ); + } + if (m_srcparams.PixelAspectRatio().m_num != (unsigned int)enc_ctx->src_params.pix_asr.numerator || + m_srcparams.PixelAspectRatio().m_denom != (unsigned int)enc_ctx->src_params.pix_asr.denominator) + { + m_srcparams.SetPixelAspectRatio( enc_ctx->src_params.pix_asr.numerator, + enc_ctx->src_params.pix_asr.denominator ); + } + // TO DO: CLEAN AREA and signal range + // FIXME: Dirac currently support 8BIT_VIDEO only. Accept from command line + // when Dirac supports multiple signal ranges. + m_srcparams.SetSignalRange(SIGNAL_RANGE_8BIT_VIDEO); + +} + +void DiracEncoder::SetEncoderParams (const dirac_encoder_context_t *enc_ctx) +{ + TEST (enc_ctx != NULL); + OLBParams bparams(12, 12, 8, 8); + + m_encparams.SetLocalDecode(enc_ctx->decode_flag); + m_encparams.SetXl( enc_ctx->src_params.width ); + m_encparams.SetYl( enc_ctx->src_params.height ); + m_encparams.SetChromaXl( enc_ctx->src_params.chroma_width ); + m_encparams.SetChromaYl( enc_ctx->src_params.chroma_height ); + + if (enc_ctx->enc_params.picture_coding_mode > 1) + { + std::ostringstream errstr; + + errstr << "Picture coding mode " + << enc_ctx->enc_params.picture_coding_mode + << " out of supported range [0-1]"; + DIRAC_THROW_EXCEPTION( + ERR_INVALID_INIT_DATA, + errstr.str(), + SEVERITY_TERMINATE); + } + + m_encparams.SetPictureCodingMode(enc_ctx->enc_params.picture_coding_mode); + if (m_encparams.FieldCoding()) + { + // Change coding dimensions to field dimensions + m_encparams.SetYl( enc_ctx->src_params.height>>1 ); + m_encparams.SetChromaYl( enc_ctx->src_params.chroma_height >> 1); + } + + unsigned int luma_depth = static_cast<unsigned int> ( + std::log((double)m_srcparams.LumaExcursion())/std::log(2.0) + 1 ); + m_encparams.SetLumaDepth(luma_depth); + + unsigned int chroma_depth = static_cast<unsigned int> ( + std::log((double)m_srcparams.ChromaExcursion())/std::log(2.0) + 1 ); + m_encparams.SetChromaDepth(chroma_depth); + + m_encparams.SetFullSearch(enc_ctx->enc_params.full_search); + m_encparams.SetCombinedME(enc_ctx->enc_params.combined_me); + m_encparams.SetXRangeME(enc_ctx->enc_params.x_range_me); + m_encparams.SetYRangeME(enc_ctx->enc_params.y_range_me); + m_encparams.SetCPD(enc_ctx->enc_params.cpd); + m_encparams.SetQf(enc_ctx->enc_params.qf); + m_encparams.SetTargetRate(enc_ctx->enc_params.trate); + m_encparams.SetLossless(enc_ctx->enc_params.lossless); + m_encparams.SetL1Sep(enc_ctx->enc_params.L1_sep); + m_encparams.SetNumL1(enc_ctx->enc_params.num_L1); + m_encparams.SetPrefilter(enc_ctx->enc_params.prefilter, + enc_ctx->enc_params.prefilter_strength); + m_encparams.SetUFactor(1.5f); + m_encparams.SetVFactor(0.75f); + m_encparams.GetPicPredParams().SetMVPrecision(enc_ctx->enc_params.mv_precision); + m_encparams.SetUsingAC(enc_ctx->enc_params.using_ac); + bparams.SetYblen( enc_ctx->enc_params.yblen ); + bparams.SetXblen( enc_ctx->enc_params.xblen ); + bparams.SetYbsep( enc_ctx->enc_params.ybsep ); + bparams.SetXbsep( enc_ctx->enc_params.xbsep ); + + // Now rationalise the GOP options + // this stuff should really be done in a constructor! + if (m_encparams.NumL1()<0) + { + //don't have a proper GOP + m_encparams.SetL1Sep( std::max(1 , m_encparams.L1Sep()) ); + } + else if (m_encparams.NumL1() == 0) + { + //have I-frame only coding + m_encparams.SetL1Sep(0); + } + m_encparams.GetPicPredParams().SetBlockSizes( bparams , enc_ctx->src_params.chroma ); + + // Set transforms parameters + m_encparams.SetIntraTransformFilter(enc_ctx->enc_params.intra_wlt_filter); + m_encparams.SetInterTransformFilter(enc_ctx->enc_params.inter_wlt_filter); + m_encparams.SetSpatialPartition(enc_ctx->enc_params.spatial_partition); + + m_encparams.SetTransformDepth(enc_ctx->enc_params.wlt_depth); + m_encparams.SetCodeBlockMode(enc_ctx->enc_params.spatial_partition && enc_ctx->enc_params.multi_quants ? QUANT_MULTIPLE : QUANT_SINGLE); +} + + +bool DiracEncoder::LoadNextFrame (unsigned char *data, int size) +{ + TESTM (m_seqcomp->Finished() != true, "Did not reach end of sequence"); + m_inp_ptr->SetMembufReference(data, size); + if (m_seqcomp->LoadNextFrame()) + { + if (!m_encparams.FieldCoding()) + m_num_loaded_pictures++; + else + m_num_loaded_pictures+=2; + return true; + } + return false; +} + +int DiracEncoder::CompressNextPicture () +{ + TESTM (m_seqcomp->Finished() != true, "Did not reach end of sequence"); + + if (!m_num_loaded_pictures) + return 0; + + const EncPicture *mypicture = m_seqcomp->CompressNextPicture(); + + m_decpnum = -1; + + if (mypicture){ + m_enc_picture = m_seqcomp->GetPictureEncoded(); + if (m_enc_picture->GetPparams().PicSort().IsIntra()==false) + m_enc_medata = &m_enc_picture->GetMEData(); + else + m_enc_medata = NULL; + + if (m_return_decoded_pictures && + mypicture->GetPparams().PictureNum() != m_show_pnum){ + int ret_val; + m_show_pnum = mypicture->GetPparams().PictureNum(); + TEST (! (m_return_decoded_pictures && !m_dec_buf) ); + if (m_return_decoded_pictures && m_dec_buf) + { + // write locally decoded picture to decode buffer + m_out_ptr->SetMembufReference(m_dec_buf, m_dec_bufsize); + ret_val = m_out_ptr->GetStream()->WriteToNextFrame(*mypicture); + + if (ret_val) + { + m_decpnum = m_show_pnum; + m_decpsort = mypicture->GetPparams().PicSort(); + } + } + } + } + else{ + m_enc_picture = NULL; + m_enc_medata = NULL; + } + + if(!m_dirac_byte_stream.IsUnitAvailable()) + return 0; + + if (mypicture){ + m_num_coded_pictures++; + TESTM (m_enc_picture != 0, "Encoder picture available"); + } + return 1; +} + +void DiracEncoder::GetPictureStats(dirac_encoder_t *encoder) +{ + + dirac_enc_picstats_t *pstats = &encoder->enc_pstats; + DiracByteStats dirac_byte_stats = m_dirac_byte_stream.GetLastUnitStats(); + + pstats->mv_bits = dirac_byte_stats.GetBitCount(STAT_MV_BYTE_COUNT); + // pstats->mv_hdr_bits = poutput.MVBytes() * 8; + + pstats->ycomp_bits = dirac_byte_stats.GetBitCount(STAT_YCOMP_BYTE_COUNT); + // pstats->ycomp_hdr_bits = poutput.ComponentHeadBytes( Y_COMP ) * 8; + + pstats->ucomp_bits = dirac_byte_stats.GetBitCount(STAT_UCOMP_BYTE_COUNT); + // pstats->ucomp_hdr_bits = poutput.ComponentHeadBytes( U_COMP ) * 8; + + pstats->vcomp_bits = dirac_byte_stats.GetBitCount(STAT_VCOMP_BYTE_COUNT); + // pstats->vcomp_hdr_bits = poutput.ComponentHeadBytes( V_COMP ) * 8; + + pstats->pic_bits = dirac_byte_stats.GetBitCount(STAT_TOTAL_BYTE_COUNT); + // pstats->pic_hdr_bits = poutput.PictureHeadBytes() * 8; + + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + if (compressor->GetEncParams().Verbose()) + { + std::cout<<std::endl<<"Number of MV bits="<<pstats->mv_bits; + std::cout<<std::endl<<"Number of bits for Y="<<pstats->ycomp_bits; + std::cout<<std::endl<<"Number of bits for U="<<pstats->ucomp_bits; + std::cout<<std::endl<<"Number of bits for V="<<pstats->vcomp_bits; + if (m_encparams.FieldCoding()) + std::cout<<std::endl<<"Total field bits="<<pstats->pic_bits; + else + std::cout<<std::endl<<"Total frame bits="<<pstats->pic_bits; + } +} + +int DiracEncoder::GetEncodedData (dirac_encoder_t *encoder) +{ + int size = 0; + dirac_enc_data_t *encdata = &encoder->enc_buf; + + string output = m_dirac_byte_stream.GetBytes(); + size = output.size(); + //std::cout << std::endl << "ParseUnit size=" << size << std::endl; + if (size > 0) + { + if (encdata->size < size ) + { + return -1; + } + memmove (encdata->buffer, output.c_str(), output.size()); + if (m_enc_picture) + { + // picture data + encoder->enc_pparams.pnum = m_enc_picture->GetPparams().PictureNum(); + encoder->enc_pparams.ptype = m_enc_picture->GetPparams().PicSort().IsIntra() ? INTRA_PICTURE : INTER_PICTURE; + encoder->enc_pparams.rtype = m_enc_picture->GetPparams().PicSort().IsRef() ? REFERENCE_PICTURE : NON_REFERENCE_PICTURE; + + // Get frame statistics + GetPictureStats (encoder); + if(m_encparams.Verbose() && encoder->enc_ctx.enc_params.picture_coding_mode==1) + { + if (encoder->enc_pparams.pnum%2 == 0) + m_field1_stats = encoder->enc_pstats; + else + { + std::cout<<std::endl<<std::endl + <<"Frame "<<encoder->enc_pparams.pnum/2; + std::cout<< " stats"; + std::cout<<std::endl<< "Number of MV bits="; + std::cout<< m_field1_stats.mv_bits + encoder->enc_pstats.mv_bits; + std::cout<< std::endl << "Number of bits for Y="; + std::cout<< m_field1_stats.ycomp_bits + encoder->enc_pstats.ycomp_bits; + std::cout<< std::endl << "Number of bits for U="; + std::cout<< m_field1_stats.ucomp_bits + encoder->enc_pstats.ucomp_bits; + std::cout<< std::endl << "Number of bits for V="; + std::cout<< m_field1_stats.vcomp_bits + encoder->enc_pstats.vcomp_bits; + std::cout << std::endl << "Total frame bits="; + std::cout<< m_field1_stats.pic_bits + encoder->enc_pstats.pic_bits; + } + } + } + else + { + // Not picture data + encoder->enc_pparams.pnum = -1; + } + encdata->size = size; + + GetInstrumentationData(encoder); + encoder->encoded_picture_avail = 1; + } + else + { + encdata->size = 0; + } + + if (m_enc_picture) + { + //Rate Control - work out bit rate to date and for current GOP + // and keep track of frame numbers + int interlace_factor = m_encparams.FieldCoding() ? 2 : 1; + int num_L1 = encoder->enc_ctx.enc_params.num_L1; + int L1_sep = encoder->enc_ctx.enc_params.L1_sep; + + // Length of the GOP in pictures - twice as many if fields + int GOP_pic_length = (num_L1+1)*L1_sep*interlace_factor; + + int offset; + if (num_L1 == 0) + { + GOP_pic_length = 10; + offset = 0; + } + else + offset = std::max(L1_sep-1,0)*interlace_factor; + + m_gop_bits += encoder->enc_pstats.pic_bits; + m_picture_count++; + + if ( (m_gop_count==0 && m_picture_count == GOP_pic_length-offset) || + (m_gop_count>0 && m_picture_count == GOP_pic_length)) + { + int denominator = encoder->enc_ctx.src_params.frame_rate.denominator; + int numerator = encoder->enc_ctx.src_params.frame_rate.numerator; + double frame_rate = (double)numerator/(double)denominator; + + double gop_duration = double(m_picture_count)/interlace_factor/frame_rate; + double bit_rate = double(m_gop_bits)/gop_duration; + + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + if (compressor->GetEncParams().Verbose()) + { + std::cout<<std::endl<<std::endl<<"Bit Rate for GOP number "; + std::cout<<m_gop_count<<" is "<<bit_rate/1000.0<<" kbps"<<std::endl; + } + + m_gop_count++; + m_gop_bits = 0; + m_picture_count = 0; + } + //End of Rate Control + } + + m_dirac_byte_stream.Clear(); + + return size; +} + +int DiracEncoder::GetDecodedData (dirac_encoder_t *encoder) +{ + dirac_picparams_t *pp = &encoder->dec_pparams; + + int ret_stat = (m_decpnum != -1); + if (m_return_decoded_pictures && m_decpnum != -1) + { + pp->ptype = m_decpsort.IsIntra() ? INTRA_PICTURE : INTER_PICTURE; + pp->rtype = m_decpsort.IsRef() ? REFERENCE_PICTURE : NON_REFERENCE_PICTURE; + pp->pnum = m_decpnum; + encoder->decoded_frame_avail = 1; + m_decpnum = -1; + } + return ret_stat; +} + +void DiracEncoder::GetSequenceStats(dirac_encoder_t *encoder, + const DiracByteStats& dirac_seq_stats) +{ + dirac_enc_seqstats_t *sstats = &encoder->enc_seqstats; + + sstats->seq_bits = dirac_seq_stats.GetBitCount(STAT_TOTAL_BYTE_COUNT); + sstats->mv_bits = dirac_seq_stats.GetBitCount(STAT_MV_BYTE_COUNT); + sstats->ycomp_bits = dirac_seq_stats.GetBitCount(STAT_YCOMP_BYTE_COUNT); + sstats->ucomp_bits = dirac_seq_stats.GetBitCount(STAT_UCOMP_BYTE_COUNT); + sstats->vcomp_bits = dirac_seq_stats.GetBitCount(STAT_VCOMP_BYTE_COUNT); + + sstats->bit_rate = int64_t((sstats->seq_bits * + (double)m_srcparams.FrameRate().m_num)/ + (m_srcparams.FrameRate().m_denom * m_num_coded_pictures)); + if (encoder->enc_ctx.enc_params.picture_coding_mode==1) + sstats->bit_rate *= 2; + + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + if (compressor->GetEncParams().Verbose()) + { + std::cout<<std::endl<<std::endl<<"Total bits for sequence="<<sstats->seq_bits; + std::cout<<std::endl<<"Of these: "<<std::endl; + std::cout<<std::endl<<sstats->ycomp_bits <<" were Y, "; + std::cout<<std::endl<<sstats->ucomp_bits <<" were U, "; + std::cout<<std::endl<<sstats->vcomp_bits<<" were V, and "; + std::cout<<std::endl<<sstats->mv_bits<<" were motion vector data."; + } +} + +int DiracEncoder::GetSequenceEnd (dirac_encoder_t *encoder) +{ + dirac_enc_data_t *encdata = &encoder->enc_buf; + DiracByteStats dirac_seq_stats=m_seqcomp->EndSequence(); + string output = m_dirac_byte_stream.GetBytes(); + int size = output.size(); + if (size > 0) + { + if (encdata->size < size ) + { + return -1; + } + memmove (encdata->buffer, output.c_str(), size); + GetSequenceStats(encoder, + dirac_seq_stats); + encdata->size = size; + } + else + { + encdata->size = 0; + } + m_dirac_byte_stream.Clear(); + return size; +} + +static bool InitialiseEncoder (const dirac_encoder_context_t *enc_ctx, bool verbose, dirac_encoder_t *encoder) +{ + TEST (enc_ctx != NULL); + TEST (encoder != NULL); + + if (enc_ctx->src_params.width == 0 || enc_ctx->src_params.height == 0) + return false; + + if (enc_ctx->src_params.chroma < format444 || + enc_ctx->src_params.chroma >= formatNK) + return false; + + if (!enc_ctx->src_params.frame_rate.numerator || + !enc_ctx->src_params.frame_rate.denominator) + return false; + + memmove (&encoder->enc_ctx, enc_ctx, sizeof(dirac_encoder_context_t)); + + encoder->dec_buf.id = 0; + + switch ( enc_ctx->src_params.chroma ) + { + case format420: + encoder->enc_ctx.src_params.chroma_width = enc_ctx->src_params.width/2; + encoder->enc_ctx.src_params.chroma_height = enc_ctx->src_params.height/2; + break; + case format422: + encoder->enc_ctx.src_params.chroma_width = enc_ctx->src_params.width/2; + encoder->enc_ctx.src_params.chroma_height = enc_ctx->src_params.height; + break; + case format444: + default: + encoder->enc_ctx.src_params.chroma_width = enc_ctx->src_params.width; + encoder->enc_ctx.src_params.chroma_height = enc_ctx->src_params.height; + break; + } + + try + { + DiracEncoder *comp = new DiracEncoder (&encoder->enc_ctx, verbose); + + encoder->compressor = comp; + if (encoder->enc_ctx.decode_flag) + { + int bufsize = (encoder->enc_ctx.src_params.width * encoder->enc_ctx.src_params.height)+ 2*(encoder->enc_ctx.src_params.chroma_width*encoder->enc_ctx.src_params.chroma_height); + encoder->dec_buf.buf[0] = new unsigned char [bufsize]; + encoder->dec_buf.buf[1] = encoder->dec_buf.buf[0] + + (encoder->enc_ctx.src_params.width * encoder->enc_ctx.src_params.height); + encoder->dec_buf.buf[2] = encoder->dec_buf.buf[1] + + (encoder->enc_ctx.src_params.chroma_width*encoder->enc_ctx.src_params.chroma_height); + + comp->SetDecodeBuffer (encoder->dec_buf.buf[0], bufsize); + } + } + catch (...) + { + return false; + } + return true; +} + +static void SetSourceParameters(dirac_encoder_context_t *enc_ctx, + const VideoFormat& video_format) +{ + TEST (enc_ctx != NULL); + dirac_sourceparams_t &src_params = enc_ctx->src_params; + + // create object containing sequence params + SourceParams default_src_params(video_format); + + src_params.height = default_src_params.Yl(); + src_params.width = default_src_params.Xl(); + src_params.chroma_height = default_src_params.ChromaHeight(); + src_params.chroma_width = default_src_params.ChromaWidth(); + src_params.chroma = default_src_params.CFormat(); + src_params.frame_rate.numerator = default_src_params.FrameRate().m_num; + src_params.frame_rate.denominator = default_src_params.FrameRate().m_denom; + src_params.pix_asr.numerator = default_src_params.PixelAspectRatio().m_num; + src_params.pix_asr.denominator = default_src_params.PixelAspectRatio().m_denom; + src_params.source_sampling = default_src_params.SourceSampling(); + src_params.topfieldfirst = default_src_params.TopFieldFirst(); + + //TODO - Need to accept these params from command line + //Set clean area + //Set signal range + //Set colour specification +} + +static void SetEncoderParameters(dirac_encoder_context_t *enc_ctx, + const VideoFormat& video_format) +{ + TEST (enc_ctx != NULL); + dirac_encparams_t &encparams = enc_ctx->enc_params; + + encparams.video_format = static_cast<int>(video_format); + // set encoder defaults + EncoderParams default_enc_params(video_format); + + encparams.qf = default_enc_params.Qf(); + encparams.cpd = default_enc_params.CPD(); + encparams.prefilter = default_enc_params.Prefilter(); + encparams.prefilter_strength = default_enc_params.PrefilterStrength(); + encparams.L1_sep = default_enc_params.L1Sep(); + encparams.lossless = default_enc_params.Lossless(); + encparams.using_ac = default_enc_params.UsingAC(); + encparams.num_L1 = default_enc_params.NumL1(); + + // Set rate to zero by default, meaning no rate control + encparams.trate = 0; + + // set default block params + OLBParams default_block_params; + SetDefaultBlockParameters(default_block_params, video_format); + encparams.xblen = default_block_params.Xblen(); + encparams.yblen = default_block_params.Yblen(); + encparams.xbsep = default_block_params.Xbsep(); + encparams.ybsep = default_block_params.Ybsep(); + + // set default MV parameters + encparams.mv_precision = default_enc_params.GetPicPredParams().MVPrecision(); + + // by default, use hierarchical, not full search + encparams.full_search = 0; + encparams.x_range_me = 32; + encparams.y_range_me = 32; + + // by default, don't use combined component motion estimation + encparams.combined_me = 0; + + // set default transform parameters + WltFilter wf; + SetDefaultTransformFilter(INTRA_PICTURE, video_format, wf); + encparams.intra_wlt_filter = wf; + SetDefaultTransformFilter(INTER_PICTURE, video_format, wf); + encparams.inter_wlt_filter = wf; + encparams.wlt_depth = default_enc_params.TransformDepth(); + encparams.spatial_partition = default_enc_params.SpatialPartition(); + encparams.multi_quants = default_enc_params.GetCodeBlockMode() == QUANT_MULTIPLE; + + encparams.picture_coding_mode = default_enc_params.FieldCoding() ? 1 : 0; +} + +#ifdef __cplusplus +extern "C" { +#endif + +extern DllExport void dirac_encoder_context_init ( dirac_encoder_context_t *enc_ctx, dirac_encoder_presets_t preset) +{ + TEST (enc_ctx != NULL); + memset (enc_ctx, 0, sizeof(dirac_encoder_context_t)); + + // preset is the video format + int ps = static_cast<int>(preset); + VideoFormat video_format(static_cast<VideoFormat>(ps)); + SetSourceParameters (enc_ctx, video_format); + SetEncoderParameters (enc_ctx, video_format); +} + +extern DllExport dirac_encoder_t *dirac_encoder_init (const dirac_encoder_context_t *enc_ctx, int verbose) +{ + /* Allocate for encoder */ + dirac_encoder_t *encoder = new dirac_encoder_t; + + memset (encoder, 0, sizeof(dirac_encoder_t)); + /* initialse the encoder context */ + if (!InitialiseEncoder(enc_ctx, verbose>0, encoder)) + { + delete encoder; + return NULL; + } + + encoder->encoded_picture_avail = encoder->decoded_frame_avail = 0; + encoder->instr_data_avail = 0; + + return encoder; +} + +#if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2) +extern DllExport int dirac_encoder_pts_offset (const dirac_encoder_t *encoder) +{ + TEST (encoder != NULL); + TEST (encoder->compressor != NULL); + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + int ret; + try + { + ret = compressor->GetPTSOffset(); + } + catch (...) + { + ret = -1; + } + + return ret; +} +#endif + +extern DllExport int dirac_encoder_load (dirac_encoder_t *encoder, unsigned char *uncdata, int uncdata_size) +{ + TEST (encoder != NULL); + TEST (encoder->compressor != NULL); + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + int ret_stat = 0; + try + { + if ( compressor->LoadNextFrame (uncdata, uncdata_size)) + { + ret_stat = uncdata_size; + } + } + catch (...) + { + if (compressor->GetEncParams().Verbose()) + std::cerr << "dirac_encoder_load failed" << std::endl; + ret_stat = -1; + } + return ret_stat; +} + +extern DllExport dirac_encoder_state_t + dirac_encoder_output (dirac_encoder_t *encoder) +{ + TEST (encoder != NULL); + TEST (encoder->compressor != NULL); + TEST (encoder->enc_buf.size != 0); + TEST (encoder->enc_buf.buffer != NULL); + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + dirac_encoder_state_t ret_stat = ENC_STATE_BUFFER; + + encoder->encoded_picture_avail = 0; + encoder->decoded_frame_avail = 0; + encoder->instr_data_avail = 0; + + try + { + // Get the next compressed picture + if (compressor->CompressNextPicture() != 0) + { + if (compressor->GetEncodedData (encoder) < 0) + ret_stat = ENC_STATE_INVALID; + else + { + if (encoder->enc_buf.size > 0) + { + ret_stat = ENC_STATE_AVAIL; + } + + } + } + else + { + // check if EOS has been signalled by the user app + if (compressor->EOS()) + { + compressor->GetSequenceEnd (encoder); + encoder->end_of_sequence = 1; + encoder->enc_pparams.pnum = -1; + ret_stat = ENC_STATE_EOS; + } + } + if (encoder->enc_ctx.decode_flag) + compressor->GetDecodedData(encoder); + } + catch (...) + { + if (compressor->GetEncParams().Verbose()) + std::cerr << "GetEncodedData failed..." << std::endl; + + ret_stat = ENC_STATE_INVALID; + } + return ret_stat; +} + +extern DllExport void dirac_encoder_end_sequence (dirac_encoder_t *encoder) +{ + TEST (encoder != NULL); + TEST (encoder->compressor != NULL); + DiracEncoder *compressor = (DiracEncoder *)encoder->compressor; + + encoder->encoded_picture_avail = 0; + encoder->decoded_frame_avail = 0; + encoder->instr_data_avail = 0; + + compressor->SignalEOS(); + +} + +extern DllExport void dirac_encoder_close (dirac_encoder_t *encoder) +{ + TEST (encoder != NULL); + TEST (encoder->compressor != NULL); + + delete (DiracEncoder *)(encoder->compressor); + + if (encoder->enc_ctx.instr_flag) + { + dealloc_instr_data(&encoder->instr); + } + + if (encoder->enc_ctx.decode_flag) + { + delete [] encoder->dec_buf.buf[0]; + } + delete encoder; +} + + +#ifdef __cplusplus +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/dirac_encoder.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/dirac_encoder.h new file mode 100644 index 000000000..750c6a51a --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/dirac_encoder.h @@ -0,0 +1,481 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: dirac_encoder.h,v 1.28 2008/11/18 23:25:54 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* Andrew Kennedy, +* Thomas Davies +* Myo Tun (Brunel University, myo.tun@brunel.ac.uk) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef DIRAC_ENCODER_H +#define DIRAC_ENCODER_H + +#include <libdirac_common/dirac_inttypes.h> +#include <libdirac_common/dirac_types.h> + +/*! \file +\brief C interface to Dirac Encoder. + + A set of 'C' functions that define the public interface to the Dirac encoder. + Refer to the the reference encoder source code, encoder/encmain.cpp for + an example of how to use the "C" interface. The pseudocode below gives + a brief description of the "C" interface usage. + +\verbatim + #include <libdirac_decoder/dirac_encoder.h> + + #define ENCBUF_SIZE 1024*1024; + unsigned char *buffer, enc_buf[ENC_BUFSIZE]; + int buffer_size; + dirac_encoder_t *encoder; + dirac_encoder_context_t enc_ctx; + + // Initialse the encoder context with the presets for SD576 - Standard + // Definition Digital + dirac_encoder_context_init (&enc_ctx, VIDEO_FORMAT_SD576I50); + + // Override parameters if required + // interlace : 1 - interlaced; 0 - progressive + enc_ctx.seq_params.interlace = 0; + enc_ctx.seq_params.topfieldfirst = 0; + enc_ctx.enc_params.qf = 7.5; + // disable instrumentation flag + enc_ctx.instr_flag = 0; + // return locally decoded output + enc_ctx.decode_flag = 1; + + // Initialise the encoder with the encoder context. + // Setting verbose output to false + encoder= dirac_encoder_init(&enc_ctx, false); + + // Set the buffer size. For SD576 4:2:0 chroma + buffer_size = (720*576*3)/2; + buffer = (unsigned char *)malloc (buffer_size); + + // Output buffer + + dirac_encoder_state_t state; + int go = 1; + do + { + read uncompressed frame data into buffer + if (end of file) + { + // push end of sequence + dirac_encoder_end_sequence(encoder); + } + // load one frame of data into encoder + if (dirac_encoder_load(encoder, buffer, buffer_size) == 0) + { + // Retrieve encoded frames from encoder + do + { + encoder->enc_buf.buffer = enc_buf; + encoder->enc_buf.size = ENCBUF_SIZE; + state = dirac_encoder_output (encoder); + switch (state) + { + case ENC_STATE_AVAIL: + // Encoded frame available in encoder->enc_buf + // Encoded frame params available in enccoder->enc_fparams + // Encoded frame stats available in enccoder->enc_fstats + break; + case ENC_STATE_BUFFER: + break; + case ENC_STATE_EOS: + // Reached end of sequence + // End of sequence information is available in encoder->enc_buf + // Sequence statistics available in encoder->enc_seqstats; + go = 0; // exit from the encoding loop + break; + case ENC_STATE_INVALID: + default: + // Unrecoverable error encountered. Exit; + exit (exit code); + } + if (encoder->decoded_frame_avail) + { + //locally decoded frame is available in + //encoder->dec_buf + //locally decoded frame parameters available + //in encoder->dec_fparams + } + if (encoder->instr_data_avail) + { + //Instrumentation data (motion vectors etc.) + //available in encoder->instr + } + } while (state == ENC_STATE_AVAIL) + } + } while (go == 1); + + // Free the encoder resources + dirac_encoder_close(encoder) + // Free the uncompressed data buffer + free (buffer); + + \endverbatim +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! Enumerated type that defines encoder state */ +typedef enum +{ + ENC_STATE_INVALID = -1, + ENC_STATE_BUFFER, + ENC_STATE_AVAIL, + ENC_STATE_EOS +} dirac_encoder_state_t ; + +/*! Enumerated type that defines prefiltering types supported by the + encoder. */ +typedef PrefilterType dirac_prefilter_t; + +/*! Enumerated type that defines encoder presets that set the encoder and + sequence paramters. More presets may be added in future*/ +typedef VideoFormat dirac_encoder_presets_t; + +/*! Enumerated type that defines motion vector precisions supported by the + encoder.*/ +typedef MVPrecisionType dirac_mvprecision_t; +/*! Structure that holds the encoder specific parameters */ +typedef struct +{ + /*! Lossless coding */ + int lossless; + /*! Quality factor */ + float qf; + /*! Full-search motion estimation */ + int full_search; + /*! Combined component motion estimation */ + int combined_me; + /*! x-range for full search ME */ + int x_range_me; + /*! y-range for full search ME */ + int y_range_me; + /*! The separation between L1 frames */ + int L1_sep; + /*! The number of L1 frames before the next intra frame. Together + with L1_sep determines the GOP structure. + */ + int num_L1; + /*! Normalised viewing distance parameter, in cycles per degree */ + float cpd; + /*! The width of blocks used for motion compensation */ + int xblen; + /*! The height of blocks used for motion compensation */ + int yblen; + /*! The horizontal separation between blocks. Always <xblen */ + int xbsep; + /*! The vertical separation between blocks. Always <yblen */ + int ybsep; + /*! Video format preset */ + int video_format; + /*! Transform filter for intra frames*/ + dirac_wlt_filter_t intra_wlt_filter; + /*! Transform filter for inter frames*/ + dirac_wlt_filter_t inter_wlt_filter; + /*! Transform depth */ + unsigned int wlt_depth; + /*! Spatial partitioning flag */ + unsigned int spatial_partition; + /*! prefilter indicator */ + dirac_prefilter_t prefilter; + /*! prefilter strength*/ + unsigned int prefilter_strength; + /*! Multiple quantisers flag */ + unsigned int multi_quants; + /*! motion-vector pixel precision */ + dirac_mvprecision_t mv_precision; + /*! target bit rate in kbps */ + int trate; + /*! picture coding mode: 0 - frame coding; 1 - field coding */ + unsigned int picture_coding_mode; + /*! arithmetic coding flag: 0 - vlc coding; 1 - arithmetic coding */ + int using_ac; +} dirac_encparams_t; + +/*! Structure that holds the parameters that set up the encoder context */ +typedef struct +{ + /*! Source parameters */ + dirac_sourceparams_t src_params; + /*! Encoder parameters */ + dirac_encparams_t enc_params; + /*! Return diagnostics info 1-return mv data, 0-no diagnostics returned */ + int instr_flag; + /*! Return locally decoded frames 1-return locally decoded frames, + 0-no decoded frames returned */ + int decode_flag; +} dirac_encoder_context_t; + +/*! Function that creates an encoder context based on a preset value. The + values can then be overridden by the user by setting each field separately + \param enc_ctx pointer to Encoder context tp be initialised. + \param preset Preset to be used to initialise the encoder context + \verbatim + + For a full list of video formats presets supported and the default values + of the source and encoder parameters. refer to Annex C of the Dirac + ByteStream Specification. + + \endverbatim +*/ +extern DllExport void dirac_encoder_context_init (dirac_encoder_context_t *enc_ctx, dirac_encoder_presets_t preset); + + +/*! Structure that holds the encoded data*/ +typedef struct +{ + /*! Buffer to hold encoded. Allocated and managed by library user. */ + unsigned char *buffer; + /*! Buffer size */ + int size; +} dirac_enc_data_t; + +/*! Structure that holds the statistics about the encoded picture */ +typedef struct +{ + /*! Number of motion vector bits */ + unsigned int mv_bits; + /*! Number of used to encode y component */ + unsigned int ycomp_bits; + /*! Number of used to encode u component */ + unsigned int ucomp_bits; + /*! Number of used to encode v component */ + unsigned int vcomp_bits; + /*! Total number of bits used to encode picture */ + unsigned int pic_bits; +} dirac_enc_picstats_t; + +/*! Structure that holds the statistics about the encoded sequence */ +typedef struct +{ + /*! Number of motion vector bits */ + int64_t mv_bits; + /*! Total number of bits used to encode sequence */ + int64_t seq_bits; + /*! Number of used to encode y component */ + int64_t ycomp_bits; + /*! Number of used to encode u component */ + int64_t ucomp_bits; + /*! Number of used to encode v component */ + int64_t vcomp_bits; + /*! Average bit rate for the sequence */ + int64_t bit_rate; +} dirac_enc_seqstats_t; + +/*! Structure that holds the motion vector information */ +typedef struct +{ + /*! X component */ + int x; + /*! Y component */ + int y; +} dirac_mv_t; + +/*! Structure that holds the motion vector cost information*/ +typedef struct +{ + /*! The Sum of Absolute Differences */ + float SAD; + /*! The (Lagrangian-weighted) motion vector cost */ + float mvcost; +} dirac_mv_cost_t; + +/*! Structure that diagnostics data returned by the encoder */ +typedef struct +{ + /*! Frame type */ + dirac_picture_type_t ptype; + /*! Reference type */ + dirac_reference_type_t rtype; + /*! Picture number */ + int pnum; + /*! Number of reference pictures */ + int num_refs; + /*! Array of Reference picture numbers */ + int refs[2]; + /*! Block separation in X direction */ + int xbsep; + /*! Block separation in Y direction */ + int ybsep; + /*! MacroBlock length in X direction */ + int sb_xlen; + /*! MacroBlock length in Y direction */ + int sb_ylen; + /*! Motion Vector array length in X direction */ + int mv_xlen; + /*! Motion Vector array length in Y direction */ + int mv_ylen; + /*! Macro-block split mode array - sb_ylen*sb_xlen*/ + int *sb_split_mode; + /*! Macro-block costs array - sb_ylen*sb_xlen*/ + float *sb_costs; + /*! Block prediction mode - mv_xlen*mv_ylen */ + int *pred_mode; + /*! Block intrac costs - mv_xlen*mv_ylen */ + float *intra_costs; + /*! Bi prediction costs - mv_xlen*mv_ylen*2 */ + dirac_mv_cost_t *bipred_costs; + /*! DC values of y_comp */ + short *dc_ycomp; + /*! DC values of u_comp */ + short *dc_ucomp; + /*! DC values of v_comp */ + short *dc_vcomp; + /*! Motion vectors for Reference frames mv_ylen*mv_xlen */ + dirac_mv_t *mv[2]; + /*! Predictions costs for Reference frames mv_ylen*mv_xlen */ + dirac_mv_cost_t *pred_costs[2]; +} dirac_instr_t; + +/*! Structure that holds the information returned by the encoder */ +typedef struct +{ + /*! Encoder context */ + dirac_encoder_context_t enc_ctx; + + /*! encoded picture available flag */ + int encoded_picture_avail; + + /*! + encoded output. This buffer must be initialised by the user of the + library + */ + dirac_enc_data_t enc_buf; + + /*! encoded picture params */ + dirac_picparams_t enc_pparams; + + /*! encoded picture stats */ + dirac_enc_picstats_t enc_pstats; + + /*! encoded sequence stats */ + dirac_enc_seqstats_t enc_seqstats; + + /*! end of sequence */ + int end_of_sequence; + + /* locally decoded frame (NB: not picture) available flag. + 1 - locally decoded frame available in dec_buf. + 0 - locally decoded frame not available. + */ + int decoded_frame_avail; + + /*! + locally decoded output buffer. This buffer is allocated and managed by + the encoder library + */ + dirac_framebuf_t dec_buf; + + /*! locally decoded picture params */ + dirac_picparams_t dec_pparams; + + /*! + instrumentation data buffer. This buffer is allocated and managed by + the encoder library. */ + dirac_instr_t instr; + + /*! instrumentation data available flag + 1 - instrumentation data available in instr + 0 - linstrumentation data not available. + */ + int instr_data_avail; + + /*! void pointer to internal sequence compressor */ + const void *compressor; +} dirac_encoder_t; + +/*! + Initialise encoder. Makes a copy of the enc_ctx passed to it. + \param enc_ctx Parameters to initialise encoder context + \param verbose boolean flag to set verbose output + \return encoder Handle to encoder if successful or NULL on failure +*/ +extern DllExport dirac_encoder_t *dirac_encoder_init (const dirac_encoder_context_t *enc_ctx, int verbose); + +#if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2) +/*! + Query the encoder for the reordering depth. + \param encoder Encoder Handle + \return encoder The number of pictures a realtime decoder must wait + before outputting the first picture in display order; + or -1 for failure. +*/ +extern DllExport int dirac_encoder_pts_offset (const dirac_encoder_t *encoder); +#endif + +/*! + Load uncompressed data into the encoder. Expects one full frame of data + \param encoder Encoder Handle + \param uncdata Uncompressed data buffer + \param uncdata_size boolean flag to set verbose output + \return return status. >0 - successful; -1 failed + Failure may be due to input data size not matching + the required frame size. +*/ +extern DllExport int dirac_encoder_load (dirac_encoder_t *encoder, unsigned char *uncdata, int uncdata_size); + +/*! + Retrieve an encoded frame from the encoder. Returns the state of the + encoder. The encoder buffer enc_buf in the encodermust be + set up with the buffer and buffer_size that will hold the encoded frame + \param encoder Encoder Handle + \return ENC_STATE_INVALID - unrecoverable error + ENC_STATE_BUFFER - load data into encoder + ENC_STATE_AVAIL - Encoded frame available + ENC_STATE_EOS - End of Sequence info available +*/ +extern DllExport dirac_encoder_state_t dirac_encoder_output (dirac_encoder_t *encoder); + +/*! + Request the encoder to end the sequence. + \param encoder Encoder Handle +*/ +extern DllExport void dirac_encoder_end_sequence (dirac_encoder_t *encoder); + +/*! + Free resources held by encoder + \param encoder Encoder Handle +*/ +extern DllExport void dirac_encoder_close (dirac_encoder_t *encoder); + +#endif +#ifdef __cplusplus +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_picture.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_picture.cpp new file mode 100644 index 000000000..5ad01bbe3 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_picture.cpp @@ -0,0 +1,383 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: enc_picture.cpp,v 1.6 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2008.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#include <libdirac_encoder/enc_picture.h>
+#include <libdirac_common/upconvert.h>
+
+using namespace dirac;
+
+EncPicture::EncPicture( const PictureParams& pp):
+ Picture( pp ),
+ m_me_data( NULL ),
+ m_status( NO_ENC ),
+ m_complexity( 0.0 ),
+ m_norm_complexity( 1.0 ),
+ m_pred_bias(0.5)
+{
+ for (int c=0; c<3; ++c ){
+ m_orig_data[c] = new PicArray( m_pic_data[c]->LengthY(), m_pic_data[c]->LengthX() );
+ m_orig_up_data[c] = NULL;
+ m_filt_data[c] = NULL;
+ m_filt_up_data[c] = NULL;
+ }
+}
+
+void EncPicture::ClearData(){
+
+ Picture::ClearData();
+
+ for (int c=0;c<3;++c){
+ if (m_orig_data[c] != NULL){
+ delete m_orig_data[c];
+ m_orig_data[c] = NULL;
+ }
+
+ if (m_orig_up_data[c] != NULL){
+ delete m_orig_up_data[c];
+ m_orig_up_data[c] = NULL;
+ }
+
+ if (m_filt_data[c] != NULL){
+ delete m_filt_data[c];
+ m_filt_data[c] = NULL;
+ }
+
+ if (m_filt_up_data[c] != NULL){
+ delete m_filt_up_data[c];
+ m_filt_up_data[c] = NULL;
+ }
+ }
+
+ if ( m_me_data != NULL )
+ delete m_me_data;
+}
+
+EncPicture::~EncPicture()
+{
+ ClearData();
+}
+
+void EncPicture::SetOrigData()
+{
+ for ( int c=0; c<3 ; ++c )
+ SetOrigData(c);
+}
+
+void EncPicture::SetOrigData( const int c )
+{
+ if ( m_pic_data[c] != NULL )
+ *(m_orig_data[c]) = *(m_pic_data[c]);
+}
+
+void EncPicture::InitMEData( const PicturePredParams& predparams , const int num_refs)
+{
+ if (m_me_data != NULL)
+ delete m_me_data;
+
+ m_me_data=new MEData( predparams, num_refs );
+}
+
+const PicArray& EncPicture::DataForME( bool combined_me ) const{
+
+ if (combined_me)
+ return CombinedData();
+ else
+ return OrigData( Y_COMP );
+}
+
+const PicArray& EncPicture::UpDataForME( bool combined_me ) const{
+
+ if (combined_me)
+ return UpCombinedData();
+ else
+ return UpOrigData( Y_COMP );
+}
+
+
+const PicArray& EncPicture::UpOrigData(CompSort cs) const
+{
+ const int c = (int) cs;
+
+ if (m_orig_up_data[c] != NULL)
+ return *m_orig_up_data[c];
+ else
+ {//we have to do the upconversion
+
+ m_orig_up_data[c] = new PicArray( 2*m_orig_data[c]->LengthY(),
+ 2*m_orig_data[c]->LengthX() );
+ UpConverter* myupconv;
+ if (c>0)
+ myupconv = new UpConverter(-(1 << (m_pparams.ChromaDepth()-1)),
+ (1 << (m_pparams.ChromaDepth()-1))-1,
+ m_pparams.ChromaXl(), m_pparams.ChromaYl());
+ else
+ myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
+ (1 << (m_pparams.LumaDepth()-1))-1,
+ m_pparams.Xl(), m_pparams.Yl());
+
+ myupconv->DoUpConverter( *(m_orig_data[c]) , *(m_orig_up_data[c]) );
+
+ delete myupconv;
+
+ return *(m_orig_up_data[c]);
+
+ }
+}
+
+const PicArray& EncPicture::FiltData(CompSort cs) const
+{
+ const int c = (int) cs;
+
+ if (m_filt_data[c] != NULL)
+ return *m_filt_data[c];
+ else
+ {//we have to do the filtering
+
+ if (m_orig_data[c] != NULL )
+ m_filt_data[c] = new PicArray( m_orig_data[c]->LengthY(),
+ m_orig_data[c]->LengthX() );
+
+ AntiAliasFilter( *(m_filt_data[c]), *(m_orig_data[c]));
+
+ return *(m_filt_data[c]);
+
+ }
+}
+
+const PicArray& EncPicture::UpFiltData(CompSort cs) const
+{
+ const int c = (int) cs;
+
+ if (m_filt_up_data[c] != NULL)
+ return *m_filt_up_data[c];
+ else
+ {//we have to do the upconversion
+
+ const PicArray& filt_data = FiltData( cs );
+
+ m_filt_up_data[c] = new PicArray( 2*filt_data.LengthY(),
+ 2*filt_data.LengthX() );
+ UpConverter* myupconv;
+ if (c>0)
+ myupconv = new UpConverter(-(1 << (m_pparams.ChromaDepth()-1)),
+ (1 << (m_pparams.ChromaDepth()-1))-1,
+ m_pparams.ChromaXl(), m_pparams.ChromaYl());
+ else
+ myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
+ (1 << (m_pparams.LumaDepth()-1))-1,
+ m_pparams.Xl(), m_pparams.Yl());
+
+ myupconv->DoUpConverter( filt_data , *(m_filt_up_data[c]) );
+
+ delete myupconv;
+
+ return *(m_filt_up_data[c]);
+
+ }
+}
+
+void EncPicture::AntiAliasFilter( PicArray& out_data, const PicArray& in_data ) const{
+
+ //Special case for first row
+ for (int i = in_data.FirstX(); i <= in_data.LastX(); ++i)
+ {
+ out_data[in_data.FirstY()][i] = (3*in_data[in_data.FirstY()][i] +
+ in_data[in_data.FirstY()+1][i] +2 )>>2;
+ }
+ //Middle section
+ for (int j = in_data.FirstY()+1; j < in_data.LastY(); ++j)
+ {
+ for (int i = in_data.FirstX(); i <= in_data.LastX(); ++i)
+ {
+ out_data[j][i] = (in_data[j-1][i] + 2*in_data[j][i] + in_data[j+1][i] + 2)>>2;
+ }
+ }
+ //Special case for last row
+ for (int i = in_data.FirstX(); i <= in_data.LastX(); ++i)
+ {
+ out_data[in_data.LastY()][i] = (in_data[in_data.LastY()-1][i] +
+ 3*in_data[in_data.LastY()][i] + 2)>>2;
+ }
+}
+
+const PicArray& EncPicture::CombinedData() const
+{
+
+ if (m_filt_data[Y_COMP] != NULL)
+ return *m_filt_data[Y_COMP];
+ else
+ {//we have to do the combining
+
+ if (m_orig_data[Y_COMP] != NULL )
+ m_filt_data[Y_COMP] = new PicArray( m_orig_data[Y_COMP]->LengthY(),
+ m_orig_data[Y_COMP]->LengthX() );
+
+ Combine( *(m_filt_data[Y_COMP]), *(m_orig_data[Y_COMP]),
+ *(m_orig_data[U_COMP]), *(m_orig_data[V_COMP])
+ );
+
+ return *(m_filt_data[Y_COMP]);
+
+ }
+}
+
+const PicArray& EncPicture::UpCombinedData() const
+{
+ if (m_filt_up_data[Y_COMP] != NULL)
+ return *m_filt_up_data[Y_COMP];
+ else
+ {//we have to do the upconversion
+
+ const PicArray& filt_data = CombinedData();
+
+ m_filt_up_data[Y_COMP] = new PicArray( 2*filt_data.LengthY(),
+ 2*filt_data.LengthX() );
+ UpConverter* myupconv;
+ myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
+ (1 << (m_pparams.LumaDepth()-1))-1,
+ m_pparams.Xl(), m_pparams.Yl());
+
+ myupconv->DoUpConverter( filt_data , *(m_filt_up_data[Y_COMP]) );
+
+ delete myupconv;
+
+ return *(m_filt_up_data[Y_COMP]);
+
+ }
+}
+
+
+
+void EncPicture::Combine( PicArray& comb_data, const PicArray& y_data,
+ const PicArray& u_data, const PicArray& v_data ) const
+{
+ int hcr = y_data.LengthX()/u_data.LengthX();
+ int vcr = y_data.LengthY()/u_data.LengthY();
+
+ float val, valc, valy;
+
+ if (vcr==1){
+ for (int j=0; j<comb_data.LengthY(); ++j) {
+ if (hcr==1){// 444 format
+ for (int i=0; i<comb_data.LengthX(); ++i ){
+ val = float(u_data[j][i]);
+ val *= val;
+ valc = val;
+
+ val = float(v_data[j][i]);
+ val *= val;
+ valc += val;
+
+ valy = float(y_data[j][i]) + 128.0;
+ valy *= valy;
+ comb_data[j][i] = ValueType( std::sqrt(valc+valy)-128.0 );
+ }// i
+ }
+ else{ // 422 format
+ for (int i=0; i<comb_data.LengthX(); i+=2 ){
+
+ val = float(u_data[j][i>>1]);
+ val *= val;
+ valc = val;
+
+ val = float(v_data[j][i>>1]);
+ val *= val;
+ valc += val;
+
+ valy = float(y_data[j][i]) + 128.0;
+ valy *= valy;
+ comb_data[j][i] = ValueType( std::sqrt(valc+valy)-128.0 );
+
+ valy = float(y_data[j][i+1]) + 128.0;
+ valy *= valy;
+
+ comb_data[j][i+1] = ValueType( std::sqrt(valc+valy)-128.0 );
+
+ }// i
+ }
+ }// j
+ }
+ else{ // 420 format
+ for (int j=0; j<comb_data.LengthY(); j+=2 ) {
+
+ for (int i=0; i<comb_data.LengthX(); i+=2 ){
+
+ val = float(u_data[j>>1][i>>1]);
+ val *= val;
+ valc = val;
+
+ val = float(v_data[j>>1][i>>1]);
+ val *= val;
+ valc += val;
+
+ valy = float(y_data[j][i]) + 128.0;
+ valy *= valy;
+ comb_data[j][i] = ValueType( std::sqrt(valc+valy)-128.0 );
+
+ valy = float(y_data[j][i+1]) + 128.0;
+ valy *= valy;
+ comb_data[j][i+1] = ValueType( std::sqrt(valc+valy)-128.0 );
+
+ valy = float(y_data[j+1][i]) + 128.0;
+ valy *= valy;
+ comb_data[j+1][i] = ValueType( std::sqrt(valc+valy)-128.0 );
+
+ valy = float(y_data[j+1][i+1]) + 128.0;
+ valy *= valy;
+ comb_data[j+1][i+1] = ValueType( std::sqrt(valc+valy)-128.0 );
+
+ }// i
+ }// j
+
+ }
+
+
+}
+
+
+void EncPicture::DropRef( int rindex ){
+
+ std::vector<int>& refs = m_pparams.Refs();
+
+ if (rindex==1 || rindex==2 )
+ refs.erase( refs.begin()+rindex-1 );
+
+ // Now reconfigure the motion data
+ if ( m_me_data!=NULL )
+ m_me_data->DropRef( rindex );
+
+}
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_picture.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_picture.h new file mode 100644 index 000000000..cbef4f5ce --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_picture.h @@ -0,0 +1,163 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: enc_picture.h,v 1.6 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2008.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef _ENC_PICTURE_H_
+#define _ENC_PICTURE_H_
+
+#include <libdirac_common/picture.h>
+#include <libdirac_common/motion.h>
+
+
+namespace dirac
+{
+static const unsigned int DONE_ME_INIT = 0x1;
+static const unsigned int DONE_PEL_ME = 0x2;
+static const unsigned int DONE_SUBPEL_ME = 0x4;
+static const unsigned int DONE_ME_MODE_DECN = 0x8;
+static const unsigned int DONE_MV_CODING = 0x10;
+static const unsigned int DONE_MC = 0x20;
+static const unsigned int DONE_DWT = 0x40;
+static const unsigned int DONE_QUANT_SEL = 0x80;
+static const unsigned int DONE_RES_CODING = 0x100;
+static const unsigned int DONE_IDWT = 0x200;
+static const unsigned int DONE_MC_BACK = 0x400;
+static const unsigned int DONE_SET_PTYPE = 0x800;
+static const unsigned int DONE_PIC_COMPLEXITY = 0x1000;
+
+static const unsigned int ALL_ENC = 0xFFFFFFFF;
+static const unsigned int NO_ENC = 0;
+
+class EncPicture : public Picture
+{
+public:
+ EncPicture( const PictureParams& pp );
+
+ virtual ~EncPicture();
+
+ //! Initialise the motion estimation data arrays
+ void InitMEData( const PicturePredParams& predparams, const int num_refs);
+
+ //! Returns the motion data
+ MEData& GetMEData(){ return *m_me_data;}
+
+ //! Returns the motion data
+ const MEData& GetMEData() const { return *m_me_data;}
+
+ //! Drops a reference from the motion vector data
+ void DropRef( int rindex );
+
+
+ //! Returns a given component of the original data
+ const PicArray& OrigData(CompSort c) const { return *m_orig_data[(int) c];}
+
+ //! Returns a given upconverted component of the original data
+ const PicArray& UpOrigData(CompSort cs) const;
+
+ //! Initialises a copy of the data arrays into the original data
+ void SetOrigData();
+
+ //! Returns a version of the picture data suitable for motion estimation
+ const PicArray& DataForME(bool combined_me) const;
+
+ //! Returns a version of the picture data suitable for subpel motion estimation
+ const PicArray& UpDataForME(bool combined_me) const;
+
+
+ void UpdateStatus( const unsigned int mask ){ m_status |= mask; }
+
+ void FlipStatus( const unsigned int mask){ m_status ^= mask; }
+
+ void SetStatus( const int status ){ m_status = status; }
+
+ unsigned int GetStatus() const{ return m_status; }
+
+
+ double GetComplexity() const {return m_complexity; }
+
+ void SetComplexity(double c){ m_complexity = c; }
+
+ double GetNormComplexity() const { return m_norm_complexity; }
+
+ void SetNormComplexity( double c ){ m_norm_complexity = c; }
+
+ double GetPredBias() const { return m_pred_bias; }
+
+ void SetPredBias( double b ){ m_pred_bias = b; }
+
+
+private:
+
+ virtual void ClearData();
+
+ //! Filters a (field) picture vertically to reduce aliasing for motion estimation purposes
+ void AntiAliasFilter( PicArray& out_data, const PicArray& in_data ) const;
+
+ //! Returns an anti-aliased version of the original data
+ const PicArray& FiltData(CompSort c) const;
+
+ const PicArray& CombinedData() const;
+ const PicArray& UpCombinedData() const;
+ void Combine( PicArray& comb_data, const PicArray& y_data,
+ const PicArray& u_data, const PicArray& v_data ) const;
+
+ //! Returns an upconverted anti-aliased version of the original data
+ const PicArray& UpFiltData(CompSort c) const;
+
+
+ void SetOrigData(const int c);
+
+private:
+
+ PicArray* m_orig_data[3];
+ mutable PicArray* m_orig_up_data[3];
+ mutable PicArray* m_filt_data[3];
+ mutable PicArray* m_filt_up_data[3];
+
+ MEData* m_me_data;
+
+ unsigned int m_status;
+
+ double m_complexity;
+ double m_norm_complexity;
+
+ double m_pred_bias;
+};
+
+
+}
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_queue.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_queue.cpp new file mode 100644 index 000000000..f64da8a0b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_queue.cpp @@ -0,0 +1,292 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: enc_queue.cpp,v 1.3 2008/08/14 01:58:39 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2008.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#include <libdirac_encoder/enc_queue.h>
+#include <algorithm>
+using namespace dirac;
+
+//Simple constructor for decoder operation
+EncQueue::EncQueue(){}
+
+//Copy constructor. Why anyone would need this I don't know.
+EncQueue::EncQueue(const EncQueue& cpy)
+ {
+ // first delete all frames in the current buffer
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ delete m_pic_data[i];
+ }//i
+
+ // next create new arrays, copying from the initialising buffer
+ m_pic_data.resize(cpy.m_pic_data.size());
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i){
+ m_pic_data[i] = new EncPicture( *(cpy.m_pic_data[i]) );
+ }//i
+
+ // now copy the map
+ m_pnum_map = cpy.m_pnum_map;
+
+}
+
+//Assignment=. Not sure why this would be used either.
+EncQueue& EncQueue::operator=(const EncQueue& rhs){
+ if (&rhs!=this)
+ {
+ // delete all the frames in the lhs buffer
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ delete m_pic_data[i];
+ }//i
+
+ // next create new arrays, copying from the rhs
+ m_pic_data.resize(rhs.m_pic_data.size());
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ m_pic_data[i] = new EncPicture( *(rhs.m_pic_data[i]) );
+ }//i
+
+ // now copy the map
+ m_pnum_map = rhs.m_pnum_map;
+
+ }
+ return *this;
+}
+
+//Destructor
+EncQueue::~EncQueue()
+{
+ for (size_t i=0 ; i<m_pic_data.size() ;++i)
+ delete m_pic_data[i];
+}
+
+EncPicture& EncQueue::GetPicture( const unsigned int pnum )
+{//get picture with a given picture number, NOT with a given position in the buffer.
+ //If the picture number does not occur, the first picture in the buffer is returned.
+
+ std::map<unsigned int,unsigned int>::iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos = 0;
+ if (it != m_pnum_map.end())
+ pos = it->second;
+
+ return *(m_pic_data[pos]);
+}
+
+const EncPicture& EncQueue::GetPicture( const unsigned int pnum ) const
+{ //as above, but const version
+
+ std::map<unsigned int,unsigned int>::const_iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos=0;
+ if (it != m_pnum_map.end())
+ pos = it->second;
+
+ return *(m_pic_data[pos]);
+}
+
+EncPicture& EncQueue::GetPicture( const unsigned int pnum, bool& is_present )
+{//get picture with a given picture number, NOT with a given position in the buffer.
+ //If the picture number does not occur, the first picture in the buffer is returned.
+
+ std::map<unsigned int,unsigned int>::iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos = 0;
+ if (it != m_pnum_map.end())
+ {
+ is_present = true;
+ pos = it->second;
+ }
+ else
+ is_present=false;
+
+ return *(m_pic_data[pos]);
+}
+
+const EncPicture& EncQueue::GetPicture( const unsigned int pnum, bool& is_present ) const
+{ //as above, but const version
+
+ std::map<unsigned int,unsigned int>::const_iterator it = m_pnum_map.find(pnum);
+
+ unsigned int pos=0;
+ if (it != m_pnum_map.end())
+ {
+ is_present = true;
+ pos = it->second;
+ }
+ else
+ is_present=false;
+
+ return *(m_pic_data[pos]);
+}
+
+bool EncQueue::IsPictureAvail( const unsigned int pnum ) const
+{
+
+ std::map<unsigned int,unsigned int>::const_iterator it = m_pnum_map.find(pnum);
+
+ if (it != m_pnum_map.end())
+ return true;
+ else
+ return false;
+}
+
+std::vector<int> EncQueue::Members() const
+{
+ std::vector<int> members( 0 );
+ for (unsigned int i=0; i<m_pic_data.size(); ++i )
+ {
+ const PictureParams& pparams = m_pic_data[i]->GetPparams();
+ members.push_back( pparams.PictureNum() );
+ }// i
+
+ return members;
+}
+
+void EncQueue::PushPicture( const PictureParams& pp )
+{// Put a new picture onto the top of the stack
+
+ // if picture is present - return
+ if (IsPictureAvail(pp.PictureNum()))
+ return;
+
+// if ( pp.PicSort().IsRef() )
+// m_ref_count++;
+
+ EncPicture* pptr = new EncPicture(pp);
+ // add the picture to the buffer
+ m_pic_data.push_back(pptr);
+
+ // put the picture number into the index table
+ std::pair<unsigned int,unsigned int> temp_pair(pp.PictureNum() , m_pic_data.size()-1);
+ m_pnum_map.insert(temp_pair);
+}
+
+void EncQueue::CopyPicture( const EncPicture& picture )
+{
+ PushPicture(picture.GetPparams());
+
+ bool is_present;
+
+ EncPicture & p= GetPicture(picture.GetPparams().PictureNum(), is_present);
+ if(is_present)
+ p = picture;
+}
+
+void EncQueue::ClearSlot(const unsigned int pos)
+{
+ // Clear a slot corresponding to position pos to take more data
+
+ std::pair<unsigned int,unsigned int>* tmp_pair;
+
+ if (pos<m_pic_data.size())
+ {
+ delete m_pic_data[pos];
+
+ m_pic_data.erase(m_pic_data.begin() + pos);
+
+ //make a new map
+ m_pnum_map.clear();
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ tmp_pair = new std::pair<unsigned int,unsigned int>( m_pic_data[i]->GetPparams().PictureNum() , i);
+ m_pnum_map.insert(*tmp_pair);
+ delete tmp_pair;
+ }//i
+ }
+}
+
+
+void EncQueue::SetRetiredPictureNum(const int show_pnum, const int current_coded_pnum)
+{
+
+ if ( IsPictureAvail(current_coded_pnum))
+ {
+ PictureParams &pparams = GetPicture(current_coded_pnum).GetPparams();
+ pparams.SetRetiredPictureNum(-1);
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ if (m_pic_data[i]->GetPparams().PicSort().IsRef() )
+ {
+ if ( (m_pic_data[i]->GetPparams().PictureNum() + m_pic_data[i]->GetPparams().ExpiryTime() ) <= show_pnum)
+ {
+ pparams.SetRetiredPictureNum(m_pic_data[i]->GetPparams().PictureNum());
+ break;
+ }
+ }
+ }//i
+ }
+}
+
+void EncQueue::CleanAll(const int show_pnum, const int current_coded_pnum)
+{// clean out all frames that have expired
+ if (IsPictureAvail(current_coded_pnum))
+ {
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i)
+ {
+ if ( (m_pic_data[i]->GetPparams().PictureNum() + m_pic_data[i]->GetPparams().ExpiryTime() ) <= show_pnum)
+ ClearSlot(i);
+ }//i
+ }
+}
+
+void EncQueue::CleanRetired(const int show_pnum, const int current_coded_pnum)
+{// clean out all frames that have expired
+ if ( IsPictureAvail(current_coded_pnum) )
+ {
+ PictureParams &pparams = GetPicture(current_coded_pnum).GetPparams();
+ // Remove Reference picture specified in retired picture number.
+ if (pparams.PicSort().IsRef() && pparams.RetiredPictureNum()>= 0)
+ Remove(pparams.RetiredPictureNum());
+ pparams.SetRetiredPictureNum(-1);
+ // Remove non-reference frames that have expired
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i){
+ if ( (m_pic_data[i]->GetPparams().PictureNum()+
+ m_pic_data[i]->GetPparams().ExpiryTime() )<=show_pnum
+ && m_pic_data[i]->GetPparams().PicSort().IsNonRef() )
+ ClearSlot(i);
+ }//i
+ }
+}
+
+void EncQueue::Remove(const int pnum)
+{
+ for (size_t i=0 ; i<m_pic_data.size() ; ++i){
+ if ( m_pic_data[i]->GetPparams().PictureNum() == pnum)
+ ClearSlot(i);
+ }//i
+}
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_queue.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_queue.h new file mode 100644 index 000000000..2d282ebce --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/enc_queue.h @@ -0,0 +1,222 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: enc_queue.h,v 1.3 2008/08/14 02:30:50 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Anuradha Suraparaju
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#ifndef _ENC_QUEUE_H_
+#define _ENC_QUEUE_H_
+
+#include <vector>
+#include <map>
+#include <libdirac_encoder/enc_picture.h>
+#include <libdirac_common/common.h>
+
+namespace dirac
+{
+ //! Holds pictures both for reference and to overcome reordering delay
+ /*!
+ The buffer holds pictures in a stack to overcome both reordering due to
+ bi-directional prediction and use as references for subsequence motion
+ estimation. Pictures, and components of pictures, can be accessed by their
+ picture numbers. GOP parameters can be included in the constructors so
+ that pictures can be given types (I picture, L1 picture or L2 picture) on
+ being pushed onto the stack; alternatively, these parameters can be
+ overridden.
+ */
+ class EncQueue{
+ public:
+ //! Default Constructor
+ EncQueue();
+
+ //! Constructor
+ /*!
+ Creates a EncQueue using the chroma format. Suitable for
+ compressing when there are no L2 pictures, or when the temporal
+ prediction structure is to be determined on the fly.
+
+ \param cf the Chroma format of pictures in the buffer
+ \param xlen the luma width of pictures in the buffer
+ \param ylen the luma height of pictures in the buffer
+ \param luma_depth the video depth of the luma comp in the buffer
+ \param chroma_depth the video depth of the chroma comp in the buffer
+ \param using_ac True if using Arithmetic coding to code coefficient data
+
+ */
+ EncQueue(ChromaFormat cf,
+ const int xlen,
+ const int ylen,
+ const unsigned int luma_depth,
+ const unsigned int chroma_depth,
+ bool using_ac);
+
+ //! Constructor
+ /*!
+ Creates a EncQueue using the chroma format, the number of L1
+ pictures between I pictures and the separation in pictures between L1
+ pictures. Suitable for compressing when there is a full GOP structure
+ or when the temporal prediction structure is to be determined on
+ the fly.
+
+ \param cf the Chroma format of pictures in the buffer
+ \param numL1 the number of Layer 1 pictures before the next I picture. 0 means that there is only one I picture.
+ \param L1sep the number of Layer 2 pictures between Layer 1 pictures
+ \param xlen the luma width of pictures in the buffer
+ \param ylen the luma height of pictures in the buffer
+ \param luma_depth the video depth of the luma comp in the buffer
+ \param chroma_depth the video depth of the chroma comp in the buffer
+ \param interlace Set true if material is being coded in interlaced mode
+ \param using_ac True if using Arithmetic coding to code coefficient data
+ */
+ EncQueue(ChromaFormat cf,
+ const int numL1,
+ const int L1sep,
+ const int xlen,
+ const int ylen,
+ const unsigned int luma_depth,
+ const unsigned int chroma_depth,
+ bool interlace,
+ bool using_ac);
+
+ //! Copy constructor
+ /*!
+ Copy constructor. Removes the current contents of the pictureture buffer
+ and copies in the contents of the initialising buffer.
+ */
+ EncQueue(const EncQueue& cpy);
+
+ //! Operator=.
+ /*!
+ Operator=. Assigns all elements of the rhs to the lhs.
+ */
+ EncQueue& operator=(const EncQueue& rhs);
+
+ //! Destructor
+ ~EncQueue();
+
+ //! Get picture with a given picture number (NOT with a given position in the buffer)
+ EncPicture& GetPicture(const unsigned int pnum );
+
+ //! Get picture with a given picture number (NOT with a given position in the buffer)
+ const EncPicture& GetPicture(const unsigned int pnum) const;
+
+ //! Get picture with a given picture number, setting a flag to true if it's there
+ EncPicture& GetPicture(const unsigned int pnum, bool& is_present);
+
+ //! Get picture with a given picture number, setting a flag to true if it's there
+ const EncPicture& GetPicture(const unsigned int pnum, bool& is_present) const;
+
+ //! Return true if picture with the particular picture number is available else return false
+ bool IsPictureAvail(const unsigned int pnum) const;
+
+ //! Returns a list of member pictures
+ std::vector<int> Members() const;
+
+ //! Returns the size of the queue
+ int Size() const { return m_pic_data.size(); }
+
+ //! Put a new picture into the top of the buffer
+ /*!
+ Put a new picture into the top of the buffer. EncPicture parameters
+ associated with the picture will be as given by the picture parameter
+ object.
+ */
+ void PushPicture(const PictureParams& pp);
+
+ //! Put a copy of a new picture into the buffer
+ /*!
+ Put a copy of a new picture into the buffer.
+ */
+ void CopyPicture( const EncPicture& picture );
+
+ //! Sets the reference picture number that will be cleaned
+ /*!
+ Indicate which picture which has been output and which is no longer
+ required for reference. Expiry times are set in each picture's
+ picture parameters.
+ \param show_pnum picture number in display order that can be output
+ \param current_coded_pnum picture number in display order of picture currently being coded
+ */
+ void SetRetiredPictureNum(const int show_pnum, const int current_coded_pnum);
+
+ //! Delete all expired pictures
+ /*!
+ Delete pictures which have been output and which are no longer
+ required for reference. Expiry times are set in each picture's
+ picture parameters.
+ \param show_pnum picture number in display order that can be output
+ \param current_coded_pnum picture number in display order of picture currently being coded
+ */
+ void CleanAll(const int show_pnum, const int current_coded_pnum);
+
+ //! Delete retired reference pictures and expired non-ref pictures
+ /*!
+ Delete pictures which have been output and retired reference pictures.
+ Expiry times are set in each picture's picture parameters.
+ \param show_pnum picture number in display order that can be output
+ \param current_coded_pnum picture number in display order of picture currently being coded
+ */
+ void CleanRetired(const int show_pnum, const int current_coded_pnum);
+
+ //! Delete picture
+ /*!
+ Delete picture.
+ \param pnum picture number in display order to be deleted from picture buffer
+ */
+ void Remove(int pnum);
+
+ private:
+ //! Clear internal data slot number pos
+ /*!
+ Clear internal data slot number pos
+ */
+ void ClearSlot(const unsigned int pos);
+
+ private:
+
+// //! the count of the number of reference pictures in the buffer
+// int m_ref_count;
+
+ //! the buffer storing all the values
+ std::vector<EncPicture*> m_pic_data;
+
+ //!the map from picture numbers to position in the buffer
+ std::map<unsigned int,unsigned int> m_pnum_map;
+
+ };
+
+} // namespace dirac
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/picture_compress.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/picture_compress.cpp new file mode 100644 index 000000000..93c6be9b4 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/picture_compress.cpp @@ -0,0 +1,710 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_compress.cpp,v 1.28 2009/01/21 05:20:57 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Scott R Ladd,
+* Chris Bowley,
+* Anuradha Suraparaju,
+* Tim Borer,
+* Andrew Kennedy
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+//Compression of pictures//
+/////////////////////////
+
+#include <libdirac_encoder/picture_compress.h>
+#include <libdirac_encoder/comp_compress.h>
+#include <libdirac_encoder/prefilter.h>
+#include <libdirac_common/mot_comp.h>
+#include <libdirac_motionest/pixel_match.h>
+#include <libdirac_motionest/me_subpel.h>
+#include <libdirac_motionest/me_mode_decn.h>
+#include <libdirac_common/mv_codec.h>
+#include <libdirac_encoder/quant_chooser.h>
+#include <libdirac_common/dirac_assertions.h>
+using namespace dirac;
+
+#include <iostream>
+#include <sstream>
+
+PictureCompressor::PictureCompressor( EncoderParams& encp ) :
+ m_encparams(encp),
+ m_skipped(false),
+ m_use_global(false),
+ m_use_block_mv(true),
+ m_global_pred_mode(REF1_ONLY),
+ m_me_data(NULL),
+ m_medata_avail(false),
+ m_is_a_cut(false)
+{}
+
+PictureCompressor::~PictureCompressor()
+{}
+
+
+void PictureCompressor::PixelME( EncQueue& my_buffer , int pnum )
+{
+ PixelMatcher pix_match( m_encparams );
+ pix_match.DoSearch( my_buffer , pnum );
+}
+
+void PictureCompressor::CalcComplexity( EncQueue& my_buffer, int pnum , const OLBParams& olbparams )
+{
+ EncPicture& my_picture = my_buffer.GetPicture( pnum );
+ PictureParams& pparams = my_picture.GetPparams();
+
+ if ( (my_picture.GetStatus()&DONE_PEL_ME) != 0 ){
+ MEData& me_data = my_picture.GetMEData();
+
+ TwoDArray<MvCostData>* pcosts1;
+ TwoDArray<MvCostData>* pcosts2;
+
+ pcosts1 = &me_data.PredCosts(1);
+ if (pparams.NumRefs()>1)
+ pcosts2 = &me_data.PredCosts(2);
+ else
+ pcosts2 = pcosts1;
+
+ float cost1, cost2, cost;
+ double total_cost1 = 0.0;
+ double total_cost2 = 0.0;
+ double total_cost = 0.0;
+
+ int count1=0;int count=0;
+
+ float cost_threshold = float(olbparams.Xblen()*olbparams.Yblen()*10);
+
+ for (int j=4; j<pcosts1->LengthY()-4; ++j){
+ for (int i=4; i<pcosts1->LengthX()-4; ++i){
+ cost1 = (*pcosts1)[j][i].SAD;
+ cost2 = (*pcosts2)[j][i].SAD;
+ cost = std::min(cost1, cost2);
+ total_cost1 += cost1;
+ total_cost2 += cost2;
+ total_cost += cost;
+ if (pparams.NumRefs()>1 && cost<=cost_threshold){
+ ++count;
+ if (cost1<=cost2)
+ ++count1;
+ }
+ }
+
+ }
+ total_cost1 *= olbparams.Xbsep()*olbparams.Ybsep();
+ total_cost1 /= olbparams.Xblen()*olbparams.Yblen();
+
+ total_cost2 *= olbparams.Xbsep()*olbparams.Ybsep();
+ total_cost2 /= olbparams.Xblen()*olbparams.Yblen();
+
+ if (pparams.NumRefs()>1){
+ my_picture.SetPredBias(float(count1)/float(count));
+ }
+ else
+ my_picture.SetPredBias(0.5);
+
+ total_cost *= olbparams.Xbsep()*olbparams.Ybsep();
+ total_cost /= olbparams.Xblen()*olbparams.Yblen();
+
+// my_picture.SetComplexity( total_cost );
+ my_picture.SetComplexity( total_cost*total_cost );
+
+ }
+
+}
+
+void PictureCompressor::CalcComplexity2( EncQueue& my_buffer, int pnum )
+{
+ // to be used after doing motion compensation
+ EncPicture& my_picture = my_buffer.GetPicture( pnum );
+ const PicArray& pic_data = my_picture.Data( Y_COMP );
+
+ if ( (my_picture.GetStatus()&DONE_MC) != 0 ){
+
+ float cost;
+ double total_sq_cost = 0.0;
+ double total_cost = 0.0;
+
+ for (int j=0; j<pic_data.LengthY(); ++j){
+ for (int i=0; i<pic_data.LengthX(); ++i){
+ cost = float( pic_data[j][i] );
+ total_cost += cost;
+ total_sq_cost += cost*cost;
+ }
+
+ }
+
+ total_cost /= ( pic_data.LengthX()*pic_data.LengthY() );
+ total_sq_cost /= ( pic_data.LengthX()*pic_data.LengthY() );
+
+ my_picture.SetComplexity( total_sq_cost - total_cost*total_cost );
+
+ }
+
+}
+
+
+
+void PictureCompressor::NormaliseComplexity( EncQueue& my_buffer, int pnum )
+{
+ EncPicture& my_picture = my_buffer.GetPicture( pnum );
+
+ if ( (my_picture.GetStatus()&DONE_PIC_COMPLEXITY) != 0 ){
+
+ std::vector<int> queue_members = my_buffer.Members();
+
+ double mean_complexity = 0.0;
+ int count = 0;
+ for (size_t i=0; i<queue_members.size(); ++ i){
+ int n = queue_members[i];
+ EncPicture& enc_pic = my_buffer.GetPicture( n );
+
+ if ( (enc_pic.GetStatus()&DONE_PIC_COMPLEXITY) != 0
+ && enc_pic.GetPparams().PicSort().IsInter()
+ && n >= pnum - 10
+ && n <= pnum + 10){
+ mean_complexity += enc_pic.GetComplexity();
+ count++;
+ }
+
+ }
+ mean_complexity /= count;
+ my_picture.SetNormComplexity( my_picture.GetComplexity() / mean_complexity );
+
+ }
+
+}
+
+void PictureCompressor::SubPixelME( EncQueue& my_buffer , int pnum )
+{
+ const std::vector<int>& refs = my_buffer.GetPicture(pnum).GetPparams().Refs();
+ const int num_refs = refs.size();
+
+ PictureParams& pparams = my_buffer.GetPicture(pnum).GetPparams();
+ MEData& me_data = my_buffer.GetPicture(pnum).GetMEData();
+ PicturePredParams& predparams = me_data.GetPicPredParams();
+
+ float lambda;
+ if ( pparams.IsBPicture())
+ lambda = m_encparams.L2MELambda();
+ else
+ lambda = m_encparams.L1MELambda();
+
+//lambda *= my_buffer.GetPicture(pnum).GetNormComplexity();
+
+ // Set up the lambda to be used
+ me_data.SetLambdaMap( num_refs , lambda );
+
+ m_orig_prec = predparams.MVPrecision();
+
+ // Step 2.
+ // Pixel accurate vectors are then refined to sub-pixel accuracy
+
+ if (m_orig_prec != MV_PRECISION_PIXEL)
+ {
+ SubpelRefine pelrefine( m_encparams );
+ pelrefine.DoSubpel( my_buffer , pnum );
+ }
+ else
+ {
+ // FIXME: HACK HACK
+ // Mutiplying the motion vectors by 2 and setting MV precision to
+ // HALF_PIXEL to implement pixel accurate motion estimate
+ MvArray &mv_arr1 = me_data.Vectors(1);
+ for (int j = 0; j < mv_arr1.LengthY(); ++j)
+ {
+ for (int i = 0; i < mv_arr1.LengthX(); ++i)
+ mv_arr1[j][i] = mv_arr1[j][i] << 1;
+ }
+ if (num_refs > 1)
+ {
+ MvArray &mv_arr2 = me_data.Vectors(2);
+ for (int j = 0; j < mv_arr2.LengthY(); ++j)
+ {
+ for (int i = 0; i < mv_arr2.LengthX(); ++i)
+ mv_arr2[j][i] = mv_arr2[j][i] << 1;
+ }
+ }
+ predparams.SetMVPrecision(MV_PRECISION_HALF_PIXEL);
+ }
+
+}
+
+void PictureCompressor::ModeDecisionME( EncQueue& my_buffer, int pnum )
+{
+ MEData& me_data = my_buffer.GetPicture(pnum).GetMEData();
+ PictureParams& pparams = my_buffer.GetPicture(pnum).GetPparams();
+ PicturePredParams& predparams = me_data.GetPicPredParams();
+
+ ModeDecider my_mode_dec( m_encparams );
+ my_mode_dec.DoModeDecn( my_buffer , pnum );
+
+ const int num_refs = pparams.NumRefs();
+
+ if (m_orig_prec == MV_PRECISION_PIXEL)
+ {
+ // FIXME: HACK HACK
+ // Divide the motion vectors by 2 to convert back to pixel
+ // accurate motion vectors and reset MV precision to
+ // PIXEL accuracy
+ MvArray &mv_arr1 = me_data.Vectors(1);
+ for (int j = 0; j < mv_arr1.LengthY(); ++j)
+ {
+ for (int i = 0; i < mv_arr1.LengthX(); ++i)
+ mv_arr1[j][i] = mv_arr1[j][i] >> 1;
+ }
+ if (num_refs > 1)
+ {
+ MvArray &mv_arr2 = me_data.Vectors(2);
+ for (int j = 0; j < mv_arr2.LengthY(); ++j)
+ {
+ for (int i = 0; i < mv_arr2.LengthX(); ++i)
+ mv_arr2[j][i] = mv_arr2[j][i]>>1;
+ }
+ }
+ predparams.SetMVPrecision(MV_PRECISION_PIXEL);
+ }
+
+}
+
+void PictureCompressor::IntraModeAnalyse( EncQueue& my_buffer, int pnum )
+{
+ MEData& me_data = my_buffer.GetPicture(pnum).GetMEData();
+
+ // Count the number of intra blocks
+ const TwoDArray<PredMode>& modes = me_data.Mode();
+
+ int count_intra = 0;
+ for ( int j=0 ; j<modes.LengthY() ; ++j )
+ {
+ for ( int i=0 ; i<modes.LengthX() ; ++i )
+ {
+ if ( modes[j][i] == INTRA )
+ count_intra++;
+ }
+ }// j
+
+ me_data.SetIntraBlockRatio(static_cast<double>( count_intra ) /
+ static_cast<double>( modes.LengthX() * modes.LengthY() ) );
+
+}
+
+void PictureCompressor::MotionCompensate( EncQueue& my_buffer, int pnum,
+ AddOrSub dirn )
+{
+ EncPicture* my_pic = &my_buffer.GetPicture(pnum);
+ std::vector<int>& my_refs = my_pic->GetPparams().Refs();
+ Picture* ref_pics[2];
+
+ ref_pics[0]=&my_buffer.GetPicture(my_refs[0]);
+ if (my_refs.size()>1)
+ ref_pics[1]=&my_buffer.GetPicture(my_refs[1]);
+ else
+ ref_pics[1]=&my_buffer.GetPicture(my_refs[0]);
+
+ PicturePredParams& predparams = my_pic->GetMEData().GetPicPredParams();
+ MotionCompensator::CompensatePicture( predparams , dirn ,
+ my_pic->GetMEData() , my_pic, ref_pics );
+}
+
+void PictureCompressor::Prefilter( EncQueue& my_buffer, int pnum )
+{
+ Picture& my_picture = my_buffer.GetPicture( pnum );
+
+ for (int c=0; c<3; ++c ){
+ if ( m_encparams.Prefilter() == RECTLP )
+ LPFilter( my_picture.Data( (CompSort) c) , m_encparams.Qf(),
+ m_encparams.PrefilterStrength() );
+
+ if ( m_encparams.Prefilter() == DIAGLP )
+// DiagFilter( my_picture.Data( (CompSort) c), 3.0, 5 );
+ DiagFilter( my_picture.Data( (CompSort) c) , m_encparams.Qf(),
+ m_encparams.PrefilterStrength() );
+ }
+
+}
+
+void PictureCompressor::DoDWT( EncQueue& my_buffer , int pnum, Direction dirn )
+{
+ Picture& my_picture = my_buffer.GetPicture( pnum );
+ PictureParams& pparams = my_picture.GetPparams();
+ const PictureSort& psort = pparams.PicSort();
+
+ // Set the wavelet filter
+ if ( psort.IsIntra() ){
+ m_encparams.SetTransformFilter( m_encparams.IntraTransformFilter() );
+ m_encparams.SetUsualCodeBlocks( INTRA_PICTURE );
+ }
+ else{
+ m_encparams.SetTransformFilter( m_encparams.InterTransformFilter() );
+ m_encparams.SetUsualCodeBlocks( INTER_PICTURE );
+ }
+
+ const int depth=m_encparams.TransformDepth();
+ const WltFilter filter = m_encparams.TransformFilter();
+ WaveletTransform wtransform( depth, filter );
+
+ if ( dirn==FORWARD )
+ my_picture.InitWltData( depth );
+
+ for (int c=0; c<3; ++c){
+
+ PicArray& comp_data = my_buffer.GetPicture( pnum ).Data((CompSort) c );
+ CoeffArray& coeff_data = my_buffer.GetPicture( pnum ).WltData((CompSort) c );
+
+ wtransform.Transform( dirn , comp_data, coeff_data );
+
+ }
+
+}
+
+void PictureCompressor::CodeResidue( EncQueue& my_buffer ,
+ int pnum, PictureByteIO* p_picture_byteio )
+{
+ EncPicture& my_picture = my_buffer.GetPicture( pnum );
+
+ PictureParams& pparams = my_picture.GetPparams();
+
+ if ( !m_skipped ){
+ // If not skipped we continue with the coding ...
+ if (m_encparams.Verbose() )
+ std::cout<<std::endl<<"Using QF: "<<m_encparams.Qf();
+
+ //Write Transform Header
+ TransformByteIO *p_transform_byteio = new TransformByteIO(pparams,
+ static_cast<CodecParams&>(m_encparams));
+ p_picture_byteio->SetTransformData(p_transform_byteio);
+ p_transform_byteio->Output();
+
+ /* Code component data */
+ /////////////////////////
+
+ CompCompressor my_compcoder(m_encparams , pparams );
+
+ const int depth=m_encparams.TransformDepth();
+
+ PicArray* comp_data[3];
+ CoeffArray* coeff_data[3];
+ OneDArray<unsigned int>* est_bits[3];
+ float lambda[3];
+
+ // Construction and definition of objects
+ for (int c=0;c<3;++c){
+ comp_data[c] = &my_picture.Data((CompSort) c );
+ coeff_data[c] = &my_picture.WltData((CompSort) c );
+ est_bits[c] = new OneDArray<unsigned int>( Range( 1, 3*depth+1 ) );
+ }// c
+
+ /* Do the wavelet transforms and select the component
+ * quantisers using perceptual weighting
+ */
+ double cpd_scale;
+ if (pparams.PicSort().IsIntra() ){
+ cpd_scale = 1.0;
+ }
+ else{
+ float intra_ratio = my_picture.GetMEData().IntraBlockRatio();
+
+ cpd_scale = 5.0*intra_ratio*1.0 + (1.0-5.0*intra_ratio)*0.125;
+ cpd_scale = std::max( 0.125, std::min( 1.2, cpd_scale ) );
+ }
+ for (int c=0; c<3; ++c){
+ lambda[c] = GetCompLambda( my_picture, (CompSort) c );
+
+ coeff_data[c]->SetBandWeights( m_encparams , pparams, (CompSort) c, cpd_scale);
+
+ SubbandList& bands = coeff_data[c]->BandList();
+ SetupCodeBlocks( bands );
+ SelectQuantisers( *(coeff_data[c]) , bands , lambda[c],
+ *est_bits[c] , m_encparams.GetCodeBlockMode(), pparams, (CompSort) c );
+
+ p_transform_byteio->AddComponent( my_compcoder.Compress(
+ *(coeff_data[c]), bands, (CompSort) c, *est_bits[c] ) );
+ }
+
+ // Destruction of objects
+ for (int c=0; c<3; ++c)
+ delete est_bits[c];
+
+ }//?m_skipped
+
+}
+
+void PictureCompressor::CodeMVData(EncQueue& my_buffer, int pnum, PictureByteIO* pic_byteio)
+{
+
+ // Code the MV data
+
+ EncPicture& my_picture = my_buffer.GetPicture(pnum);
+ PictureParams& pparams = my_picture.GetPparams();
+ MvData& mv_data = static_cast<MvData&> (my_picture.GetMEData());
+
+ // If we're using global motion parameters, code them
+ if (m_use_global){
+ /*
+ Code the global motion parameters
+ TBC ....
+ */
+ }
+
+ // If we're using block motion vectors, code them
+ if ( m_use_block_mv ){
+ MvDataByteIO *mv_byteio = new MvDataByteIO(pparams, mv_data.GetPicPredParams());
+ pic_byteio->SetMvData(mv_byteio);
+
+ SplitModeCodec smode_coder( mv_byteio->SplitModeData()->DataBlock(), TOTAL_MV_CTXS);
+ smode_coder.Compress( mv_data );
+ mv_byteio->SplitModeData()->Output();
+
+ PredModeCodec pmode_coder( mv_byteio->PredModeData()->DataBlock(), TOTAL_MV_CTXS, pparams.NumRefs() );
+ pmode_coder.Compress( mv_data );
+ mv_byteio->PredModeData()->Output();
+
+ VectorElementCodec vcoder1h( mv_byteio->MV1HorizData()->DataBlock(), 1,
+ HORIZONTAL, TOTAL_MV_CTXS);
+ vcoder1h.Compress( mv_data );
+ mv_byteio->MV1HorizData()->Output();
+
+ VectorElementCodec vcoder1v( mv_byteio->MV1VertData()->DataBlock(), 1,
+ VERTICAL, TOTAL_MV_CTXS);
+ vcoder1v.Compress( mv_data );
+ mv_byteio->MV1VertData()->Output();
+
+ if ( pparams.NumRefs()>1 )
+ {
+ VectorElementCodec vcoder2h( mv_byteio->MV2HorizData()->DataBlock(), 2,
+ HORIZONTAL, TOTAL_MV_CTXS);
+ vcoder2h.Compress( mv_data );
+ mv_byteio->MV2HorizData()->Output();
+
+ VectorElementCodec vcoder2v( mv_byteio->MV2VertData()->DataBlock(), 2,
+ VERTICAL, TOTAL_MV_CTXS);
+ vcoder2v.Compress( mv_data );
+ mv_byteio->MV2VertData()->Output();
+ }
+
+ DCCodec ydc_coder( mv_byteio->YDCData()->DataBlock(), Y_COMP, TOTAL_MV_CTXS);
+ ydc_coder.Compress( mv_data );
+ mv_byteio->YDCData()->Output();
+
+ DCCodec udc_coder( mv_byteio->UDCData()->DataBlock(), U_COMP, TOTAL_MV_CTXS);
+ udc_coder.Compress( mv_data );
+ mv_byteio->UDCData()->Output();
+
+ DCCodec vdc_coder( mv_byteio->VDCData()->DataBlock(), V_COMP, TOTAL_MV_CTXS);
+ vdc_coder.Compress( mv_data );
+ mv_byteio->VDCData()->Output();
+
+ mv_byteio->Output();
+ }
+}
+
+float PictureCompressor::GetCompLambda( const EncPicture& my_picture,
+ const CompSort csort )
+{
+ const PictureParams& pparams = my_picture.GetPparams();
+
+ const PictureSort psort = pparams.PicSort();
+
+ float lambda;
+
+ if ( psort.IsIntra() ){
+ if ( m_is_a_cut )
+ lambda = m_encparams.L1Lambda()/8;
+ else
+ lambda = m_encparams.ILambda();
+
+ }
+ else{
+ double log_intra_lambda = std::log10( m_encparams.ILambda() );
+/*
+double picture_lambda = m_encparams.L1Lambda() / my_picture.GetNormComplexity();
+if (pparams.IsBPicture() )
+ picture_lambda *= 1.2;
+
+ double log_picture_lambda = std::log10( picture_lambda );
+*/
+///*
+ double log_picture_lambda;
+ if (pparams.IsBPicture() )
+ log_picture_lambda= std::log10( m_encparams.L2Lambda() );
+ else
+ log_picture_lambda= std::log10( m_encparams.L1Lambda() );
+
+//*/
+ float intra_ratio = my_picture.GetMEData().IntraBlockRatio();
+
+ lambda= std::pow(10.0, 3.0*intra_ratio*log_intra_lambda+
+ (1.0-3.0*intra_ratio)*log_picture_lambda );
+
+//lambda /= my_picture.GetNormComplexity();
+
+ }
+
+ if (csort == U_COMP)
+ lambda*= m_encparams.UFactor();
+ if (csort == V_COMP)
+ lambda*= m_encparams.VFactor();
+
+ return lambda;
+}
+
+void PictureCompressor::SetupCodeBlocks( SubbandList& bands )
+{
+ int xregions;
+ int yregions;
+
+ for (int band_num = 1; band_num<=bands.Length() ; ++band_num){
+ if (m_encparams.SpatialPartition()){
+ int level = m_encparams.TransformDepth() - (band_num-1)/3;
+ const CodeBlocks &cb = m_encparams.GetCodeBlocks(level);
+ xregions = cb.HorizontalCodeBlocks();
+ yregions = cb.VerticalCodeBlocks();
+ }
+ else{
+ xregions = 1;
+ yregions = 1;
+ }
+
+ bands( band_num ).SetNumBlocks( yregions , xregions );
+ }// band_num
+}
+
+void PictureCompressor::SelectQuantisers( CoeffArray& coeff_data ,
+ SubbandList& bands ,
+ const float lambda,
+ OneDArray<unsigned int>& est_bits,
+ const CodeBlockMode cb_mode,
+ const PictureParams& pp,
+ const CompSort csort )
+{
+
+ // Set up the multiquantiser mode
+ for ( int b=bands.Length() ; b>=1 ; --b ){
+ // Set multiquants flag in the subband only if
+ // a. Global m_cb_mode flag is set to QUANT_MULTIPLE in encparams
+ // and
+ // b. Current subband has more than one block
+ if (
+ cb_mode == QUANT_MULTIPLE &&
+ (bands(b).GetCodeBlocks().LengthX() > 1 ||
+ bands(b).GetCodeBlocks().LengthY() > 1)
+ )
+ bands(b).SetUsingMultiQuants( true );
+ else
+ bands(b).SetUsingMultiQuants( false );
+ }// b
+
+ // Select all the quantizers
+ if ( !m_encparams.Lossless() ){
+ // Set quantizers for all bands.
+ for ( int b=bands.Length() ; b>=1 ; --b )
+ est_bits[b] = SelectMultiQuants( coeff_data , bands , b, lambda,
+ pp, csort );
+ }
+ else{
+ for ( int b=bands.Length() ; b>=1 ; --b ){
+ bands(b).SetQuantIndex( 0 );
+ est_bits[b] = 0;
+ TwoDArray<CodeBlock>& blocks = bands(b).GetCodeBlocks();
+ for (int j=0; j<blocks.LengthY() ;++j)
+ for (int i=0; i<blocks.LengthX() ;++i)
+ blocks[j][i].SetQuantIndex( 0 );
+ }// b
+ }
+}
+
+int PictureCompressor::SelectMultiQuants( CoeffArray& coeff_data , SubbandList& bands ,
+ const int band_num , const float lambda, const PictureParams& pp, const CompSort csort)
+{
+ Subband& node( bands( band_num ) );
+
+ // Now select the quantisers //
+ ///////////////////////////////
+
+ QuantChooser qchooser( coeff_data , lambda );
+
+ // For the DC band in I pictures, remove the average
+ if ( band_num == bands.Length() && pp.PicSort().IsIntra() )
+ AddSubAverage( coeff_data , node.Xl() , node.Yl() , SUBTRACT);
+
+ // The total estimated bits for the subband
+ int band_bits( 0 );
+ qchooser.SetEntropyCorrection( m_encparams.EntropyFactors().Factor( band_num, pp, csort ) );
+ band_bits = qchooser.GetBestQuant( node );
+
+ // Put the DC band average back in if necessary
+ if ( band_num == bands.Length() && pp.PicSort().IsIntra() )
+ AddSubAverage( coeff_data , node.Xl() , node.Yl() , ADD);
+
+ if ( band_bits == 0 )
+ node.SetSkip( true );
+ else
+ node.SetSkip( false );
+
+ return band_bits;
+}
+
+
+void PictureCompressor::AddSubAverage( CoeffArray& coeff_data, int xl, int yl ,
+ AddOrSub dirn)
+{
+
+ ValueType last_val=0;
+ ValueType last_val2;
+
+ if ( dirn == SUBTRACT )
+ {
+ for ( int j=0 ; j<yl ; j++)
+ {
+ for ( int i=0 ; i<xl ; i++)
+ {
+ last_val2 = coeff_data[j][i];
+ coeff_data[j][i] -= last_val;
+ last_val = last_val2;
+ }// i
+ }// j
+ }
+ else
+ {
+ for ( int j=0 ; j<yl ; j++)
+ {
+ for ( int i=0 ; i<xl; i++ )
+ {
+ coeff_data[j][i] += last_val;
+ last_val = coeff_data[j][i];
+ }// i
+ }// j
+
+ }
+}
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/picture_compress.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/picture_compress.h new file mode 100644 index 000000000..84f2d983b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/picture_compress.h @@ -0,0 +1,201 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: picture_compress.h,v 1.7 2008/08/14 02:30:50 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2004.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+* Scott R Ladd,
+* Anuradha Suraparaju
+* Andrew Kennedy
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+
+#ifndef _PICTURE_COMPRESS_H_
+#define _PICTURE_COMPRESS_H_
+
+#include <libdirac_encoder/enc_queue.h>
+#include <libdirac_common/common.h>
+#include <libdirac_common/motion.h>
+#include <libdirac_byteio/picture_byteio.h>
+
+namespace dirac
+{
+
+ class MvData;
+
+ //! Compress a single image picture
+ /*!
+ This class compresses a single picture at a time, using parameters
+ supplied at its construction. PictureCompressor is used by
+ SequenceCompressor.
+ */
+ class PictureCompressor
+ {
+ public:
+ //! Constructor
+ /*!
+ Creates a FrameEncoder with specific set of parameters the control
+ the compression process. It encodes motion data before encoding
+ each component of the picture.
+ \param encp encoder parameters
+ */
+ PictureCompressor( EncoderParams& encp );
+
+ //! Destructor
+ ~PictureCompressor( );
+
+ //! Do pixel accurate motion estimate
+ void PixelME( EncQueue& my_buffer , int pnum );
+
+ //! Calculate the complexity of a picture
+ void CalcComplexity( EncQueue& my_buffer, int pnum , const OLBParams& olbparams );
+ void CalcComplexity2( EncQueue& my_buffer, int pnum );
+
+ //! Normalise picture complexity with respect to others in the queue
+ void NormaliseComplexity( EncQueue& my_buffer, int pnum );
+
+ //! Do subpixel accurate motion vector refinement
+ void SubPixelME( EncQueue& my_buffer , int pnum );
+
+ //! Do mode decision based on sub-pel vectors
+ void ModeDecisionME( EncQueue& my_buffer, int pnum );
+
+ //! Detect cuts in the current picture
+ void IntraModeAnalyse( EncQueue& my_buffer, int pnum );
+
+ //! Does motion compensation on picture pnum (forward or backward)
+ void MotionCompensate( EncQueue& my_buffer, int pnum, AddOrSub dirn );
+
+ //! Prefilter if required
+ void Prefilter( EncQueue& my_buffer, int pnum );
+
+ //! Do the DWT on a given picture
+ void DoDWT( EncQueue& my_buffer , int pnum, Direction dirn );
+
+ //! Compress a specific picture within a group of pictures (GOP)
+ /*!
+ Compresses a specified picture within a group of pictures.
+ \param my_pbuffer picture buffer in which the reference frames resides
+ \param pnum picture number to compress
+ \param pic_byteio compressed picture in Dirac bytestream format
+ */
+ void CodeResidue( EncQueue& my_pbuffer , int pnum , PictureByteIO* pic_byteio);
+
+ //! Compresses the motion vector data
+ void CodeMVData( EncQueue& my_buffer, int pnum, PictureByteIO* pic_byteio);
+
+ //! Returns true if the picture has been skipped rather than coded normally
+ bool IsSkipped(){ return m_skipped; }
+
+ //! Returns true if Motion estimation data is available
+ bool IsMEDataAvail() const { return m_medata_avail; }
+
+ //! Returns the motion estimation data
+ const MEData* GetMEData() const;
+
+ private:
+ //! Copy constructor is private and body-less
+ /*!
+ Copy constructor is private and body-less. This class should not
+ be copied.
+ */
+ PictureCompressor( const PictureCompressor& cpy );
+
+ //! Assignment = is private and body-less
+ /*!
+ Assignment = is private and body-less. This class should not be
+ assigned.
+ */
+ PictureCompressor& operator=(const PictureCompressor& rhs);
+
+ //! Initialise the coefficient data array for holding wavelet coefficients
+ void InitCoeffData( CoeffArray& coeff_data, const int xl, const int yl );
+
+ //! Returns the value lambda according to picture and component type
+ float GetCompLambda( const EncPicture& my_picture,
+ const CompSort csort );
+
+ void SelectQuantisers( CoeffArray& coeff_data ,
+ SubbandList& bands ,
+ const float lambda,
+ OneDArray<unsigned int>& est_counts,
+ const CodeBlockMode cb_mode,
+ const PictureParams& pp,
+ const CompSort csort );
+
+ int SelectMultiQuants( CoeffArray& coeff_data ,
+ SubbandList& bands ,
+ const int band_num,
+ const float lambda,
+ const PictureParams& pp,
+ const CompSort csort );
+
+ void SetupCodeBlocks( SubbandList& bands );
+
+
+ void AddSubAverage(CoeffArray& coeff_data,int xl,int yl,AddOrSub dirn);
+
+ private:
+
+ //member variables
+ // a local copy of the encoder params
+ EncoderParams& m_encparams;
+
+ // True if the picture has been skipped, false otherwise
+ bool m_skipped;
+
+ // True if we use global motion vectors, false otherwise
+ bool m_use_global;
+
+ // True if we use block motion vectors, false otherwise
+ bool m_use_block_mv;
+
+ // Prediction mode to use if we only have global motion vectors
+ PredMode m_global_pred_mode;
+
+ // A pointer to the current picture motion vector data
+ MEData* m_me_data;
+
+ // True if motion estimation data is available
+ bool m_medata_avail;
+
+ // True if we have detected a cut
+ bool m_is_a_cut;
+
+ // The original MV precision type
+ MVPrecisionType m_orig_prec;
+
+ };
+
+} // namespace dirac
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/prefilter.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/prefilter.cpp new file mode 100644 index 000000000..7920ed0d1 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/prefilter.cpp @@ -0,0 +1,588 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: prefilter.cpp,v 1.9 2008/10/29 02:42:06 asuraparaju Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2008.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author),
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+#include<libdirac_encoder/prefilter.h>
+#include<libdirac_common/arrays.h>
+
+using namespace dirac;
+
+void dirac::CWMFilter( Picture& picture, const int strength )
+{
+ CWMFilterComponent( picture.Data(Y_COMP), strength );
+ CWMFilterComponent( picture.Data(U_COMP), strength );
+ CWMFilterComponent( picture.Data(V_COMP), strength );
+}
+
+void dirac::CWMFilterComponent( PicArray& pic_data, const int strength )
+{
+ // Do centre-weighted median denoising
+
+ PicArray pic_copy( pic_data );
+
+ const int width( 3 );
+ const int offset( (width-1)/2 );
+ const int centre_weight = std::max(1, (width*width+1)-strength );
+ const int list_length = centre_weight+(width*width)-1;
+
+ ValueType* val_list = new ValueType[list_length];
+
+ for (int j=offset; j<pic_data.LengthY()-offset; ++j){
+ for (int i=offset; i<pic_data.LastX()-offset; ++i){
+ // Make the value list
+ int pos=0;
+ for (; pos<centre_weight-1; ++pos)
+ val_list[pos] = pic_copy[j][i];
+
+ for (int s=-offset; s<=offset; ++s){
+ for (int r=-offset; r<=offset; ++r){
+ val_list[pos]=pic_copy[j+s][i+r];
+ pos++;
+ }// r
+ }// s
+
+ pic_data[j][i] = Median( val_list, list_length );
+ }// i
+ }// j
+
+ delete[] val_list;
+}
+
+ValueType dirac::Median( const ValueType* val_list, const int length)
+{
+
+
+ OneDArray<ValueType> ordered_vals( length );
+
+ // Place the values in order
+ int pos=0;
+ ordered_vals[0] = val_list[0];
+ for (int i=1 ; i<length ; ++i )
+ {
+ for (int k=0 ; k<i ; ++k)
+ {
+ if (val_list[i]<ordered_vals[k])
+ {
+ pos=k;
+ break;
+ }
+ else
+ pos=k+1;
+ }// k
+
+ if ( pos==i)
+ ordered_vals[i] = val_list[i];
+ else
+ {
+ for (int k=i-1 ; k>=pos ; --k )
+ {
+ ordered_vals[k+1] = ordered_vals[k];
+ }// k
+ ordered_vals[pos] = val_list[i];
+ }
+ }// i
+
+ // return the middle value
+ if ( length%2!=0 )
+ return ordered_vals[(length-1)/2];
+ else
+ return (ordered_vals[(length/2)-1]+ordered_vals[length/2]+1)>>1;
+
+}
+
+/*************************************************************/
+
+
+void VFilter( PicArray& pic_data, const OneDArray<int>& filter, const int bits );
+void HFilter( PicArray& pic_data, const OneDArray<int>& filter, const int bits );
+
+double sinxoverx( const double val )
+{
+ if ( 0.0f == val )
+ return 1.0;
+ else
+ return sin(val)/val;
+
+}
+
+OneDArray<int> MakeLPRectFilter( const float bw, const int bits )
+{
+ const int tl = 8;
+ const float pi = 3.1415926535;
+
+ OneDArray<double> double_filter( Range( -tl, tl ) );
+ OneDArray<int> int_filter( Range( -tl, tl) );
+
+ // Use the Hanning window
+ for (int i=double_filter.First(); i<=double_filter.Last(); ++i)
+ {
+ double_filter[i] = cos( (pi*i)/
+ (double_filter.Length()+1) );
+ }
+
+ // Apply sinc function
+ for (int i=double_filter.First(); i<=double_filter.Last(); ++i)
+ {
+ double_filter[i] *= sinxoverx( pi*1.0*bw*i );
+ }
+
+ // Get DC gain = 1<<bits
+ double sum = 0.0;
+ for (int i=double_filter.First(); i<=double_filter.Last(); ++i)
+ sum += double_filter[i];
+
+ for (int i=double_filter.First(); i<=double_filter.Last(); ++i)
+ {
+ double_filter[i] *= double(1<<(bits+4));
+ double_filter[i] /= sum;
+ }
+
+ // Turn the float filter into an integer filter
+ for (int i=double_filter.First(); i<=double_filter.Last(); ++i)
+ {
+ int_filter[i] = double_filter[i]>0 ? int( double_filter[i]+0.5 ) : -int( -double_filter[i]+0.5 );
+ int_filter[i] = (int_filter[i]+8)>>4;
+ }
+
+ return int_filter;
+}
+
+void dirac::LPFilter( PicArray& pic_data, const float qf, const int strength )
+{
+ float bw = (std::min( std::max( qf+3.0f-float(strength), 1.0f ), 10.0f ))/10.0;
+
+ // filter with 14-bit accuracy
+ OneDArray<int> filter=MakeLPRectFilter(bw, 14);
+
+ HFilter( pic_data, filter, 14 );
+ VFilter( pic_data, filter, 14 );
+
+}
+
+void HFilter( PicArray& pic_data, const OneDArray<int>& filter, const int bits )
+{
+ ValueType* line_data = new ValueType[pic_data.LengthX()];
+ const int offset = (1<<(bits-1));
+
+ int sum;
+
+ for (int j=0; j<pic_data.LengthY(); ++j)
+ {
+ // Do the first bit
+ for (int i=0; i<filter.Last(); ++i)
+ {
+ sum = offset;
+ for (int k=filter.Last(); k>=filter.First(); --k)
+ sum += filter[k]*pic_data[j][std::max(i-k,0)];
+ sum >>= bits;
+ sum = std::min( 127, std::max( -128, sum) );
+ line_data[i] = ValueType( sum );
+ }// i
+ // Do the middle bit
+ for (int i=filter.Last(); i<=pic_data.LastX()+filter.First(); ++i)
+ {
+ sum = offset;
+ for (int k=filter.Last(); k>=filter.First(); --k)
+ sum += filter[k]*pic_data[j][i-k];
+ sum >>= bits;
+ sum = std::min( 127, std::max( -128, sum) );
+ line_data[i] = ValueType( sum );
+ }// i
+ // Do the last bit
+ for (int i=pic_data.LastX()+filter.First()+1; i<pic_data.LengthX(); ++i)
+ {
+ sum = offset;
+ for (int k=filter.Last(); k>=filter.First(); --k)
+ sum += filter[k]*pic_data[j][std::min(i-k,pic_data.LastX())];
+ sum >>= bits;
+ sum = std::min( 127, std::max( -128, sum) );
+ line_data[i] = ValueType( sum );
+ }// i
+
+ // Copy data back
+
+ for (int i=0; i<pic_data.LengthX(); ++i )
+ pic_data[j][i] = line_data[i];
+
+ }// j
+
+ delete[] line_data;
+}
+
+void VFilter( PicArray& pic_data, const OneDArray<int>& filter, const int bits )
+{
+ PicArray tmp_data( pic_data );
+ const int offset = (1<<(bits-1));
+
+ int sum;
+
+ // Do the first bit
+ for (int j=0; j<filter.Last(); ++j)
+ {
+
+ for (int i=0; i<pic_data.LengthX(); ++i)
+ {
+ sum = offset;
+ for (int k=filter.Last(); k>=filter.First(); --k)
+ sum += filter[k]*pic_data[std::max(j-k,0)][i];
+ sum >>= bits;
+ sum = std::min( 127, std::max( -128, sum) );
+ tmp_data[j][i] = ValueType( sum );
+ }// i
+
+ }// j
+
+ // Do the middle bit
+ for (int j=filter.Last(); j<=pic_data.LastY()+filter.First(); ++j)
+ {
+
+ for (int i=0; i<pic_data.LengthX(); ++i)
+ {
+ sum = offset;
+ for (int k=filter.Last(); k>=filter.First(); --k)
+ sum += filter[k]*pic_data[j-k][i];
+ sum >>= bits;
+ sum = std::min( 127, std::max( -128, sum) );
+ tmp_data[j][i] = ValueType( sum );
+ }// i
+
+ }// j
+
+ // Do the last bit
+ for (int j=pic_data.LastY()+filter.First()+1; j<pic_data.LengthY(); ++j)
+ {
+
+ for (int i=0; i<pic_data.LengthX(); ++i)
+ {
+ sum = offset;
+ for (int k=filter.Last(); k>=filter.First(); --k)
+ sum += filter[k]*pic_data[std::min(j-k,pic_data.LastY())][i];
+ sum >>= bits;
+ sum = std::min( 127, std::max( -128, sum) );
+ tmp_data[j][i] = ValueType( sum );
+ }// i
+
+ }// j
+
+ // Copy data across
+ pic_data = tmp_data;
+
+}
+
+/***************************************************************************/
+
+ValueType DiagFilterBchkD( const PicArray& pic,
+ const int xpos, const int ypos,
+ const TwoDArray<int>& filter,
+ const int shift)
+{
+ // Half the filter length
+ const int len2 = 6;
+
+ const int height = pic.LengthY();
+ const int width = pic.LengthX();
+
+ int uplus, uneg, vplus, vneg;
+ int val = (1<<(shift-1));
+
+ // Do 0 position horizontally
+ val += filter[0][0]*pic[ypos][xpos];
+
+ for (int i=1; i<=len2;++i){
+ uplus = xpos + i;
+ uplus = (uplus>=width ? width-1 : uplus);
+ uneg = xpos - i;
+ uneg = (uneg<0 ? 0 : uneg );
+ val += filter[0][i]*(pic[ypos][uplus]+pic[ypos][uneg] );
+ }
+
+ // Do other positions vertically//
+ //////////////////////////////////
+
+ for (int j=1; j<=len2;++j){
+ vplus = ypos + j;
+ vplus = ( vplus>=height ? height-1 : vplus);
+ vneg = ypos - j;
+ vneg = (vneg<0 ? 0 : vneg );
+
+ // Do 0 position horizontally
+ val += filter[j][0]*(pic[vneg][xpos]+pic[vplus][xpos]);
+ for (int i=1; i<=len2;++i){
+ uplus = xpos + i;
+ uplus = (uplus>=width ? width-1 : uplus);
+ uneg = xpos - i;
+ uneg = (uneg<0 ? 0 : uneg );
+ val += filter[j][i]*(pic[vneg][uplus]+pic[vneg][uneg]+
+ pic[vplus][uplus]+pic[vplus][uneg] );
+ }
+ }
+
+ val >>= shift;
+
+ return ValueType(val);
+}
+
+ValueType DiagFilterD( const PicArray& pic,
+ const int xpos, const int ypos,
+ const TwoDArray<int>& filter,
+ const int shift)
+{
+ // Half the filter length
+ const int len2 = 6;
+
+ int uplus, uneg, vplus, vneg;
+ int val = (1<<(shift-1));
+
+ // Do 0 position horizontally
+ val += filter[0][0]*pic[ypos][xpos];
+
+ for (int i=1; i<=len2;++i){
+ uplus = xpos + i;
+ uneg = xpos - i;
+ val += filter[0][i]*(pic[ypos][uplus]+pic[ypos][uneg] );
+ }
+
+ // Do other positions vertically//
+ //////////////////////////////////
+
+ for (int j=1; j<=len2;++j){
+ vplus = ypos + j;
+ vneg = ypos - j;
+
+ // Do 0 position horizontally
+ val += filter[j][0]*(pic[vneg][xpos]+pic[vplus][xpos]);
+ for (int i=1; i<=len2;++i){
+ uplus = xpos + i;
+ uneg = xpos - i;
+ val += filter[j][i]*(pic[vneg][uplus]+pic[vneg][uneg]+
+ pic[vplus][uplus]+pic[vplus][uneg] );
+ }
+ }
+
+ val >>= shift;
+
+ return ValueType(val);
+}
+
+
+TwoDArray<int> GetDiagLPFilter( const float bw )
+{
+ TwoDArray<int> f( 7, 7 );
+
+ // Bandwidth quantised to range 0.2-1
+ int qbf = int( bw*10.0 + 0.5 );
+ qbf = std::min( std::max( qbf, 2 ) , 10 );
+
+ switch (qbf){
+
+ case 1 :
+ f[0][0]=1651; f[0][1]=1544; f[0][2]=1259; f[0][3]=887; f[0][4]=530; f[0][5]=260; f[0][6]=99;
+ f[1][0]=1544; f[1][1]=1442; f[1][2]=1170; f[1][3]=817; f[1][4]=480; f[1][5]=229; f[1][6]=83;
+ f[2][0]=1259; f[2][1]=1170; f[2][2]=935; f[2][3]=634; f[2][4]=354; f[2][5]=153; f[2][6]=45;
+ f[3][0]=887; f[3][1]=817; f[3][2]=634; f[3][3]=405; f[3][4]=202; f[3][5]=70; f[3][6]=11;
+ f[4][0]=530; f[4][1]=480; f[4][2]=354; f[4][3]=202; f[4][4]=80; f[4][5]=15; f[4][6]=0;
+ f[5][0]=260; f[5][1]=229; f[5][2]=153; f[5][3]=70; f[5][4]=15; f[5][5]=0; f[5][6]=0;
+ f[6][0]=99; f[6][1]=83; f[6][2]=45; f[6][3]=11; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 2:
+
+ f[0][0]=2855; f[0][1]=2540; f[0][2]=1775; f[0][3]=947; f[0][4]=364; f[0][5]=89; f[0][6]=10;
+ f[1][0]=2540; f[1][1]=2251; f[1][2]=1551; f[1][3]=804; f[1][4]=290; f[1][5]=59; f[1][6]=1;
+ f[2][0]=1775; f[2][1]=1551; f[2][2]=1020; f[2][3]=475; f[2][4]=130; f[2][5]=3; f[2][6]=-10;
+ f[3][0]=947; f[3][1]=804; f[3][2]=475; f[3][3]=165; f[3][4]=5; f[3][5]=-22; f[3][6]=-6;
+ f[4][0]=364; f[4][1]=290; f[4][2]=130; f[4][3]=5; f[4][4]=-28; f[4][5]=-10; f[4][6]=0;
+ f[5][0]=89; f[5][1]=59; f[5][2]=3; f[5][3]=-22; f[5][4]=-10; f[5][5]=0; f[5][6]=0;
+ f[6][0]=10; f[6][1]=1; f[6][2]=-10; f[6][3]=-6; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 3:
+
+ f[0][0]=5767; f[0][1]=4718; f[0][2]=2498; f[0][3]=745; f[0][4]=72; f[0][5]=5; f[0][6]=23;
+ f[1][0]=4718; f[1][1]=3796; f[1][2]=1875; f[1][3]=423; f[1][4]=-58; f[1][5]=-41; f[1][6]=7;
+ f[2][0]=2498; f[2][1]=1875; f[2][2]=643; f[2][3]=-146; f[2][4]=-241; f[2][5]=-88; f[2][6]=-9;
+ f[3][0]=745; f[3][1]=423; f[3][2]=-146; f[3][3]=-367; f[3][4]=-220; f[3][5]=-51; f[3][6]=-2;
+ f[4][0]=72; f[4][1]=-58; f[4][2]=-241; f[4][3]=-220; f[4][4]=-78; f[4][5]=-5; f[4][6]=0;
+ f[5][0]=5; f[5][1]=-41; f[5][2]=-88; f[5][3]=-51; f[5][4]=-5; f[5][5]=0; f[5][6]=0;
+ f[6][0]=23; f[6][1]=7; f[6][2]=-9; f[6][3]=-2; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 4:
+
+ f[0][0]=10534; f[0][1]=7642; f[0][2]=2603; f[0][3]=194; f[0][4]=56; f[0][5]=120; f[0][6]=28;
+ f[1][0]=7642; f[1][1]=5237; f[1][2]=1218; f[1][3]=-383; f[1][4]=-153; f[1][5]=40; f[1][6]=2;
+ f[2][0]=2603; f[2][1]=1218; f[2][2]=-771; f[2][3]=-958; f[2][4]=-269; f[2][5]=-3; f[2][6]=-7;
+ f[3][0]=194; f[3][1]=-383; f[3][2]=-958; f[3][3]=-541; f[3][4]=-18; f[3][5]=48; f[3][6]=4;
+ f[4][0]=56; f[4][1]=-153; f[4][2]=-269; f[4][3]=-18; f[4][4]=96; f[4][5]=22; f[4][6]=0;
+ f[5][0]=120; f[5][1]=40; f[5][2]=-3; f[5][3]=48; f[5][4]=22; f[5][5]=0; f[5][6]=0;
+ f[6][0]=28; f[6][1]=2; f[6][2]=-7; f[6][3]=4; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 5 :
+
+ f[0][0]=16421; f[0][1]=10159; f[0][2]=1716; f[0][3]=33; f[0][4]=325; f[0][5]=57; f[0][6]=6;
+ f[1][0]=10159; f[1][1]=5309; f[1][2]=-580; f[1][3]=-747; f[1][4]=44; f[1][5]=-43; f[1][6]=-25;
+ f[2][0]=1716; f[2][1]=-580; f[2][2]=-2310; f[2][3]=-763; f[2][4]=100; f[2][5]=-19; f[2][6]=-12;
+ f[3][0]=33; f[3][1]=-747; f[3][2]=-763; f[3][3]=308; f[3][4]=326; f[3][5]=27; f[3][6]=1;
+ f[4][0]=325; f[4][1]=44; f[4][2]=100; f[4][3]=326; f[4][4]=84; f[4][5]=-14; f[4][6]=0;
+ f[5][0]=57; f[5][1]=-43; f[5][2]=-19; f[5][3]=27; f[5][4]=-14; f[5][5]=0; f[5][6]=0;
+ f[6][0]=6; f[6][1]=-25; f[6][2]=-12; f[6][3]=1; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 6 :
+
+ f[0][0]=23511; f[0][1]=11883; f[0][2]=566; f[0][3]=524; f[0][4]=231; f[0][5]=18; f[0][6]=41;
+ f[1][0]= 11883; f[1][1]=3647; f[1][2]=-2496; f[1][3]=-361; f[1][4]=-96; f[1][5]=-97; f[1][6]=1;
+ f[2][0]=566; f[2][1]=-2496; f[2][2]=-2329; f[2][3]=459; f[2][4]=152; f[2][5]=-7; f[2][6]=18;
+ f[3][0]=524; f[3][1]=-361; f[3][2]=459; f[3][3]=979; f[3][4]=33; f[3][5]=-28; f[3][6]=3;
+ f[4][0]=231; f[4][1]=-96; f[4][2]=152; f[4][3]=33; f[4][4]=-184; f[4][5]=-15; f[4][6]=0;
+ f[5][0]=18; f[5][1]=-97; f[5][2]=-7; f[5][3]=-28; f[5][4]=-15; f[5][5]=0; f[5][6]=0;
+ f[6][0]=41; f[6][1]=1; f[6][2]=18; f[6][3]=3; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 7 :
+
+ f[0][0]=32188; f[0][1]=12652; f[0][2]=3; f[0][3]=921; f[0][4]=1; f[0][5]=128; f[0][6]=0;
+ f[1][0]=12652; f[1][1]=295; f[1][2]=-3414; f[1][3]=-2; f[1][4]=-343; f[1][5]=-1; f[1][6]=-37;
+ f[2][0]=3; f[2][1]=-3414; f[2][2]=-212; f[2][3]=1273; f[2][4]=1; f[2][5]=98; f[2][6]=0;
+ f[3][0]=921; f[3][1]=-2; f[3][2]=1273; f[3][3]=110; f[3][4]=-363; f[3][5]=0; f[3][6]=-8;
+ f[4][0]=1; f[4][1]=-343; f[4][2]=1; f[4][3]=-363; f[4][4]=-29; f[4][5]=29; f[4][6]=0;
+ f[5][0]=128; f[5][1]=-1; f[5][2]=98; f[5][3]=0; f[5][4]=29; f[5][5]=0; f[5][6]=0;
+ f[6][0]=0; f[6][1]=-37; f[6][2]=0; f[6][3]=-8; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 8 :
+
+ f[0][0]=41902; f[0][1]=12084; f[0][2]=435; f[0][3]=610; f[0][4]=188; f[0][5]=34; f[0][6]=37;
+ f[1][0]=12084; f[1][1]=-4268; f[1][2]=-2715; f[1][3]=-286; f[1][4]=-144; f[1][5]=-84; f[1][6]=-2;
+ f[2][0]=435; f[2][1]=-2715; f[2][2]=2809; f[2][3]=640; f[2][4]=127; f[2][5]=10; f[2][6]=17;
+ f[3][0]=610; f[3][1]=-286; f[3][2]=640; f[3][3]=-1250; f[3][4]=-45; f[3][5]=-26; f[3][6]=2;
+ f[4][0]=188; f[4][1]=-144; f[4][2]=127; f[4][3]=-45; f[4][4]=259; f[4][5]=-8; f[4][6]=0;
+ f[5][0]=34; f[5][1]=-84; f[5][2]=10; f[5][3]=-26; f[5][4]=-8; f[5][5]=0; f[5][6]=0;
+ f[6][0]=37; f[6][1]=-2; f[6][2]=17; f[6][3]=2; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ case 9 :
+
+ f[0][0]=53098; f[0][1]=10449; f[0][2]=1546; f[0][3]=73; f[0][4]=342; f[0][5]=38; f[0][6]=12;
+ f[1][0]=10449; f[1][1]=-9060; f[1][2]=-873; f[1][3]=-727; f[1][4]=52; f[1][5]=-65; f[1][6]=-20;
+ f[2][0]=1546; f[2][1]=-873; f[2][2]=4261; f[2][3]=-627; f[2][4]=137; f[2][5]=-27; f[2][6]=-7;
+ f[3][0]=73; f[3][1]=-727; f[3][2]=-627; f[3][3]=-804; f[3][4]=328; f[3][5]=14; f[3][6]=2;
+ f[4][0]=342; f[4][1]=52; f[4][2]=137; f[4][3]=328; f[4][4]=-83; f[4][5]=-20; f[4][6]=0;
+ f[5][0]=38; f[5][1]=-65; f[5][2]=-27; f[5][3]=14; f[5][4]=-20; f[5][5]=0; f[5][6]=0;
+ f[6][0]=12; f[6][1]=-20; f[6][2]=-7; f[6][3]=2; f[6][4]=0; f[6][5]=0; f[6][6]=0;
+
+ break;
+
+ default:// case 10
+
+ for (int j=0; j<f.LengthY(); ++j ){
+ for (int i=0; i<f.LengthX(); ++i ){
+ f[j][i] = 0;
+ }
+ }
+ f[0][0] = 65536;
+
+ }
+
+ return f;
+
+}
+
+
+// Does a diagnonal prefilter
+void dirac::DiagFilter( PicArray& pic_data, const float qf, const int strength ){
+ // One quadrant of the filter taps
+
+
+ float ffactor = (8.0+strength-4.0 - qf )/5.0;
+ int factor = std::max(0, std::min( 256, int( ffactor*256.0 ) ) ) ;
+
+ float bw = (1.0-ffactor)*0.6+0.4;
+
+ //std::cout<<std::endl<<"Diagonal prefiltering with bandwidth = "<<bw;
+
+ if (bw>0.9)
+ return;
+
+ TwoDArray<int> filter = GetDiagLPFilter( bw );
+
+ filter[0][0] = ( factor*filter[0][0] + ( (1<<8)-factor )*(1<<16) + (1<<7) ) >> 8;
+
+ for (int i=1;i<7; ++i )
+ filter[0][i] = ( factor*filter[0][i] + (1<<7) ) >> 8;
+
+ for (int j=1;j<7; ++j )
+ for (int i=0;i<7; ++i )
+ filter[j][i] = ( factor*filter[j][i] + (1<<7) ) >> 8;
+
+
+ PicArray tmp_data( pic_data.LengthY(), pic_data.LengthX(), pic_data.CSort() );
+
+ const int shift = 16;
+
+ for (int j=0; j<7;++j)
+ for (int i=0; i<pic_data.LengthX();++i)
+ tmp_data[j][i] = DiagFilterBchkD( pic_data, i, j, filter, shift);
+
+ for (int j=7; j<pic_data.LengthY()-7;++j){
+ for (int i=0; i<7;++i)
+ tmp_data[j][i] = DiagFilterBchkD( pic_data, i, j, filter, shift );
+
+ for (int i=7; i<pic_data.LengthX()-7;++i)
+ tmp_data[j][i] = DiagFilterD( pic_data, i, j, filter, shift );
+
+ for (int i=pic_data.LengthX()-7; i<pic_data.LengthX();++i)
+ tmp_data[j][i] = DiagFilterBchkD( pic_data, i, j, filter, shift );
+
+ }
+
+ for (int j=pic_data.LengthY()-7; j<pic_data.LengthY();++j)
+ for (int i=0; i<pic_data.LengthX();++i)
+ tmp_data[j][i] = DiagFilterBchkD( pic_data, i, j, filter, shift );
+
+ pic_data = tmp_data;
+
+}
+
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/prefilter.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/prefilter.h new file mode 100644 index 000000000..2a37c4aaf --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/prefilter.h @@ -0,0 +1,68 @@ +/* ***** BEGIN LICENSE BLOCK *****
+*
+* $Id: prefilter.h,v 1.1 2008/04/29 14:09:35 tjdwave Exp $ $Name: $
+*
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License
+* Version 1.1 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+* the specific language governing rights and limitations under the License.
+*
+* The Original Code is BBC Research and Development code.
+*
+* The Initial Developer of the Original Code is the British Broadcasting
+* Corporation.
+* Portions created by the Initial Developer are Copyright (C) 2008.
+* All Rights Reserved.
+*
+* Contributor(s): Thomas Davies (Original Author)
+*
+* Alternatively, the contents of this file may be used under the terms of
+* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
+* Public License Version 2.1 (the "LGPL"), in which case the provisions of
+* the GPL or the LGPL are applicable instead of those above. If you wish to
+* allow use of your version of this file only under the terms of the either
+* the GPL or LGPL and not to allow others to use your version of this file
+* under the MPL, indicate your decision by deleting the provisions above
+* and replace them with the notice and other provisions required by the GPL
+* or LGPL. If you do not delete the provisions above, a recipient may use
+* your version of this file under the terms of any one of the MPL, the GPL
+* or the LGPL.
+* ***** END LICENSE BLOCK ***** */
+
+
+#ifndef _PREFILTER_H_
+#define _PREFILTER_H_
+
+
+#include<libdirac_common/picture.h>
+
+namespace dirac
+{
+
+/*************************************************************/
+
+//! Denoises an input frame
+void CWMFilter( Picture& picture, const int strength );
+
+void CWMFilterComponent( PicArray& pic_data, const int strength );
+
+ValueType Median( const ValueType* val_list, const int length);
+
+
+/*************************************************************/
+
+//! Denoises a component
+void LPFilter( PicArray& pic_data, const float qf, const int strength );
+
+//! Diagonally filters an input component
+void DiagFilter( PicArray& pic_data, const float qf , const int strength );
+
+} // namespace dirac
+
+#endif
diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quality_monitor.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quality_monitor.cpp new file mode 100644 index 000000000..93934f372 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quality_monitor.cpp @@ -0,0 +1,184 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: quality_monitor.cpp,v 1.33 2008/08/14 01:04:26 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_encoder/quality_monitor.h> +#include <libdirac_common/wavelet_utils.h> +using namespace dirac; + +using std::log10; + +QualityMonitor::QualityMonitor(EncoderParams& encp) : + m_encparams(encp), + m_mse_averageY(3), + m_mse_averageU(3), + m_mse_averageV(3), + m_picture_total(3) +{ + ResetAll(); +} + +QualityMonitor::~QualityMonitor() +{} + +void QualityMonitor::ResetAll() +{ + + for (int i=0; i<3 ; ++i ) + { + m_mse_averageY[i] = 0.0; + m_mse_averageU[i] = 0.0; + m_mse_averageV[i] = 0.0; + m_picture_total[i] = 0; + }// i + m_totalmse_averageY = 0.0; + m_totalmse_averageU = 0.0; + m_totalmse_averageV = 0.0; + m_allpicture_total = 0; +} + +void QualityMonitor::WriteLog() +{ + const double Ymax = double( (1<<m_encparams.LumaDepth())-1 ); + const double UVmax = double( (1<<m_encparams.ChromaDepth())-1 ); + + std::cout<<std::endl<<"Overall mean PSNR values"; + std::cout<<std::endl<<"------------------------"; + std::cout<<std::endl<<"Y: "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(Ymax*Ymax/(m_totalmse_averageY/m_allpicture_total))<<std::endl; + std::cout<<std::endl<<"U: "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_totalmse_averageU/m_allpicture_total))<<std::endl; + std::cout<<std::endl<<"V: "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_totalmse_averageV/m_allpicture_total))<<std::endl; + + + std::cout<<std::endl<<"Mean PSNR values by picture type and component"; + std::cout<<std::endl<<"--------------------------------------------"; + std::cout<<std::endl; + + std::cout<<std::endl<<" || Y || U || V ||"; + std::cout<<std::endl<<"=================||==================================================="; + std::cout<<std::endl<<" Intra || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(Ymax*Ymax/(m_mse_averageY[0]/m_picture_total[0]))<<" || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_mse_averageU[0]/m_picture_total[0]))<<" || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_mse_averageV[0]/m_picture_total[0]))<<" || "; + std::cout<<std::endl<<"-----------------||---------------------------------------------------"; + std::cout<<std::endl<<" Inter Ref || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(Ymax*Ymax/(m_mse_averageY[1]/m_picture_total[1]))<<" || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_mse_averageU[1]/m_picture_total[1]))<<" || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_mse_averageV[1]/m_picture_total[1]))<<" || "; + std::cout<<std::endl<<"-----------------||---------------------------------------------------"; + std::cout<<std::endl<<" Inter Non Ref || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(Ymax*Ymax/(m_mse_averageY[2]/m_picture_total[2]))<<" || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_mse_averageU[2]/m_picture_total[2]))<<" || "; + std::cout.width(5);std::cout.precision(4); + std::cout<<10*std::log10(UVmax*UVmax/(m_mse_averageV[2]/m_picture_total[2]))<<" || "; + std::cout<<std::endl<<"-----------------||---------------------------------------------------"; +} + +void QualityMonitor::UpdateModel(const EncPicture& enc_picture ) +{ + const double Ymax = double( (1<<m_encparams.LumaDepth())-1 ); + const double UVmax = double( (1<<m_encparams.ChromaDepth())-1 ); + + const PictureSort& psort = enc_picture.GetPparams().PicSort(); + int idx = psort.IsIntra() ? 0 : (psort.IsRef() ? 1 : 2); + + double fmseY, fmseU, fmseV; + + fmseY = QualityVal( enc_picture.Data(Y_COMP) , enc_picture.OrigData(Y_COMP), + m_encparams.Xl(), m_encparams.Yl()); + m_mse_averageY[idx] += fmseY; + m_totalmse_averageY += fmseY; + + fmseU = QualityVal( enc_picture.Data(U_COMP) , enc_picture.OrigData(U_COMP), + m_encparams.ChromaXl(), + m_encparams.ChromaYl()); + m_mse_averageU[idx] += fmseU; + m_totalmse_averageU += fmseU; + + fmseV = QualityVal( enc_picture.Data(V_COMP) , enc_picture.OrigData(V_COMP), + m_encparams.ChromaXl(), + m_encparams.ChromaYl()); + m_mse_averageV[idx] += fmseV; + m_totalmse_averageV += fmseV; + + m_picture_total[idx]++; + m_allpicture_total++; + + if (m_encparams.Verbose() ) + { + std::cout<<std::endl<< (!m_encparams.FieldCoding() ? "Frame" : "Field"); + std::cout << " PSNR: Y="<<10.0 * std::log10( Ymax*Ymax / fmseY ); + std::cout<<", U="<<10.0 * std::log10( UVmax*UVmax / fmseU ); + std::cout<<", V="<<10.0 * std::log10( UVmax*UVmax / fmseV ); + } + +} + + +double QualityMonitor::QualityVal(const PicArray& coded_data, + const PicArray& orig_data, + const int xlen, const int ylen) +{ + long double sum_sq_diff = 0.0; + double diff; + for ( int j=0;j<ylen; ++j ) + { + for ( int i=0;i<xlen; ++i ) + { + diff = orig_data[j][i] - coded_data[j][i]; + sum_sq_diff += diff*diff; + + }// i + }// j + + + sum_sq_diff /= xlen*ylen; + + return (double) sum_sq_diff; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quality_monitor.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quality_monitor.h new file mode 100644 index 000000000..7f21a944d --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quality_monitor.h @@ -0,0 +1,124 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: quality_monitor.h,v 1.19 2008/08/14 02:30:50 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _QUALITY_MONITOR_H_ +#define _QUALITY_MONITOR_H_ + +#include <libdirac_common/common.h> +#include <libdirac_encoder/enc_picture.h> +#include <libdirac_common/wavelet_utils.h> +namespace dirac +{ + + //! Class to monitor the quality of pictures and adjust coding parameters appropriately + class QualityMonitor + { + public: + + //! Constructor. Sets up initial Lagrangian values + /* + Constructor sets up initial Lagrangian values. + */ + QualityMonitor(EncoderParams& ep); + + + //! Destructor + ~QualityMonitor(); + + //////////////////////////////////////////////////////////// + // // + // Assumes default copy constructor, assignment = // + // and destructor // + //////////////////////////////////////////////////////////// + + //! Update the mse factors, returning true if we need to recode + /*! + Update the mse factors, returning true if we need to recode + \param enc_picture the picture being encoded + */ + void UpdateModel(const EncPicture& enc_picture ); + + //! Reset the quality factors (say if there's been a cut) + void ResetAll(); + + //! Write a log of the quality to date + void WriteLog(); + + private: + //functions + + + //! Calculate the quality of coded wrt original picture + double QualityVal( const PicArray& coded_data , + const PicArray& orig_data, + const int xlen, + const int ylen); + + //member variables// + //////////////////// + + //! A reference to the encoder parameters + EncoderParams& m_encparams; + + //! The overall average Y mse + long double m_totalmse_averageY; + + //! The overall average U mse + long double m_totalmse_averageU; + + //! The overall average V mse + long double m_totalmse_averageV; + + //! The total number of pictures coded + int m_allpicture_total; + + //! The average Y mse for the picture types + OneDArray<long double> m_mse_averageY; + + //! The average U mse for the picture types + OneDArray<long double> m_mse_averageU; + + //! The average V mse for the picture types + OneDArray<long double> m_mse_averageV; + + //! The number of pictures of each type + OneDArray<int> m_picture_total; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quant_chooser.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quant_chooser.cpp new file mode 100644 index 000000000..9f369ffe8 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quant_chooser.cpp @@ -0,0 +1,363 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: quant_chooser.cpp,v 1.20 2009/01/21 05:22:05 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +//Compression of an individual component, +//after motion compensation if appropriate +////////////////////////////////////////// + +#include <libdirac_encoder/quant_chooser.h> + +using namespace dirac; + +// Custom 4th power, to speed things up +static inline double pow4 (double x) +{ + return x * x * x* x; +} + +// Constructor +QuantChooser::QuantChooser( const CoeffArray& coeff_data, + const float lambda ): + m_coeff_data( coeff_data ), + m_lambda( lambda ), + m_entropy_correctionfactor( 1.0 ) +{} + + +int QuantChooser::GetBestQuant( Subband& node ) +{ + // NB : quantiser selection only supports a single quantiser per subband + // Setting MultiQuants=true and using this function will get the same + // quantiser for each codeblock + + m_subband_wt = node.Wt(); + + // The largest value in the block or band + CoeffType max_val; + + // The index of the maximum bit of the largest value + int max_bit( 0 ); + + max_val = BlockAbsMax( node ); + + if ( max_val>=1 ) + max_bit = int( std::floor( std::log( float( max_val ) )/std::log( 2.0 ) ) ); + else + { + // Exit saying 'Skip this subband' if there's no data in it + node.SetSkip( true ); + return 0; + } + + // The number of quantisers to be tested + int num_quants( 4 * max_bit + 5 ); + + // Set the array sizes + m_costs.Resize( num_quants ); + m_count0.Resize( num_quants ); + m_count1=node.Xl()*node.Yl(); + m_countPOS.Resize( num_quants ); + m_countNEG.Resize( num_quants ); + m_error_total.Resize( num_quants ); + + // Total estimated bits for the subband + double bit_sum( 0.0 ); + + // Step 1. Do integral bits first + m_bottom_idx = 0; + m_top_idx = num_quants-1; + m_index_step = 4; + + IntegralErrorCalc( node, 2 , 2); + LagrangianCalc( ); + SelectBestQuant(); + + // Step 2. Do 1/2-bit accuracy next + m_bottom_idx = std::max( m_min_idx - 2 , 0 ); + m_top_idx = std::min( m_min_idx + 2 , num_quants-1 ); + m_index_step = 2; + + NonIntegralErrorCalc( node, 2 , 2); + LagrangianCalc( ); + SelectBestQuant(); + + // Step 3. Finally, do 1/4-bit accuracy next + m_bottom_idx = std::max( m_min_idx - 1 , 0 ); + m_top_idx = std::min( m_min_idx + 1 , num_quants-1 ); + m_index_step = 1; + + NonIntegralErrorCalc( node, 1 , 2); + LagrangianCalc( ); + SelectBestQuant(); + + bit_sum = m_costs[m_min_idx].ENTROPY * node.Xl() * node.Yl(); + + node.SetQuantIndex( m_min_idx ); + + TwoDArray<CodeBlock>& block_list( node.GetCodeBlocks() ); + + // Set the codeblock quantisers + for (int j=0 ; j<block_list.LengthY() ; ++j ) + for (int i=0 ; i<block_list.LengthX() ; ++i ) + block_list[j][i].SetQuantIndex( m_min_idx ); + + // Set the codeblock skip flags + for (int j=0 ; j<block_list.LengthY() ; ++j ) + for (int i=0 ; i<block_list.LengthX() ; ++i ) + SetSkip( block_list[j][i], m_min_idx ); + + + return static_cast<int>( bit_sum ); + +} + +void QuantChooser::IntegralErrorCalc( Subband& node, const int xratio , const int yratio ) +{ + + CoeffType val, quant_val , abs_val; + + CalcValueType error; + + m_count1 = ( (node.Xl()/xratio)*(node.Yl()/yratio) ); + for (int q = m_bottom_idx ; q<=m_top_idx ; q+=4 ) + { + m_error_total[q] = 0.0; + m_count0[q] =0; + m_countPOS[q] = 0; + m_countNEG[q] = 0; + } + + // Work out the error totals and counts for each quantiser + for ( int j=node.Yp(); j<node.Yp()+node.Yl() ; j+=yratio ) + { + for ( int i=node.Xp(); i<node.Xp()+node.Xl() ; i+=xratio ) + { + val = m_coeff_data[j][i]; + abs_val = quant_val = abs(val); + + int q = m_bottom_idx; + for ( ; q<=m_top_idx ; q+=4 ) + { + // Quantiser is 2^(q/4), so we divide by this + quant_val >>= (q>>2); + if (!quant_val) + break; + + m_count0[q] += quant_val; + // Multiply back up so that we can quantise again in the next loop step + quant_val <<= (q>>2)+2; + quant_val += dirac_quantiser_lists.InterQuantOffset4( q )+2; + quant_val >>= 2; + if (val>0) + m_countPOS[q]++; + else + m_countNEG[q]++; + + error = abs_val-quant_val; + + // Using the fourth power to measure the error + m_error_total[q] += pow4( static_cast<double>( error ) ); + + }// q + double derror = pow4 ( static_cast<double>( abs_val ) ); + for (; q <= m_top_idx; q+= 4) + { + m_error_total[q] += derror; + } + }// i + }// j + +} + +void QuantChooser::NonIntegralErrorCalc( Subband& node , const int xratio , const int yratio ) +{ + + CoeffType val, abs_val; + + CalcValueType quant_val; + CalcValueType error; + + m_count1 = ( (node.Xl()/xratio)*(node.Yl()/yratio) ); + for (int q = m_bottom_idx ; q<=m_top_idx ; q+=m_index_step ) + { + m_error_total[q] = 0.0; + m_count0[q] =0; + m_countPOS[q] = 0; + m_countNEG[q] = 0; + } + + // Work out the error totals and counts for each quantiser + for ( int j=node.Yp(); j<node.Yp()+node.Yl() ; j+=yratio ) + { + for ( int i=node.Xp(); i<node.Xp()+node.Xl() ; i+=xratio ) + { + + val = m_coeff_data[j][i]; + abs_val = abs( val ); + + int q=m_bottom_idx; + for ( ; q<=m_top_idx ; q+=m_index_step ) + { + // Since the quantiser isn't a power of 2 we have to divide each time + quant_val = static_cast<CalcValueType>( abs_val ); + quant_val <<= 2; + quant_val /= dirac_quantiser_lists.QuantFactor4( q ); + + if ( !quant_val ) + break; + + m_count0[q] += quant_val; + quant_val *= dirac_quantiser_lists.QuantFactor4( q ); + quant_val += dirac_quantiser_lists.InterQuantOffset4( q )+2; + quant_val >>= 2; + + if ( val>0 ) + m_countPOS[q]++; + else + m_countNEG[q]++; + + error = abs_val-quant_val; + m_error_total[q] += pow4( error ); + }// q + double derror = pow4( abs_val ); + for ( ; q <= m_top_idx; q += m_index_step) + m_error_total[q] += derror; + }// i + }// j + +} + + +void QuantChooser::LagrangianCalc() +{ + + // probabilities + double p0,p1; + + double sign_entropy; + + // Do Lagrangian costs calculation + for ( int q=m_bottom_idx ; q<=m_top_idx ; q += m_index_step ) + { + + m_costs[q].Error = m_error_total[q]/double(m_count1); + m_costs[q].Error = std::sqrt( m_costs[q].Error )/( m_subband_wt*m_subband_wt ); + + // Calculate probabilities and entropy + p0 = double( m_count0[q] )/ double( m_count0[q]+m_count1 ); + p1 = 1.0 - p0; + + if ( p0 != 0.0 && p1 != 0.0) + m_costs[q].ENTROPY = -( p0*std::log(p0)+p1*std::log(p1) ) / std::log(2.0); + else + m_costs[q].ENTROPY = 0.0; + + // We want the entropy *per symbol*, not per bit ... + m_costs[q].ENTROPY *= double(m_count0[q]+m_count1); + m_costs[q].ENTROPY /= double(m_count1); + + // Now add in the sign entropy + if ( m_countPOS[q] + m_countNEG[q] != 0 ) + { + p0 = double( m_countNEG[q] )/double( m_countPOS[q]+m_countNEG[q] ); + p1 = 1.0-p0; + if ( p0 != 0.0 && p1 != 0.0) + sign_entropy = -( (p0*std::log(p0)+p1*std::log(p1) ) / std::log(2.0)); + else + sign_entropy = 0.0; + } + else + sign_entropy = 0.0; + + // We want the entropy *per symbol*, not per bit ... + sign_entropy *= double( m_countNEG[q] + m_countPOS[q] ); + sign_entropy /= double(m_count1); + + m_costs[q].ENTROPY += sign_entropy; + + // Sort out correction factors + m_costs[q].ENTROPY *= m_entropy_correctionfactor; + m_costs[q].TOTAL = m_costs[q].Error+m_lambda*m_costs[q].ENTROPY; + + }// q +} + +void QuantChooser::SelectBestQuant() +{ + // Selects the best quantiser to use for a subband block + + m_min_idx = m_bottom_idx; + for ( int q=m_bottom_idx + m_index_step; q<=m_top_idx ; q +=m_index_step ) + { + if ( m_costs[q].TOTAL < m_costs[m_min_idx].TOTAL) + m_min_idx = q; + }// q + +} + +void QuantChooser::SetSkip( CodeBlock& cblock , const int qidx) +{ + const int u_threshold = dirac_quantiser_lists.QuantFactor4( qidx ); + + // Sets the skip flag for a codeblock + bool can_skip = true; + for (int j=cblock.Ystart(); j<cblock.Yend(); ++j ) + { + for (int i=cblock.Xstart(); i<cblock.Xend(); ++i ) + { + if ( (std::abs(m_coeff_data[j][i])<<2) >= u_threshold ) + can_skip = false; + } + } + cblock.SetSkip( can_skip ); +} + +CoeffType QuantChooser::BlockAbsMax( const Subband& node ) +{ + int val( 0 ); + + for (int j=node.Yp() ; j<node.Yp()+node.Yl(); ++j) + { + for (int i=node.Xp() ; i<node.Xp()+node.Xl(); ++i) + { + val = std::max( val , std::abs(m_coeff_data[j][i]) ); + }// i + }// j + + return val; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quant_chooser.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quant_chooser.h new file mode 100644 index 000000000..c1d28302c --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/quant_chooser.h @@ -0,0 +1,130 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: quant_chooser.h,v 1.7 2008/05/27 01:29:54 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#ifndef _QUANT_CHOOSER_H_ +#define _QUANT_CHOOSER_H_ + +#include <libdirac_common/arrays.h> +#include <libdirac_common/wavelet_utils.h> +#include <libdirac_common/common.h> + +namespace dirac +{ + //! Choose a quantiser + /*! + This class chooses a quantiser or quantisers for a subband + */ + class QuantChooser + { + public: + + //! Constructor + QuantChooser( const CoeffArray& pic_data , const float lambda ); + + //! Finds the best quantisers for the subband, returning the predicted number of bits needed + int GetBestQuant( Subband& node ); + + //! Sets the factor used for correcting the entropy calculation + void SetEntropyCorrection( const float ecfac ){ m_entropy_correctionfactor = ecfac; } + private: + //! Copy constructor is private and body-less. This class should not be copied. + QuantChooser(const QuantChooser& cpy); + + //! Assignment = is private and body-less. This class should not be assigned. + QuantChooser& operator=(const QuantChooser& rhs); + + //! Calculate errors and entropies for integral-bit quantisers + void IntegralErrorCalc( Subband& node , const int xratio , const int yratio ); + + //! Calculate errors and entropies for non-integral-bit quantisers + void NonIntegralErrorCalc( Subband& node, const int xratio, const int yratio ); + + //! Having got statistics, calculate the Lagrangian costs + void LagrangianCalc(); + + //! Select the best quantisation index on the basis of the Lagrangian calculations + void SelectBestQuant(); + + CoeffType BlockAbsMax( const Subband& node ); + + //! Set the skip flag for a codeblock + void SetSkip( CodeBlock& cblock , const int qidx); + + private: + //! The perceptual weighting factor of the subband being tested + float m_subband_wt; + + //! The smallest quantisation index being tested + int m_bottom_idx; + //! The largest quantisation index being tested + int m_top_idx; + //! The step we use in jumping through the list of quantisers + int m_index_step; + + //! The index of the quantiser with the lowest cost + int m_min_idx; + + //! A local reference to the data under consideration + const CoeffArray& m_coeff_data; + + //! The lambda value to be used in the Lagrangian calculation + const float m_lambda; + + //! A value for correcting the crude calculation of the entropy + float m_entropy_correctionfactor; + + //! An array used to count the number of zeroes + OneDArray<int> m_count0; + //! The number of ones (equal to the number of coefficients) + int m_count1; + //! An array used to count the number of positive values + OneDArray<int> m_countPOS; + //! An array used to count the number of negative values + OneDArray<int> m_countNEG; + //! An array used to collate the sum of the perceptually-weighted errors + OneDArray<double> m_error_total; + //! An array used to collate the computed costs + OneDArray<CostType> m_costs; + + }; + +} // namespace dirac + + + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp new file mode 100644 index 000000000..bd5b62346 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.cpp @@ -0,0 +1,530 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: rate_control.cpp,v 1.33 2008/12/16 01:21:02 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Myo Tun (Original Author, myo.tun@brunel.ac.uk) +* Jonathan Loo (Jonathan.Loo@brunel.ac.uk) +* School of Engineering and Design, Brunel University, UK +* Thomas Davies (bugfixes to improve stability and a major + refactor to introduce a buffer model) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +//////////////Rate Control Algorithm////////////////// +/* +The algorithm controls the bitrate by adaptively changing the Quality +Factor, QF of each frame before encoding by the +m_fcoder.Compress( , , , ) function in CompressNextPicture() (seq_compress.cpp). +The first sub-group which is I, L1, L2, L2 frames are encoded +by using the initial QF which is set to 7. The corresponding bitrate R is then +calculated. Adaption for the next subgroup is carried out by determining a model + parameter K, whose relationship to QF and bit rate is: + +QF = 10-5/2log(K/R^(-2)) + +K is determined from the first subgroup data (QF and rate), and used to +calculate a new QF from the target rates for the next subgroup. + +The same procedure applies for the calculation of the QF for the remaining +sub-groups until it reaches to the end of a GOP. + +For the next GOP, the initial QF of the first sub-group is the average value of +the QF of the first sub-group and last sub-group from the previous GOP. The +calculation of the QF of each and every sub-group is carried out in the +CalcNextQualFactor( , ) function at the rate_control.cpp. + +The target bitrate is varied according to a decoder buffer model, consisting of +the average bitrate over a GOP plus an adjustment to steer the buffer towards a +target occupancy. A target bit rate corresponding to + the different sub-groups still neeeds to be calculated from this overall target. + +In order to do this, the modified version of test model version 5, TM5 bit +allocation procedure is employed and target bit rates for each sub-group are +calculated by using the allocated bits to each frame types. The modified version +of TM5 bit allocation procedure is implemented in Allocate ( , ) function at the +rate_control.cpp. +*/ + + +#include <math.h> +#include <libdirac_encoder/rate_control.h> +using namespace dirac; + +//Default constructor +FrameComplexity::FrameComplexity(): + m_XI(169784), + m_XL1(36016), + m_XL2(4824) +{} + +//Default constructor +RateController::RateController(int trate, SourceParams& srcp, EncoderParams& encp): + m_qf (encp.Qf()), + m_I_qf (encp.Qf()), + m_I_qf_long_term(encp.Qf()), + m_target_rate(trate), + m_buffer_size(5000*trate),// for the moment, set buffer size to 5 seconds + m_buffer_bits((m_buffer_size*9)/10),// initial occupancy of 90% + m_encparams(encp), + m_fcount(encp.L1Sep() ), + m_intra_only(false), + m_L2_complexity_sum(0) +{ + SetFrameDistribution(); + CalcTotalBits(srcp); + + if (m_intra_only) + m_Iframe_bits = m_total_GOP_bits; + else + { + m_Iframe_bits = m_total_GOP_bits/10; + m_L1frame_bits = (m_Iframe_bits*3)/m_num_L1frame; + if (m_encparams.L1Sep()>1) + m_L2frame_bits = ( m_total_GOP_bits - m_Iframe_bits - + m_L1frame_bits*m_num_L1frame )/ + (m_encparams.GOPLength()-1-m_num_L1frame); + else + m_L2frame_bits = 0; + + } +} + +void RateController::SetFrameDistribution() +{ + m_num_L1frame = m_encparams.NumL1(); + m_num_Iframe = 1; + + if (m_num_L1frame == 0) + { + m_num_Iframe = m_encparams.GOPLength(); + m_intra_only = true; + } + + m_num_L2frame = m_encparams.GOPLength() - m_num_Iframe - m_num_L1frame; +} + +void RateController::CalcTotalBits(const SourceParams& sourceparams) +{ + const Rational& frame_rate = sourceparams.FrameRate(); + double f_rate = double(frame_rate.m_num)/double(frame_rate.m_denom); + int GOP_length = m_encparams.GOPLength(); + + m_GOP_duration = GOP_length/f_rate; + m_total_GOP_bits = (long int)(m_GOP_duration*1000.0)*m_target_rate; //Unit in bits + + m_GOP_target = m_total_GOP_bits; + + m_picture_bits = m_total_GOP_bits/GOP_length; + + if (m_encparams.Verbose()) + { + std::cout<<"\nRate Control Encoding with target bit rate = "; + std::cout<<m_target_rate<<" kbps"<< std::endl; + + std::cout<<"GOP Length = "<<GOP_length<< std::endl; + + std::cout<<"Frame Rate = "<<f_rate<< std::endl; + + std::cout<<"GOP Duration = "<<m_GOP_duration<< std::endl; + + std::cout<<"Total Allocated Num. of bits for each GOP = "; + std::cout<<m_total_GOP_bits<<" ("<<m_picture_bits<<" per frame)"; + std::cout<<std::endl; + } +} + +void RateController::Report() +{ + + std::cout<<std::endl; + std::cout<<std::endl<<"GOP target is "<<m_GOP_target; + std::cout<<std::endl<<"Allocated frame bits by type: "; + std::cout<<"I frames - "<<m_Iframe_bits; + std::cout<<"; L1/P frames - "<<m_L1frame_bits; + std::cout<<"; L2/B frames - "<<m_L2frame_bits; + std::cout<<std::endl; +} + + +double RateController::TargetSubgroupRate() +{ + long int bits = (m_encparams.L1Sep()-1)*m_L2frame_bits+ + m_L1frame_bits; + return (double)(bits)/(1000.0*m_GOP_duration); + +} + +double RateController::ProjectedSubgroupRate() +{ + int bits = (m_encparams.L1Sep()-1)*m_frame_complexity.L2Complexity()+ + m_frame_complexity.L1Complexity(); + + return (double)(bits)/(1000.0*m_GOP_duration); +} +void RateController::CalcNextQualFactor(const PictureParams& pparams, int num_bits) +{ + + // Decrement the subgroup frame counter. This is zero just after the last + // L2 frame before the next L1 frame i.e. before the start of an L1L2L2 + // subgroup + m_fcount--; + UpdateBuffer( num_bits ); + + // filter tap for adjusting the QF + double target_ratio = 0.9; + + int field_factor = m_encparams.FieldCoding() ? 2 : 1; + + double top_size = (1.0 - target_ratio)-0.5; + double bottom_size = target_ratio-0.1; + double actual_ratio = double(m_buffer_bits)/double(m_buffer_size); + double tap; + + if ((pparams.PictureNum()/field_factor)<=3*m_encparams.L1Sep() ) + tap = 1.0; + else{ + if (actual_ratio>target_ratio) + tap = (actual_ratio-target_ratio)/top_size; + else + tap = (target_ratio-actual_ratio)/bottom_size; + + tap = std::min( 1.0, std::max(tap, 0.25 )); + } + + + if (!m_intra_only) + { + bool emergency_realloc = false; + int target; + + // First, do normal coding + + if ( pparams.PicSort().IsIntra() == true ) + { + target = m_Iframe_bits; + + if (num_bits < target/2 ) + emergency_realloc = true; + + // Update the statistics + m_frame_complexity.SetIComplexity( num_bits ); + + // We've just coded an intra frame so we need to set qf for + // the next group of L2(B) frames + m_qf = std::max(tap*m_qf+(1.0-tap)*m_encparams.Qf(), m_encparams.Qf()-1.0); + m_encparams.SetQf( m_qf ); + + if (pparams.PictureNum()/field_factor==0) + { + // We've just coded the very first frame, which is a special + // case as the two L2 frames which normally follow are missing + m_fcount = m_encparams.L1Sep(); + } + + } + + //Update complexities + if ( (pparams.PictureNum()/field_factor) % m_encparams.L1Sep() !=0 ) + { + // Scheduled B/L2 picture + + target = m_L2frame_bits; + + if (num_bits < target/2 ){ + emergency_realloc = true; + } + + m_L2_complexity_sum += num_bits; + } + else if ( pparams.PicSort().IsIntra() == false ) + { + // Scheduled P/L1 picture (if inserted I picture, don't change the complexity) + + target = m_L1frame_bits; + + if (num_bits < target/2 || num_bits > target*3 ){ + emergency_realloc = true; + } + + m_frame_complexity.SetL1Complexity(num_bits); + } + + if ( m_fcount==0 || emergency_realloc==true) + { + if (emergency_realloc==true && m_encparams.Verbose()==true ) + std::cout<<std::endl<<"Major mis-prediction of frame bit rate: re-allocating"; + + + /* We recompute allocations for the next subgroup */ + + if ( m_encparams.L1Sep()>1 && m_fcount<m_encparams.L1Sep()-1) + { + m_frame_complexity.SetL2Complexity(m_L2_complexity_sum/ + (m_encparams.L1Sep()-1-m_fcount)); + } + Allocate( (pparams.PictureNum()/field_factor) ); + + /* We work out what this means for the quality factor and set it*/ + + // Get the target number of bits for the coming subgroup + // calculated from allocations + double trate = TargetSubgroupRate(); + + // Get the projected rate for the coming subgroup, calculated + // from measured values (complexities) + double prate = ProjectedSubgroupRate(); + + if (m_encparams.Verbose()==true ) + { + std::cout<<std::endl<<"Target subgroup rate = "<<trate; + std::cout<<", projected subgroup rate = "<<prate; + } + // Determine K value + double K = std::pow(prate, 2)*std::pow(10.0, ((double)2/5*(10-m_qf)))/16; + + // Determine a new QF + double new_qf = 10 - (double)5/2*log10(16*K/std::pow(trate, 2)); + if ( ( std::abs(m_qf-new_qf)<0.25 && new_qf > 4.0 ) || new_qf>8.0) + m_qf = new_qf; + else + m_qf = tap*new_qf+(1.0-tap)*m_qf; + + m_qf = ReviewQualityFactor( m_qf , num_bits ); + + if ( m_qf<8.0 ){ + if (prate<2*trate) + m_qf = std::max(m_qf,m_encparams.Qf()-1.0); + else + m_qf = std::max(m_qf,m_encparams.Qf()-2.0); + } + + m_encparams.SetQf(m_qf); + + + /* Resetting */ + + // Reset the frame counter + if (m_fcount==0) + m_fcount = m_encparams.L1Sep(); + + // Reset the count of L2 bits + m_L2_complexity_sum = 0; + } + + } + else + { + // We're doing intra-only coding + + + // Target rate + double trate = double(m_total_GOP_bits)/(1000.0*m_num_Iframe); + + // Projected rate with current QF + double prate = double(num_bits)/1000.0; + + + // Determine K value + double K = std::pow(prate, 2)*std::pow(10.0, ((double)2/5*(10-m_qf)))/16; + + // Determine a new QF + double new_qf = 10 - (double)5/2*log10(16*K/std::pow(trate, 2)); + + // Adjust the QF to meet the target + + double abs_delta = std::abs( new_qf - m_qf ); + if ( abs_delta>0.01) + { + // Rate of convergence to new QF + double r; + + /* Use an S-shaped curve to compute r + Where the qf difference is less than 1/2, r decreases to zero + exponentially, so for small differences in QF we jump straight + to the target value. For large differences in QF, r converges + exponentially to 0.75, so we converge to the target value at + a fixed rate. + + Overall behaviour is to converge steadily for 2 or 3 frames until + close and then lock to the correct value. This avoids very rapid + changes in quality. + + Actual parameters may be adjusted later. Some applications may + require instant lock. + */ + double lg_diff = std::log( abs_delta/2.0 ); + if ( lg_diff< 0.0 ) + r = 0.5*std::exp(-lg_diff*lg_diff/2.0); + else + r = 1.0-0.5*std::exp(-lg_diff*lg_diff/2.0); + + r *= 0.75; + + m_qf = r*m_qf + (1.0-r)*new_qf; + m_qf = ReviewQualityFactor( m_qf , num_bits ); + + m_encparams.SetQf(m_qf); + } + + + } + +} + + +void RateController::UpdateBuffer( const long int num_bits ) +{ + m_buffer_bits -= num_bits; + m_buffer_bits += m_picture_bits; + + if (m_encparams.Verbose()) + { + std::cout<<std::endl<<"Buffer occupancy = "<<((double)m_buffer_bits*100.0) + /((double)m_buffer_size)<<"%"; + } + + if (m_buffer_bits<0) + { + if (m_encparams.Verbose()) + { + std::cout<<std::endl<<"WARNING: decoder buffer is out of bits - bit rate is too high"; + } +// m_buffer_bits = 0; + } + + if (m_buffer_bits>m_buffer_size) + { + if (m_encparams.Verbose()) + { + std::cout<<std::endl<<"WARNING: decoder buffer has overflowed - bit rate is too low. Assuming bit-stuffing."; + } + m_buffer_bits = m_buffer_size; + } + + +} + +void RateController::Allocate (const int fnum) +{ + const int XI = m_frame_complexity.IComplexity(); + const int XL1 = m_frame_complexity.L1Complexity(); + const int XL2 = m_frame_complexity.L2Complexity(); + + double buffer_occ = ( (double)m_buffer_bits)/((double)m_buffer_size); + + if ( !m_intra_only) + { + double correction; + if (buffer_occ<0.9 && ( (fnum+1) % 4*m_encparams.L1Sep())==0 ) + { + // If we're undershooting buffer target, correct slowly + correction = std::min( 0.25, 0.25*(0.9 - buffer_occ )/0.9 ); + m_GOP_target = ( long int)(double(m_total_GOP_bits)*( 1.0-correction) ); + } + else if (buffer_occ>0.9 && ((fnum+1) % m_encparams.L1Sep())==0) + { + // If we're overshooting buffer target, correct quickly + correction = std::min( 0.5, 0.5*( buffer_occ - 0.9 )/0.9 ); + m_GOP_target = ( long int)(double(m_total_GOP_bits)*( 1.0+correction) ); + } + } + + + const long int min_bits = m_total_GOP_bits/(100*m_encparams.GOPLength()); + + // Allocate intra bits + m_Iframe_bits = (long int) (m_GOP_target + / (m_num_Iframe + +(double)(m_num_L1frame*XL1)/XI + +(double)(m_num_L2frame*XL2)/XI)); + + m_Iframe_bits = std::max( min_bits, m_Iframe_bits ); + + // Allocate L1 bits + m_L1frame_bits = (long int) (m_GOP_target + / (m_num_L1frame + +(double)(m_num_Iframe*XI)/XL1 + +(double)(m_num_L2frame*XL2)/XL1)); + + m_L1frame_bits = std::max( min_bits, m_L1frame_bits ); + + // Allocate L2 bits + m_L2frame_bits = (long int) (m_GOP_target + / (m_num_L2frame + +(double)(m_num_Iframe*XI)/XL2 + +(double)(m_num_L1frame*XL1)/XL2)); + + m_L2frame_bits = std::max( min_bits, m_L2frame_bits ); +} + + + +float RateController::ReviewQualityFactor( const float qfac, const long int num_bits ) +{ + if (num_bits>m_total_GOP_bits/2) + { + // The frame is too big, so reset to a smaller quality factor + return ClipQualityFactor(qfac-2); + } + else + { + // Keep the quality factor in a sensible range + return ClipQualityFactor( qfac ); + } +} + +float RateController::ClipQualityFactor( const float qfac ) +{ + // Keep the quality factor in a sensible range + if ( !m_intra_only ) + return std::min( std::max(qfac, 0.0f), 16.0f); + else + return std::max(qfac, 0.0f); +} + +void RateController::CalcNextIntraQualFactor() +{ + m_I_qf = (m_I_qf + m_qf)/2.0; + m_I_qf = ClipQualityFactor( m_I_qf ); + m_encparams.SetQf(m_I_qf); + + const double ff = 0.95; + m_I_qf_long_term *= ff; + m_I_qf_long_term += ( 1.0 - ff )*m_I_qf; +} + +void RateController::SetCutPictureQualFactor() +{ + m_qf = std::min( m_qf , m_I_qf_long_term ); + m_encparams.SetQf( m_qf ); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.h new file mode 100644 index 000000000..a54bb5d95 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/rate_control.h @@ -0,0 +1,221 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: rate_control.h,v 1.7 2008/01/31 11:25:18 tjdwave Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Myo Tun (Original Author, myo.tun@brunel.ac.uk) +* Jonathan Loo (Jonathan.Loo@brunel.ac.uk) +* School of Engineering and Design, Brunel University, UK +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +//Compression of an individual component, +//after motion compensation if appropriate +////////////////////////////////////////// + +#ifndef _RATE_CONTROL_H_ +#define _RATE_CONTROL_H_ + +#include <libdirac_common/common.h> + +namespace dirac +{ + class FrameComplexity + { + public: + //! Default constructor + FrameComplexity(); + + //! Return the complexity of I frame + int IComplexity() {return m_XI;} + + //! Return the complexity of L1 frame + int L1Complexity() {return m_XL1;} + + //! Return the complexity of L2 frame + int L2Complexity() {return m_XL2;} + + //! Set the complexity of I frame + void SetIComplexity(int cpx) {m_XI = cpx;} + + //! Set the complexity of L1 frame + void SetL1Complexity(int cpx) {m_XL1 = cpx;} + + //! Set the complexity of L2 frame + void SetL2Complexity(int cpx) {m_XL2 = cpx;} + + + private: + + //! Complexity of I frame + int m_XI; + + //! Complexity of L1 frame + int m_XL1; + + //! Complexity of L2 frame + int m_XL2; + }; + + + //! A clas for allocation the bits to each and every types of frames in a GOP + class RateController + { + public: + + //! Default constructor + RateController(int trate, SourceParams& srcp, EncoderParams& encp); + + + //! Calculate the Quality factor of the next frame to encode + void CalcNextQualFactor(const PictureParams& fparams, int num_bits); + + //! Calculate the Quality factor of the next I frame to encode + void CalcNextIntraQualFactor(); + + //! Use the long-term average intra quality factor + void SetCutPictureQualFactor(); + + //! Return I frame qf + double IntraQualFactor() {return m_I_qf;} + + //! Return qf + double QualFactor() {return m_qf;} + + //! Report the allocation to picture types + void Report(); + + + private: + + double TargetSubgroupRate(); + + double ProjectedSubgroupRate(); + + //! Allocate the bits to each type of frame in a GOP + void Allocate(const int fnum); + + //! Calculate the total number of bits in a GOP + void CalcTotalBits(const SourceParams& sourceparams); + + //! Set the value of Current IQF + void SetIntraQualFactor(double value){m_I_qf = value;} + + //! Set the number of I, L1 and L2 frames in the GOP + void SetFrameDistribution(); + + //! Review the quality factor to make sure it's being set sensibly + float ReviewQualityFactor( const float qfac, const long int num_bits ); + + //! Clip the quality factor to something sensible + float ClipQualityFactor( const float qfac ); + + //! Update the internal decoder buffer model + void UpdateBuffer( const long int num_bits ); + + + private: + + //! Current Quality Factor + double m_qf; + + //! I frame Quality Factor + double m_I_qf; + + //! Long-term average of I frame Quality Factor + double m_I_qf_long_term; + + //! Target bit rate in kbps + const int m_target_rate; + + //! Number of bits for I frame + long int m_Iframe_bits; + + //! Number of bits for L1 frame + long int m_L1frame_bits; + + //! Number of bits for L2 frame + long int m_L2frame_bits; + + //! Number of I frames + int m_num_Iframe; + + //! Number of L1 frames + int m_num_L1frame; + + //! Number of L2 frames + int m_num_L2frame; + + //! Total Number of bits in a GOP + long int m_total_GOP_bits; + + //! Mean number of bits in a picture + long int m_picture_bits; + + //! Size of the decoded bit buffer + const long int m_buffer_size; + + //! Number of bits in the buffer + long int m_buffer_bits; + + //! The old buffer occupancy + long int m_old_buffer_bits; + + //! The rate of change of buffer occupancy + double m_buffer_rate_of_change; + + //! The target number of bits for the current GOP + long int m_GOP_target; + + //! The duration of a GOP + double m_GOP_duration; + + //! A reference to the encoder parameters + EncoderParams& m_encparams; + + //! A class to hold the frame complexity object + FrameComplexity m_frame_complexity; + + //! A frame counter, giving the position within a subgroup + int m_fcount; + + // Indicated whether a sequence is being coded intra only or not + bool m_intra_only; + + // Sum of complexity of L2 frames + int m_L2_complexity_sum; + + }; + + +}// namespace dirac +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/seq_compress.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/seq_compress.cpp new file mode 100644 index 000000000..da4f73b2b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/seq_compress.cpp @@ -0,0 +1,892 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: seq_compress.cpp,v 1.87 2008/10/29 02:42:06 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Anuradha Suraparaju, +* Andrew Kennedy +* Myo Tun (Brunel University, myo.tun@brunel.ac.uk) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_encoder/seq_compress.h> +#include <libdirac_encoder/prefilter.h> + +using namespace dirac; + +SequenceCompressor::SequenceCompressor( StreamPicInput* pin , + EncoderParams& encp, + DiracByteStream& dirac_byte_stream): + m_all_done(false), + m_just_finished(true), + m_srcparams(pin->GetSourceParams()), + m_encparams(encp), + m_predparams(encp.GetPicPredParams()), + m_L1_sep(encp.L1Sep()), + m_pparams(m_srcparams.CFormat(), + m_encparams.Xl(), + m_encparams.Yl(), + m_encparams.LumaDepth(), + m_encparams.ChromaDepth() ), + m_pic_in(pin), + m_current_display_pnum(-1), + m_current_code_pnum(0), + m_show_pnum(-1),m_last_picture_read(-1), + m_gop_start_num(0), + m_delay(1), + m_qmonitor( m_encparams ), + m_pcoder( m_encparams ), + m_dirac_byte_stream(dirac_byte_stream), + m_eos_signalled(false) +{ + // Set up the compression of the sequence + + //TBD: put into the constructor for EncoderParams + m_encparams.SetEntropyFactors( new EntropyCorrector(m_encparams.TransformDepth()) ); + + // Set up generic picture parameters + m_pparams.SetUsingAC(m_encparams.UsingAC() ); + + // Set up a rate controller if rate control being used + if (m_encparams.TargetRate() != 0) + m_ratecontrol = new RateController(m_encparams.TargetRate(), + m_pic_in->GetSourceParams(), encp); + + // Copy in the block parameters in case we want to change them dynamically + m_basic_olb_params2 = &m_predparams.LumaBParams(2); + m_basic_olb_params1 = new OLBParams( 2*m_predparams.LumaBParams(2).Xblen(), + 2*m_predparams.LumaBParams(2).Yblen(), + 2*m_predparams.LumaBParams(2).Xbsep(), + 2*m_predparams.LumaBParams(2).Ybsep() ); + + m_basic_olb_params0 = new OLBParams( 4*m_predparams.LumaBParams(2).Xblen(), + 4*m_predparams.LumaBParams(2).Yblen(), + 4*m_predparams.LumaBParams(2).Xbsep(), + 4*m_predparams.LumaBParams(2).Ybsep() ); + + + m_intra_olbp = new OLBParams( 2*m_basic_olb_params2->Xbsep() , + 2*m_basic_olb_params2->Ybsep() , + m_basic_olb_params2->Xbsep() , + m_basic_olb_params2->Ybsep() ); + + SetMotionParameters(); + +} + +void SequenceCompressor::SetMotionParameters(){ + + if ( m_encparams.TargetRate() != 0 ){ + OLBParams new_olb_params = *m_basic_olb_params2; + + if (m_encparams.Qf()<2.5) + new_olb_params = *m_basic_olb_params1; + else if (m_encparams.Qf()<1.5) + new_olb_params = *m_basic_olb_params0; + + m_predparams.SetBlockSizes( new_olb_params , m_srcparams.CFormat() ); + + } + + int xl = m_encparams.Xl(); + int yl = m_encparams.Yl(); + + // Make sure we have enough macroblocks to cover the pictures + m_predparams.SetXNumSB( (xl+m_predparams.LumaBParams(0).Xbsep()-1)/ + m_predparams.LumaBParams(0).Xbsep() ); + m_predparams.SetYNumSB( (yl+m_predparams.LumaBParams(0).Ybsep()-1)/ + m_predparams.LumaBParams(0).Ybsep() ); + + m_predparams.SetXNumBlocks( 4 * m_predparams.XNumSB() ); + m_predparams.SetYNumBlocks( 4 * m_predparams.YNumSB() ); +} + + +SequenceCompressor::~SequenceCompressor() +{ + delete m_intra_olbp; + delete m_basic_olb_params1; + delete m_basic_olb_params0; + + if ( m_encparams.Verbose()) + MakeSequenceReport(); + + //TBD: put into the destructor for EncoderParams + delete &m_encparams.EntropyFactors(); + + if (m_encparams.TargetRate()!=0) + delete m_ratecontrol; +} + +bool SequenceCompressor::CanEncode() +{ + const int queue_size = std::max( 4 , 2*m_encparams.L1Sep() ); + + if (m_eos_signalled) + { + if (m_encparams.NumL1() > 0) + { + /* + * Long-GOP sequence + */ + int field_factor = m_encparams.PictureCodingMode() ? 2 : 1; + int last_frame_read = m_last_picture_read/field_factor; + int current_code_fnum = m_current_code_pnum/field_factor; + + if ((last_frame_read >= (current_code_fnum + (last_frame_read%m_encparams.L1Sep())))) + return true; + + /* + * Encode the remaining picture in the frame buffer. We check if + * the reference pictures are available and modify the picture sort + * accordingly. + */ + if (current_code_fnum <= last_frame_read) + { + m_current_display_pnum = m_current_code_pnum; + return true; + } + } + else + { + if (m_last_picture_read >= m_current_display_pnum) + return true; + } + } + else + { + if (m_last_picture_read >= m_current_display_pnum + queue_size) + return true; + } + return false; +} + +const EncPicture* SequenceCompressor::CompressNextPicture() +{ + + // This function codes the next picture in coding order and returns the next picture in display order + // In general these will differ, and because of re-ordering there is a m_delay which needs to be imposed. + // This creates problems at the start and at the end of the sequence which must be dealt with. + // At the start we just keep outputting picture 0. At the end you will need to loop for longer to get all + // the pictures out. It's up to the calling function to do something with the decoded pictures as they + // come out - write them to screen or to file, or whatever. + + // current_pnum is the number of the current picture being coded in display order + // m_current_code_pnum is the number of the current picture in coding order. This function increments + // m_current_code_pnum by 1 each time and works out what the number is in display order. + // m_show_pnum is the index of the picture number that can be shown when current_pnum has been coded. + // Var m_delay is the m_delay caused by reordering (as distinct from buffering) + + TESTM (m_last_picture_read >= 0, "Data loaded before calling CompressNextPicture"); + + const int field_factor = m_encparams.FieldCoding() ? 2 : 1; + + // If we have a scheduled P picture, reset the P separation to normal + if ( m_encparams.L1Sep()!=m_L1_sep ){ + if ( (m_current_code_pnum-field_factor) % (m_encparams.L1Sep()*field_factor)==0 ) + m_L1_sep = m_encparams.L1Sep(); + } + + m_current_display_pnum = CodedToDisplay( m_current_code_pnum ); + m_show_pnum = std::max( m_current_code_pnum - m_delay , 0 ); + + if ( CanEncode() ) + { + + // Compress the picture// + /////////////////////// + + const std::vector<int>& queue_members = m_enc_pbuffer.Members(); + + EncPicture* current_pic = &m_enc_pbuffer.GetPicture( m_current_display_pnum ); + PictureParams* current_pp = ¤t_pic->GetPparams(); + + // 1. Set the picture type and refs for all the pictures in the queue not already encoded + for (size_t i=0; i<queue_members.size(); ++i){ + int pnum = queue_members[i]; + EncPicture& enc_pic = m_enc_pbuffer.GetPicture(pnum); + + if ( (enc_pic.GetStatus() & DONE_SET_PTYPE) == 0 ){ + PictureParams& pparams = enc_pic.GetPparams(); + // only look one subgroup ahead + if ((m_encparams.NumL1() == 0) || pparams.PictureNum() < m_current_display_pnum + m_encparams.L1Sep() ){ + SetPicTypeAndRefs( pparams ); + enc_pic.UpdateStatus( DONE_SET_PTYPE ); + } + } + } + + /* Do motion estimation and compensation if inter*/ + bool is_a_cut( false ); + + //2. Set up block sizes etc + SetMotionParameters(); + + // Loop over the whole queue and ... + for (size_t i=0; i<queue_members.size(); ++i){ + int pnum = queue_members[i]; + EncPicture& enc_pic = m_enc_pbuffer.GetPicture(pnum); + + if ( ( enc_pic.GetStatus() & DONE_SET_PTYPE) != 0 ){ + PictureParams& pparams = enc_pic.GetPparams(); + + if ( pparams.PicSort().IsInter() ){ + // 3.Initialise motion data + if ( ( enc_pic.GetStatus() & DONE_ME_INIT) == 0 ){ + enc_pic.InitMEData( m_predparams , pparams.NumRefs() ); + enc_pic.UpdateStatus( DONE_ME_INIT ); + } + + // 4. Do pixel-accurate motion estimation + if ( ( enc_pic.GetStatus() & DONE_PEL_ME) == 0 ){ + m_pcoder.PixelME( m_enc_pbuffer, pnum ); + enc_pic.UpdateStatus( DONE_PEL_ME ); + } + +// // 5. Set picture complexity +// if ( (enc_pic.GetStatus() & DONE_PIC_COMPLEXITY ) == 0 ){ +// m_pcoder.CalcComplexity( m_enc_pbuffer, pnum, m_predparams.LumaBParams(2) ); +// enc_pic.UpdateStatus( DONE_PIC_COMPLEXITY ); +// } + + //6. Revise the number of references if one ref is a bad predictor +// if ( (enc_pic.GetStatus() & DONE_PIC_COMPLEXITY)!=0 && +// pparams.NumRefs()==2){ +// if (enc_pic.GetPredBias()>0.8) +// enc_pic.DropRef(2); +// else if(enc_pic.GetPredBias()<0.2) +// enc_pic.DropRef(1); +// } + } + } + + } + if ( current_pp->PicSort().IsInter() ){ +// // 7. Normalise complexity for the current picture +// m_pcoder.NormaliseComplexity( m_enc_pbuffer, m_current_display_pnum ); + + bool subgroup_reconfig; + + do{ + subgroup_reconfig = false; + + //8. Do subpel refinement + m_pcoder.SubPixelME( m_enc_pbuffer, m_current_display_pnum ); + + //9. Do mode decision + m_pcoder.ModeDecisionME( m_enc_pbuffer, m_current_display_pnum ); + + //10. Work out how many blocks are intra + m_pcoder.IntraModeAnalyse( m_enc_pbuffer, m_current_display_pnum ); + + //11. Change the GOP structure to PPP if there are too many intras + if ( m_L1_sep>1 && current_pic->GetMEData().IntraBlockRatio()>0.25 + && (m_current_display_pnum % (m_encparams.L1Sep()*field_factor))==0){ + + subgroup_reconfig = true; + + m_L1_sep = 1; + for (int i = 0; i<field_factor*m_encparams.L1Sep(); ++i){ + + int pnum = m_current_display_pnum-i+(field_factor-1); + + EncPicture& enc_pic = m_enc_pbuffer.GetPicture(pnum); + PictureParams& pparams = enc_pic.GetPparams(); + + SetPicTypeAndRefs( pparams ); + enc_pic.UpdateStatus( DONE_SET_PTYPE ); + } + current_pic->SetStatus( DONE_SET_PTYPE ); + + // Current picture to code has now changed: recalculate + m_current_display_pnum = CodedToDisplay( m_current_code_pnum ); + current_pic = &m_enc_pbuffer.GetPicture(m_current_display_pnum ); + current_pp = ¤t_pic->GetPparams(); + + } + + }while(subgroup_reconfig==true); + + //11. Do cut detection and insert intra pictures + if ( current_pic->GetMEData().IntraBlockRatio()>0.3333 ){ + is_a_cut = true; + if ( m_encparams.L1Sep()>1 && + (m_current_display_pnum % (field_factor*m_encparams.L1Sep())) == 0){ + m_gop_start_num = current_pp->PictureNum();//restart the GOP + } + + if ( current_pp->PicSort().IsRef() ) // Set the picture type to intra + current_pic->SetPictureSort (PictureSort::IntraRefPictureSort()); + else + current_pic->SetPictureSort (PictureSort::IntraNonRefPictureSort()); + + if ( m_encparams.Verbose() ) + std::cout<<std::endl<<"Cut detected and I-picture inserted!"; + + } + else{ + //12. Do motion compensation if not a cut +// MEData& me_data = current_pic->GetMEData(); +// +// if (me_data.IntraBlockRatio()>0.1)//FIXME: this is broken with adaptive block sizes +// m_predparams.SetBlockSizes(*m_intra_olbp, m_srcparams.CFormat() ); + + m_pcoder.MotionCompensate(m_enc_pbuffer, m_current_display_pnum, SUBTRACT ); + current_pic->UpdateStatus( DONE_MC ); + } + + } + + if ( current_pp->PicSort().IsRef()==true ) + m_enc_pbuffer.SetRetiredPictureNum( m_show_pnum, m_current_display_pnum ); + + // 12. Now code the residual data and motion data + if (m_encparams.TargetRate() != 0) + UpdateIntraPicCBRModel( *current_pp, is_a_cut ); + + // 13. Write a sequence header if necessary + if( (m_encparams.NumL1() > 0 && current_pp->PicSort().IsRef()==true && + current_pp->PicSort().IsIntra()==true && (m_current_display_pnum % m_encparams.L1Sep() == 0)) || + (m_encparams.NumL1() == 0 && (m_current_display_pnum % m_encparams.GOPLength())==0)) + { + if (m_encparams.Verbose()) + { + std::cout<<std::endl<<std::endl<<"GOP start: writing sequence header before picture "; + std::cout<<m_current_display_pnum; + } + SequenceHeaderByteIO *p_seqheader_byteio = new SequenceHeaderByteIO + ( m_pic_in->GetSourceParams(), + m_encparams); + p_seqheader_byteio->Output(); + + m_dirac_byte_stream.AddSequenceHeader(p_seqheader_byteio); + } + + // 13. Write the picture header. + PictureByteIO* p_picture_byteio = new PictureByteIO(*current_pp, m_current_display_pnum ); + p_picture_byteio->Output(); + + if ( m_encparams.Verbose() ){ + if (m_encparams.TargetRate()!=0 ) + m_ratecontrol->Report(); + + if (m_encparams.FieldCoding()) + std::cout<<std::endl<<std::endl<<"Compressing field "<<m_current_code_pnum<<", "; + else + std::cout<<std::endl<<std::endl<<"Compressing frame "<<m_current_code_pnum<<", "; + std::cout<<m_current_display_pnum<<" in display order"; + + if (is_a_cut==true || current_pp->PicSort().IsIntra()==false ) + std::cout<<std::endl<<current_pic->GetMEData().IntraBlockRatio()*100.0<<"% of blocks are intra "; + if (is_a_cut==true) + std::cout<<std::endl<<"Cut detected and intra picture inserted."; + + std::cout<<std::endl<<"Picture type is "; + if (current_pp->PicSort().IsRef() ) + std::cout<<"REF"; + else std::cout<<"NON-REF"; + + std::cout<<" , "; + if (current_pp->PicSort().IsIntra()) + std::cout<<"INTRA"; + else std::cout<<"INTER"; + + if ( current_pp->PicSort().IsInter() ){ + std::cout<<std::endl<<"References " + << (m_encparams.FieldCoding() ? "field " : "frame ") + << current_pp->Refs()[0]; + if (current_pp->Refs().size() > 1) + std::cout<<" and "<< current_pp->Refs()[1]; + } + } + + // 14. Code the motion vectors + if ( current_pp->PicSort().IsInter() ) + m_pcoder.CodeMVData(m_enc_pbuffer , m_current_display_pnum, p_picture_byteio); + + // 15. Do prefiltering on the residue if necessary + if (m_encparams.Prefilter() != NO_PF ) + m_pcoder.Prefilter( m_enc_pbuffer, m_current_display_pnum ); + + // 16. Do the transform on the 3 components + m_pcoder.DoDWT( m_enc_pbuffer, m_current_display_pnum , FORWARD); + + // 17. Select the quantisers + + // 18. Code the residue + m_pcoder.CodeResidue(m_enc_pbuffer , m_current_display_pnum, p_picture_byteio); + + const PictureSort& psort = current_pp->PicSort(); + + /* All coding is done - so output and reconstruct */ + + m_dirac_byte_stream.AddPicture(p_picture_byteio); + + // 19. Do the inverse DWT if necessary + m_pcoder.DoDWT( m_enc_pbuffer, m_current_display_pnum , BACKWARD); + + + // 20. Motion compensate back if necessary + if (psort.IsInter() && !is_a_cut ) + m_pcoder.MotionCompensate(m_enc_pbuffer, m_current_display_pnum, ADD ); + + // Reset block sizes for next picture + m_predparams.SetBlockSizes(*m_basic_olb_params2, m_srcparams.CFormat() ); + + // 21. Clip the data to keep it in range + current_pic->Clip(); + + // Use the results of encoding to update the CBR model + if (m_encparams.TargetRate() != 0 ) + UpdateCBRModel(*current_pic, p_picture_byteio); + + // 22. Measure the encoded picture quality + if ( m_encparams.LocalDecode() ) + m_qmonitor.UpdateModel( *current_pic ); + + // Increment our position + m_current_code_pnum++; + + CleanBuffers(); + + current_pic->SetStatus( ALL_ENC ); + + } + + // Return the latest picture that can be shown + if ( m_enc_pbuffer.GetPicture(m_show_pnum).GetStatus() == ALL_ENC ){ + if ( m_encparams.Verbose() ){ + std::cout<<std::endl<<"Return " << + (m_encparams.FieldCoding() ? "field " : "frame ") << + m_show_pnum << " in display order"; + } + return &m_enc_pbuffer.GetPicture(m_show_pnum ); + } + else + return NULL; +} + + + +void SequenceCompressor::CleanBuffers() +{ + // If we're not at the beginning, clean the buffer + if ( m_current_code_pnum != 0 ) + m_enc_pbuffer.CleanRetired( m_show_pnum, m_current_display_pnum ); +} + +const EncPicture *SequenceCompressor::GetPictureEncoded() +{ + if (m_current_display_pnum >= 0) + return &m_enc_pbuffer.GetPicture( m_current_display_pnum ); + + return 0; +} + +DiracByteStats SequenceCompressor::EndSequence() +{ + DiracByteStats seq_stats; + + if (m_just_finished) + { + seq_stats=m_dirac_byte_stream.EndSequence(); + m_just_finished = false; + m_all_done = true; + } + + return seq_stats; +} + + + +void SequenceCompressor::MakeSequenceReport() +{ + if ( m_encparams.LocalDecode() ) + m_qmonitor.WriteLog(); + + std::cout<<std::endl; + +} + +void SequenceCompressor::UpdateIntraPicCBRModel( const PictureParams& pparams, const bool is_a_cut ){ + // For intra pictures we want to update before coding + // especially if they're inserted + + if ( pparams.PicSort().IsIntra() && m_current_display_pnum > 0 && + m_encparams.NumL1() != 0){ + // Calculate the new QF for encoding the following I picture + if ( is_a_cut ) + m_ratecontrol->SetCutPictureQualFactor(); + else + m_ratecontrol->CalcNextIntraQualFactor(); + } +} + +FrameSequenceCompressor::FrameSequenceCompressor( + StreamPicInput* pin , + EncoderParams& encp, + DiracByteStream& dirac_byte_stream): + SequenceCompressor(pin, encp, dirac_byte_stream) +{ +} + +void FrameSequenceCompressor::SetPicTypeAndRefs( PictureParams& pparams ) +{ + // Set the temporal prediction parameters for frame coding + + const int pnum = pparams.PictureNum(); + const int rel_pnum = pnum - m_gop_start_num; + const int gop_len = m_encparams.GOPLength(); + const int num_L1 = m_encparams.NumL1(); + + pparams.SetRetiredPictureNum( -1 ); + pparams.Refs().clear(); + + if ( num_L1>0 ){ + + if ( rel_pnum % gop_len == 0){ + if (gop_len > 1) + pparams.SetPicSort( PictureSort::IntraRefPictureSort()); + else // I-picture only coding + pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); + + // I picture expires after we've coded the next I picture + pparams.SetExpiryTime( 2*m_L1_sep ); + } + else if (rel_pnum % m_L1_sep == 0){ + pparams.SetPicSort( PictureSort::InterRefPictureSort()); + + // Ref the previous I or L1 picture + pparams.Refs().push_back( pnum - m_L1_sep ); + + // if we don't have the first L1 picture ... + if ( ((rel_pnum-m_L1_sep) % gop_len>0) && m_L1_sep>1) + // ... other ref is the prior I/L1 picture but one + pparams.Refs().push_back( pnum - 2*m_L1_sep ); + + // Expires after the next L1 or I picture + pparams.SetExpiryTime( 2*m_L1_sep ); + if (rel_pnum % m_encparams.L1Sep() == 0 ) + pparams.SetExpiryTime(2*m_encparams.L1Sep()); + } + else if ((rel_pnum+1) % m_L1_sep == 0){ + pparams.SetPicSort( PictureSort::InterNonRefPictureSort()); + + // .. and the previous picture + pparams.Refs().push_back(pnum-1); + // Refs are the next I or L1 picture ... + if (m_enc_pbuffer.IsPictureAvail(pnum+1)) + pparams.Refs().push_back(pnum+1); + + pparams.SetExpiryTime( 1 ); + } + else{ + pparams.SetPicSort( PictureSort::InterRefPictureSort()); + + // .. and the previous picture + pparams.Refs().push_back(pnum-1); + // Refs are the next I or L1 picture ... + int next_ref = ((pnum/m_L1_sep)+1)*m_L1_sep; + if (m_enc_pbuffer.IsPictureAvail(next_ref)) + pparams.Refs().push_back(next_ref); + + pparams.SetExpiryTime( 2 ); + } + + } + else{ + pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); + pparams.SetExpiryTime( 1 ); + } + +} + +bool FrameSequenceCompressor::LoadNextFrame() +{ + PictureParams pp( m_pparams ); + pp.SetPictureNum( m_last_picture_read+1 ); + + // Set an initially huge expiry time as we don't know when it will expire yet + pp.SetExpiryTime(1<<30); + + m_enc_pbuffer.PushPicture( pp ); + + m_pic_in->ReadNextPicture( m_enc_pbuffer.GetPicture(m_last_picture_read+1) ); + + // Copy into the original data + m_enc_pbuffer.GetPicture(m_last_picture_read+1).SetOrigData(); + + if ( m_encparams.Prefilter()==CWM ) + CWMFilter(m_enc_pbuffer.GetPicture( m_last_picture_read+1 ) , + m_encparams.PrefilterStrength() ); + + if ( m_pic_in->End() ) + { + m_all_done = true; + return false; + } + + m_last_picture_read++; + + return true; +} + +int FrameSequenceCompressor::CodedToDisplay( const int cnum ) +{ + int div; + + if (m_L1_sep>0) + { + // We have L1 and L2 pictures + if (cnum==0) + return 0; + else if ((cnum-1)% m_L1_sep==0) + {//we have L1 or subsequent I pictures + div=(cnum-1)/m_L1_sep; + return cnum+m_L1_sep-1; + } + else//we have L2 pictures + return cnum-1; + } + else + {//we just have I-pictures, so no re-ordering + + return cnum; + } +} + +void FrameSequenceCompressor::UpdateCBRModel(EncPicture& my_frame, + const PictureByteIO* p_picture_byteio) +{ + // Update the quality factor + m_ratecontrol->CalcNextQualFactor(my_frame.GetPparams(), p_picture_byteio->GetSize()*8); + +} + + +FieldSequenceCompressor::FieldSequenceCompressor( + StreamPicInput* pin , + EncoderParams& encp, + DiracByteStream& dirac_byte_stream): + SequenceCompressor(pin, encp, dirac_byte_stream) +{ + m_delay = 2; +} + +bool FieldSequenceCompressor::LoadNextFrame() +{ + PictureParams pp( m_pparams ); + pp.SetExpiryTime( 1<<30 ); + + int pnum = m_last_picture_read+1; + + for (int j=pnum; j<=pnum+1; ++j){ + pp.SetPictureNum( j ); + m_enc_pbuffer.PushPicture( pp ); + } + + StreamFieldInput* field_input = (StreamFieldInput*) m_pic_in; + field_input->ReadNextFrame( m_enc_pbuffer.GetPicture( pnum ), m_enc_pbuffer.GetPicture(pnum+1) ); + + // Copy data across + for (int j=pnum; j<=pnum+1; ++j){ + m_enc_pbuffer.GetPicture( j ).SetOrigData(); + + if ( m_encparams.Prefilter()==CWM ) + CWMFilter(m_enc_pbuffer.GetPicture( j ), m_encparams.PrefilterStrength() ); + + } + + if ( m_pic_in->End() ){ + m_all_done = true; + return false; + } + + m_last_picture_read +=2; + + return true; +} + +void FieldSequenceCompressor::PreMotionEstmationFilter(PicArray& comp) +{ + //Special case for first row + for (int i = comp.FirstX(); i <= comp.LastX(); ++i) + { + comp[comp.FirstY()][i] = (3*comp[comp.FirstY()][i] + + comp[comp.FirstY()+1][i] +2 )>>2; + } + //Middle section + for (int j = comp.FirstY()+1; j < comp.LastY(); ++j) + { + for (int i = comp.FirstX(); i <= comp.LastX(); ++i) + { + comp[j][i] = (comp[j-1][i] + 2*comp[j][i] + comp[j+1][i] + 2)>>2; + } + } + //Special case for last row + for (int i = comp.FirstX(); i <= comp.LastX(); ++i) + { + comp[comp.LastY()][i] = (comp[comp.LastY()-1][i] + + 3*comp[comp.LastY()][i] + 2)>>2; + } +} + +void FieldSequenceCompressor::SetPicTypeAndRefs( PictureParams& pparams ) +{ +// FIXME: won't work with adaptive GOP properly + // Set the temporal prediction parameters for field coding + + const int pnum = pparams.PictureNum(); + const int rel_pnum = pparams.PictureNum()-m_gop_start_num; + const int gop_len = m_encparams.GOPLength(); + const int num_L1 = m_encparams.NumL1(); + + pparams.SetRetiredPictureNum( -1 ); + pparams.Refs().clear(); + + if ( num_L1>0 ){ + + if ( (rel_pnum/2) % gop_len == 0){ + // Field 1 is Intra Field + if (gop_len > 1){ + pparams.SetPicSort( PictureSort::IntraRefPictureSort()); + // I picture expires after we've coded the next L1 picture + pparams.SetExpiryTime( gop_len * 2); + pparams.SetExpiryTime( 2*m_L1_sep ); + if ( pnum%2){ + pparams.SetPicSort( PictureSort::InterRefPictureSort()); + // Ref the previous I field + pparams.Refs().push_back( pnum-1 ); + } + } + else{ + // I-picture only coding + pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); + pparams.SetExpiryTime( gop_len ); + } + } + else if ((rel_pnum/2) % m_L1_sep == 0){ + + pparams.SetPicSort( PictureSort::InterRefPictureSort()); + + if (pnum%2){ + // Field 2 + // Ref the first field of same picture + pparams.Refs().push_back( pnum - 1); + // Ref the previous field 2 of I or L1 picture + pparams.Refs().push_back( pnum - m_L1_sep*2 ); + } + else{ + // Field 1 + // Ref the field 1 of previous I or L1 picture + pparams.Refs().push_back( pnum - m_L1_sep*2 ); + // Ref the field 2 of previous I or L1 picture + pparams.Refs().push_back( pnum - m_L1_sep*2 + 1 ); + } + + // Expires after the next L1 or I picture + pparams.SetExpiryTime( (m_L1_sep+1)*2-1 ); + if ((rel_pnum/2) % m_encparams.L1Sep() == 0 ) + pparams.SetExpiryTime((2*m_encparams.L1Sep())+1*2-1); + } + else if ((rel_pnum/2+1) % m_L1_sep == 0){ + // Bi-directional non-reference fields. + if (pnum%2) + pparams.SetPicSort( PictureSort::InterNonRefPictureSort()); + else + pparams.SetPicSort( PictureSort::InterRefPictureSort()); + + pparams.Refs().push_back(pnum-1); + if (m_enc_pbuffer.IsPictureAvail(pnum+2)) + pparams.Refs().push_back(pnum+2); + + pparams.SetExpiryTime( 1 ); + } + else{ + // Bi-directional reference fields. + pparams.SetPicSort( PictureSort::InterRefPictureSort()); + + pparams.Refs().push_back(pnum-1); + int next_ref = (((pnum/2)/m_L1_sep+1)*m_L1_sep)*2+(pnum%2); + if (m_enc_pbuffer.IsPictureAvail(next_ref)) + pparams.Refs().push_back(next_ref); + pparams.SetExpiryTime( 4 ); + } + + } + else{ + pparams.SetPicSort( PictureSort::IntraNonRefPictureSort()); + pparams.SetExpiryTime( 2 ); + } +} + +FieldSequenceCompressor::~FieldSequenceCompressor() +{ +} + +int FieldSequenceCompressor::CodedToDisplay( const int pnum ) +{ + // Frame the field pnum belongs to + int fnum = pnum>>1; + if (m_L1_sep>0) + { + // We have L1 and L2 frames + if (fnum==0) + return pnum; + else if ((fnum-1)% m_L1_sep==0) + {//we have L1 or subsequent I frames + return (pnum+(m_L1_sep-1)*2); + } + else//we have L2 frames + return (pnum - 2); + } + else + {//we just have I-frames, so no re-ordering + return (pnum); + } +} + +void FieldSequenceCompressor::UpdateCBRModel(EncPicture& my_picture, + const PictureByteIO* p_picture_byteio) +{ + if (m_current_display_pnum%2 == 0) + m_field1_bytes = p_picture_byteio->GetSize(); + else + m_field2_bytes = p_picture_byteio->GetSize(); + + // Update the quality factor + if (my_picture.GetPparams().PictureNum()%2) + m_ratecontrol->CalcNextQualFactor(my_picture.GetPparams(), (m_field1_bytes+m_field2_bytes)*8); + +} + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/seq_compress.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/seq_compress.h new file mode 100644 index 000000000..37f5496be --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_encoder/seq_compress.h @@ -0,0 +1,387 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: seq_compress.h,v 1.33 2008/10/20 04:20:12 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Scott R Ladd, +* Anuradha Suraparaju +* Andrew Kennedy +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _SEQ_COMPRESS_H_ +#define _SEQ_COMPRESS_H_ + +///////////////////////////////////////// +//-------------------------------------// +//Class to manage compressing sequences// +//-------------------------------------// +///////////////////////////////////////// + +#include <libdirac_byteio/dirac_byte_stream.h> +#include <libdirac_common/common.h> +#include <libdirac_encoder/enc_queue.h> +#include <libdirac_common/pic_io.h> +#include <libdirac_common/dirac_assertions.h> +#include <libdirac_encoder/quality_monitor.h> +#include <libdirac_encoder/picture_compress.h> +#include <libdirac_encoder/rate_control.h> + +#include <fstream> + +namespace dirac +{ + + //! Compresses a sequence of frames/fields from a stream. + /*! + This class compresses a sequence of frames/fields, frame by frame. + or field by field. It currently uses GOP parameters set in the encoder + parameters in order to define the temporal prediction structure. + A version to incorporate non-GOP structures is TBC. + + This is an abstract class. + */ + class SequenceCompressor{ + public: + //! Constructor + /*! + Creates a sequence compressor, and prepares to begin compressing + with the first picture.Sets up picture padding in the picture input if + necesary + \param pin an input stream containing a sequence of frames + \param encp parameters for the encoding process + \param dirac_byte_stream Output destination for compressed data + */ + SequenceCompressor(StreamPicInput* pin, + EncoderParams& encp, + DiracByteStream& dirac_byte_stream); + + //! Destructor + /*! + Destructor. Must delete IO objects created by constructor. + */ + virtual ~SequenceCompressor(); + + //! Load data + /*! + Load one picture of data into the Sequence Compressor. Sets + m_all_done to true if no more data is available to be loaded. + Input can be frame or field. So the child class will have to + implement this function. + \return true - if frame load succeeded. + false - otherwise + */ + virtual bool LoadNextFrame() = 0; + + //! Compress the next picture in sequence + /*! + This function codes the next picture in coding order and returns the + next picture in display order. In general these will differ, and + because of re-ordering there is a delay which needs to be imposed. + This creates problems at the start and at the end of the sequence + which must be dealt with. At the start we just keep outputting + picture 0. At the end you will need to loop for longer to get all + the pictures out. It's up to the calling function to do something + with the decoded pictures as they come out -- write them to screen + or to file, for example. . + If coding is fast enough the compressed version could be watched + real-time (with suitable buffering in the calling function to + account for encode-time variations). + + NOTE: LoadNextFrame must be called atleast once before invoking this + method. + + \return pointer to the next locally decoded picture available for display + */ + const EncPicture *CompressNextPicture(); + + //! Set up the appropriate prediction parameters for a picture + virtual void SetPicTypeAndRefs( PictureParams& pparams ) = 0; + + //! Return a pointer to the most recent picture encoded + const EncPicture *GetPictureEncoded(); + + DiracByteStats EndSequence(); + + //! Determine if compression is complete. + /*! + Indicates whether or not the last picture in the sequence has been + compressed. + \return true if last picture has been compressed; false if not + */ + bool Finished(){return m_all_done;} + + //! Signal end of sequence + void SignalEOS() { m_eos_signalled = true; } + + //! The delay required for correct timestamps + int PTSOffset(){return m_delay;} + + protected: + + //! Set up the motion block parameters + void SetMotionParameters(); + + //! Uses the GOP parameters to convert picture numbers in coded order to display order. + /*! + Uses the GOP parameters to convert picture numbers in coded order + to display order. Pure virtual function. The child class will + have to define it. + \param pnum the picture number in coded order + */ + virtual int CodedToDisplay(const int pnum) = 0; + + //! Make a report to screen on the coding results for the whole sequence + void MakeSequenceReport(); + + //! Remove unwanted pictures from picture buffers + virtual void CleanBuffers(); + + //! Update the CBR model based on the data we've compressed. + //Purely virtual. The child class will have to define it. + virtual void UpdateCBRModel(EncPicture& my_picture, const PictureByteIO* picture_byteio) = 0; + + //! Update the parameters to be used in advance of coding an intra frame + void UpdateIntraPicCBRModel( const PictureParams& , const bool is_a_cut ); + + //! Returns true if the encoder can encode a picture + bool CanEncode(); + + //! Completion flag, returned via the Finished method. + bool m_all_done; + + //! Flag indicating whether we've just finished. + /*! + Flag which is false if we've been all-done for more than one + picture, true otherwise (so that we can take actions on finishing + once only). + */ + bool m_just_finished; + + //! A class to hold the basic block parameters + OLBParams* m_basic_olb_params0; + + //! A class to hold the basic block parameters + OLBParams* m_basic_olb_params1; + + //! A class to hold the basic block parameters + const OLBParams* m_basic_olb_params2; + + //! A class to hold block parameters to use when there are lots of intra blocks + OLBParams* m_intra_olbp; + + //! The parameters of the input source + SourceParams& m_srcparams; + + //! The parameters used for encoding. + EncoderParams& m_encparams; + + //! The parameters used for ME/MC + PicturePredParams& m_predparams; + + //! The L1 separation currently in use + int m_L1_sep; + + //! Generic picture parameters for initialising pictures + PictureParams m_pparams; + + //! Pointer pointing at the picture input. + StreamPicInput* m_pic_in; + + //! A picture buffer used for local storage of pictures whilst pending re-ordering or being used for reference. + EncQueue m_enc_pbuffer; + + //state variables for CompressNextPicture + + //! The number of the current picture to be coded, in display order + int m_current_display_pnum; + + //! The number of the current picture to be coded, in coded order + int m_current_code_pnum; + + //! The number of the picture which should be output for concurrent display or storage + int m_show_pnum; + + //! The index, in display order, of the last picture read + int m_last_picture_read; + + //! The picture number of the last GOP start + int m_gop_start_num; + + //! A delay so that we don't display what we haven't coded + int m_delay; + + //! A class for monitoring the quality of pictures and adjusting parameters appropriately + QualityMonitor m_qmonitor; + + //! A class for monitoring and controlling bit rate + RateController* m_ratecontrol; + + //! A class to hold the picture compressor object + PictureCompressor m_pcoder; + + //! Output destination for compressed data in bitstream format + DiracByteStream& m_dirac_byte_stream; + + //! Flag to check if End of Sequence has been signalled by the end user + bool m_eos_signalled; + + private: + //! Copy constructor is private and body-less + /*! + Copy constructor is private and body-less. This class should not + be copied. + */ + SequenceCompressor(const SequenceCompressor& cpy); + + //! Assignment = is private and body-less + /*! + Assignment = is private and body-less. This class should not be + assigned.. + */ + SequenceCompressor& operator=(const SequenceCompressor& rhs); + + + }; + + //! Compresses a sequence of frames from a stream. + /*! + This class compresses a sequence of frames, frame by frame. It + currently uses GOP parameters set in the encoder parameters in order + to define the temporal prediction structure. A version to incorporate + non-GOP structures is TBC. + */ + class FrameSequenceCompressor : public SequenceCompressor + { + public: + //! Constructor + /*! + Creates a sequence compressor that compresses frames i.e. + progressive data, and prepares to begin compressing + with the first frame.Sets up frame padding in the picture input if + necesary + \param pin an input stream containing a sequence of frames + \param encp parameters for the encoding process + \param dirac_byte_stream Output destination for compressed data + */ + FrameSequenceCompressor(StreamPicInput* pin, + EncoderParams& encp, + DiracByteStream& dirac_byte_stream); + + //! Destructor + /*! + Destructor. Must delete IO objects created by constructor. + */ + virtual ~FrameSequenceCompressor(){}; + + //! Load data + /*! + Load one frame of data into the Sequence Compressor. Sets + m_all_done to true if no more data is available to be loaded. + \return true - if frame load succeeded. + false - otherwise + */ + virtual bool LoadNextFrame(); + + //! Set up the appropriate prediction parameters for a picture + virtual void SetPicTypeAndRefs( PictureParams& pparams ); + +protected: + virtual int CodedToDisplay(const int pnum); + virtual void UpdateCBRModel(EncPicture& my_picture, const PictureByteIO* picture_byteio); + + }; + + //! Compresses a sequence of fields from a stream. + /*! + This class compresses a sequence of fields, field by field. It + currently uses GOP parameters set in the encoder parameters in order + to define the temporal prediction structure. A version to incorporate + non-GOP structures is TBC. + */ + class FieldSequenceCompressor : public SequenceCompressor + { + public: + //! Constructor + /*! + Creates a sequence compressor that compresses fields i.e. + interlaced data, and prepares to begin compressing + with the first field. + \param pin an input stream containing a sequence of frames + \param encp parameters for the encoding process + \param dirac_byte_stream Output destination for compressed data + */ + FieldSequenceCompressor(StreamPicInput* pin, + EncoderParams& encp, + DiracByteStream& dirac_byte_stream); + + //! Destructor + /*! + Destructor. Must delete IO objects created by constructor. + */ + virtual ~FieldSequenceCompressor(); + + //! Load data + /*! + Load one frame i.e. two fields of data into the Sequence + Compressor. Sets m_all_done to true if no more data is available + to be loaded. + \return true - if both fields load succeeded. + false - otherwise + */ + virtual bool LoadNextFrame(); + + + //! Set up the appropriate prediction parameters for a picture + virtual void SetPicTypeAndRefs( PictureParams& pparams ); + + protected: + + virtual int CodedToDisplay(const int pnum); + + virtual void UpdateCBRModel(EncPicture& my_picture, const PictureByteIO* picture_byteio); + private: + //! Filter fields + /*! + Low pass filter the components in the fields used in Motion + Estimation so that ME works better. Using a 1/4 1/2 1/4 filter + */ + void PreMotionEstmationFilter (PicArray& comp); + + // Field1 bytes + int m_field1_bytes; + // Field2 bytes + int m_field2_bytes; + }; +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/block_match.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/block_match.cpp new file mode 100644 index 000000000..bf5725c6e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/block_match.cpp @@ -0,0 +1,469 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: block_match.cpp,v 1.21 2008/10/29 02:46:22 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_motionest/block_match.h> +#include <libdirac_motionest/me_utils.h> +using namespace dirac; + +#include <cmath> +using std::vector; + +namespace dirac +{ + +void AddNewVlist( CandidateList& vect_list, const MVector& mv, + const int xr , const int yr , const int step ) +{ + //Creates a new motion vector list in a square region around mv + + vector<MVector> tmp_list; + vect_list.push_back(tmp_list); + int list_num=vect_list.size()-1; + + MVector tmp_mv( mv ); + AddVect(vect_list , tmp_mv , list_num ); + + for ( int i=1 ; i<=xr ; ++i ) + { + tmp_mv.x = mv.x + i*step; + AddVect( vect_list , tmp_mv , list_num ); + + tmp_mv.x = mv.x - i*step; + AddVect( vect_list , tmp_mv , list_num ); + } + + for ( int j=1 ; j<=yr ; ++j) + { + for ( int i=-xr ; i<=xr ; ++i) + { + tmp_mv.x = mv.x + i*step; + tmp_mv.y = mv.y + j*step; + AddVect(vect_list,tmp_mv,list_num); + + tmp_mv.y = mv.y -j*step; + AddVect(vect_list,tmp_mv,list_num); + + }// i + }// j + + // If we've not managed to add any element to the list + // remove the list so we don't ever have to check its size + if ( vect_list[list_num].size() == 0 ) + vect_list.erase( vect_list.begin() + list_num ); +} + +void AddNewVlist( CandidateList& vect_list , const MVector& mv , const int xr , const int yr) +{ + // Creates a new motion vector list in a square region around mv + + vector<MVector> tmp_list; + vect_list.push_back(tmp_list); + int list_num=vect_list.size()-1; + + MVector tmp_mv(mv); + AddVect(vect_list,tmp_mv,list_num); + + for ( int i=1 ; i<=xr ; ++i) + { + tmp_mv.x = mv.x + i; + AddVect( vect_list , tmp_mv , list_num ); + + tmp_mv.x = mv.x - i; + AddVect( vect_list , tmp_mv , list_num ); + } + + for ( int j=1 ; j<=yr ; ++j) + { + for ( int i=-xr ; i<=xr ; ++i) + { + tmp_mv.x = mv.x + i; + tmp_mv.y = mv.y + j; + AddVect( vect_list , tmp_mv , list_num ); + + tmp_mv.y = mv.y-j; + AddVect( vect_list , tmp_mv , list_num ); + } + } + + // If we've not managed to add any element to the list + // remove the list so we don't ever have to check its size + if ( vect_list[list_num].size() == 0 ) + vect_list.erase( vect_list.begin() + list_num ); +} + +void AddNewVlistD( CandidateList& vect_list , const MVector& mv , const int xr , const int yr ) +{ + //As above, but using a diamond pattern + + vector<MVector> tmp_list; + vect_list.push_back( tmp_list ); + + int list_num=vect_list.size()-1; + int xlim; + + MVector tmp_mv( mv ); + AddVect( vect_list , tmp_mv , list_num ); + + for ( int i=1 ; i<=xr ; ++i) + { + tmp_mv.x = mv.x + i; + AddVect( vect_list , tmp_mv , list_num ); + + tmp_mv.x = mv.x - i; + AddVect( vect_list , tmp_mv , list_num ); + } + + for ( int j=1 ; j<=yr ; ++j) + { + xlim = xr * (yr-std::abs(j)) / yr; + for ( int i=-xlim ; i<=xlim ; ++i) + { + tmp_mv.x = mv.x + i; + tmp_mv.y = mv.y + j; + AddVect( vect_list , tmp_mv , list_num ); + + tmp_mv.y = mv.y - j; + AddVect( vect_list , tmp_mv , list_num ); + } + } + + // If we've not managed to add any element to the list + // remove the list so we don't ever have to check its size + if ( vect_list[list_num].size() == 0 ) + vect_list.erase( vect_list.begin() + list_num ); +} + +void AddVect(CandidateList& vect_list,const MVector& mv,int list_num) +{ + + bool is_in_list=false; + + size_t lnum=0; + size_t i; + + while( !is_in_list && lnum<vect_list.size() ) + { + i=0; + while( !is_in_list && i<vect_list[lnum].size()) + { + if ( vect_list[lnum][i].x == mv.x && vect_list[lnum][i].y == mv.y ) + is_in_list=true; + ++i; + } + ++lnum; + } + + if ( !is_in_list ) + vect_list[list_num].push_back(mv); + +} + +BlockMatcher::BlockMatcher( const PicArray& pic_data , + const PicArray& ref_data , + const OLBParams& bparams , + const int precision , + const MvArray& mv_array , + const TwoDArray< MvCostData >& cost_array): + m_pic_data(pic_data), + m_ref_data(ref_data), + m_mv_array(mv_array), + m_cost_array(cost_array), + m_peldiff( ref_data , pic_data ), //NB: ORDER!!!!!!!!!!!!!!!!!!!!!!!!!!!! + m_subpeldiff( 3 ), + m_bparams( bparams ), + m_var_max( (pic_data.LengthX()+pic_data.LengthY() )/216 ), + m_var_max_up( (pic_data.LengthX()+pic_data.LengthY() )/27 ), + m_precision( precision ) +{ + m_subpeldiff[0] = new BlockDiffHalfPel( ref_data, pic_data ); + m_subpeldiff[1] = new BlockDiffQuarterPel( ref_data, pic_data ); + m_subpeldiff[2] = new BlockDiffEighthPel( ref_data, pic_data ); +} + +BlockMatcher::~BlockMatcher() +{ + for (int i=0; i<3; ++i ) + delete m_subpeldiff[i]; +} + + +ValueType BlockMatcher::GetVar( const MVector& predmv , const MVector& mv ) const +{ + MVector diff; + diff.x = mv.x-predmv.x; + diff.y = mv.y-predmv.y; + + return Norm1( diff ); +} + +ValueType BlockMatcher::GetVarUp( const MVector& predmv , const MVector& mv ) const +{ + MVector diff; + diff.x = mv.x-predmv.x; + diff.y = mv.y-predmv.y; + + return std::min( Norm1( diff ) , Norm1( mv ) ); +} + +void BlockMatcher::FindBestMatchPel(const int xpos , const int ypos , + const CandidateList& cand_list, + const MVector& mv_prediction, + const int list_start) +{ + BlockDiffParams dparams; + dparams.SetBlockLimits( m_bparams , m_pic_data , xpos , ypos); + + //now test against the offsets in the MV list to get the lowest cost// + ////////////////////////////////////////////////////////////////////// + + float best_cost = m_cost_array[ypos][xpos].total; + + MVector best_mv = m_mv_array[ypos][xpos]; + + for ( size_t lnum=list_start ; lnum<cand_list.size() ; ++lnum) + { + for (size_t i=0 ; i<cand_list[lnum].size() ; ++i) + { + m_peldiff.Diff( dparams , + cand_list[lnum][i] , + best_cost , + best_mv); + }// i + }// num + + // Write the results in the arrays // + ///////////////////////////////////// + + m_mv_array[ypos][xpos] = best_mv; + m_cost_array[ypos][xpos].SAD = best_cost; + m_cost_array[ypos][xpos].mvcost = GetVar( mv_prediction , best_mv); + m_cost_array[ypos][xpos].SetTotal( 0.0 ); +} + +void BlockMatcher::FindBestMatchSubp( const int xpos, const int ypos, + const CandidateList& cand_list, + const MVector& mv_prediction, + const float lambda) +{ + + BlockDiffParams dparams; + dparams.SetBlockLimits( m_bparams , m_pic_data , xpos , ypos); + + //now test against the offsets in the MV list to get the lowest cost// + ////////////////////////////////////////////////////////////////////// + + // Numbers of the lists to do more searching in + vector<int> list_nums; + + // Costs of the initial vectors in each list + OneDArray<float> list_costs( cand_list.size() ); + + // First test the first in each of the lists to choose which lists to pursue + MvCostData best_costs( m_cost_array[ypos][xpos] ); + best_costs.total = 100000000.0f; + MVector best_mv( m_mv_array[ypos][xpos] ); + + MvCostData cand_costs; + MVector cand_mv; + + for (size_t list_num=0 ; list_num<cand_list.size() ; ++list_num ) + { + for (size_t i=0 ; i<cand_list[list_num].size() ; ++i ) + { + cand_mv = cand_list[list_num][i]; + cand_costs.mvcost = GetVarUp( mv_prediction , cand_mv ); + + m_subpeldiff[m_precision-1]->Diff( dparams, + cand_mv , + cand_costs.mvcost, + lambda, + best_costs , + best_mv); + }// + }// list_num + + + // Write the results in the arrays // + ///////////////////////////////////// + + m_mv_array[ypos][xpos] = best_mv; + m_cost_array[ypos][xpos] = best_costs; + +} +void BlockMatcher::RefineMatchSubp(const int xpos, const int ypos, + const MVector& mv_prediction, + const float lambda) +{ + + BlockDiffParams dparams; + dparams.SetBlockLimits( m_bparams , m_pic_data , xpos , ypos); + + m_cost_array[ypos][xpos].mvcost = GetVarUp( mv_prediction, + m_mv_array[ypos][xpos]<<m_precision ); + m_cost_array[ypos][xpos].SetTotal( lambda ); + + // Initialise to the best pixel value + MvCostData best_costs( m_cost_array[ypos][xpos] ); + MVector pel_mv( m_mv_array[ypos][xpos] ); + MVector best_mv( pel_mv ); + + // If the integer value is good enough, bail out + if ( best_costs.SAD < 2*dparams.Xl()*dparams.Yl() ) + { + m_mv_array[ypos][xpos] = m_mv_array[ypos][xpos]<<m_precision; + return; + } + + // Next, test the predictor. If that's good enough, bail out + MvCostData pred_costs; + pred_costs.mvcost = 0; + pred_costs.SAD = m_subpeldiff[m_precision-1]->Diff( dparams, mv_prediction); + pred_costs.total = pred_costs.SAD; + + if (pred_costs.SAD<2*dparams.Xl()*dparams.Yl() ) + { + m_mv_array[ypos][xpos] = mv_prediction; + m_cost_array[ypos][xpos] = pred_costs; + return; + } + + // Now, let's see if we can do better than this + + MvCostData cand_costs; + MVector cand_mv, old_best_mv; + + for (int i=1; i<=m_precision; ++i ) + { + best_mv = best_mv<<1; + MVector temp_best_mv = best_mv; + + // Do a neighbourhood of best_mv + + // Stage 1 - look at the 4 nearest points + cand_mv.x = best_mv.x - 1; + cand_mv.y = best_mv.y; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + cand_mv.x = best_mv.x + 1; + cand_mv.y = best_mv.y; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + cand_mv.x = best_mv.x; + cand_mv.y = best_mv.y - 1; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + cand_mv.x = best_mv.x; + cand_mv.y = best_mv.y + 1; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + + // Stage 2. If we've done better than the original value, + // look at the other two neighbours + if ( temp_best_mv.x != best_mv.x ) + { + MVector new_best_mv = temp_best_mv; + cand_mv.x = new_best_mv.x; + cand_mv.y = new_best_mv.y - 1; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + + cand_mv.x = new_best_mv.x; + cand_mv.y = new_best_mv.y + 1; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + } + else if ( temp_best_mv.y != best_mv.y ) + { + MVector new_best_mv = temp_best_mv; + cand_mv.x = new_best_mv.x - 1; + cand_mv.y = new_best_mv.y; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + + cand_mv.x = new_best_mv.x + 1; + cand_mv.y = new_best_mv.y; + m_subpeldiff[i-1]->Diff( dparams, cand_mv , + GetVarUp( mv_prediction, + cand_mv<<(m_precision-i) ) , + lambda , best_costs , + temp_best_mv); + } + + best_mv = temp_best_mv; + + // Bail out if we can't do better than 10% worse than the predictor at + // each stage + if ( best_costs.total>1.1*pred_costs.total ) + { + m_mv_array[ypos][xpos] = mv_prediction; + m_cost_array[ypos][xpos] = pred_costs; + return; + } + + }//i + + + // Write the results in the arrays // + ///////////////////////////////////// + + m_mv_array[ypos][xpos] = best_mv; + m_cost_array[ypos][xpos] = best_costs; + +} + +} // namespace dirac diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/block_match.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/block_match.h new file mode 100644 index 000000000..2bcb5e2b3 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/block_match.h @@ -0,0 +1,207 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: block_match.h,v 1.10 2007/09/03 14:52:40 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _BLOCK_MATCH_H_ +#define _BLOCK_MATCH_H_ + +#include <libdirac_motionest/me_utils.h> +#include <vector> +//handles the business of finding the best block match + +namespace dirac +{ + + typedef std::vector< std::vector< MVector > > CandidateList; + + //! Add a new motion vector list of neighbours of a vector to the set of lists + /* + Add a new motion vector list to the set of lists consisting of the + square neighbourhood [mv.x-xr,mv.x+xr] by + [mv.y-yr,mv.y+yr]. Vectors that already occur in previous lists are + not added. + */ + void AddNewVlist( CandidateList& vect_list , const MVector& mv , const int xr , const int yr ); + + //! Add a new motion vector list to the set of lists for sub-pixel matching + /* + Add a new motion vector list to the set of lists consisting of the + vectors of the form (mv.x+m*step,mv.y+n*step) where m lies between + -xr and xr and n lies between -yr and yr. Vectors that already occur + in previous lists are not added. + */ + void AddNewVlist( CandidateList& vect_list , const MVector& mv , const int xr , const int yr , const int step ); + + //! Add a new motion vector list of diagnonal neighbours of a vector to the set of lists + /* + Add a new motion vector list to the set of lists consisting of the + diagonal neighbourhood of height 2yr+1 pixels and width 2xr+1 centred + on \param mv. + Vectors that already occur in previous lists are not added. + */ + void AddNewVlistD( CandidateList& vect_list , const MVector& mv , const int xr, const int yr); + + //! Add a motion vector to the set of motion vector lists + /*! + Add a motion vector to the set of motion vector lists, making sure + it's not a duplicate. + */ + void AddVect( CandidateList& vect_list , const MVector& mv , const int list_num); + + //! Get the (absolute) variation between two motion vectors + /*! + Return the variation between two motion vectors, computed as the sum + of absolute differences of their components. + */ + ValueType GetVar(const MVector& mv1,const MVector& mv2); + + //! Get the (absolute) variation between a motion vector and a list of motion vectors + /*! + Return the variation between a motion vector and a list of motion + vectos, computed as the sum of absolute differences between the + components of the vector and the median vector produced by the list of + vectors + */ + ValueType GetVar(const std::vector<MVector>& pred_list,const MVector& mv); + + + //! Class to do block matching + + // Subsumes FindBestMatch and FindBestMatchSubpel + class BlockMatcher + { + public: + //! Constructor + /*! + Constructor + \param ref_data the reference picture component + \param pic_data the picture being matched + \param bparams the (overlapped) block parameters to be used for the matching + \param precision the number of bits of precision being used for estimation + \param mv_array the array of vectors we're going to write into + \param cost_array the array of costs we're going to write into + + */ + BlockMatcher( const PicArray& ref_data , + const PicArray& pic_data , + const OLBParams& bparams , + const int precision , + const MvArray& mv_array , + const TwoDArray< MvCostData >& cost_array); + + ~BlockMatcher(); + + //! Find the best matching vector from a list of candidates + /*! + Find the best matching vector from a list of candidates. + \param xpos the horizontal location of the block being matched + \param ypos the vertical location of the block being matched + \param cand_list the list of candidate vectors + \param mv_prediction Prediction used for each block used to control the variation in the motion vector field. + \param list_start index into the candidate vectors list + */ + void FindBestMatchPel( const int xpos , const int ypos , + const CandidateList& cand_list, + const MVector& mv_prediction, + const int list_start); + + //! Find the best matching vector from a list of candidates, to sub-pixel accuracy (TBC: merge with FindBestMatch) + /*! + Find the best matching vector from a list of candidates. + \param xpos the horizontal location of the block being matched + \param ypos the vertical location of the block being matched + \param cand_list the list of candidate vectors + \param mv_prediction the prediction for the motion vector + \param lambda the Lagrangian parameter + */ + void FindBestMatchSubp( const int xpos, const int ypos, + const CandidateList& cand_list, + const MVector& mv_prediction, + const float lambda); + + void RefineMatchSubp(const int xpos, const int ypos, + const MVector& mv_prediction, + const float lambda); + + //! Get a measure of the difference between a motion vector and a prediction + /*! + Get a measure of the difference between a motion vector and a prediction + \param predmv the predicting motion vector + \param mv the motion vector + */ + ValueType GetVar( const MVector& predmv , const MVector& mv ) const; + + //! Get a measure of the difference between a motion vector and a prediction, to 1/8pel accuracy + /*! + Get a measure of the difference between a motion vector and a prediction, to 1/8pel accuracy + \param predmv the predicting motion vector + \param mv the motion vector + */ + ValueType GetVarUp( const MVector& predmv , const MVector& mv ) const; + + void SetPrecision( const int n ){ m_precision = n; } + + private: + // Local copies of the picture and reference + const PicArray& m_pic_data; + const PicArray& m_ref_data; + + // Local copy of the motion vector array being populated + const MvArray& m_mv_array; + + // Local copy of the costs being determined through the matching + const TwoDArray< MvCostData >& m_cost_array; + + // Block difference elements. Will choose between them depending + // on whether we're at the edge of the picture + PelBlockDiff m_peldiff; + + OneDArray<BlockDiffUp* > m_subpeldiff; + + // The block parameters we're using + OLBParams m_bparams; + + // The maximum variations allowed in calculating motion vector costs + const int m_var_max; + const int m_var_max_up; + + // The motion vector precision + int m_precision; + + }; + +} // namespace dirac +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert.cpp new file mode 100644 index 000000000..75bd0739e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert.cpp @@ -0,0 +1,204 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: downconvert.cpp,v 1.10 2007/03/19 16:19:00 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Richard Felton (Original Author), +* Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_motionest/downconvert.h> +using namespace dirac; + +DownConverter::DownConverter() +{} + + +#if !defined(HAVE_MMX) +//General function - does some admin and calls the correct function +//NOTE: The mmx version of this function is defined in downconvert_mmx.cpp +//Ensusre that changes made in this function are reflected in the mmx version +//as well. +void DownConverter::DoDownConvert(const PicArray& old_data, PicArray& new_data) +{ + //Down-convert by a factor of two. + m_row_buffer= new ValueType[old_data.LengthX()]; + //Variables that will be used by the filter calculations + int sum; + int colpos; + + // The area of the picture that will be downconverted + const int xlen = 2*new_data.LengthX(); + const int ylen = 2*new_data.LengthY(); + + + //There are three y loops to cope with the leading edge, middle + //and trailing edge of each column. + colpos=0; + for( int y=0; y<Stage_I_Size*2 ; y+=2 , colpos++ ) + { + // We are filtering each column but doing it bit by bit. + // This means our main loop is in the x direction and + // there is a much greater chance the data we need will + // be in the cache. + + for( int x=0 ; x<xlen ; x++ ) + { + // In down conversion we interpolate every pixel + // so there is no copying. + // Excuse the complicated ternary stuff but it sorts out the edge + sum = (old_data[y][x] + old_data[y+1][x])*StageI_I; + sum += (old_data[((y-1)>=0)?(y-1):0][x] + old_data[y+2][x])*StageI_II; + sum += (old_data[((y-2)>=0)?(y-2):0][x] + old_data[y+3][x])*StageI_III; + sum += (old_data[((y-3)>=0)?(y-3):0][x] + old_data[y+4][x])*StageI_IV; + sum += (old_data[((y-4)>=0)?(y-4):0][x] + old_data[y+5][x])*StageI_V; + sum += (old_data[((y-5)>=0)?(y-5):0][x] + old_data[y+6][x])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + m_row_buffer[x] = sum >> StageI_Shift; + }// x + //Speaking of which - the row loop. + + RowLoop(colpos,new_data); + }// y + + // This loop is like the last one but it deals with the center + // section of the image and so the ternary operations are dropped + // from the filter section. + for( int y=Stage_I_Size*2 ; y<ylen-Stage_I_Size*2 ; y+=2 , colpos++ ) + { + for( int x=0 ; x<xlen ; x++ ) + { + + sum = (old_data[y][x] + old_data[y+1][x])*StageI_I; + sum += (old_data[y-1][x] + old_data[y+2][x])*StageI_II; + sum += (old_data[y-2][x] + old_data[y+3][x])*StageI_III; + sum += (old_data[y-3][x] + old_data[y+4][x])*StageI_IV; + sum += (old_data[y-4][x] + old_data[y+5][x])*StageI_V; + sum += (old_data[y-5][x] + old_data[y+6][x])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + m_row_buffer[x] = sum >> StageI_Shift; + }// x + + RowLoop( colpos , new_data ); + }// y + + // Another similar loop! - this time we are dealing with + // the trailing edge so the ternary stuff is back in the + // filter calcs but in the second parameter. + + for( int y=ylen-(Stage_I_Size*2) ; y<ylen-1 ; y+=2 , colpos++ ) + { + for( int x=0; x<xlen ; x++ ) + { + + sum = (old_data[y][x] + old_data[((y+1)<ylen)?(y+1):(ylen-1)][x])*StageI_I; + sum += (old_data[y-1][x] + old_data[((y+2)<ylen)?(y+2):(ylen-1)][x])*StageI_II; + sum += (old_data[y-2][x] + old_data[((y+3)<ylen)?(y+3):(ylen-1)][x])*StageI_III; + sum += (old_data[y-3][x] + old_data[((y+4)<ylen)?(y+4):(ylen-1)][x])*StageI_IV; + sum += (old_data[y-4][x] + old_data[((y+5)<ylen)?(y+5):(ylen-1)][x])*StageI_V; + sum += (old_data[y-5][x] + old_data[((y+6)<ylen)?(y+6):(ylen-1)][x])*StageI_VI; + + // Do rounding right + sum += 1<<(StageI_Shift-1); + m_row_buffer[x] = sum >> StageI_Shift; + + }// x + + RowLoop( colpos , new_data ); + + }// y + + // Tidy up the data + delete[] m_row_buffer; + +} +#endif + + +// The loop over the columns is the same every time so lends itself to isolation +// as an individual function. +void DownConverter::RowLoop( const int colpos , PicArray& new_data) +{ + + //Calculation variables + int sum; + const int xlen = 2*new_data.LengthX(); + int linepos=0; + + // Leading Column Edge + // Similar loops to the x case in ByHalf_opto, for explanation look there. + // Note the factor of two difference as we only want to fill in every other + // line as the others have already been created by the line loops. + + for( int x=0; x<(2*Stage_I_Size) ; x+=2 , linepos++ ) + { + sum = (m_row_buffer[((x)>=0)?(x):0] + m_row_buffer[x+1])*StageI_I; + sum += (m_row_buffer[((x-1)>=0)?(x-1):0] + m_row_buffer[x+2])*StageI_II; + sum += (m_row_buffer[((x-2)>=0)?(x-2):0] + m_row_buffer[x+3])*StageI_III; + sum += (m_row_buffer[((x-3)>=0)?(x-3):0] + m_row_buffer[x+4])*StageI_IV; + sum += (m_row_buffer[((x-4)>=0)?(x-4):0] + m_row_buffer[x+5])*StageI_V; + sum += (m_row_buffer[((x-5)>=0)?(x-5):0] + m_row_buffer[x+6])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + + new_data[colpos][linepos] = sum >> StageI_Shift; + + } + //Middle of column + for( int x=(2*Stage_I_Size) ; x<xlen-(2*Stage_I_Size) ; x+=2 , linepos++) + { + sum = (m_row_buffer[x] + m_row_buffer[x+1])*StageI_I; + sum += (m_row_buffer[x-1] + m_row_buffer[x+2])*StageI_II; + sum += (m_row_buffer[x-2] + m_row_buffer[x+3])*StageI_III; + sum += (m_row_buffer[x-3] + m_row_buffer[x+4])*StageI_IV; + sum += (m_row_buffer[x-4] + m_row_buffer[x+5])*StageI_V; + sum += (m_row_buffer[x-5] + m_row_buffer[x+6])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + + new_data[colpos][linepos] = sum >> StageI_Shift; + + } + //Trailing column edge + for( int x=xlen-(2*Stage_I_Size) ; x< xlen-1 ; x+=2 , linepos++ ) + { + sum = (m_row_buffer[x] + m_row_buffer[((x+1)<xlen)?(x+1):(xlen-1)])*StageI_I; + sum += (m_row_buffer[x-1] + m_row_buffer[((x+2)<xlen)?(x+2):(xlen-1)])*StageI_II; + sum += (m_row_buffer[x-2] + m_row_buffer[((x+3)<xlen)?(x+3):(xlen-1)])*StageI_III; + sum += (m_row_buffer[x-3] + m_row_buffer[((x+4)<xlen)?(x+4):(xlen-1)])*StageI_IV; + sum += (m_row_buffer[x-4] + m_row_buffer[((x+5)<xlen)?(x+5):(xlen-1)])*StageI_V; + sum += (m_row_buffer[x-5] + m_row_buffer[((x+6)<xlen)?(x+6):(xlen-1)])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + + new_data[colpos][linepos] = sum >> StageI_Shift; + + } + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert.h new file mode 100644 index 000000000..bb2bdcf1e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert.h @@ -0,0 +1,94 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: downconvert.h,v 1.11 2007/03/19 16:19:00 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Richard Felton (Original Author), +* Thomas Davies +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _DOWNCONVERT_H_ +#define _DOWNCONVERT_H_ + +#include <libdirac_common/common.h> +namespace dirac +{ + + //! A class for fast downconversion of picture data + /*! + A class for fast down-conversion of picture data. The picture data is + downconverted by a factor of two in each dimension, using fast + filtering techniques. The filter is a half-band filter designed to + trade off frequency response, ringiness, and aliasing + */ + class DownConverter{ + + public: + + //! Constructor + DownConverter(); + //! Destructor + ~DownConverter(){}; + + //! A function to do the actual down-conversion + /*! + A function to do the actual downconversion. + \param old_data the picture data to be downconverted + \param new_data the resulting down-converted data. The array must be of the correct size. + */ + void DoDownConvert(const PicArray& old_data, PicArray& new_data); + + private: + //Copy constructor + DownConverter(const DownConverter& cpy);//private, body-less: class should not be copied + //Assignment= + DownConverter& operator=(const DownConverter& rhs);//private, body-less: class should not be assigned + + //Applies the filter to a single column + void RowLoop(const int colpos , PicArray& new_data ); + + ValueType* m_row_buffer; + + //Define filter parameters + static const int Stage_I_Size = 6; + static const int StageI_I = 86; + static const int StageI_II = 46; + static const int StageI_III = 4; + static const int StageI_IV = -8; + static const int StageI_V = -4; + static const int StageI_VI = 4; + static const int StageI_Shift = 8; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert_mmx.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert_mmx.cpp new file mode 100644 index 000000000..efdc261e5 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/downconvert_mmx.cpp @@ -0,0 +1,246 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: downconvert_mmx.cpp,v 1.2 2007/03/19 16:19:00 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Anuradha Suraparaju (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_motionest/downconvert.h> +using namespace dirac; + +#if defined (HAVE_MMX) +#include <mmintrin.h> + +typedef union +{ + __m64 m; + int i[2]; +} u_sum; + + +#define mmx_add(pic1,pic2,tap,zero,sum1,sum2) \ + tmp = _mm_add_pi16 (*(__m64 *)pic1, *(__m64 *)pic2); \ + m1 = _mm_unpacklo_pi16 ( tmp, zero); \ + m2 = _mm_unpackhi_pi16 ( tmp, zero); \ + m1 = _mm_madd_pi16 (m1, tap); \ + m2 = _mm_madd_pi16 (m2, tap); \ + *sum1 = _mm_add_pi32 (*sum1, m1); \ + *sum2 = _mm_add_pi32 (*sum2, m2); \ + +//General function - does some admin and calls the correct function +void DownConverter::DoDownConvert(const PicArray& old_data, PicArray& new_data) +{ + //Down-convert by a factor of two. + m_row_buffer= new ValueType[old_data.LengthX()]; + //Variables that will be used by the filter calculations + int sum; + int colpos; + + // The area of the picture that will be downconverted + const int xlen = 2*new_data.LengthX(); + const int ylen = 2*new_data.LengthY(); + + + //There are three y loops to cope with the leading edge, middle + //and trailing edge of each column. + colpos=0; + + static __m64 zero = _mm_set_pi16(0, 0, 0, 0); + static __m64 tap0 = _mm_set_pi16 (0, StageI_I, 0, StageI_I); + static __m64 tap1 = _mm_set_pi16 (0, StageI_II, 0, StageI_II); + static __m64 tap2 = _mm_set_pi16 (0, StageI_III, 0, StageI_III); + static __m64 tap3 = _mm_set_pi16 (0, StageI_IV, 0, StageI_IV); + static __m64 tap4 = _mm_set_pi16 (0, StageI_V, 0, StageI_V); + static __m64 tap5 = _mm_set_pi16 (0, StageI_VI, 0, StageI_VI); + static __m64 round = _mm_set_pi32 ( 1<<(StageI_Shift-1), 1<<(StageI_Shift-1)); + + u_sum sum1, sum2; + __m64 tmp, m1, m2; + + int stopX = (xlen >> 2)<<2; + for( int y=0; y<Stage_I_Size*2 ; y+=2 , colpos++ ) + { + // We are filtering each column but doing it bit by bit. + // This means our main loop is in the x direction and + // there is a much greater chance the data we need will + // be in the cache. + + for( int x=0 ; x<stopX ; x+=4 ) + { + // In down conversion we interpolate every pixel + // so there is no copying. + // Excuse the complicated ternary stuff but it sorts out the edge + sum1.m = _mm_set_pi32 (0, 0); + sum2.m = _mm_set_pi32 (0, 0); + + mmx_add (&old_data[y][x], &old_data[y+1][x], tap0, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[((y-1)>=0)?(y-1):0][x] , &old_data[y+2][x], tap1, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[((y-2)>=0)?(y-2):0][x] , &old_data[y+3][x], tap2, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[((y-3)>=0)?(y-3):0][x] , &old_data[y+4][x], tap3, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[((y-4)>=0)?(y-4):0][x] , &old_data[y+5][x], tap4, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[((y-5)>=0)?(y-5):0][x] , &old_data[y+6][x], tap5, zero, &sum1.m, &sum2.m); + + sum1.m = _mm_add_pi32 (sum1.m, round); + sum2.m = _mm_add_pi32 (sum2.m, round); + sum1.m = _mm_srai_pi32 (sum1.m, StageI_Shift); + sum2.m = _mm_srai_pi32 (sum2.m, StageI_Shift); + m_row_buffer[x] = sum1.i[0]; + m_row_buffer[x+1] = sum1.i[1]; + m_row_buffer[x+2] = sum2.i[0]; + m_row_buffer[x+3] = sum2.i[1]; + }// x + _mm_empty(); + + for( int x=stopX ; x<xlen ; x++ ) + { + // In down conversion we interpolate every pixel + // so there is no copying. + // Excuse the complicated ternary stuff but it sorts out the edge + sum = (old_data[y][x] + old_data[y+1][x])*StageI_I; + sum += (old_data[((y-1)>=0)?(y-1):0][x] + old_data[y+2][x])*StageI_II; + sum += (old_data[((y-2)>=0)?(y-2):0][x] + old_data[y+3][x])*StageI_III; + sum += (old_data[((y-3)>=0)?(y-3):0][x] + old_data[y+4][x])*StageI_IV; + sum += (old_data[((y-4)>=0)?(y-4):0][x] + old_data[y+5][x])*StageI_V; + sum += (old_data[((y-5)>=0)?(y-5):0][x] + old_data[y+6][x])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + m_row_buffer[x] = sum >> StageI_Shift; + }// x + //Speaking of which - the row loop. + + RowLoop(colpos,new_data); + }// y + + // This loop is like the last one but it deals with the center + // section of the image and so the ternary operations are dropped + // from the filter section. + for( int y=Stage_I_Size*2 ; y<ylen-Stage_I_Size*2 ; y+=2 , colpos++ ) + { + for( int x=0 ; x<stopX ; x+=4 ) + { + // In down conversion we interpolate every pixel + // so there is no copying. + // Excuse the complicated ternary stuff but it sorts out the edge + sum1.m = _mm_set_pi32 (0, 0); + sum2.m = _mm_set_pi32 (0, 0); + + mmx_add (&old_data[y][x], &old_data[y+1][x], tap0, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-1][x] , &old_data[y+2][x], tap1, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-2][x] , &old_data[y+3][x], tap2, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-3][x] , &old_data[y+4][x], tap3, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-4][x] , &old_data[y+5][x], tap4, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-5][x] , &old_data[y+6][x], tap5, zero, &sum1.m, &sum2.m); + + sum1.m = _mm_add_pi32 (sum1.m, round); + sum2.m = _mm_add_pi32 (sum2.m, round); + sum1.m = _mm_srai_pi32 (sum1.m, StageI_Shift); + sum2.m = _mm_srai_pi32 (sum2.m, StageI_Shift); + m_row_buffer[x] = sum1.i[0]; + m_row_buffer[x+1] = sum1.i[1]; + m_row_buffer[x+2] = sum2.i[0]; + m_row_buffer[x+3] = sum2.i[1]; + }// x + _mm_empty(); + + for( int x=stopX ; x<xlen ; x++ ) + { + sum = (old_data[y][x] + old_data[y+1][x])*StageI_I; + sum += (old_data[y-1][x] + old_data[y+2][x])*StageI_II; + sum += (old_data[y-2][x] + old_data[y+3][x])*StageI_III; + sum += (old_data[y-3][x] + old_data[y+4][x])*StageI_IV; + sum += (old_data[y-4][x] + old_data[y+5][x])*StageI_V; + sum += (old_data[y-5][x] + old_data[y+6][x])*StageI_VI; + sum += 1<<(StageI_Shift-1);//do rounding right + m_row_buffer[x] = sum >> StageI_Shift; + }// x + + RowLoop( colpos , new_data ); + }// y + + // Another similar loop! - this time we are dealing with + // the trailing edge so the ternary stuff is back in the + // filter calcs but in the second parameter. + + for( int y=ylen-(Stage_I_Size*2) ; y<ylen-1 ; y+=2 , colpos++ ) + { + for( int x=0 ; x<stopX ; x+=4 ) + { + // In down conversion we interpolate every pixel + // so there is no copying. + // Excuse the complicated ternary stuff but it sorts out the edge + sum1.m = _mm_set_pi32 (0, 0); + sum2.m = _mm_set_pi32 (0, 0); + + mmx_add (&old_data[y][x], &old_data[((y+1)<ylen)?(y+1):(ylen-1)][x], tap0, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-1][x] , &old_data[((y+2)<ylen)?(y+2):(ylen-1)][x], tap1, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-2][x] , &old_data[((y+3)<ylen)?(y+3):(ylen-1)][x], tap2, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-3][x] , &old_data[((y+4)<ylen)?(y+4):(ylen-1)][x], tap3, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-4][x] , &old_data[((y+5)<ylen)?(y+5):(ylen-1)][x], tap4, zero, &sum1.m, &sum2.m); + mmx_add(&old_data[y-5][x] , &old_data[((y+6)<ylen)?(y+6):(ylen-1)][x], tap5, zero, &sum1.m, &sum2.m); + + sum1.m = _mm_add_pi32 (sum1.m, round); + sum2.m = _mm_add_pi32 (sum2.m, round); + sum1.m = _mm_srai_pi32 (sum1.m, StageI_Shift); + sum2.m = _mm_srai_pi32 (sum2.m, StageI_Shift); + + m_row_buffer[x] = sum1.i[0]; + m_row_buffer[x+1] = sum1.i[1]; + m_row_buffer[x+2] = sum2.i[0]; + m_row_buffer[x+3] = sum2.i[1]; + }// x + _mm_empty(); + + for( int x=stopX; x<xlen ; x++ ) + { + + sum = (old_data[y][x] + old_data[((y+1)<ylen)?(y+1):(ylen-1)][x])*StageI_I; + sum += (old_data[y-1][x] + old_data[((y+2)<ylen)?(y+2):(ylen-1)][x])*StageI_II; + sum += (old_data[y-2][x] + old_data[((y+3)<ylen)?(y+3):(ylen-1)][x])*StageI_III; + sum += (old_data[y-3][x] + old_data[((y+4)<ylen)?(y+4):(ylen-1)][x])*StageI_IV; + sum += (old_data[y-4][x] + old_data[((y+5)<ylen)?(y+5):(ylen-1)][x])*StageI_V; + sum += (old_data[y-5][x] + old_data[((y+6)<ylen)?(y+6):(ylen-1)][x])*StageI_VI; + + // Do rounding right + sum += 1<<(StageI_Shift-1); + m_row_buffer[x] = sum >> StageI_Shift; + + }// x + + RowLoop( colpos , new_data ); + + }// y + + // Tidy up the data + delete[] m_row_buffer; + +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_mode_decn.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_mode_decn.cpp new file mode 100644 index 000000000..a23e705de --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_mode_decn.cpp @@ -0,0 +1,573 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_mode_decn.cpp,v 1.34 2008/10/20 04:19:32 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Tim Borer +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_motionest/me_mode_decn.h> +#include <libdirac_encoder/enc_queue.h> +using namespace dirac; + +#include <algorithm> + +using std::vector; + +ModeDecider::ModeDecider( const EncoderParams& encp): + m_encparams( encp ), + m_level_factor(3), + m_mode_factor(3), + m_me_data_set(3) +{ + +} + + +ModeDecider::~ModeDecider() +{ + if (m_psort.IsInter()) + { + delete m_me_data_set[0]; + delete m_me_data_set[1]; + } +} + +void ModeDecider::DoModeDecn( EncQueue& my_buffer, int pic_num ) +{ + + m_predparams = &(my_buffer.GetPicture(pic_num).GetMEData().GetPicPredParams() ); + + // The following factors normalise costs for sub-SBs and SBs to those of + // blocks, so that the overlap is take into account (e.g. a sub-SB has + // length XBLEN+XBSEP and YBLEN+YBSEP). The SB costs for a 1x1 + // decomposition are not directly comprable to those for other decompositions + // because of the block overlaps. These factors remove these effects, so that + // all SAD costs are normalised to the area corresponding to non-overlapping + // 16 blocks of size XBLEN*YBLEN. + + m_level_factor[0] = float( 16 * m_predparams->LumaBParams(2).Xblen() * m_predparams->LumaBParams(2).Yblen() )/ + float( m_predparams->LumaBParams(0).Xblen() * m_predparams->LumaBParams(0).Yblen() ); + + m_level_factor[1] = float( 4 * m_predparams->LumaBParams(2).Xblen() * m_predparams->LumaBParams(2).Yblen() )/ + float( m_predparams->LumaBParams(1).Xblen() * m_predparams->LumaBParams(1).Yblen() ); + + m_level_factor[2] = 1.0f; + + for (int i=0 ; i<=2 ; ++i) + m_mode_factor[i] = 80.0*std::pow(0.8 , 2-i); + + // We've got 'raw' block motion vectors for up to two reference pictures. Now we want + // to make a decision as to mode. In this initial implementation, this is bottom-up + // i.e. find mvs for SBs and sub-SBs and see whether it's worthwhile merging. + + int ref1,ref2; + + // Initialise // + //////////////// + + m_psort = my_buffer.GetPicture(pic_num).GetPparams().PicSort(); + if (m_psort.IsInter()) + { + // Extract the references + const vector<int>& refs = my_buffer.GetPicture(pic_num).GetPparams().Refs(); + num_refs = refs.size(); + ref1 = refs[0]; + + // The picture we're doing estimation from + m_pic_data = &(my_buffer.GetPicture( pic_num ).DataForME(m_encparams.CombinedME()) ); + + // Set up the hierarchy of motion vector data objects + PicturePredParams predparams0 = *m_predparams; + predparams0.SetXNumBlocks( m_predparams->XNumBlocks()/4 ); + predparams0.SetYNumBlocks( m_predparams->YNumBlocks()/4 ); + + PicturePredParams predparams1 = *m_predparams; + predparams1.SetXNumBlocks( m_predparams->XNumBlocks()/2 ); + predparams1.SetYNumBlocks( m_predparams->YNumBlocks()/2 ); + + m_me_data_set[0] = new MEData( predparams0, num_refs ); + m_me_data_set[1] = new MEData( predparams1, num_refs ); + + m_me_data_set[2] = &my_buffer.GetPicture(pic_num).GetMEData(); + + // Set up the lambdas to use per block + m_me_data_set[0]->SetLambdaMap( 0 , m_me_data_set[2]->LambdaMap() , 1.0/m_level_factor[0] ); + m_me_data_set[1]->SetLambdaMap( 1 , m_me_data_set[2]->LambdaMap() , 1.0/m_level_factor[1] ); + + // Set up the reference pictures + m_ref1_updata = &(my_buffer.GetPicture( ref1 ).UpDataForME(m_encparams.CombinedME()) ); + + if (num_refs>1) + { + ref2 = refs[1]; + m_ref2_updata = &(my_buffer.GetPicture( ref2).UpDataForME(m_encparams.CombinedME()) ); + // Create an object for computing bi-directional prediction calculations + if ( m_predparams->MVPrecision()==MV_PRECISION_EIGHTH_PIXEL ) + m_bicheckdiff = new BiBlockEighthPel( *m_ref1_updata , + *m_ref2_updata , + *m_pic_data ); + else if ( m_predparams->MVPrecision()==MV_PRECISION_QUARTER_PIXEL ) + m_bicheckdiff = new BiBlockQuarterPel( *m_ref1_updata , + *m_ref2_updata , + *m_pic_data ); + else + m_bicheckdiff = new BiBlockHalfPel( *m_ref1_updata , + *m_ref2_updata , + *m_pic_data ); + } + else + { + ref2 = ref1; + } + + + // Create an object for doing intra calculations + m_intradiff = new IntraBlockDiff( *m_pic_data ); + + // Loop over all the superblocks, doing the work // + /////////////////////////////////////////////////// + + for (m_ysb_loc=0 ; m_ysb_loc<m_predparams->YNumSB() ; ++m_ysb_loc ){ + for (m_xsb_loc=0 ; m_xsb_loc<m_predparams->XNumSB(); ++m_xsb_loc ){ + DoSBDecn(); + }//m_xsb_loc + }//m_ysb_loc + + delete m_intradiff; + if (num_refs>1) + delete m_bicheckdiff; + } + + // Finally, although not strictly part of motion estimation, + // we have to assign DC values for + // blocks we're decided are intra. + SetDC( my_buffer , pic_num ); + +} + +void ModeDecider::DoSBDecn() +{ + // Does the mode decision for the given SB, in three stages + + // Start with 4x4 modes + DoLevelDecn(2); + float old_best_SB_cost = m_me_data_set[2]->SBCosts()[m_ysb_loc][m_xsb_loc]; + + // Next do 2x2 modes + DoLevelDecn(1); + + // Do 1x1 mode if merging worked before + if ( m_me_data_set[2]->SBCosts()[m_ysb_loc][m_xsb_loc] <= old_best_SB_cost) + { + old_best_SB_cost = m_me_data_set[2]->SBCosts()[m_ysb_loc][m_xsb_loc]; + DoLevelDecn(0); + } + +} + +void ModeDecider::DoLevelDecn( int level ) +{ + // Computes the best costs if we were to + // stick to a decomposition at this level + + // Looks at two cases: the prediction mode is + // constant across the SB; and the pred mode + // for each constituent is different. + + // The limits of the prediction units + const int xstart = m_xsb_loc <<level; + const int ystart = m_ysb_loc <<level; + + const int xend = xstart + (1<<level); + const int yend = ystart + (1<<level); + + // Case 1: prediction modes are all different + + float SB_cost = 0.0; + for ( int j=ystart ; j<yend ; ++j) + { + for (int i=xstart ; i<xend ; ++i) + { + if ( level<2 ) + DoME( i , j , level); + SB_cost += DoUnitDecn( i , j ,level ); + + }// i + }// j + + // if we've improved on the best cost, we should propagate data in + // the base level motion vector set + if (level == 2) + { + m_me_data_set[2]->SBSplit()[m_ysb_loc][m_xsb_loc] = 2; + m_me_data_set[2]->SBCosts()[m_ysb_loc][m_xsb_loc] = SB_cost; + } + + if ( level<2 && SB_cost <= m_me_data_set[2]->SBCosts()[m_ysb_loc][m_xsb_loc] ) + { + m_me_data_set[2]->SBCosts()[m_ysb_loc][m_xsb_loc] = SB_cost; + m_me_data_set[2]->SBSplit()[m_ysb_loc][m_xsb_loc] = level; + + // Parameters of the base-level blocks corresponding to each + // prediction unit + int xblock_start; + int yblock_start; + int xblock_end; + int yblock_end; + + for ( int j=ystart ; j<yend ; ++j ) + { + yblock_start = j<<(2-level); + yblock_end = (j+1)<<(2-level); + for ( int i=xstart ; i<xend ; ++i ) + { + xblock_start = i<<(2-level); + xblock_end = (i+1)<<(2-level); + + for ( int v=yblock_start ; v<yblock_end ; ++v ) + { + for ( int u=xblock_start ; u<xblock_end ; ++u ) + { + m_me_data_set[2]->Mode()[v][u] = m_me_data_set[level]->Mode()[j][i]; + m_me_data_set[2]->DC( Y_COMP )[v][u] = m_me_data_set[level]->DC( Y_COMP )[j][i]; + m_me_data_set[2]->Vectors(1)[v][u] = m_me_data_set[level]->Vectors(1)[j][i]; + if ( num_refs>1 ) + m_me_data_set[2]->Vectors(2)[v][u] = m_me_data_set[level]->Vectors(2)[j][i]; + + }// u + }// v + + }// i + }// j + + } + +} + + +void ModeDecider::DoME(const int xpos , const int ypos , const int level) +{ + // Do motion estimation for a prediction unit using the + // four vectors derived from the next level as a guide + + MEData& me_data = *(m_me_data_set[level]); + const MEData& guide_data = *(m_me_data_set[level+1]); + + // The corresponding location of the guide data + const int guide_xpos = xpos<<1; + const int guide_ypos = ypos<<1; + + // The location of the lowest level vectors + const int xblock = xpos << ( 2 - level); + const int yblock = ypos << ( 2 - level); + + // The list of potential candidate vectors + CandidateList cand_list; + + // The lambda to use for motion estimation + const float lambda = me_data.LambdaMap()[ypos][xpos]; + + // The predicting motion vector + MVector mv_pred; + + for ( int j=0 ; j<2 ; ++j ) + for (int i=0 ; i<2 ; ++i ) + AddNewVlist( cand_list , guide_data.Vectors(1)[guide_ypos+j][guide_xpos+i] , 0 , 0 ); + + if (xblock>0 && yblock>0) + mv_pred = MvMedian( m_me_data_set[2]->Vectors(1)[yblock][xblock-1] , + m_me_data_set[2]->Vectors(1)[yblock-1][xblock-1], + m_me_data_set[2]->Vectors(1)[yblock-1][xblock]); + else if (xblock==0 && yblock>0) + mv_pred = MvMean( m_me_data_set[2]->Vectors(1)[yblock-1][xblock], + m_me_data_set[2]->Vectors(1)[yblock-1][xblock+1]); + else if (xblock>0 && yblock==0) + mv_pred = MvMean( m_me_data_set[2]->Vectors(1)[yblock][xblock-1], + m_me_data_set[2]->Vectors(1)[yblock+1][xblock-1]); + else{ + mv_pred.x = 0; + mv_pred.y = 0; + } + + BlockMatcher my_bmatch1( *m_pic_data , + *m_ref1_updata , + m_predparams->LumaBParams(level) , + m_predparams->MVPrecision(), + me_data.Vectors(1) , me_data.PredCosts(1) ); + me_data.PredCosts(1)[ypos][xpos].total = 100000000.0f; + my_bmatch1.FindBestMatchSubp( xpos , ypos , cand_list, mv_pred, lambda ); + + if (num_refs>1) + {//do the same for the other reference + + cand_list.clear(); + + for ( int j=0 ; j<2 ; ++j ) + for (int i=0 ; i<2 ; ++i ) + AddNewVlist( cand_list , guide_data.Vectors(2)[guide_ypos+j][guide_xpos+i] , 0 , 0 ); + + if (xblock>0 && yblock>0) + mv_pred = MvMedian( m_me_data_set[2]->Vectors(2)[yblock][xblock-1] , + m_me_data_set[2]->Vectors(2)[yblock-1][xblock-1], + m_me_data_set[2]->Vectors(2)[yblock-1][xblock]); + else if (xblock==0 && yblock>0) + mv_pred = MvMean( m_me_data_set[2]->Vectors(2)[yblock-1][xblock], + m_me_data_set[2]->Vectors(2)[yblock-1][xblock+1]); + else if (xblock>0 && yblock==0) + mv_pred = MvMean( m_me_data_set[2]->Vectors(2)[yblock][xblock-1], + m_me_data_set[2]->Vectors(2)[yblock+1][xblock-1]); + else{ + mv_pred.x = 0; + mv_pred.y = 0; + } + + BlockMatcher my_bmatch2( *m_pic_data , + *m_ref2_updata , + m_predparams->LumaBParams(level) , + m_predparams->MVPrecision(), + me_data.Vectors(2) , me_data.PredCosts(2) ); + me_data.PredCosts(2)[ypos][xpos].total = 100000000.0f; + my_bmatch2.FindBestMatchSubp( xpos , ypos , cand_list, mv_pred, lambda ); + + } +} + + + +float ModeDecider::DoUnitDecn(const int xpos , const int ypos , const int level ) +{ + // For a given prediction unit (SB, subSB or block) find the best + // mode, given that the REF1 and REF2 motion estimation has + // already been done. + + MEData& me_data = *( m_me_data_set[level] ); + + // Coords of the top-leftmost block belonging to this unit +// const int xblock = xpos<<(2-level); +// const int yblock = ypos<<(2-level); + + const float loc_lambda = me_data.LambdaMap()[ypos][xpos]; + + float unit_cost; + float mode_cost(0.0); + float min_unit_cost; + float best_SAD_value; + + BlockDiffParams dparams; + + dparams.SetBlockLimits( m_predparams->LumaBParams( level ) , *m_pic_data, xpos , ypos); + + // First check REF1 costs // + /**************************/ + +// mode_cost = ModeCost( xblock , yblock )*m_mode_factor[level]; + me_data.Mode()[ypos][xpos] = REF1_ONLY; + me_data.PredCosts(1)[ypos][xpos].total *= m_level_factor[level]; + min_unit_cost = me_data.PredCosts(1)[ypos][xpos].total + mode_cost; + best_SAD_value = me_data.PredCosts(1)[ypos][xpos].SAD; + + if (num_refs>1) + { + // Next check REF2 costs // + /*************************/ + +// mode_cost = ModeCost( xblock , yblock )*m_mode_factor[level]; + me_data.PredCosts(2)[ypos][xpos].total *= m_level_factor[level]; + unit_cost = me_data.PredCosts(2)[ypos][xpos].total + mode_cost; + if ( unit_cost<min_unit_cost ) + { + me_data.Mode()[ypos][xpos] = REF2_ONLY; + min_unit_cost = unit_cost; + best_SAD_value = me_data.PredCosts(2)[ypos][xpos].SAD; + } + + // Calculate the cost if we were to use bi-predictions // + /****************************************************************/ +// mode_cost = ModeCost( xpos , ypos )*m_mode_factor[level]; + + me_data.BiPredCosts()[ypos][xpos].mvcost = + me_data.PredCosts(1)[ypos][xpos].mvcost+ + me_data.PredCosts(2)[ypos][xpos].mvcost; + + me_data.BiPredCosts()[ypos][xpos].SAD = m_bicheckdiff->Diff(dparams , + me_data.Vectors(1)[ypos][xpos] , + me_data.Vectors(2)[ypos][xpos] ); + + me_data.BiPredCosts()[ypos][xpos].SetTotal( loc_lambda ); + + me_data.BiPredCosts()[ypos][xpos].total *= m_level_factor[level]; + unit_cost = me_data.BiPredCosts()[ypos][xpos].total + mode_cost; + + if ( unit_cost<min_unit_cost ) + { + me_data.Mode()[ypos][xpos] = REF1AND2; + min_unit_cost = unit_cost; + best_SAD_value = me_data.BiPredCosts()[ypos][xpos].SAD; + } + + } + + // Calculate the cost if we were to code the block as intra // + /************************************************************/ + + if ( level==2 && best_SAD_value> 4.0*m_predparams->LumaBParams( level ).Xblen()* + m_predparams->LumaBParams( level ).Yblen() ) + { +// mode_cost = ModeCost( xblock , yblock ) * m_mode_factor[level]; + me_data.IntraCosts()[ypos][xpos] = m_intradiff->Diff( dparams , me_data.DC( Y_COMP )[ypos][xpos] ); +// me_data.IntraCosts()[ypos][xpos] += loc_lambda * +// GetDCVar( me_data.DC( Y_COMP )[ypos][xpos] , GetDCPred( xblock , yblock ) ); + me_data.IntraCosts()[ypos][xpos] *= m_level_factor[level]; + unit_cost = me_data.IntraCosts()[ypos][xpos] + mode_cost; + + if ( unit_cost<min_unit_cost && me_data.IntraCosts()[ypos][xpos]<0.85*best_SAD_value) + { + me_data.Mode()[ypos][xpos] = INTRA; + min_unit_cost = unit_cost; + } + } + + return min_unit_cost; +} + +ValueType ModeDecider::GetDCPred( int xblock , int yblock ) +{ + ValueType dc_pred = 0; + + if ( xblock>0 && m_me_data_set[2]->Mode()[yblock][xblock-1] == INTRA ) + { + dc_pred = m_me_data_set[2]->DC( Y_COMP )[yblock][xblock-1]; + if ( yblock>0 && m_me_data_set[2]->Mode()[yblock-1][xblock] == INTRA ) + { + dc_pred += m_me_data_set[2]->DC( Y_COMP )[yblock-1][xblock]; + dc_pred >>= 1; + } + } + + return dc_pred; +} + +float ModeDecider::ModeCost(const int xindex , const int yindex) +{ + // Computes the variation of the given mode, predmode, from its immediate neighbours + // First, get a prediction for the mode + + unsigned int mode_predictor = (unsigned int)(REF1_ONLY); + const TwoDArray<PredMode>& preddata( m_me_data_set[2]->Mode() ); + + unsigned int num_ref1_nbrs( 0 ); + unsigned int num_ref2_nbrs( 0 ); + + if (xindex > 0 && yindex > 0) + { + num_ref1_nbrs += ((unsigned int)( preddata[yindex-1][xindex] ) ) & 1; + num_ref1_nbrs += ((unsigned int)( preddata[yindex-1][xindex-1] ) ) & 1; + num_ref1_nbrs += ((unsigned int)( preddata[yindex][xindex-1] ) ) & 1; + + mode_predictor = num_ref1_nbrs>>1; + + num_ref2_nbrs += ((unsigned int)( preddata[yindex-1][xindex] ) ) & 2; + num_ref2_nbrs += ((unsigned int)( preddata[yindex-1][xindex-1] ) ) & 2; + num_ref2_nbrs += ((unsigned int)( preddata[yindex][xindex-1] ) ) & 2; + num_ref2_nbrs >>= 1; + + mode_predictor ^= ( (num_ref2_nbrs>>1)<<1 ); + } + else if (xindex > 0 && yindex == 0) + mode_predictor = (unsigned int)( preddata[0][xindex-1] ); + else if (xindex == 0 && yindex > 0) + mode_predictor = (unsigned int)( preddata[yindex-1][0] ); + + unsigned int var = (mode_predictor & 1)+((mode_predictor>>1) &1); + + return var*m_me_data_set[2]->LambdaMap()[yindex][xindex]; +} + + +float ModeDecider::GetDCVar( const ValueType dc_val , const ValueType dc_pred) +{ + return 4.0*std::abs( static_cast<float>( dc_val - dc_pred ) ); +} + +ValueType ModeDecider::GetBlockDC(const PicArray& pic_data, + int xunit , int yunit , int split, CompSort cs) +{ + BlockDiffParams dparams; + + if ( cs!=Y_COMP ) + dparams.SetBlockLimits( m_predparams->ChromaBParams( split ) , + pic_data, xunit , yunit); + else + dparams.SetBlockLimits( m_predparams->LumaBParams( split ) , + pic_data, xunit , yunit); + + IntraBlockDiff intradiff( pic_data ); + + return intradiff.CalcDC( dparams ); +} + +void ModeDecider::SetDC( const PicArray& pic_data , MEData& me_data , CompSort cs ) +{ + + TwoDArray<ValueType>& dcarray = me_data.DC( cs ); + TwoDArray<ValueType> temp_dcarray (dcarray.LengthY(), dcarray.LengthX() ); + + for ( int y=0 ; y<dcarray.LengthY() ; ++y ){ + for ( int x=0 ; x<dcarray.LengthX() ; ++x ){ + temp_dcarray[y][x] = GetBlockDC( pic_data , x , y , 2, cs ); + } + } + + for ( int x=0 ; x<dcarray.LengthX() ; ++x ){ + dcarray[0][x] = temp_dcarray[0][x]; + } + for ( int y=1 ; y<dcarray.LengthY()-1 ; ++y ){ + dcarray[y][0] = temp_dcarray[y][0]; + for ( int x=1 ; x<dcarray.LengthX()-1 ; ++x ){ + dcarray[y][x] = (temp_dcarray[y-1][x-1]+3*temp_dcarray[y-1][x]+temp_dcarray[y-1][x+1]+ + 3*temp_dcarray[y][x-1]+ 3*temp_dcarray[y][x+1]+ + temp_dcarray[y+1][x-1]+3*temp_dcarray[y+1][x]+temp_dcarray[y+1][x+1]+8 )>>4; + } + dcarray[y][dcarray.LastX()] = temp_dcarray[y][dcarray.LastX()]; + } +} + +void ModeDecider::SetDC( EncQueue& my_buffer , int pic_num ) +{ + MEData& me_data = my_buffer.GetPicture(pic_num).GetMEData(); + SetDC( my_buffer.GetPicture( pic_num ).OrigData(Y_COMP) , me_data , Y_COMP ); + SetDC( my_buffer.GetPicture( pic_num ).OrigData(U_COMP) , me_data , U_COMP ); + SetDC( my_buffer.GetPicture( pic_num ).OrigData(V_COMP) , me_data , V_COMP ); + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_mode_decn.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_mode_decn.h new file mode 100644 index 000000000..08f4b6e00 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_mode_decn.h @@ -0,0 +1,167 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_mode_decn.h,v 1.18 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _ME_MODE_DECN_H_ +#define _ME_MODE_DECN_H_ + +#include <libdirac_common/motion.h> +#include <libdirac_motionest/block_match.h> + +namespace dirac +{ + class EncQueue; + + //! Decides between superblock and block prediction modes. + /*! + Loops over all the superblocks and decides on the best modes. A + superblock is a square of 16 blocks. There are three possible + splitting levels: + level 0 means the superblock is considered as a single block; + level 1 means the superblock is considered as 4 larger blocks, + termed sub-superblocks; + level 0 means the superblock is split right down to blocks. + + In deciding which modes + to adopt, the ModeDecider object calculates costs for all + permutations, doing motion estimation for the level 1 and level 0 + modes as these have not been calculated before. + The process of decision for each is as follows. For each SB, we loop + over the levels, and call DoLevelDecn. DoLevelDecn does motion + estimation if it's necessary. Then it assumes that we don't have a + common block mode and calls DoUnitDecn which finds the best mode for + each unit in the SB at that level, individually. When we've got a + best cost for that level we go up to the next one. + */ + class ModeDecider + { + + public: + //! Constructor + /*! + The constructor creates arrays for handling the motion vector data + at splitting levels 0 and 1, as motion + estimation must be performed for these levels. + */ + ModeDecider(const EncoderParams& encp ); + + //! Destructor + /*! + The destructor destroys the classes created in the constructor + */ + ~ModeDecider(); + + //! Does the actual mode decision + /*! + Does the mode decision + \param my_buffer the buffer of all the relevant frames + \param pic_num the picture number for which motion estimation is being done + */ + void DoModeDecn( EncQueue& my_buffer , int pic_num ); + + private: + ModeDecider( const ModeDecider& cpy );//private, body-less copy constructor: this class should not be copied + ModeDecider& operator=( const ModeDecider& rhs );//private, body-less assignment=: this class should not be assigned + + //functions + void DoSBDecn(); //called by do_mode_decn for each SB + + //! Make a mode decision given a particular level of decomposition + void DoLevelDecn( int level ); + + //! Decide on a mode for a given prediction unit (block, sub-SB or SB) + float DoUnitDecn( const int xpos , const int ypos , const int level ); + + //! Do motion estimation for a prediction unit at a given level + void DoME( const int xpos , const int ypos , const int level ); + + //! Return a measure of the cost of coding a given mode + float ModeCost( const int xindex , const int yindex ); + + //! Get a prediction for the dc value of a block + ValueType GetDCPred( int xblock , int yblock ); + + //! Get a measure of DC value variance + float GetDCVar( const ValueType dc_val , const ValueType dc_pred); + + //! Go through all the intra blocks and extract the chroma dc values to be coded + void SetDC( EncQueue& my_buffer, int pic_num); + + //! Called by previous fn for each component + void SetDC(const PicArray& pic_data, MEData& me_data,CompSort cs); + + //! Called by previous fn for each block + ValueType GetBlockDC(const PicArray& pic_data, int xloc,int yloc,int split, CompSort cs); + + + // Member data + PictureSort m_psort; + + //! A local reference to the encoder parameters + const EncoderParams& m_encparams; + + //! A local pointer to the picture prediction params + const PicturePredParams* m_predparams; + + //! The Lagrangian parameter for motion estimation + float m_lambda; + + //! Correction factor for comparing SAD costs for different SB splittings + OneDArray<float> m_level_factor; + + + //! Correction factor for comparing mode costs for different SB splittings + OneDArray<float> m_mode_factor; + + //! Motion vector data for each level of splitting + OneDArray< MEData* > m_me_data_set; + + const PicArray* m_pic_data; + const PicArray* m_ref1_updata; + const PicArray* m_ref2_updata; + int num_refs; + + IntraBlockDiff* m_intradiff; + BiBlockDiff* m_bicheckdiff; + + //position variables, used in all the mode decisions + int m_xsb_loc,m_ysb_loc; //coords of the current SB + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_subpel.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_subpel.cpp new file mode 100644 index 000000000..51376808b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_subpel.cpp @@ -0,0 +1,176 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_subpel.cpp,v 1.20 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_motionest/me_subpel.h> +#include <libdirac_encoder/enc_queue.h> +using namespace dirac; + +#include <iostream> + +using std::vector; + +SubpelRefine::SubpelRefine(const EncoderParams& encp): + m_encparams(encp), + m_nshift(4) +{ + //define the relative coordinates of the four neighbours + m_nshift[0].x = -1; + m_nshift[0].y = 0; + + m_nshift[1].x = -1; + m_nshift[1].y = -1; + + m_nshift[2].x = 0; + m_nshift[2].y = -1; + + m_nshift[3].x = 1; + m_nshift[3].y = -1; + +} + +void SubpelRefine::DoSubpel( EncQueue& my_buffer,int pic_num ) +{ + m_predparams = &(my_buffer.GetPicture(pic_num).GetMEData().GetPicPredParams() ); + + //main loop for the subpel refinement + int ref1,ref2; + + const PictureSort psort = my_buffer.GetPicture(pic_num).GetPparams().PicSort(); + + if (psort.IsInter()) + { + // Get the references + const vector<int>& refs = my_buffer.GetPicture(pic_num).GetPparams().Refs(); + + int num_refs = refs.size(); + ref1 = refs[0]; + if (num_refs>1) + ref2 = refs[1]; + else + ref2 = ref1; + + const PicArray& pic_data = my_buffer.GetPicture(pic_num).DataForME(m_encparams.CombinedME()); + const PicArray& refup1_data = my_buffer.GetPicture(ref1).UpDataForME(m_encparams.CombinedME()); + const PicArray& refup2_data = my_buffer.GetPicture(ref2).UpDataForME(m_encparams.CombinedME()); + + MEData& me_data = my_buffer.GetPicture(pic_num).GetMEData(); + + // Now match the pictures + MatchPic( pic_data , refup1_data , me_data ,1 ); + + if (ref1 != ref2 ) + MatchPic( pic_data , refup2_data , me_data ,2 ); + + } +} + +void SubpelRefine::MatchPic(const PicArray& pic_data , const PicArray& refup_data , MEData& me_data , + int ref_id) +{ + // Match a picture against a single reference. Loop over all the blocks + // doing the matching + + // Initialisation // + //////////////////// + + // Provide aliases for the appropriate motion vector data components + MvArray& mv_array = me_data.Vectors( ref_id ); + TwoDArray<MvCostData>& pred_costs = me_data.PredCosts( ref_id ); + + // Provide a block matching object to do the work + BlockMatcher my_bmatch( pic_data , refup_data , m_predparams->LumaBParams(2) , + m_predparams->MVPrecision() , mv_array , pred_costs ); + + // Do the work // + ///////////////// + + // Loop over all the blocks, doing the work + + for (int yblock=0 ; yblock<m_predparams->YNumBlocks() ; ++yblock){ + for (int xblock=0 ; xblock<m_predparams->XNumBlocks() ; ++xblock){ + DoBlock(xblock , yblock , my_bmatch , me_data , ref_id ); + }// xblock + }// yblock + +} + +void SubpelRefine::DoBlock(const int xblock , const int yblock , + BlockMatcher& my_bmatch, MEData& me_data , const int ref_id ) +{ + // For each block, home into the sub-pixel vector + + // Provide aliases for the appropriate motion vector data components + MvArray& mv_array = me_data.Vectors( ref_id ); + + const MVector mv_pred = GetPred( xblock , yblock , mv_array ); + const float loc_lambda = me_data.LambdaMap()[yblock][xblock]; + + my_bmatch.RefineMatchSubp( xblock , yblock , mv_pred, loc_lambda ); +} + +MVector SubpelRefine::GetPred(int xblock,int yblock,const MvArray& mvarray) +{ + MVector mv_pred; + ImageCoords n_coords; + vector<MVector> neighbours; + + if (xblock>0 && yblock>0 && xblock<mvarray.LastX()) + { + + for (int i=0 ; i<m_nshift.Length() ; ++i) + { + n_coords.x = xblock+m_nshift[i].x; + n_coords.y = yblock+m_nshift[i].y; + neighbours.push_back(mvarray[n_coords.y][n_coords.x]); + + }// i + } + else + { + for (int i=0 ; i<m_nshift.Length(); ++i ) + { + n_coords.x = xblock+m_nshift[i].x; + n_coords.y = yblock+m_nshift[i].y; + if (n_coords.x>=0 && n_coords.y>=0 && n_coords.x<mvarray.LengthX() && n_coords.y<mvarray.LengthY()) + neighbours.push_back(mvarray[n_coords.y][n_coords.x]); + }// i + } + + mv_pred = MvMedian(neighbours); + + return mv_pred; +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_subpel.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_subpel.h new file mode 100644 index 000000000..bd5724928 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_subpel.h @@ -0,0 +1,115 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_subpel.h,v 1.15 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _ME_SUBPEL_H_ +#define _ME_SUBPEL_H_ + +#include <libdirac_common/common.h> +#include <libdirac_common/motion.h> +#include <libdirac_motionest/block_match.h> +namespace dirac +{ + + class EncQueue; + class MvData; + class PicArray; + + //! The SubpelRefine class takes pixel-accurate motion vectors and refines them to 1/8-pixel accuracy + /*! + The SubpelRefine class takes pixel-accurate motion vectors and refines + them to 1/8-pixel accuracy. It uses references upconverted by a factor + of 2 in each dimension, with the remaining precision gained by doing + linear interpolation between values on-the-fly. + */ + class SubpelRefine + { + public: + //! Constructor + /*! + The constructor initialises the encoder parameters. + \param encp the parameters used for controlling ME/MC + */ + SubpelRefine(const EncoderParams& encp); + + //! Destructor + ~SubpelRefine(){} + + //! Does the actual sub-pixel refinement + /*! + Does the actual sub-pixel refinement. + \param my_buffer the buffer of pictures being used + \param pic_num the picture number on which motion estimation is being performed + */ + void DoSubpel( EncQueue& my_buffer , int pic_num ); + + private: + //! Private, body-less copy constructor: this class should not be copied + SubpelRefine( const SubpelRefine& cpy ); + + //! Private, body-less assignment=: this class should not be assigned + SubpelRefine& operator=( const SubpelRefine& rhs ); + + //! Match a picture from its (upconverted) reference, and record the block mvs + void MatchPic(const PicArray& pic_data , const PicArray& refup_data , MEData& me_data , + int ref_id); + + //! Match an individual block + void DoBlock( const int xblock , const int yblock , + BlockMatcher& my_bmatch, MEData& me_data , const int ref_id ); + + //! Get a prediction for a block MV from the neighbouring blocks + MVector GetPred( int xblock , int yblock , const MvArray& mvarray ); + + //member variables + + //! Local reference to the encoder params + const EncoderParams& m_encparams; + + //! A local pointer to the encoder params + const PicturePredParams* m_predparams; + + //! The list of candidate vectors being tested + CandidateList m_cand_list; + + //! The relative coords of the set of neighbours used to generate MV predictions + OneDArray<ImageCoords> m_nshift; + + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils.cpp new file mode 100644 index 000000000..007334151 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils.cpp @@ -0,0 +1,1785 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_utils.cpp,v 1.23 2008/10/21 04:55:46 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Peter Meerwald (pmeerw@users.sourceforge.net) +* Steve Bearcroft (bearcrsw@users.sourceforge.net) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +/////////////////////////////////// +//-------------------------------// +//utilities for motion estimation// +//-------------------------------// +/////////////////////////////////// + +#if defined(HAVE_MMX) +#include <climits> +#endif +#include <libdirac_motionest/me_utils.h> +#include <libdirac_motionest/me_utils_mmx.h> +#include <libdirac_common/common.h> + +using namespace dirac; + +#include <algorithm> +//#define INTRA_HAAR + +void BlockDiffParams::SetBlockLimits( const OLBParams& bparams , + const PicArray& m_pic_data , + const int xbpos , const int ybpos) +{ + const int loc_xp = xbpos * bparams.Xbsep() - bparams.Xoffset(); + const int loc_yp = ybpos * bparams.Ybsep() - bparams.Yoffset(); + + m_xp=std::max( loc_xp , 0 ); + m_yp=std::max( loc_yp , 0 ); + + m_xl = bparams.Xblen() - m_xp + loc_xp; + m_yl = bparams.Yblen() - m_yp + loc_yp; + + //constrain block lengths to fall within the picture + m_xl = ( ( m_xp + m_xl - 1) > m_pic_data.LastX() ) ? ( m_pic_data.LastX() + 1 - m_xp ): m_xl; + m_yl = ( ( m_yp + m_yl - 1) > m_pic_data.LastY() ) ? ( m_pic_data.LastY() + 1 - m_yp ) : m_yl; + + m_xend = m_xp+m_xl; + m_yend = m_yp+m_yl; + +} + +// Block difference class functions + +// Constructors ... + +BlockDiff::BlockDiff(const PicArray& ref,const PicArray& pic) : + m_pic_data( pic ), + m_ref_data( ref ) +{} + +PelBlockDiff::PelBlockDiff( const PicArray& ref , const PicArray& pic ) : + BlockDiff( ref , pic ) +{} + +IntraBlockDiff::IntraBlockDiff( const PicArray& pic ) : + m_pic_data( pic ) +{} + +BiBlockDiff::BiBlockDiff( const PicArray& ref1 , const PicArray& ref2 , + const PicArray& pic) : + m_pic_data( pic ), + m_ref_data1( ref1 ), + m_ref_data2( ref2 ) +{} + +BlockDiffUp::BlockDiffUp( const PicArray& ref , const PicArray& pic ): + BlockDiff( ref , pic ) +{} + +BlockDiffHalfPel::BlockDiffHalfPel( const PicArray& ref , const PicArray& pic ) : + BlockDiffUp( ref , pic ) +{} + +BlockDiffQuarterPel::BlockDiffQuarterPel( const PicArray& ref , const PicArray& pic ) : + BlockDiffUp( ref , pic ) +{} + +BlockDiffEighthPel::BlockDiffEighthPel( const PicArray& ref , const PicArray& pic ) : + BlockDiffUp( ref , pic ) +{} + +BiBlockHalfPel::BiBlockHalfPel( const PicArray& ref1 , const PicArray& ref2 , + const PicArray& pic ): + BiBlockDiff( ref1 , ref2 , pic) +{} + +BiBlockQuarterPel::BiBlockQuarterPel( const PicArray& ref1 , const PicArray& ref2 , + const PicArray& pic ): + BiBlockDiff( ref1 , ref2 , pic) +{} + +BiBlockEighthPel::BiBlockEighthPel( const PicArray& ref1 , const PicArray& ref2 , + const PicArray& pic ): + BiBlockDiff( ref1 , ref2 , pic) +{} + + +// Difference functions ... + +float PelBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + + CalcValueType sum( 0 ); + + const ImageCoords ref_start( dparams.Xp()+mv.x , dparams.Yp()+mv.y ); + const ImageCoords ref_stop( dparams.Xend()+mv.x , dparams.Yend()+mv.y ); + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + if ( !bounds_check ) + { +#if defined(HAVE_MMX) + return static_cast<float>(simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, INT_MAX)); +#else + ValueType diff; + for ( int j=dparams.Yp() ; j<dparams.Yp()+dparams.Yl() ; ++j ) + { + for(int i=dparams.Xp() ; i< dparams.Xp()+dparams.Xl() ; ++i ) + { + diff = m_pic_data[j][i]-m_ref_data[j+mv.y][i+mv.x]; + sum += std::abs( diff ); + }// i + }// j +#endif /* HAVE_MMX */ + } + else + { +#if defined (HAVE_MMX) + return static_cast<float>(bchk_simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, INT_MAX)); +#else + ValueType diff; + for ( int j=dparams.Yp() ; j < dparams.Yp()+dparams.Yl() ; ++j ) + { + for( int i=dparams.Xp() ; i < dparams.Xp()+dparams.Xl() ; ++i ) + { + diff = m_pic_data[j][i] - m_ref_data[BChk(j+mv.y , m_ref_data.LengthY())][BChk(i+mv.x , m_ref_data.LengthX())]; + sum += std::abs( diff ); + + }// i + }// j + +#endif /* HAVE_MMX */ + } + + return static_cast<float>( sum ); +} + +void PelBlockDiff::Diff( const BlockDiffParams& dparams, + const MVector& mv, + float& best_sum, + MVector& best_mv ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return; + } + + CalcValueType sum( 0 ); + + const ImageCoords ref_start( dparams.Xp()+mv.x , dparams.Yp()+mv.y ); + const ImageCoords ref_stop( dparams.Xend()+mv.x , dparams.Yend()+mv.y ); + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + if ( !bounds_check ) + { +#if defined (HAVE_MMX) + sum = simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, static_cast<int>(best_sum)); + if (sum < best_sum) + { + best_sum = sum; + best_mv = mv; + } + return; +#else + ValueType diff; + ValueType *pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() ); // - go down a row and back along + + + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + + for( int y=dparams.Yl(); y>0; --y, pic_curr+=pic_next, ref_curr+=pic_next ) + { + for( int x=dparams.Xl(); x>0; --x, ++pic_curr, ++ref_curr ) + { + diff = (*pic_curr)-(*ref_curr); + sum += std::abs( diff ); + }// x + + if ( sum>=best_sum ) + return; + + }// y +#endif /* HAVE_MMX */ + } + else + { +#if defined (HAVE_MMX) + sum = (bchk_simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, static_cast<int>(best_sum))); + if (sum < best_sum) + { + best_sum = sum; + best_mv = mv; + } + return; +#else + ValueType diff; + for ( int j=dparams.Yp() ; j<dparams.Yend() ; ++j ) + { + for( int i=dparams.Xp() ; i<dparams.Xend() ; ++i ) + { + diff = m_pic_data[j][i] - m_ref_data[BChk(j+mv.y , m_ref_data.LengthY())][BChk(i+mv.x , m_ref_data.LengthX())]; + sum += std::abs( diff ); + + }// i + + if ( sum>=best_sum ) + return; + + }// j +#endif /* HAVE_MMX */ + } + + best_sum = sum; + best_mv = mv; + +} + +ValueType IntraBlockDiff::CalcDC( const BlockDiffParams& dparams ){ + + CalcValueType int_dc( 0 ); + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + + for ( int j=dparams.Yp() ; j<dparams.Yp()+dparams.Yl() ; ++j) + for(int i=dparams.Xp(); i<dparams.Xp()+dparams.Xl() ; ++i ) + int_dc += static_cast<int>( m_pic_data[j][i] ); + + int_dc /= ( dparams.Xl() * dparams.Yl() ); + + return static_cast<ValueType>( int_dc ); +} + +#ifdef INTRA_HAAR +float IntraBlockDiff::Diff( const BlockDiffParams& dparams , ValueType& dc_val ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + dc_val = 0; + return 0; + } + + dc_val = CalcDC(dparams); + + // Now compute the resulting SAD + ValueType dc( dc_val ); + CalcValueType intra_cost( 0 ); + + for (int j=dparams.Yp(); j<dparams.Yend() ; j+=2){ + for( int i=dparams.Xp() ; i<dparams.Xend() ;i+=2 ){ + intra_cost += std::abs( m_pic_data[j][i] + + m_pic_data[j][i+1] + + m_pic_data[j+1][i] + + m_pic_data[j+1][i+1] + - 4*dc ); + intra_cost += std::abs( m_pic_data[j][i] + + m_pic_data[j][i+1] + - m_pic_data[j+1][i] + - m_pic_data[j+1][i+1] ); + intra_cost += std::abs( m_pic_data[j][i] + - m_pic_data[j][i+1] + + m_pic_data[j+1][i] + - m_pic_data[j+1][i+1] ); + intra_cost += std::abs( m_pic_data[j][i] + - m_pic_data[j][i+1] + - m_pic_data[j+1][i] + + m_pic_data[j+1][i+1] ); + } + } + + return static_cast<float>( intra_cost ); +} + +#else + +float IntraBlockDiff::Diff( const BlockDiffParams& dparams , ValueType& dc_val ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + dc_val = 0; + return 0; + } + + //computes the cost if block is predicted by its dc component +#if defined(HAVE_MMX) + CalcValueType intra_cost = + simple_intra_block_diff_mmx_4 (dparams, m_pic_data, dc_val); + +#ifdef DIRAC_DEBUG + CalcValueType int_dc( 0 ); + ValueType non_mmx_dc(0); + + for ( int j=dparams.Yp() ; j<dparams.Yp()+dparams.Yl() ; ++j) + for(int i=dparams.Xp(); i<dparams.Xp()+dparams.Xl() ; ++i ) + int_dc += static_cast<int>( m_pic_data[j][i] ); + + int_dc /= ( dparams.Xl() * dparams.Yl() ); + + non_mmx_dc = static_cast<ValueType>( int_dc ); + + // Now compute the resulting SAD + ValueType dc( non_mmx_dc ); + CalcValueType non_mmx_intra_cost( 0 ); + + for (int j=dparams.Yp(); j<dparams.Yend() ; ++j) + for( int i=dparams.Xp() ; i<dparams.Xend() ;++i ) + non_mmx_intra_cost += std::abs( m_pic_data[j][i] - dc ); + + if (non_mmx_dc != dc_val || non_mmx_intra_cost != intra_cost) + { + std::cerr << "MMX vals: dc=" << dc_val; + std::cerr << " cost=" << intra_cost << std::endl; + //print_arr (pic_data, width[i%5], height[i%5]); + std::cerr << "non-MMX vals: dc=" << non_mmx_dc; + std::cerr << " cost=" << non_mmx_intra_cost << std::endl; + } +#endif + return static_cast<float>( intra_cost ); +#else + CalcValueType int_dc( 0 ); + + for ( int j=dparams.Yp() ; j<dparams.Yp()+dparams.Yl() ; ++j) + for(int i=dparams.Xp(); i<dparams.Xp()+dparams.Xl() ; ++i ) + int_dc += static_cast<int>( m_pic_data[j][i] ); + + int_dc /= ( dparams.Xl() * dparams.Yl() ); + + dc_val = static_cast<ValueType>( int_dc ); + + // Now compute the resulting SAD + ValueType dc( dc_val ); + CalcValueType intra_cost( 0 ); + + for (int j=dparams.Yp(); j<dparams.Yend() ; ++j) + for( int i=dparams.Xp() ; i<dparams.Xend() ;++i ) + intra_cost += std::abs( m_pic_data[j][i] - dc ); + + return static_cast<float>( intra_cost ); +#endif //HAVE_MMX +} +#endif + +float BlockDiffHalfPel::Diff( const BlockDiffParams& dparams , + const MVector& mv ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + //Where to start in the upconverted image + const ImageCoords ref_start( ( dparams.Xp()<<1 ) + mv.x ,( dparams.Yp()<<1 ) + mv.y ); + const ImageCoords ref_stop( ref_start.x+(dparams.Xl()<<1) , ref_start.y+(dparams.Yl()<<1)); + + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + float sum( 0 ); + + if ( !bounds_check ) + { +#if defined (HAVE_MMX) + MVector rmdr(0,0); + const ImageCoords start_pos(dparams.Xp(), dparams.Yp()); + const ImageCoords end_pos(dparams.Xp() + dparams.Xl(), dparams.Yp() + dparams.Yl()); + sum = simple_block_diff_up_mmx_4 (m_pic_data, m_ref_data, + start_pos, end_pos, + ref_start, ref_stop, + rmdr, + sum, + static_cast<float>(INT_MAX)); +#else + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + sum += std::abs( *ref_curr - *pic_curr ); + }// x + }// y +#endif + + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + for( int y=dparams.Yl(), ry=ref_start.y, by=BChk(ry,m_ref_data.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data.LengthY())) + { + for( int x=dparams.Xl() , rx=ref_start.x , bx=BChk(rx,m_ref_data.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , bx=BChk(rx,m_ref_data.LengthX())) + { + sum += std::abs( m_ref_data[by][bx] -*pic_curr); + }// x + }// y + + } + + return sum; + +} + +void BlockDiffHalfPel::Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return; + } + + //Where to start in the upconverted image + const ImageCoords ref_start( ( dparams.Xp()<<1 ) + mv.x ,( dparams.Yp()<<1 ) + mv.y ); + const ImageCoords ref_stop( ref_start.x+(dparams.Xl()<<1) , ref_start.y+(dparams.Yl()<<1)); + + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + const float start_val( mvcost*lambda ); + float sum( start_val ); + + if ( !bounds_check ) + { +#if defined (HAVE_MMX) + + const ImageCoords start_pos(dparams.Xp(), dparams.Yp()); + const ImageCoords end_pos(dparams.Xp() + dparams.Xl(), dparams.Yp() + dparams.Yl()); + MVector rmdr(0,0); + sum = simple_block_diff_up_mmx_4 (m_pic_data, m_ref_data, + start_pos, end_pos, + ref_start, ref_stop, + rmdr, + sum, + best_costs.total); + if ( sum>=best_costs.total ) + return; +#else + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + sum += std::abs( *ref_curr - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y +#endif + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + for( int y=dparams.Yl(), ry=ref_start.y, by=BChk(ry,m_ref_data.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data.LengthY())) + { + for( int x=dparams.Xl() , rx=ref_start.x , bx=BChk(rx,m_ref_data.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , bx=BChk(rx,m_ref_data.LengthX())) + { + sum += std::abs( m_ref_data[by][bx] -*pic_curr); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + + } + + best_mv = mv; + best_costs.total = sum; + best_costs.mvcost = mvcost; + best_costs.SAD = sum - start_val; +} + +float BlockDiffQuarterPel::Diff( const BlockDiffParams& dparams , const MVector& mv ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + // Set up the start point in the reference image by rounding the motion vector + // to 1/2 pel accuracy.NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>1 , mv.y>>1 ); + + //Get the remainder after rounding. NB rmdr values always 0 or 1 + const MVector rmdr( mv.x & 1 , mv.y & 1 ); + + //Where to start in the upconverted image + const ImageCoords ref_start( ( dparams.Xp()<<1 ) + roundvec.x ,( dparams.Yp()<<1 ) + roundvec.y ); + const ImageCoords ref_stop( ref_start.x+(dparams.Xl()<<1) , ref_start.y+(dparams.Yl()<<1)); + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + float sum( 0.0f ); + CalcValueType temp; + + + if ( !bounds_check ) + { +#if defined (HAVE_MMX) + const ImageCoords start_pos(dparams.Xp(), dparams.Yp()); + const ImageCoords end_pos(dparams.Xp() + dparams.Xl(), dparams.Yp() + dparams.Yl()); + + sum = simple_block_diff_up_mmx_4 (m_pic_data, m_ref_data, + start_pos, end_pos, + ref_start, ref_stop, + rmdr, + sum, + static_cast<float>(INT_MAX)); + +#else + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + if( rmdr.x == 0 && rmdr.y == 0 ) + { + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + sum += std::abs( *ref_curr - *pic_curr ); + }// x + }// y + } + else if( rmdr.y == 0 ) + { + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + sum += std::abs( temp - *pic_curr ); + }// x + }// y + } + else if( rmdr.x == 0 ) + { + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[m_ref_data.LengthX()] ) + + 1 + ) >> 1; + sum += std::abs( temp - *pic_curr ); + }// x + }// y + } + else + { + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[m_ref_data.LengthX()+0] ) + + CalcValueType( ref_curr[m_ref_data.LengthX()+1] ) + + 2 + ) >> 2; + sum += std::abs( temp - *pic_curr ); + }// x + }// y + } +#endif // HAVE_MMX + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + + // weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (2 - rmdr.x) * (2 - rmdr.y), //tl + rmdr.x * (2 - rmdr.y), //tr + (2 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + const int refXlen( m_ref_data.LengthX() ); + const int refYlen( m_ref_data.LengthY() ); + + for(int y = dparams.Yp(), uY = ref_start.y,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen); + y < dparams.Yend(); ++y, uY += 2,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen)) + { + for(int x = dparams.Xp(), uX = ref_start.x,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen); + x < dparams.Xend(); ++x, uX += 2,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen)) + { + + temp = ( linear_wts[0] * CalcValueType( m_ref_data[BuY][BuX] ) + + linear_wts[1] * CalcValueType( m_ref_data[BuY][BuX1] ) + + linear_wts[2] * CalcValueType( m_ref_data[BuY1][BuX] )+ + linear_wts[3] * CalcValueType( m_ref_data[BuY1][BuX1] ) + + 2 + ) >> 2; + sum += std::abs( temp - m_pic_data[y][x] ); + }// x + }// y + + } + + return sum; + +} + +void BlockDiffQuarterPel::Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return; + } + + // Set up the start point in the reference image by rounding the motion vector + // to 1/2 pel accuracy.NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>1 , mv.y>>1 ); + + //Get the remainder after rounding. NB rmdr values always 0 or 1 + const MVector rmdr( mv.x & 1 , mv.y & 1 ); + + //Where to start in the upconverted image + const ImageCoords ref_start( ( dparams.Xp()<<1 ) + roundvec.x ,( dparams.Yp()<<1 ) + roundvec.y ); + const ImageCoords ref_stop( ref_start.x+(dparams.Xl()<<1) , ref_start.y+(dparams.Yl()<<1)); + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + const float start_val( mvcost*lambda ); + float sum( start_val ); + + CalcValueType temp; + + if ( !bounds_check ) + { +#if defined (HAVE_MMX) + const ImageCoords start_pos(dparams.Xp(), dparams.Yp()); + const ImageCoords end_pos(dparams.Xp() + dparams.Xl(), dparams.Yp() + dparams.Yl()); + + sum = simple_block_diff_up_mmx_4 (m_pic_data, m_ref_data, + start_pos, end_pos, + ref_start, ref_stop, + rmdr, + sum, + best_costs.total); + + if ( sum>=best_costs.total ) + return; +#else + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + if( rmdr.x == 0 && rmdr.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + sum += std::abs( *ref_curr - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + }// y + } + else if( rmdr.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + sum += std::abs( temp - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + }// y + } + else if( rmdr.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[m_ref_data.LengthX()] ) + + 1 + ) >> 1; + sum += std::abs( temp - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[m_ref_data.LengthX()+0] ) + + CalcValueType( ref_curr[m_ref_data.LengthX()+1] ) + + 2 + ) >> 2; + sum += std::abs( temp - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + + } +#endif // HAVE_MMX + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + + // weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (2 - rmdr.x) * (2 - rmdr.y), //tl + rmdr.x * (2 - rmdr.y), //tr + (2 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + const int refXlen( m_ref_data.LengthX() ); + const int refYlen( m_ref_data.LengthY() ); + + for(int y = dparams.Yp(), uY = ref_start.y,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen); + y < dparams.Yend(); ++y, uY += 2,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen)) + { + for(int x = dparams.Xp(), uX = ref_start.x,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen); + x < dparams.Xend(); ++x, uX += 2,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen)) + { + + temp = ( linear_wts[0] * CalcValueType( m_ref_data[BuY][BuX] ) + + linear_wts[1] * CalcValueType( m_ref_data[BuY][BuX1] ) + + linear_wts[2] * CalcValueType( m_ref_data[BuY1][BuX] )+ + linear_wts[3] * CalcValueType( m_ref_data[BuY1][BuX1] ) + + 2 + ) >> 2; + sum += std::abs( temp - m_pic_data[y][x] ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + + } + + // Since we've got here, we must have beaten the best cost to date + + best_mv = mv; + best_costs.total = sum; + best_costs.mvcost = mvcost; + best_costs.SAD = sum - start_val; +} + +float BlockDiffEighthPel::Diff( const BlockDiffParams& dparams , const MVector& mv ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + //Set up the start point in the reference image by rounding the motion vector + //NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>2 , mv.y>>2 ); + + //Get the remainder after rounding. NB rmdr values always 0,1,2 or 3 + const MVector rmdr( mv.x & 3 , mv.y & 3 ); + + //Where to start in the upconverted image + const ImageCoords ref_start( ( dparams.Xp()<<1 ) + roundvec.x ,( dparams.Yp()<<1 ) + roundvec.y ); + const ImageCoords ref_stop( ref_start.x+(dparams.Xl()<<1) , ref_start.y+(dparams.Yl()<<1)); + + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + + //weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (4 - rmdr.x) * (4 - rmdr.y), //tl + rmdr.x * (4 - rmdr.y), //tr + (4 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + float sum( 0.0f ); + + CalcValueType temp; + + if ( !bounds_check ) + { + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + if( rmdr.x == 0 && rmdr.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + sum += CalcValueType( std::abs( ref_curr[0] - *pic_curr ) ); + }// x + }// y + } + else if( rmdr.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = (( linear_wts[0] * CalcValueType( ref_curr[0] ) + + linear_wts[1] * CalcValueType( ref_curr[1] ) + + 8 + ) >> 4); + sum += std::abs( temp - *pic_curr ); + }// x + }// y + } + else if( rmdr.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = (( linear_wts[0] * CalcValueType( ref_curr[0] ) + + linear_wts[2] * CalcValueType( ref_curr[m_ref_data.LengthX()+0] ) + + 8 + ) >> 4); + sum += std::abs( temp - *pic_curr ); + }// x + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = (( linear_wts[0] * CalcValueType( ref_curr[0] ) + + linear_wts[1] * CalcValueType( ref_curr[1] ) + + linear_wts[2] * CalcValueType( ref_curr[m_ref_data.LengthX()+0] ) + + linear_wts[3] * CalcValueType( ref_curr[m_ref_data.LengthX()+1] ) + + 8 + ) >> 4); + sum += std::abs( temp - *pic_curr ); + }// x + }// y + } + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + const int refXlen( m_ref_data.LengthX() ); + const int refYlen( m_ref_data.LengthY() ); + + for(int y = dparams.Yp(), uY = ref_start.y,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen); + y < dparams.Yend(); ++y, uY += 2,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen)) + { + for(int x = dparams.Xp(), uX = ref_start.x,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen); + x < dparams.Xend(); ++x, uX += 2,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen)) + { + + temp = ( linear_wts[0] * CalcValueType( m_ref_data[BuY][BuX] ) + + linear_wts[1] * CalcValueType( m_ref_data[BuY][BuX1] ) + + linear_wts[2] * CalcValueType( m_ref_data[BuY1][BuX] )+ + linear_wts[3] * CalcValueType( m_ref_data[BuY1][BuX1] ) + + 8 + ) >> 4; + sum += std::abs( temp - m_pic_data[y][x] ); + }// x + }// y + + } + + return sum; +} + +void BlockDiffEighthPel::Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return; + } + //Set up the start point in the reference image by rounding the motion vector + //NB: bit shift rounds negative values DOWN, as required + const MVector roundvec( mv.x>>2 , mv.y>>2 ); + + //Get the remainder after rounding. NB rmdr values always 0,1,2 or 3 + const MVector rmdr( mv.x & 3 , mv.y & 3 ); + + //Where to start in the upconverted image + const ImageCoords ref_start( ( dparams.Xp()<<1 ) + roundvec.x ,( dparams.Yp()<<1 ) + roundvec.y ); + const ImageCoords ref_stop( ref_start.x+(dparams.Xl()<<1) , ref_start.y+(dparams.Yl()<<1)); + + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + + //weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts[4] = { (4 - rmdr.x) * (4 - rmdr.y), //tl + rmdr.x * (4 - rmdr.y), //tr + (4 - rmdr.x) * rmdr.y, //bl + rmdr.x * rmdr.y }; //br + + bool bounds_check( false ); + + if ( ref_start.x<0 || + ref_stop.x >= m_ref_data.LengthX() || + ref_start.y<0 || + ref_stop.y >= m_ref_data.LengthY() ) + bounds_check = true; + + const float start_val( mvcost*lambda ); + float sum( start_val ); + + CalcValueType temp; + + if ( !bounds_check ) + { + ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; + const int ref_next( (m_ref_data.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + if( rmdr.x == 0 && rmdr.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + sum += CalcValueType( std::abs( ref_curr[0] - *pic_curr ) ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + } + else if( rmdr.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = (( linear_wts[0] * CalcValueType( ref_curr[0] ) + + linear_wts[1] * CalcValueType( ref_curr[1] ) + + 8 + ) >> 4); + sum += std::abs( temp - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + } + else if( rmdr.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = (( linear_wts[0] * CalcValueType( ref_curr[0] ) + + linear_wts[2] * CalcValueType( ref_curr[m_ref_data.LengthX()+0] ) + + 8 + ) >> 4); + sum += std::abs( temp - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2 ) + { + temp = (( linear_wts[0] * CalcValueType( ref_curr[0] ) + + linear_wts[1] * CalcValueType( ref_curr[1] ) + + linear_wts[2] * CalcValueType( ref_curr[m_ref_data.LengthX()+0] ) + + linear_wts[3] * CalcValueType( ref_curr[m_ref_data.LengthX()+1] ) + + 8 + ) >> 4); + sum += std::abs( temp - *pic_curr ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + } + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + const int refXlen( m_ref_data.LengthX() ); + const int refYlen( m_ref_data.LengthY() ); + + for(int y = dparams.Yp(), uY = ref_start.y,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen); + y < dparams.Yend(); ++y, uY += 2,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen)) + { + for(int x = dparams.Xp(), uX = ref_start.x,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen); + x < dparams.Xend(); ++x, uX += 2,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen)) + { + + temp = ( linear_wts[0] * CalcValueType( m_ref_data[BuY][BuX] ) + + linear_wts[1] * CalcValueType( m_ref_data[BuY][BuX1] ) + + linear_wts[2] * CalcValueType( m_ref_data[BuY1][BuX] )+ + linear_wts[3] * CalcValueType( m_ref_data[BuY1][BuX1] ) + + 8 + ) >> 4; + sum += std::abs( temp - m_pic_data[y][x] ); + }// x + + if ( sum>=best_costs.total ) + return; + + }// y + + } + + // If we've got here we must have done better than the best costs so far + best_mv = mv; + best_costs.total = sum; + best_costs.mvcost = mvcost; + best_costs.SAD = sum - start_val; +} + +float BiBlockHalfPel::Diff( const BlockDiffParams& dparams , + const MVector& mv1 , + const MVector& mv2 ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + // First create a difference array, and subtract the reference 1 data into it + TwoDArray<ValueType> diff_array( dparams.Yl() , dparams.Xl() ); + + //Where to start in the upconverted images + const ImageCoords ref_start1( ( dparams.Xp()<<1 ) + mv1.x ,( dparams.Yp()<<1 ) + mv1.y ); + const ImageCoords ref_stop1( ref_start1.x+(dparams.Xl()<<1) , ref_start1.y+(dparams.Yl()<<1)); + + const ImageCoords ref_start2( ( dparams.Xp()<<1 ) + mv2.x ,( dparams.Yp()<<1 ) + mv2.y ); + const ImageCoords ref_stop2( ref_start2.x+(dparams.Xl()<<1) , ref_start2.y+(dparams.Yl()<<1)); + + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + + ValueType* diff_curr = &diff_array[0][0]; + + bool bounds_check( false ); + + if ( ref_start1.x<0 || + ref_stop1.x >= m_ref_data1.LengthX() || + ref_start1.y<0 || + ref_stop1.y >= m_ref_data1.LengthY() ) + bounds_check = true; + + if ( !bounds_check ) + { + ValueType *ref_curr = &m_ref_data1[ref_start1.y][ref_start1.x]; + const int ref_next( (m_ref_data1.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + *diff_curr = ( (*pic_curr)<<1 ) - *ref_curr; + + }// x + }// y + + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=dparams.Yl(), ry=ref_start1.y, by=BChk(ry,m_ref_data1.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data1.LengthY())) + { + for( int x=dparams.Xl() , rx=ref_start1.x , bx=BChk(rx,m_ref_data1.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , ++diff_curr, bx=BChk(rx,m_ref_data1.LengthX())) + { + *diff_curr = ( (*pic_curr)<<1 ) - m_ref_data1[by][bx]; + }// x + }// y + + } + + // Now do the other reference + + bounds_check = false; + + if ( ref_start2.x<0 || + ref_stop2.x >= m_ref_data2.LengthX() || + ref_start2.y<0 || + ref_stop2.y >= m_ref_data2.LengthY() ) + bounds_check = true; + + float sum( 0 ); + + diff_curr = &diff_array[0][0]; + ValueType temp; + + if ( !bounds_check ) + { + ValueType *ref_curr = &m_ref_data2[ref_start2.y][ref_start2.x]; + const int ref_next( (m_ref_data2.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (*diff_curr - *ref_curr )>>1; + sum += std::abs( temp ); + + }// x + }// y + + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=dparams.Yl(), ry=ref_start2.y, by=BChk(ry,m_ref_data2.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data2.LengthY())) + { + for( int x=dparams.Xl() , rx=ref_start2.x , bx=BChk(rx,m_ref_data2.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , ++diff_curr, bx=BChk(rx,m_ref_data2.LengthX())) + { + temp = (*diff_curr - m_ref_data2[by][bx] )>>1; + sum += std::abs( temp ); + }// x + }// y + + } + + return sum; + +} + +float BiBlockQuarterPel::Diff( const BlockDiffParams& dparams , + const MVector& mv1 , + const MVector& mv2 ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + // First create a difference array, and subtract the reference 1 data into it + TwoDArray<ValueType> diff_array( dparams.Yl() , dparams.Xl() ); + + // Set up the start point in the reference images by rounding the motion vectors + // to 1/2 pel accuracy.NB: bit shift rounds negative values DOWN, as required + const MVector roundvec1 ( mv1.x>>1 , mv1.y>>1 ); + const MVector roundvec2 ( mv2.x>>1 , mv2.y>>1 ); + + //Get the remainders after rounding. NB rmdr values always 0 or 1 + const MVector rmdr1( mv1.x & 1 , mv1.y & 1 ); + const MVector rmdr2( mv2.x & 1 , mv2.y & 1 ); + + //Where to start in the upconverted images + const ImageCoords ref_start1( ( dparams.Xp()<<1 ) + roundvec1.x ,( dparams.Yp()<<1 ) + roundvec1.y ); + const ImageCoords ref_stop1( ref_start1.x+(dparams.Xl()<<1) , ref_start1.y+(dparams.Yl()<<1)); + + const ImageCoords ref_start2( ( dparams.Xp()<<1 ) + roundvec2.x ,( dparams.Yp()<<1 ) + roundvec2.y ); + const ImageCoords ref_stop2( ref_start2.x+(dparams.Xl()<<1) , ref_start2.y+(dparams.Yl()<<1)); + + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + + ValueType* diff_curr = &diff_array[0][0]; + + bool bounds_check( false ); + + if ( ref_start1.x<0 || + ref_stop1.x >= m_ref_data1.LengthX() || + ref_start1.y<0 || + ref_stop1.y >= m_ref_data1.LengthY() ) + bounds_check = true; + + ValueType temp; + + if ( !bounds_check ) + { +#if defined (HAVE_MMX) + const ImageCoords start_pos(dparams.Xp(), dparams.Yp()); + const ImageCoords end_pos(dparams.Xp() + dparams.Xl(), dparams.Yp() + dparams.Yl()); + + simple_biblock_diff_pic_mmx_4 (m_pic_data, m_ref_data1, diff_array, + start_pos, end_pos, + ref_start1, ref_stop1, + rmdr1); +#else + ValueType *ref_curr = &m_ref_data1[ref_start1.y][ref_start1.x]; + const int ref_next( (m_ref_data1.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + + + if( rmdr1.x == 0 && rmdr1.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + *diff_curr = ( (*pic_curr)<<1 ) - *ref_curr; + }// x + }// y + } + else if( rmdr1.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + else if( rmdr1.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[m_ref_data1.LengthX()] ) + + 1 + ) >> 1; + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[m_ref_data1.LengthX()+0] ) + + CalcValueType( ref_curr[m_ref_data1.LengthX()+1] ) + + 2 + ) >> 2; + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + +#endif + } + else + { + const ValueType linear_wts[4] = { (2 - rmdr1.x) * (2 - rmdr1.y), //tl + rmdr1.x * (2 - rmdr1.y), //tr + (2 - rmdr1.x) * rmdr1.y, //bl + rmdr1.x * rmdr1.y }; //br + + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=dparams.Yl(), ry=ref_start1.y, by=BChk(ry,m_ref_data1.LengthY()), by1=BChk(ry+1,m_ref_data1.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data1.LengthY()), by1=BChk(ry+1,m_ref_data1.LengthY()) ) + { + for( int x=dparams.Xl() , rx=ref_start1.x , bx=BChk(rx,m_ref_data1.LengthX()), bx1=BChk(rx+1,m_ref_data1.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , ++diff_curr, bx=BChk(rx,m_ref_data1.LengthX()), bx1=BChk(rx+1,m_ref_data1.LengthX())) + { + temp = ( linear_wts[0] * CalcValueType( m_ref_data1[by][bx] ) + + linear_wts[1] * CalcValueType( m_ref_data1[by][bx1] ) + + linear_wts[2] * CalcValueType( m_ref_data1[by1][bx] )+ + linear_wts[3] * CalcValueType( m_ref_data1[by1][bx1] ) + + 2 + ) >> 2; + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + + // Now do the other reference + + bounds_check = false; + + if ( ref_start2.x<0 || + ref_stop2.x >= m_ref_data2.LengthX() || + ref_start2.y<0 || + ref_stop2.y >= m_ref_data2.LengthY() ) + bounds_check = true; + + float sum( 0 ); + + diff_curr = &diff_array[0][0]; + + if ( !bounds_check ) + { + + +#if defined (HAVE_MMX) + sum = static_cast<float>( simple_biblock_diff_up_mmx_4 (diff_array, + m_ref_data2, + ref_start2, ref_stop2, + rmdr2) ); +#else + ValueType *ref_curr = &m_ref_data2[ref_start2.y][ref_start2.x]; + const int ref_next( (m_ref_data2.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + if( rmdr2.x == 0 && rmdr2.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + sum += std::abs( (*diff_curr - *ref_curr)>>1 ); + }// x + }// y + } + else if( rmdr2.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + else if( rmdr2.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[m_ref_data2.LengthX()] ) + + 1 + ) >> 1; + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[m_ref_data2.LengthX()+0] ) + + CalcValueType( ref_curr[m_ref_data2.LengthX()+1] ) + + 2 + ) >> 2; + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } +#endif + } + else + { + const ValueType linear_wts[4] = { (2 - rmdr2.x) * (2 - rmdr2.y), //tl + rmdr2.x * (2 - rmdr2.y), //tr + (2 - rmdr2.x) * rmdr2.y, //bl + rmdr2.x * rmdr2.y }; //br + + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=dparams.Yl(), ry=ref_start2.y, by=BChk(ry,m_ref_data2.LengthY()),by1=BChk(ry+1,m_ref_data2.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data2.LengthY()),by1=BChk(ry+1,m_ref_data2.LengthY())) + { + for( int x=dparams.Xl() , rx=ref_start2.x , bx=BChk(rx,m_ref_data2.LengthX()), bx1=BChk(rx+1,m_ref_data2.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , ++diff_curr, bx=BChk(rx,m_ref_data2.LengthX()), bx1=BChk(rx+1,m_ref_data2.LengthX())) + { + temp = ( linear_wts[0] * CalcValueType( m_ref_data2[by][bx] ) + + linear_wts[1] * CalcValueType( m_ref_data2[by][bx1] ) + + linear_wts[2] * CalcValueType( m_ref_data2[by1][bx] )+ + linear_wts[3] * CalcValueType( m_ref_data2[by1][bx1] ) + + 2 + ) >> 2; + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + + return sum; + +} + +float BiBlockEighthPel::Diff( const BlockDiffParams& dparams , + const MVector& mv1 , + const MVector& mv2 ) +{ + if (dparams.Xl() <= 0 || dparams.Yl() <= 0) + { + return 0; + } + + // First create a difference array, and subtract the reference 1 data into it + TwoDArray<ValueType> diff_array( dparams.Yl() , dparams.Xl() ); + + // Set up the start point in the reference images by rounding the motion vectors + // to 1/2 pel accuracy.NB: bit shift rounds negative values DOWN, as required + const MVector roundvec1 ( mv1.x>>2 , mv1.y>>2 ); + const MVector roundvec2 ( mv2.x>>2 , mv2.y>>2 ); + + //Get the remainders after rounding. NB rmdr values always 0-3 + const MVector rmdr1( mv1.x & 3 , mv1.y & 3 ); + const MVector rmdr2( mv2.x & 3 , mv2.y & 3 ); + + //weights for doing linear interpolation, calculated from the remainder values + const ValueType linear_wts1[4] = { (4 - rmdr1.x) * (4 - rmdr1.y), //tl + rmdr1.x * (4 - rmdr1.y), //tr + (4 - rmdr1.x) * rmdr1.y, //bl + rmdr1.x * rmdr1.y }; //br + const ValueType linear_wts2[4] = { (4 - rmdr2.x) * (4 - rmdr2.y), //tl + rmdr2.x * (4 - rmdr2.y), //tr + (4 - rmdr2.x) * rmdr2.y, //bl + rmdr2.x * rmdr2.y }; //br + + //Where to start in the upconverted images + const ImageCoords ref_start1( ( dparams.Xp()<<1 ) + roundvec1.x ,( dparams.Yp()<<1 ) + roundvec1.y ); + const ImageCoords ref_stop1( ref_start1.x+(dparams.Xl()<<1) , ref_start1.y+(dparams.Yl()<<1)); + + const ImageCoords ref_start2( ( dparams.Xp()<<1 ) + roundvec2.x ,( dparams.Yp()<<1 ) + roundvec2.y ); + const ImageCoords ref_stop2( ref_start2.x+(dparams.Xl()<<1) , ref_start2.y+(dparams.Yl()<<1)); + + ValueType* pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; + const int pic_next( m_pic_data.LengthX() - dparams.Xl() );// go down a row and back up + + ValueType* diff_curr = &diff_array[0][0]; + + bool bounds_check( false ); + + if ( ref_start1.x<0 || + ref_stop1.x >= m_ref_data1.LengthX() || + ref_start1.y<0 || + ref_stop1.y >= m_ref_data1.LengthY() ) + bounds_check = true; + + ValueType temp; + + if ( !bounds_check ) + { + ValueType *ref_curr = &m_ref_data1[ref_start1.y][ref_start1.x]; + const int ref_next( (m_ref_data1.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + if( rmdr1.x == 0 && rmdr1.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + *diff_curr = ( (*pic_curr)<<1 ) - *ref_curr; + }// x + }// y + } + else if( rmdr1.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (( linear_wts1[0] * CalcValueType( ref_curr[0] ) + + linear_wts1[1] * CalcValueType( ref_curr[1] ) + + 8 + ) >> 4); + + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + else if( rmdr1.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (( linear_wts1[0] * CalcValueType( ref_curr[0] ) + + linear_wts1[2] * CalcValueType( ref_curr[m_ref_data1.LengthX()+0] ) + + 8 + ) >> 4); + + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (( linear_wts1[0] * CalcValueType( ref_curr[0] ) + + linear_wts1[1] * CalcValueType( ref_curr[1] ) + + linear_wts1[2] * CalcValueType( ref_curr[m_ref_data1.LengthX()+0] ) + + linear_wts1[3] * CalcValueType( ref_curr[m_ref_data1.LengthX()+1] ) + + 8 + ) >> 4); + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + + + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=dparams.Yl(), ry=ref_start1.y, by=BChk(ry,m_ref_data1.LengthY()), by1=BChk(ry+1,m_ref_data1.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data1.LengthY()), by1=BChk(ry+1,m_ref_data1.LengthY()) ) + { + for( int x=dparams.Xl() , rx=ref_start1.x , bx=BChk(rx,m_ref_data1.LengthX()), bx1=BChk(rx+1,m_ref_data1.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , ++diff_curr, bx=BChk(rx,m_ref_data1.LengthX()), bx1=BChk(rx+1,m_ref_data1.LengthX())) + { + temp = ( linear_wts1[0] * CalcValueType( m_ref_data1[by][bx] ) + + linear_wts1[1] * CalcValueType( m_ref_data1[by][bx1] ) + + linear_wts1[2] * CalcValueType( m_ref_data1[by1][bx] )+ + linear_wts1[3] * CalcValueType( m_ref_data1[by1][bx1] ) + + 8 + ) >> 4; + *diff_curr = ( (*pic_curr)<<1 ) - temp; + }// x + }// y + } + + // Now do the other reference + + bounds_check = false; + + if ( ref_start2.x<0 || + ref_stop2.x >= m_ref_data2.LengthX() || + ref_start2.y<0 || + ref_stop2.y >= m_ref_data2.LengthY() ) + bounds_check = true; + + float sum( 0 ); + + diff_curr = &diff_array[0][0]; + + if ( !bounds_check ) + { + ValueType *ref_curr = &m_ref_data2[ref_start2.y][ref_start2.x]; + const int ref_next( (m_ref_data2.LengthX() - dparams.Xl())*2 );// go down 2 rows and back up + + if( rmdr2.x == 0 && rmdr2.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + sum += std::abs( (*diff_curr - *ref_curr)>>1 ); + }// x + }// y + } + else if( rmdr2.y == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (( linear_wts2[0] * CalcValueType( ref_curr[0] ) + + linear_wts2[1] * CalcValueType( ref_curr[1] ) + + 8 + ) >> 4); + + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + else if( rmdr2.x == 0 ) + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (( linear_wts2[0] * CalcValueType( ref_curr[0] ) + + linear_wts2[2] * CalcValueType( ref_curr[m_ref_data2.LengthX()+0] ) + + 8 + ) >> 4); + + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + else + { + for( int y=dparams.Yl(); y > 0; --y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=dparams.Xl(); x > 0; --x, ++pic_curr, ref_curr+=2, ++diff_curr ) + { + temp = (( linear_wts2[0] * CalcValueType( ref_curr[0] ) + + linear_wts2[1] * CalcValueType( ref_curr[1] ) + + linear_wts2[2] * CalcValueType( ref_curr[m_ref_data2.LengthX()+0] ) + + linear_wts2[3] * CalcValueType( ref_curr[m_ref_data2.LengthX()+1] ) + + 8 + ) >> 4); + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + + } + else + { + // We're doing bounds checking because we'll fall off the edge of the reference otherwise. + for( int y=dparams.Yl(), ry=ref_start1.y, by=BChk(ry,m_ref_data2.LengthY()),by1=BChk(ry+1,m_ref_data2.LengthY()); + y>0; + --y, pic_curr+=pic_next, ry+=2 , by=BChk(ry,m_ref_data2.LengthY()),by1=BChk(ry+1,m_ref_data2.LengthY())) + { + for( int x=dparams.Xl() , rx=ref_start1.x , bx=BChk(rx,m_ref_data2.LengthX()), bx1=BChk(rx+1,m_ref_data2.LengthX()); + x>0 ; + --x, ++pic_curr, rx+=2 , ++diff_curr, bx=BChk(rx,m_ref_data2.LengthX()), bx1=BChk(rx+1,m_ref_data2.LengthX())) + { + temp = ( linear_wts2[0] * CalcValueType( m_ref_data2[by][bx] ) + + linear_wts2[1] * CalcValueType( m_ref_data2[by][bx1] ) + + linear_wts2[2] * CalcValueType( m_ref_data2[by1][bx] )+ + linear_wts2[3] * CalcValueType( m_ref_data2[by1][bx1] ) + + 8 + ) >> 4; + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + } + + return sum; + +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils.h new file mode 100644 index 000000000..51c464b7b --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils.h @@ -0,0 +1,557 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_utils.h,v 1.14 2008/08/14 00:58:24 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1- +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _ME_UTILS_H_ +#define _ME_UTILS_H_ + +#include <algorithm> +#include <libdirac_common/motion.h> +#include <libdirac_common/common.h> +namespace dirac +{ + + /////////////////////////////////// + //Utilities for motion estimation// + //-------------------------------// + /////////////////////////////////// + + //! A class encapsulating parameters for calculating a block difference value (a single instance of matching) + class BlockDiffParams + { + + public: + //! Constructor + BlockDiffParams(){} + + //! Constructor + BlockDiffParams( const int x_p , const int y_p , const int x_l , const int y_l): + m_xp(x_p), + m_yp(y_p), + m_xl(x_l), + m_yl(y_l), + m_xend(x_l+x_p), + m_yend(y_l+y_p) + {} + + //////////////////////////////////////////////////////////////////// + //NB: Assume default copy constructor, assignment = and destructor// + //////////////////////////////////////////////////////////////////// + + // Sets ... + + + //! Set the limits of the block to fit in a picture + + void SetBlockLimits( const OLBParams& bparams , + const PicArray& pic_data , + const int xbpos , const int ybpos); + + // ... and gets + + //! Return the x-position of the top-left block corner + int Xp() const {return m_xp;} + + //! Return the y-position of the top-left block corner + int Yp() const {return m_yp;} + + //! Return the block width + int Xl() const {return m_xl;} + + //! Return the block height + int Yl() const {return m_yl;} + + //! Return the block horizontal endpoint + int Xend() const {return m_xend;} + + //! Return the block vertical endpoint + int Yend() const {return m_yend;} + + private: + + int m_xp; + int m_yp; + int m_xl; + int m_yl; + int m_xend; + int m_yend; + }; + + ////////////////////////////////////////////////// + //----Different difference classes, so that-----// + //bounds-checking need only be done as necessary// + ////////////////////////////////////////////////// + + //! An abstract class for doing block difference calculations + class BlockDiff + { + public: + //! Constructor, initialising the reference and picture data + /* + Constructor, initialising the reference and picture data + \param ref the reference picture + \param pic the picture being matched + */ + BlockDiff( const PicArray& ref , const PicArray& pic ); + + //! Destructor + virtual ~BlockDiff(){} + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv the motion vector being used + */ + virtual float Diff( const BlockDiffParams& dparams , const MVector& mv )=0; + + protected: + + const PicArray& m_pic_data; + const PicArray& m_ref_data; + + private: + //! Private, bodyless copy-constructor: class should not be copied + BlockDiff( const BlockDiff& cpy ); + + //! Private, bodyless assignment=: class should not be assigned + BlockDiff& operator=( const BlockDiff& rhs ); + }; + + //! A class for doing block differences to pixel accuracy, inherited from BlockDiff + class PelBlockDiff: public BlockDiff + { + public: + //! Constructor, initialising the reference and picture data + /* + Constructor, initialising the reference and picture data + \param ref the reference picture + \param pic the picture being matched + */ + PelBlockDiff( const PicArray& ref , const PicArray& pic ); + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv the motion vector being used + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv ); + + //! Do the difference, overwriting the best MV so far if appropriate + /*! + Do the difference, overwriting the best MV so far if appropriate, + and bailing out if we do worse + \param dparams block parameters + \param mv the motion vector being used + \param best_sum the best SAD value obtain yet + \param best_mv the MV giving the best SAD value so far + */ + void Diff( const BlockDiffParams& dparams , + const MVector& mv , + float& best_sum , + MVector& best_mv ); + + private: + //! Private, bodyless copy-constructor: class should not be copied + PelBlockDiff(const PelBlockDiff& cpy); + + //! Private, bodyless assignment=: class should not be assigned + PelBlockDiff& operator=(const PelBlockDiff& rhs); + }; + + + //! A class for calculating the difference between a block and its DC value (average) + class IntraBlockDiff + { + public: + //! Constructor, initialising the picture data + /* + Constructor, initialising the picture data + \param pic the picture being matched + */ + IntraBlockDiff( const PicArray& pic ); + + //! Do the difference, calculating the DC value and returning SAD + /*! + Do the difference, calculating the DC value and returning SAD + \param dparams block parameters + \param dc_val DC value + */ + float Diff( const BlockDiffParams& dparams , ValueType& dc_val ); + + //! Calculate a DC value + ValueType CalcDC( const BlockDiffParams& dparams); + + private: + //! Private, bodyless copy-constructor: class should not be copied + IntraBlockDiff(const IntraBlockDiff& cpy); + + //! Private, bodyless assignment=: class should not be assigned + IntraBlockDiff& operator=(const IntraBlockDiff& rhs); + + const PicArray& m_pic_data; + }; + + //! A virtual class for bi-directional differences + class BiBlockDiff + { + public: + //! Constructor, initialising the references and picture data + /* + Constructor, initialising the references and picture data + \param ref1 the first reference picture + \param ref2 the second reference picture + \param pic the picture being matched + */ + BiBlockDiff( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic); + + //! Virtual destructor + virtual ~BiBlockDiff( ) {} + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv1 the motion vector being used for reference 1 + \param mv2 the motion vector being used for reference 2 + */ + virtual float Diff( const BlockDiffParams& dparams , const MVector& mv1 , const MVector& mv2 )=0; + + protected: + const PicArray& m_pic_data; + const PicArray& m_ref_data1; + const PicArray& m_ref_data2; + + private: + //! Private, bodyless copy-constructor: class should not be copied + BiBlockDiff(const BiBlockDiff& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BiBlockDiff& operator=(const BiBlockDiff& rhs); + }; + + // Classes where the reference is upconverted // + //////////////////////////////////////////////// + //! A virtual class for doing differences with sub-pixel vectors + class BlockDiffUp: public BlockDiff + { + + public: + + //! Constructor, initialising the reference and picture data + /* + Constructor, initialising the reference and picture data + \param ref the reference picture + \param pic the picture being matched + */ + BlockDiffUp( const PicArray& ref , const PicArray& pic ); + + //! Destructor + virtual ~BlockDiffUp(){} + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv the motion vector being used + */ + virtual float Diff( const BlockDiffParams& dparams , const MVector& mv )=0; + + //! Do the actual difference, overwriting the best MV so far if appropriate + /*! + Do the actual difference, overwriting the best MV so far if appropriate, + and bailing out if we do worse + \param dparams block parameters + \param mv the motion vector being used + \param mvcost the (prediction) cost of the motion vector mv + \param lambda the weighting to be given to mvcost + \param best_costs the best Lagrangian costs obtained yet + \param best_mv the MV giving the best Lagrangian costs so far + */ + virtual void Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv)=0; + private: + //! Private, bodyless copy-constructor: class should not be copied + BlockDiffUp(const BlockDiffUp& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BlockDiffUp& operator=(const BlockDiffUp& rhs); + }; + + //! A class for doing differences with half-pixel accurate vectors + class BlockDiffHalfPel: public BlockDiffUp + { + + public: + //! Constructor, initialising the reference and picture data + /* + Constructor, initialising the reference and picture data + \param ref the reference picture + \param pic the picture being matched + */ + BlockDiffHalfPel( const PicArray& ref , const PicArray& pic ); + + //! Destructor + ~BlockDiffHalfPel(){} + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv the motion vector being used + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv ); + + //! Do the actual difference, overwriting the best MV so far if appropriate + /*! + Do the actual difference, overwriting the best MV so far if appropriate, + and bailing out if we do worse + \param dparams block parameters + \param mv the motion vector being used + \param mvcost the (prediction) cost of the motion vector mv + \param lambda the weighting to be given to mvcost + \param best_costs the best Lagrangian costs obtained yet + \param best_mv the MV giving the best Lagrangian costs so far + */ + void Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv); + + private: + //! Private, bodyless copy-constructor: class should not be copied + BlockDiffHalfPel(const BlockDiffHalfPel& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BlockDiffHalfPel& operator=(const BlockDiffHalfPel& rhs); + + }; + + //! A class for doing differences with quarter-pixel accurate vectors + class BlockDiffQuarterPel: public BlockDiffUp + { + public: + //! Constructor, initialising the reference and picture data + /* + Constructor, initialising the reference and picture data + \param ref the reference picture + \param pic the picture being matched + */ + BlockDiffQuarterPel( const PicArray& ref , const PicArray& pic ); + + //! Destructor + ~BlockDiffQuarterPel(){} + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv the motion vector being used + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv ); + + //! Do the actual difference, overwriting the best MV so far if appropriate + /*! + Do the actual difference, overwriting the best MV so far if appropriate, + and bailing out if we do worse + \param dparams block parameters + \param mv the motion vector being used + \param mvcost the (prediction) cost of the motion vector mv + \param lambda the weighting to be given to mvcost + \param best_costs the best Lagrangian costs obtained yet + \param best_mv the MV giving the best Lagrangian costs so far + */ + void Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv); + + private: + //! Private, bodyless copy-constructor: class should not be copied + BlockDiffQuarterPel(const BlockDiffQuarterPel& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BlockDiffQuarterPel& operator=(const BlockDiffQuarterPel& rhs); + }; + + //! A class for doing differences with eighth-pixel accurate vectors + class BlockDiffEighthPel: public BlockDiffUp + { + public: + //! Constructor, initialising the reference and picture data + /* + Constructor, initialising the reference and picture data + \param ref the reference picture + \param pic the picture being matched + */ + BlockDiffEighthPel( const PicArray& ref , const PicArray& pic ); + + //! Destructor + ~BlockDiffEighthPel(){} + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv the motion vector being used + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv ); + + //! Do the actual difference, overwriting the best MV so far if appropriate + /*! + Do the actual difference, overwriting the best MV so far if appropriate, + and bailing out if we do worse + \param dparams block parameters + \param mv the motion vector being used + \param mvcost the (prediction) cost of the motion vector mv + \param lambda the weighting to be given to mvcost + \param best_costs the best Lagrangian costs obtained yet + \param best_mv the MV giving the best Lagrangian costs so far + */ + void Diff( const BlockDiffParams& dparams, + const MVector& mv , + const float mvcost, + const float lambda, + MvCostData& best_costs , + MVector& best_mv); + + private: + //! Private, bodyless copy-constructor: class should not be copied + BlockDiffEighthPel(const BlockDiffEighthPel& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BlockDiffEighthPel& operator=(const BlockDiffEighthPel& rhs); + }; + + //! A class for computing a bidirection difference for half-pel vectors + class BiBlockHalfPel: public BiBlockDiff + { + public: + //! Constructor, initialising the references and picture data + /* + Constructor, initialising the reference and picture data + \param ref1 the first reference picture + \param ref2 the second reference picture + \param pic the picture being matched + */ + BiBlockHalfPel( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic ); + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv1 the motion vector being used for reference 1 + \param mv2 the motion vector being used for reference 2 + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv1 , const MVector& mv2 ); + private: + //! Private, bodyless copy-constructor: class should not be copied + BiBlockHalfPel(const BiBlockHalfPel& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BiBlockHalfPel& operator=(const BiBlockHalfPel& rhs); + }; + + //! A class for computing a bidirection difference for quarter-pel vectors + class BiBlockQuarterPel: public BiBlockDiff + { + public: + //! Constructor, initialising the references and picture data + /* + Constructor, initialising the reference and picture data + \param ref1 the first reference picture + \param ref2 the second reference picture + \param pic the picture being matched + */ + BiBlockQuarterPel( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic ); + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv1 the motion vector being used for reference 1 + \param mv2 the motion vector being used for reference 2 + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv1 , const MVector& mv2 ); + + private: + //! Private, bodyless copy-constructor: class should not be copied + BiBlockQuarterPel(const BiBlockQuarterPel& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BiBlockQuarterPel& operator=(const BiBlockQuarterPel& rhs); + }; + + //! A class for computing a bidirection difference for eighth-pel vectors + class BiBlockEighthPel: public BiBlockDiff + { + public: + //! Constructor, initialising the references and picture data + /* + Constructor, initialising the reference and picture data + \param ref1 the first reference picture + \param ref2 the second reference picture + \param pic the picture being matched + */ + BiBlockEighthPel( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic ); + + //! Do the difference, returning SAD + /*! + Do the difference, returning SAD + \param dparams block parameters + \param mv1 the motion vector being used for reference 1 + \param mv2 the motion vector being used for reference 2 + */ + float Diff( const BlockDiffParams& dparams , const MVector& mv1 , const MVector& mv2 ); + private: + //! Private, bodyless copy-constructor: class should not be copied + BiBlockEighthPel(const BiBlockEighthPel& cpy); + + //! Private, bodyless assignment=: class should not be assigned + BiBlockEighthPel& operator=(const BiBlockEighthPel& rhs); + }; + +} // namespace dirac +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils_mmx.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils_mmx.cpp new file mode 100644 index 000000000..692b9c148 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils_mmx.cpp @@ -0,0 +1,1134 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_utils_mmx.cpp,v 1.8 2007/08/24 16:13:38 asuraparaju Exp $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is contributed by Peter Meerwald. +* +* The Initial Developer of the Original Code is Peter Meerwald. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Peter Meerwald (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_common/dirac_assertions.h> +#include <libdirac_motionest/me_utils_mmx.h> + +#if defined HAVE_MMX +using namespace dirac; + +namespace dirac +{ + typedef union + { + int i[2]; + short h[4]; + __m64 m; + } u_mmx_val; + + CalcValueType simple_block_diff_mmx_4 ( + const BlockDiffParams& dparams, const MVector& mv, + const PicArray& pic_data, const PicArray& ref_data, + CalcValueType i_best_sum) + { + u_mmx_val u_sum; + + u_sum.i[0] = u_sum.i[1] = 0; + + ValueType *src = &(pic_data[dparams.Yp()][dparams.Xp()]); + ValueType *refd = &(ref_data[dparams.Yp()+mv.y][dparams.Xp()+mv.x]); + + int height = dparams.Yl(); + int width = dparams.Xl(); + int stopX = (width>>2)<<2; + int pic_next = (pic_data.LengthX() - width); + int ref_next = (ref_data.LengthX() - width); + CalcValueType mop_sum = 0; + for (int j = 0; j < height; j++) + { + for (int i = 0; i < stopX; i+=4) + { + // pic - ref + __m64 pic = _mm_sub_pi16 (*(__m64 *)src, *(__m64 *)refd); + // abs (pic - ref) + __m64 ref = _mm_srai_pi16(pic, 15); + pic = _mm_xor_si64(pic, ref); + pic = _mm_sub_pi16 (pic, ref); + // sum += abs(pic -ref) + ref = _mm_xor_si64(ref, ref); + ref = _mm_unpackhi_pi16(pic, ref); + pic = _mm_unpacklo_pi16(pic, pic); + pic = _mm_srai_pi32 (pic, 16); + pic = _mm_add_pi32 (pic, ref); + u_sum.m = _mm_add_pi32 (u_sum.m, pic); + src += 4; + refd += 4; + } + for (int i = stopX; i < width; i++) + { + mop_sum += std::abs(*src - *refd); + src++; + refd++; + } + if ((u_sum.i[0] + u_sum.i[1] + mop_sum) >= i_best_sum) + { + _mm_empty(); + return i_best_sum; + } + src += pic_next; + refd += ref_next; + } + _mm_empty(); + + return u_sum.i[0] + u_sum.i[1] + mop_sum; + } + + + CalcValueType simple_intra_block_diff_mmx_4 ( + const BlockDiffParams& dparams, + const PicArray& pic_data, ValueType &dc_val) + { + __m64 tmp = _mm_set_pi16(0, 0, 0, 0); + u_mmx_val u_sum; + u_sum.i[0] = u_sum.i[1] = 0; + + ValueType *src = &(pic_data[dparams.Yp()][dparams.Xp()]); + + int height = dparams.Yl(); + int width = dparams.Xl(); + int stopX = (width>>2)<<2; + int pic_next = (pic_data.LengthX() - width); + CalcValueType mop_sum = 0; + for (int j = 0; j < height; j++) + { + for (int i = 0; i < stopX; i+=4) + { + __m64 pic = *(__m64 *)src; + // sum += (pic) + tmp = _mm_xor_si64(tmp, tmp); + tmp = _mm_unpackhi_pi16(pic, tmp); + tmp = _mm_slli_pi32 (tmp, 16); + tmp = _mm_srai_pi32 (tmp, 16); + pic = _mm_unpacklo_pi16(pic, pic); + pic = _mm_srai_pi32 (pic, 16); + pic = _mm_add_pi32 (pic, tmp); + u_sum.m = _mm_add_pi32 (u_sum.m, pic); + src += 4; + } + // Mop up + for (int i = stopX; i < width; ++i) + { + mop_sum += *src; + src++; + } + src += pic_next; + } + + CalcValueType int_dc = (u_sum.i[0] + u_sum.i[1] + mop_sum)/(width*height); + + dc_val = static_cast<ValueType>( int_dc ); + + // Now compute the resulting SAD + __m64 dc = _mm_set_pi16 ( dc_val, dc_val , dc_val , dc_val); + u_sum.m = _mm_xor_si64(u_sum.m, u_sum.m); // initialise sum to 0 + mop_sum = 0; + + src = &(pic_data[dparams.Yp()][dparams.Xp()]); + for (int j = 0; j < height; ++j) + { + for (int i = 0; i < stopX; i+=4) + { + __m64 pic = *(__m64 *)src; + // pic - dc + pic = _mm_sub_pi16 (pic, dc); + // abs (pic - dc) + tmp = _mm_srai_pi16(pic, 15); + pic = _mm_xor_si64(pic, tmp); + pic = _mm_sub_pi16 (pic, tmp); + // sum += abs(pic -dc) + tmp = _mm_xor_si64(tmp, tmp); + tmp = _mm_unpackhi_pi16(pic, tmp); + pic = _mm_unpacklo_pi16(pic, pic); + pic = _mm_srai_pi32 (pic, 16); + pic = _mm_add_pi32 (pic, tmp); + u_sum.m = _mm_add_pi32 (u_sum.m, pic); + src += 4; + } + // Mop up + for (int i = stopX; i < width; ++i) + { + mop_sum += std::abs(*src - dc_val); + src++; + } + src += pic_next; + } + CalcValueType intra_cost = u_sum.i[0] + u_sum.i[1] + mop_sum; + _mm_empty(); + + return intra_cost; + + } + + /* + * NOTE: we are not doing any bounds checks here. This function must + * be invoked only when the reference images start and stop fall + * withing bounds + */ + float simple_block_diff_up_mmx_4( + const PicArray& pic_data, const PicArray& ref_data, + const ImageCoords& start_pos, const ImageCoords& end_pos, + const ImageCoords& ref_start, const ImageCoords& ref_stop, + const MVector& rmdr, float cost_so_far, + float best_total_cost_so_far) + { + ValueType *pic_curr = &pic_data[start_pos.y][start_pos.x]; + ValueType *ref_curr = &ref_data[ref_start.y][ref_start.x]; + + const int width = end_pos.x - start_pos.x; + int height = end_pos.y - start_pos.y; + const int ref_stride = ref_data.LengthX(); + + // go down a row and back up + const int pic_next = pic_data.LengthX() - width; + // go down 2 rows and back up + const int ref_next = ref_data.LengthX()*2 - width*2; + + REPORTM (ref_start.x>=0 && ref_stop.x < ref_data.LengthX() && + ref_start.y>=0 && ref_stop.y < ref_data.LengthY(), + "Reference image coordinates within bounds"); + + CalcValueType sum = 0; + CalcValueType mop_sum(0); + int stopX = (width>>2)<<2; + __m64 m_sum = _mm_set_pi16(0, 0, 0, 0); + u_mmx_val u_sum; + if (rmdr.x == 0 && rmdr.y == 0 ) + { + //std::cerr << "Inmmx routine rmdr.x = rmdr.y = 0" << std::endl; +#if 1 + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + m_sum = _mm_xor_si64 (m_sum, m_sum); + mop_sum= 0; + for( int x=0; x < stopX; x+=4, pic_curr+=4, ref_curr+=8 ) + { + __m64 pic = *(__m64 *)pic_curr; + __m64 ref = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 ref2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + ref = _mm_unpacklo_pi16 ( ref, ref2); + // ref - pic + pic = _mm_sub_pi16 (pic, ref); + // abs (ref - pic) + ref = _mm_srai_pi16(pic, 15); + pic = _mm_xor_si64(pic, ref); + pic = _mm_sub_pi16 (pic, ref); + // sum += abs(ref -pic) + /** + * Since we are re-initialising m_sum with every loop + * maybe we don't need the following since overflow may + * not occur + ref = _mm_xor_si64(ref, ref); + ref = _mm_unpackhi_pi16(pic, ref); + pic = _mm_unpacklo_pi16(pic, pic); + pic = _mm_srai_pi32 (pic, 16); + pic = _mm_add_pi32 (pic, ref); + m_sum = _mm_add_pi32 (m_sum, pic); + **/ + m_sum = _mm_add_pi16 (m_sum, pic); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr,ref_curr+=2) + { + mop_sum += std::abs (*ref_curr - *pic_curr); + } + u_sum.m = m_sum; + //sum += (u_sum.i[0] + u_sum.i[1] + mop_sum); + sum += (u_sum.h[0] + u_sum.h[1] + u_sum.h[2] + u_sum.h[3] + mop_sum); + _mm_empty(); + if ((sum + cost_so_far )>= best_total_cost_so_far) + { + return best_total_cost_so_far; + } + } + _mm_empty(); + return sum + cost_so_far; +#else + float sum = cost_so_far; + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ref_curr+=2 ) + { + sum += std::abs( *ref_curr - *pic_curr ); + }// x + + if ( sum>= best_total_cost_so_far) + return best_total_cost_so_far; + + }// y + return sum; +#endif + + } + else if( rmdr.y == 0 ) + { +#if 1 + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + m_sum = _mm_xor_si64 (m_sum, m_sum); + mop_sum= 0; + for( int x=0; x < stopX; x+=4, pic_curr+=4, ref_curr+=8 ) + { + // Load ref + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + // m3 = words 0 2 4 6 of ref_curr + __m64 m3 = _mm_unpacklo_pi16 ( m1, m2); + // m2 = words 1 3 5 7 of ref_curr + m2 = _mm_unpackhi_pi16 ( m1, m2); + // (ref_curr[0] + ref_curr[1] + 1)>>1 + m3 = _mm_add_pi16 (m3, m2); + m3 = _mm_add_pi16 (m3, m_one); + m3 = _mm_srai_pi16 (m3, 1); + // ref - pic + m1 = _mm_sub_pi16 (*(__m64 *)pic_curr, m3); + // abs (ref - pic) + m3 = _mm_srai_pi16(m1, 15); + m1 = _mm_xor_si64(m1, m3); + m1 = _mm_sub_pi16 (m1, m3); + // sum += abs(ref -pic) + /** + * Since we are re-initialising m_sum with every loop + * maybe we don't need the following since overflow may + * not occur + ref = _mm_xor_si64(ref, ref); + ref = _mm_unpackhi_pi16(pic, ref); + pic = _mm_unpacklo_pi16(pic, pic); + pic = _mm_srai_pi32 (pic, 16); + pic = _mm_add_pi32 (pic, ref); + m_sum = _mm_add_pi32 (m_sum, pic); + **/ + m_sum = _mm_add_pi16 (m_sum, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr,ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[1]+1)>>1; + mop_sum += std::abs (temp - *pic_curr); + } + u_sum.m = m_sum; + //sum += (u_sum.i[0] + u_sum.i[1] + mop_sum); + sum += (u_sum.h[0] + u_sum.h[1] + u_sum.h[2] + u_sum.h[3] + mop_sum); + _mm_empty(); + if ((sum + cost_so_far )>= best_total_cost_so_far) + { + return best_total_cost_so_far; + } + } + _mm_empty(); + return sum + cost_so_far; +#else + //std::cerr << "Inmmx routine rmdr.y == 0" << std::endl; + CalcValueType sum(0); + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + sum += std::abs( temp - *pic_curr ); + }// x + + if ( (sum+cost_so_far)>=best_total_cost_so_far) + return best_total_cost_so_far; + + }// y + return sum+cost_so_far; +#endif + } + else if( rmdr.x == 0 ) + { +#if 1 + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + m_sum = _mm_xor_si64 (m_sum, m_sum); + mop_sum= 0; + for( int x=0; x < stopX; x+=4, pic_curr+=4, ref_curr+=8 ) + { + // Load ref + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + // m1 = words 0 2 4 6 of ref_curr + m1 = _mm_unpacklo_pi16 ( m1, m2); + // m2 = words 0 2 4 6 of ref_curr+ref_stride + m2 = _mm_unpacklo_pi16 (*(__m64 *)(ref_curr+ref_stride), *(__m64 *)(ref_curr+ref_stride+4)); + __m64 m3 = _mm_unpackhi_pi16 (*(__m64 *)(ref_curr+ref_stride), *(__m64 *)(ref_curr+ref_stride+4)); + m2 = _mm_unpacklo_pi16 (m2, m3); + + // (ref_curr[0] + ref_curr[ref_stride] + 1)>>1 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_add_pi16 (m1, m_one); + m1 = _mm_srai_pi16 (m1, 1); + // ref - pic + m1 = _mm_sub_pi16 (*(__m64 *)pic_curr, m1); + // abs (ref - pic) + m3 = _mm_srai_pi16(m1, 15); + m1 = _mm_xor_si64(m1, m3); + m1 = _mm_sub_pi16 (m1, m3); + // sum += abs(ref -pic) + m_sum = _mm_add_pi16 (m_sum, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr,ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[ref_stride]+1)>>1; + mop_sum += std::abs (temp - *pic_curr); + } + u_sum.m = m_sum; + //sum += (u_sum.i[0] + u_sum.i[1] + mop_sum); + sum += (u_sum.h[0] + u_sum.h[1] + u_sum.h[2] + u_sum.h[3] + mop_sum); + _mm_empty(); + if ((sum + cost_so_far )>= best_total_cost_so_far) + { + return best_total_cost_so_far; + } + } + _mm_empty(); + return sum + cost_so_far; +#else + CalcValueType sum(0); + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ref_curr+=2 ) + { + CalcValueType temp = (ref_curr[0] + ref_curr[ref_stride]+1)>>1; + sum += std::abs (temp - *pic_curr); + }// x + + if ( (sum+cost_so_far)>=best_total_cost_so_far) + return best_total_cost_so_far; + + }// y + return sum+cost_so_far; +#endif + } + else + { +#if 1 + __m64 m_two = _mm_set_pi32(2, 2); + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + // processing four pic_data values at a time + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + m_sum = _mm_xor_si64 (m_sum, m_sum); + mop_sum= 0; + for( int x=0; x < stopX; x+=4, pic_curr+=4, ref_curr+=8 ) + { + // Load ref + // m1 = words 0 1 2 3 of line 0 ref_curr + __m64 m1 = *(__m64 *)ref_curr; + // m1 = words 0 1 2 3 of line 1 of ref_curr + __m64 m2 = *(__m64 *)(ref_curr+ref_stride); + // (ref_curr[0] + ref_curr[1] + + // ref_curr[ref_stride] + ref_curr[ref_stride+1] + 2) >>2 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_madd_pi16 (m1, m_one); + m1 = _mm_add_pi32 (m1, m_two); + m1 = _mm_srai_pi32 (m1, 2); + + + // m2 = words 4 5 6 7 of line 0 ref_curr + __m64 m3 = *(__m64 *)(ref_curr+4); + // m1 = words 4 5 6 7 of line 1 of ref_curr + m2 = *(__m64 *)(ref_curr+4+ref_stride); + // (ref_curr[0] + ref_curr[1] + + // ref_curr[ref_stride] + ref_curr[ref_stride+1] + 2) >>2 + m3 = _mm_add_pi16 (m3, m2); + m3 = _mm_madd_pi16 (m3, m_one); + m3 = _mm_add_pi32 (m3, m_two); + m3 = _mm_srai_pi32 (m3, 2); + + m1 = _mm_packs_pi32 (m1, m3); + + // load first four values pic_data + m2 = *(__m64 *)pic_curr; + + // ref - pic + m1 = _mm_sub_pi16 (m1, m2); + // abs (ref - pic) + m2 = _mm_srai_pi16(m1, 15); + m1 = _mm_xor_si64(m1, m2); + m1 = _mm_sub_pi16(m1, m2); + // sum += abs(ref -pic) + m_sum = _mm_add_pi16 (m_sum, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr,ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[1] + + ref_curr[ref_stride] + ref_curr[ref_stride+1]+2)>>2; + mop_sum += std::abs (temp - *pic_curr); + } + u_sum.m = m_sum; + sum += (u_sum.h[0] + u_sum.h[1] + u_sum.h[2] + u_sum.h[3] + mop_sum); + _mm_empty(); + if ((sum + cost_so_far )>= best_total_cost_so_far) + { + return best_total_cost_so_far; + } + } + _mm_empty(); + return sum + cost_so_far; +#else + //std::cerr << "Inmmx routine rmdr.y == 0" << std::endl; + CalcValueType sum(0); + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[ref_stride] ) + + CalcValueType( ref_curr[ref_stride+1] ) + + 2 + ) >> 2; + sum += std::abs( temp - *pic_curr ); + }// x + + if ( (sum+cost_so_far)>=best_total_cost_so_far) + return best_total_cost_so_far; + + }// y + return sum+cost_so_far; +#endif + } + return cost_so_far; + } + + /* + * NOTE: we are not doing any bounds checks here. This function must + * be invoked only when the reference images start and stop fall + * withing bounds + */ + void simple_biblock_diff_pic_mmx_4( + const PicArray& pic_data, const PicArray& ref_data, + TwoDArray<ValueType>& diff, + const ImageCoords& start_pos, const ImageCoords& end_pos, + const ImageCoords& ref_start, const ImageCoords& ref_stop, + const MVector& rmdr) + { + ValueType *pic_curr = &pic_data[start_pos.y][start_pos.x]; + ValueType *ref_curr = &ref_data[ref_start.y][ref_start.x]; + ValueType *diff_curr = &diff[0][0]; + + const int width = end_pos.x - start_pos.x; + int height = end_pos.y - start_pos.y; + const int ref_stride = ref_data.LengthX(); + + // go down a row and back up + const int pic_next = pic_data.LengthX() - width; + // go down 2 rows and back up + const int ref_next = ref_data.LengthX()*2 - width*2; + + REPORTM (ref_start.x>=0 && ref_stop.x < ref_data.LengthX() && + ref_start.y>=0 && ref_stop.y < ref_data.LengthY(), + "Reference image coordinates withing bounds"); + + int stopX = (width>>2)<<2; + if (rmdr.x == 0 && rmdr.y == 0 ) + { + //std::cerr << "Inmmx routine rmdr.x = rmdr.y = 0" << std::endl; +#if 1 + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next) + { + for( int x=0; x < stopX; x+=4, pic_curr+=4, ref_curr+=8, diff_curr += 4 ) + { + __m64 pic = *(__m64 *)pic_curr; + // pic << 1 + pic = _mm_slli_pi16(pic, 1); + // load ref + __m64 ref = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 ref2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + ref = _mm_unpacklo_pi16 ( ref, ref2); + // pic<<1 - ref + *(__m64 *)diff_curr = _mm_sub_pi16 (pic, ref); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2) + { + *diff_curr = ((*pic_curr)<<1) - *ref_curr; + } + } +#else + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2 ) + { + *diff_curr = ((*pic_curr)<<1) - *ref_curr; + }// x + }// y +#endif + } + else if( rmdr.y == 0 ) + { +#if 1 + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, pic_curr+=4, diff_curr += 4, ref_curr+=8 ) + { + // Load ref + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + // m3 = words 0 2 4 6 of ref_curr + __m64 m3 = _mm_unpacklo_pi16 ( m1, m2); + // m2 = words 1 3 5 7 of ref_curr + m2 = _mm_unpackhi_pi16 ( m1, m2); + // (ref_curr[0] + ref_curr[1] + 1)>>1 + m3 = _mm_add_pi16 (m3, m2); + m3 = _mm_add_pi16 (m3, m_one); + m3 = _mm_srai_pi16 (m3, 1); + // pic << 1 + m1 = _mm_slli_pi16(*(__m64 *)pic_curr, 1); + // diff = pic - ref + *(__m64 *)diff_curr = _mm_sub_pi16 (m1, m3); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[1]+1)>>1; + *diff_curr = ((*pic_curr)<<1) - temp; + } + } +#else + //std::cerr << "Inmmx routine rmdr.y == 0" << std::endl; + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + *diff_curr = ((*pic_curr)<<1) - temp; + }// x + + }// y +#endif + } + else if( rmdr.x == 0 ) + { +#if 1 + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, pic_curr+=4, diff_curr +=4, ref_curr+=8 ) + { + // Load ref + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + // m1 = words 0 2 4 6 of ref_curr + m1 = _mm_unpacklo_pi16 ( m1, m2); + // m2 = words 0 2 4 6 of ref_curr+ref_stride + m2 = _mm_unpacklo_pi16 (*(__m64 *)(ref_curr+ref_stride), *(__m64 *)(ref_curr+ref_stride+4)); + __m64 m3 = _mm_unpackhi_pi16 (*(__m64 *)(ref_curr+ref_stride), *(__m64 *)(ref_curr+ref_stride+4)); + m2 = _mm_unpacklo_pi16 (m2, m3); + + // (ref_curr[0] + ref_curr[ref_stride] + 1)>>1 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_add_pi16 (m1, m_one); + m1 = _mm_srai_pi16 (m1, 1); + // pic << 1 + m2 = _mm_slli_pi16 (*(__m64 *)pic_curr, 1); + // diff = pic<<1 - ref) + *(__m64 *)diff_curr = _mm_sub_pi16(m2, m1 ); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[ref_stride]+1)>>1; + *diff_curr = ((*pic_curr)<<1) - temp; + } + } +#else + //std::cerr << "Inmmx routine rmdr.y == 0" << std::endl; + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + *diff_curr = ((*pic_curr)<<1) - temp; + }// x + }// y +#endif + } + else + { +#if 1 + __m64 m_two = _mm_set_pi32(2, 2); + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + // processing four pic_data values at a time + for( int y=0; y < height; y++, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, pic_curr+=4, diff_curr+=4, ref_curr+=8 ) + { + // Load ref + // m1 = words 0 1 2 3 of line 0 ref_curr + __m64 m1 = *(__m64 *)ref_curr; + // m1 = words 0 1 2 3 of line 1 of ref_curr + __m64 m2 = *(__m64 *)(ref_curr+ref_stride); + // (ref_curr[0] + ref_curr[1] + + // ref_curr[ref_stride] + ref_curr[ref_stride+1] + 2) >>2 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_madd_pi16 (m1, m_one); + m1 = _mm_add_pi32 (m1, m_two); + m1 = _mm_srai_pi32 (m1, 2); + + // m2 = words 4 5 6 7 of line 0 ref_curr + __m64 m3 = *(__m64 *)(ref_curr+4); + // m1 = words 4 5 6 7 of line 1 of ref_curr + m2 = *(__m64 *)(ref_curr+4+ref_stride); + // (ref_curr[0] + ref_curr[1] + + // ref_curr[ref_stride] + ref_curr[ref_stride+1] + 2) >>2 + m3 = _mm_add_pi16 (m3, m2); + m3 = _mm_madd_pi16 (m3, m_one); + m3 = _mm_add_pi32 (m3, m_two); + m3 = _mm_srai_pi32 (m3, 2); + + m1 = _mm_packs_pi32 (m1, m3); + + // load first four values pic_data and <<1 + m2 = _mm_slli_pi16 (*(__m64 *)pic_curr, 1); + + // pic<<1 - ref + *(__m64 *)diff_curr = _mm_sub_pi16 (m2, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++pic_curr,++diff_curr, ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[1] + + ref_curr[ref_stride] + ref_curr[ref_stride+1]+2)>>2; + *diff_curr = ((*pic_curr)<<1) - temp; + } + } +#else + //std::cerr << "Inmmx routine rmdr.y == 0" << std::endl; + CalcValueType sum(0); + for( int y=0; y < height; ++y, pic_curr+=pic_next, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++pic_curr, ++diff_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[ref_stride] ) + + CalcValueType( ref_curr[ref_stride+1] ) + + 2 + ) >> 2; + *diff_curr = ((*pic_curr)<<1) - temp; + }// x + + }// y +#endif + } + _mm_empty(); + return; + } + + /* + * NOTE: we are not doing any bounds checks here. This function must + * be invoked only when the reference images start and stop fall + * withing bounds + */ + CalcValueType simple_biblock_diff_up_mmx_4( + const TwoDArray<ValueType>& diff_data, const PicArray& ref_data, + const ImageCoords& ref_start, const ImageCoords& ref_stop, + const MVector& rmdr) + { + ValueType *diff_curr = &diff_data[0][0]; + ValueType *ref_curr = &ref_data[ref_start.y][ref_start.x]; + + const int width = diff_data.LengthX(); + int height = diff_data.LengthY(); + const int ref_stride = ref_data.LengthX(); + + // go down 2 rows and back up + const int ref_next = ref_data.LengthX()*2 - width*2; + + REPORTM (ref_start.x>=0 && ref_stop.x < ref_data.LengthX() && + ref_start.y>=0 && ref_stop.y < ref_data.LengthY(), + "Reference image coordinates withing bounds"); + + CalcValueType mop_sum(0); + int stopX = (width>>2)<<2; + __m64 m_sum = _mm_set_pi16(0, 0, 0, 0); + u_mmx_val u_sum; + if (rmdr.x == 0 && rmdr.y == 0 ) + { + //std::cerr << "Inmmx routine rmdr.x = rmdr.y = 0" << std::endl; +#if 1 + for( int y=0; y < height; y++, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, diff_curr+=4, ref_curr+=8 ) + { + u_mmx_val diff = *(u_mmx_val *)diff_curr; + __m64 ref = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 ref2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + ref = _mm_unpacklo_pi16 ( ref, ref2); + // diff - ref + diff.m = _mm_sub_pi16 (diff.m, ref); + // (diff - ref)>>1 + diff.m = _mm_srai_pi16 (diff.m, 1); + // abs (diff - ref) + ref = _mm_srai_pi16(diff.m, 15); + diff.m = _mm_xor_si64(diff.m, ref); + diff.m = _mm_sub_pi16 (diff.m, ref); + // sum += abs(ref -pic) + ref = _mm_xor_si64(ref, ref); + ref = _mm_unpackhi_pi16(diff.m, ref); + diff.m = _mm_unpacklo_pi16(diff.m, diff.m); + diff.m = _mm_srai_pi32 (diff.m, 16); + diff.m = _mm_add_pi32 (diff.m, ref); + m_sum = _mm_add_pi32 (m_sum, diff.m); + } + // mopup; + for (int x = stopX; x < width; ++x, ++diff_curr,ref_curr+=2) + { + mop_sum += std::abs ((*diff_curr - *ref_curr)>>1); + } + } + u_sum.m = m_sum; + _mm_empty(); + return u_sum.i[0] + u_sum.i[1] + mop_sum; +#else + CalcValueType sum(0); + for( int y=0; y < height; ++y, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++diff_curr, ref_curr+=2 ) + { + sum += std::abs( (*diff_curr - *ref_curr)>>1 ); + }// x + + }// y + return sum; +#endif + + } + else if( rmdr.y == 0 ) + { +#if 1 + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + for( int y=0; y < height; y++, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, diff_curr+=4, ref_curr+=8 ) + { + // Load ref + __m64 m1 = _mm_unpacklo_pi16 (((u_mmx_val *)ref_curr)->m, ((u_mmx_val *)(ref_curr+4))->m); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + // m3 = words 0 2 4 6 of ref_curr + __m64 m3 = _mm_unpacklo_pi16 ( m1, m2); + // m2 = words 1 3 5 7 of ref_curr + m2 = _mm_unpackhi_pi16 ( m1, m2); + // (ref_curr[0] + ref_curr[1] + 1)>>1 + m3 = _mm_add_pi16 (m3, m2); + m3 = _mm_add_pi16 (m3, m_one); + m3 = _mm_srai_pi16 (m3, 1); + // diff - pic + m1 = _mm_sub_pi16 (*(__m64 *)diff_curr, m3); + // (diff - pic)>>1 + m1 = _mm_srai_pi16 (m1, 1); + // abs (diff-ref)>>1 + m3 = _mm_srai_pi16(m1, 15); + m1 = _mm_xor_si64(m1, m3); + m1 = _mm_sub_pi16 (m1, m3); + // sum += abs(diff-ref)>>1 + m2 = _mm_xor_si64(m2, m2); + m2 = _mm_unpackhi_pi16(m1, m2); + m1 = _mm_unpacklo_pi16(m1, m1); + m1 = _mm_srai_pi32 (m1, 16); + m1 = _mm_add_pi32 (m1, m2); + m_sum = _mm_add_pi32 (m_sum, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++diff_curr,ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[1]+1)>>1; + mop_sum += std::abs ((*diff_curr - temp)>>1); + } + } + u_sum.m = m_sum; + _mm_empty(); + return (u_sum.i[0] + u_sum.i[1] + mop_sum); +#else + //std::cerr << "Inmmx routine rmdr.y == 0" << std::endl; + CalcValueType sum(0); + for( int y=0; y < height; ++y, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++diff_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + 1 + ) >> 1; + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + return sum; +#endif + } + else if( rmdr.x == 0 ) + { +#if 1 + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + for( int y=0; y < height; y++, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, diff_curr+=4, ref_curr+=8 ) + { + // Load ref + __m64 m1 = _mm_unpacklo_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + __m64 m2 = _mm_unpackhi_pi16 (*(__m64 *)ref_curr, *(__m64 *)(ref_curr+4)); + // m1 = words 0 2 4 6 of ref_curr + m1 = _mm_unpacklo_pi16 ( m1, m2); + // m2 = words 0 2 4 6 of ref_curr+ref_stride + m2 = _mm_unpacklo_pi16 (*(__m64 *)(ref_curr+ref_stride), *(__m64 *)(ref_curr+ref_stride+4)); + __m64 m3 = _mm_unpackhi_pi16 (*(__m64 *)(ref_curr+ref_stride), *(__m64 *)(ref_curr+ref_stride+4)); + m2 = _mm_unpacklo_pi16 (m2, m3); + + // (ref_curr[0] + ref_curr[ref_stride] + 1)>>1 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_add_pi16 (m1, m_one); + m1 = _mm_srai_pi16 (m1, 1); + // diff - ref + m1 = _mm_sub_pi16 (*(__m64 *)diff_curr, m1); + // (diff - ref)>>1 + m1 = _mm_srai_pi16 (m1, 1); + // abs ((diff - pic)>>1) + m3 = _mm_srai_pi16(m1, 15); + m1 = _mm_xor_si64(m1, m3); + m1 = _mm_sub_pi16 (m1, m3); + // sum += abs(ref -pic) + m2 = _mm_xor_si64(m2, m2); + m2 = _mm_unpackhi_pi16(m1, m2); + m1 = _mm_unpacklo_pi16(m1, m1); + m1 = _mm_srai_pi32 (m1, 16); + m1 = _mm_add_pi32 (m1, m2); + m_sum = _mm_add_pi32 (m_sum, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++diff_curr,ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[ref_stride]+1)>>1; + mop_sum += std::abs ( (*diff_curr - temp)>>1 ); + } + } + u_sum.m = m_sum; + _mm_empty(); + return (u_sum.i[0] + u_sum.i[1] + mop_sum); +#else + CalcValueType sum(0); + for( int y=0; y < height; ++y, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++diff_curr, ref_curr+=2 ) + { + CalcValueType temp = (ref_curr[0] + ref_curr[ref_stride]+1)>>1; + sum += std::abs ( (*diff_curr - temp)>>1 ); + }// x + }// y + return sum; +#endif + } + else + { +#if 1 + __m64 m_two = _mm_set_pi32(2, 2); + __m64 m_one = _mm_set_pi16(1, 1, 1, 1); + // processing four pic_data values at a time + for( int y=0; y < height; y++, ref_curr+=ref_next ) + { + for( int x=0; x < stopX; x+=4, diff_curr+=4, ref_curr+=8 ) + { + // Load ref + // m1 = words 0 1 2 3 of line 0 ref_curr + __m64 m1 = *(__m64 *)ref_curr; + // m1 = words 0 1 2 3 of line 1 of ref_curr + __m64 m2 = *(__m64 *)(ref_curr+ref_stride); + // (ref_curr[0] + ref_curr[1] + + // ref_curr[ref_stride] + ref_curr[ref_stride+1] + 2) >>2 + m1 = _mm_add_pi16 (m1, m2); + m1 = _mm_madd_pi16 (m1, m_one); + m1 = _mm_add_pi32 (m1, m_two); + m1 = _mm_srai_pi32 (m1, 2); + + // m2 = words 4 5 6 7 of line 0 ref_curr + __m64 m3 = *(__m64 *)(ref_curr+4); + // m1 = words 4 5 6 7 of line 1 of ref_curr + m2 = *(__m64 *)(ref_curr+4+ref_stride); + // (ref_curr[0] + ref_curr[1] + + // ref_curr[ref_stride] + ref_curr[ref_stride+1] + 2) >>2 + m3 = _mm_add_pi16 (m3, m2); + m3 = _mm_madd_pi16 (m3, m_one); + m3 = _mm_add_pi32 (m3, m_two); + m3 = _mm_srai_pi32 (m3, 2); + m1 = _mm_packs_pi32 (m1, m3); + + // load first four values pic_data + m2 = *(__m64 *)diff_curr; + + // diff - ref + m1 = _mm_sub_pi16 (m2, m1); + // (diff - ref)>>1 + m1 = _mm_srai_pi16 (m1, 1); + // abs (diff - ref)>>1 + m2 = _mm_srai_pi16(m1, 15); + m1 = _mm_xor_si64(m1, m2); + m1 = _mm_sub_pi16(m1, m2); + // sum += abs(ref -pic)>>1 + m1 = _mm_madd_pi16(m1, m_one); + m_sum = _mm_add_pi32 (m_sum, m1); + } + // mopup; + for (int x = stopX; x < width; ++x, ++diff_curr,ref_curr+=2) + { + CalcValueType temp = (ref_curr[0] + ref_curr[1] + + ref_curr[ref_stride] + ref_curr[ref_stride+1]+2)>>2; + mop_sum += std::abs ( (*diff_curr - temp)>>1 ); + } + } + u_sum.m = m_sum; + _mm_empty(); + return (u_sum.i[0] + u_sum.i[1] + mop_sum); +#else + CalcValueType sum(0); + for( int y=0; y < height; ++y, ref_curr+=ref_next ) + { + for( int x=0; x < width; ++x, ++diff_curr, ref_curr+=2 ) + { + CalcValueType temp = ( CalcValueType( ref_curr[0] ) + + CalcValueType( ref_curr[1] ) + + CalcValueType( ref_curr[ref_stride] ) + + CalcValueType( ref_curr[ref_stride+1] ) + + 2 + ) >> 2; + sum += std::abs( (*diff_curr - temp)>>1 ); + }// x + }// y + return sum; +#endif + } + return 0; + } + + inline void check_active_columns( + int x, int xmax, ValueType act_cols1[4],ValueType *row1) + { + // check if we need any clipping + if (x >= 0 && (x+3) < xmax) { + // special case, nothing to do + memcpy(act_cols1, &row1[x], 4 * sizeof(ValueType)); + } + else if (x < 0) + { + act_cols1[0] = row1[0]; + //act_cols1[1] = (x + 1) < 0 ? row1[0] : row1[x+1]; + //act_cols1[2] = (x + 2) < 0 ? row1[0] : row1[x+2]; + //act_cols1[3] = (x + 3) < 0 ? row1[0] : row1[x+3]; + for (int i = 1; i < 4; ++i) + { + act_cols1[i] = (x + i) < 0 ? row1[0] : row1[x+i]; + } + } + else + { + for (int i = 0; i < 3; ++i) + { + act_cols1[i] = (x + i) < xmax ? row1[x+i] : row1[xmax-1]; + } + act_cols1[3] = row1[xmax-1]; + } + } + + CalcValueType bchk_simple_block_diff_mmx_4 ( + const BlockDiffParams& dparams, const MVector& mv, + const PicArray& pic_data, const PicArray& ref_data, + CalcValueType i_best_sum) + { + u_mmx_val u_sum; + u_mmx_val u_ref; + u_sum.i[0] = u_sum.i[1]= 0; + + ValueType *src = &(pic_data[dparams.Yp()][dparams.Xp()]); + ImageCoords ref_start(dparams.Xp()+mv.x, dparams.Yp()+mv.y); + + int height = dparams.Yl(); + int width = dparams.Xl(); + int stopX = (width>>2)<<2; + int pic_next = (pic_data.LengthX() - width); + CalcValueType mop_sum = 0; + for (int j = 0; j < height; j++) + { + for (int i = 0; i < stopX; i+=4) + { + check_active_columns(ref_start.x+i, ref_data.LengthX(), u_ref.h, ref_data[BChk(ref_start.y+j, ref_data.LengthY())]); + // pic - ref + __m64 pic = _mm_sub_pi16 (*(__m64 *)src, u_ref.m); + // abs (pic - ref) + u_ref.m = _mm_srai_pi16(pic, 15); + pic = _mm_xor_si64(pic, u_ref.m); + pic = _mm_sub_pi16 (pic, u_ref.m); + // sum += abs(pic -ref) + u_ref.m = _mm_xor_si64(u_ref.m, u_ref.m); + u_ref.m = _mm_unpackhi_pi16(pic, u_ref.m); + pic = _mm_unpacklo_pi16(pic, pic); + pic = _mm_srai_pi32 (pic, 16); + pic = _mm_add_pi32 (pic, u_ref.m); + u_sum.m = _mm_add_pi32 (u_sum.m, pic); + src += 4; + } + for (int i = stopX; i < width; i++) + { + mop_sum += std::abs(*src - + ref_data[BChk(j+ref_start.y , ref_data.LengthY())][BChk(i+ref_start.x , ref_data.LengthX())]); + src++; + } + if ((u_sum.i[0] + u_sum.i[1] + mop_sum) >= i_best_sum) + { + _mm_empty(); + return i_best_sum; + } + src += pic_next; + } + _mm_empty(); + + return u_sum.i[0] + u_sum.i[1] + mop_sum; + } +} +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils_mmx.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils_mmx.h new file mode 100644 index 000000000..855fc4a75 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/me_utils_mmx.h @@ -0,0 +1,81 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: me_utils_mmx.h,v 1.3 2008/05/27 01:29:55 asuraparaju Exp $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is contributed by Peter Meerwald. +* +* The Initial Developer of the Original Code is Peter Meerwald. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Peter Meerwald (Original Author) +* Anuradha Suraparaju +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _ME_UTILS_MMX_H_ +#define _ME_UTILS_MMX_H_ + +#if defined(HAVE_MMX) + +#include <mmintrin.h> + +#include <libdirac_motionest/me_utils.h> +#include <libdirac_common/common.h> + +namespace dirac +{ + + CalcValueType simple_block_diff_mmx_4(const BlockDiffParams& dparams, const MVector& mv, const PicArray& pic_data, const PicArray& ref_data, CalcValueType i_best_sum); + CalcValueType simple_intra_block_diff_mmx_4 ( const BlockDiffParams& dparams, const PicArray& pic_data, ValueType &dc_val); + + CalcValueType bchk_simple_block_diff_mmx_4 ( + const BlockDiffParams& dparams, const MVector& mv, + const PicArray& pic_data, const PicArray& ref_data, + CalcValueType i_best_sum); + + float simple_block_diff_up_mmx_4( + const PicArray& pic_data, const PicArray& ref_data, + const ImageCoords& start_pos, const ImageCoords& end_pos, + const ImageCoords& ref_start, const ImageCoords& ref_stop, + const MVector& rmdr, float cost_so_far, + float best_cost_so_far); + + + void simple_biblock_diff_pic_mmx_4( + const PicArray& pic_data, const PicArray& ref_data, + TwoDArray<ValueType>& diff, + const ImageCoords& start_pos, const ImageCoords& end_pos, + const ImageCoords& ref_start, const ImageCoords& ref_stop, + const MVector& rmdr); + + CalcValueType simple_biblock_diff_up_mmx_4( + const TwoDArray<ValueType>& diff_data, const PicArray& ref_data, + const ImageCoords& ref_start, const ImageCoords& ref_stop, + const MVector& rmdr); +} + +#endif /* HAVE_MMX */ +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/motion_estimate.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/motion_estimate.cpp new file mode 100644 index 000000000..bdde41891 --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/motion_estimate.cpp @@ -0,0 +1,247 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: motion_estimate.cpp,v 1.23 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#include <libdirac_encoder/enc_queue.h> +#include <libdirac_motionest/motion_estimate.h> +#include <libdirac_motionest/pixel_match.h> +#include <libdirac_motionest/me_subpel.h> +#include <libdirac_motionest/me_mode_decn.h> +using namespace dirac; + +#include <cmath> +#include <vector> + +MotionEstimator::MotionEstimator( const EncoderParams& encp ): + m_encparams( encp ) +{} + +void MotionEstimator::DoME( EncQueue& my_buffer, int pic_num ) +{ + MEData& me_data = my_buffer.GetPicture( pic_num ).GetMEData(); + + const PictureParams& pparams = my_buffer.GetPicture(pic_num).GetPparams(); + + // Step 1. + //Initial search gives vectors for each reference accurate to 1 pixel + + PixelMatcher pix_match( m_encparams ); + pix_match.DoSearch( my_buffer , pic_num ); + + float lambda; + // Get the references + const std::vector<int>& refs = my_buffer.GetPicture(pic_num).GetPparams().Refs(); + + const int num_refs = refs.size(); + if ( pparams.IsBPicture()) + lambda = m_encparams.L2MELambda(); + else + lambda = m_encparams.L1MELambda(); + + // Set up the lambda to be used + me_data.SetLambdaMap( num_refs , lambda ); + + MVPrecisionType orig_prec = m_encparams.GetPicPredParams().MVPrecision(); + + // Step 2. + // Pixel accurate vectors are then refined to sub-pixel accuracy + + if (orig_prec != MV_PRECISION_PIXEL) + { + SubpelRefine pelrefine( m_encparams ); + pelrefine.DoSubpel( my_buffer , pic_num ); + } + else + { + // FIXME: HACK HACK + // Mutiplying the motion vectors by 2 and setting MV precision to + // HALF_PIXEL to implement pixel accurate motion estimate + MvArray &mv_arr1 = me_data.Vectors(1); + for (int j = 0; j < mv_arr1.LengthY(); ++j) + { + for (int i = 0; i < mv_arr1.LengthX(); ++i) + mv_arr1[j][i] = mv_arr1[j][i] << 1; + } + if (num_refs > 1) + { + MvArray &mv_arr2 = me_data.Vectors(2); + for (int j = 0; j < mv_arr2.LengthY(); ++j) + { + for (int i = 0; i < mv_arr2.LengthX(); ++i) + mv_arr2[j][i] = mv_arr2[j][i] << 1; + } + } + m_encparams.GetPicPredParams().SetMVPrecision(MV_PRECISION_HALF_PIXEL); + } + + // Step3. + // We now have to decide how each superblock should be split + // and which references should be used, and so on. + + ModeDecider my_mode_dec( m_encparams ); + my_mode_dec.DoModeDecn( my_buffer , pic_num ); + + if (orig_prec == MV_PRECISION_PIXEL) + { + // FIXME: HACK HACK + // Divide the motion vectors by 2 to convert back to pixel + // accurate motion vectors and reset MV precision to + // PIXEL accuracy + MvArray &mv_arr1 = me_data.Vectors(1); + for (int j = 0; j < mv_arr1.LengthY(); ++j) + { + for (int i = 0; i < mv_arr1.LengthX(); ++i) + mv_arr1[j][i] = mv_arr1[j][i] >> 1; + } + if (num_refs > 1) + { + MvArray &mv_arr2 = me_data.Vectors(2); + for (int j = 0; j < mv_arr2.LengthY(); ++j) + { + for (int i = 0; i < mv_arr2.LengthX(); ++i) + mv_arr2[j][i] = mv_arr2[j][i]>>1; + } + } + m_encparams.GetPicPredParams().SetMVPrecision(MV_PRECISION_PIXEL); + } + + // Finally, although not strictly part of motion estimation, + // we have to assign DC values for chroma components for + // blocks we're decided are intra. + + SetChromaDC( my_buffer , pic_num ); + +//return false; +} + +ValueType MotionEstimator::GetChromaBlockDC(const PicArray& pic_data, + int xunit , int yunit , int split) +{ + BlockDiffParams dparams; + dparams.SetBlockLimits( m_encparams.GetPicPredParams().ChromaBParams( split ) , + pic_data, xunit , yunit); + + ValueType dc; + + IntraBlockDiff intradiff( pic_data ); + + intradiff.Diff( dparams , dc ); + + return dc; +} + +void MotionEstimator::SetChromaDC( const PicArray& pic_data , MEData& me_data , CompSort csort ) +{ + + // Lower limit of block coords in SB + int xtl,ytl; + // Upper limit of block coords in SB + int xbr,ybr; + + // Ditto, for subSBs + int xsubSBtl,ysubSBtl; + int xsubSBbr,ysubSBbr; + + TwoDArray<ValueType>& dcarray = me_data.DC( csort ); + + ValueType dc = 0; + + // Coords of the prediction units (at appropriate level) + int xunit, yunit; + + // The delimiters of the blocks contained in the prediction unit + int xstart, ystart; + int xend, yend; + + int level; + + for ( int ysb=0 ; ysb<me_data.SBSplit().LengthY() ; ++ysb ) + { + for ( int xsb=0 ; xsb<me_data.SBSplit().LengthX() ; ++xsb ) + { + + level = me_data.SBSplit()[ysb][xsb]; + + xtl = xsb<<2; + ytl = ysb<<2; + xbr = xtl+4; + ybr = ytl+4; + + xsubSBtl = xsb<<1; + ysubSBtl = ysb<<1; + xsubSBbr = xsubSBtl+2; + ysubSBbr = ysubSBtl+2; + + + for (int j = 0 ; j<(1<<level) ;++j) + { + for (int i = 0 ; i<(1<<level) ;++i) + { + xunit = ( xsb<<level ) + i; + yunit = ( ysb<<level ) + j; + + xstart = xunit<<( 2-level ); + ystart = yunit<<( 2-level ); + + xend = xstart + ( 1<<( 2-level ) ); + yend = ystart + ( 1<<( 2-level ) ); + + if ( me_data.Mode()[ystart][xstart] == INTRA ) + // Get the DC value for the unit + dc = GetChromaBlockDC( pic_data , xunit , yunit , level ); + + // Copy it into the corresponding blocks + for ( int q=ystart ; q< yend ; ++q ) + for ( int p=xstart ; p< xend ; ++p ) + dcarray[q][p] = dc; + + }// i + }// j + + }// xsb + }// ysb +} + +void MotionEstimator::SetChromaDC( EncQueue& my_buffer , int pic_num ) +{ + MEData& me_data = my_buffer.GetPicture(pic_num).GetMEData(); + SetChromaDC( my_buffer.GetPicture( pic_num ).OrigData(U_COMP) , me_data , U_COMP ); + SetChromaDC( my_buffer.GetPicture( pic_num ).OrigData(V_COMP) , me_data , V_COMP ); + +} + + diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/motion_estimate.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/motion_estimate.h new file mode 100644 index 000000000..10129dd3e --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/motion_estimate.h @@ -0,0 +1,105 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: motion_estimate.h,v 1.12 2008/08/14 00:51:09 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + + +#ifndef _MOTION_ESTIMATE_H_ +#define _MOTION_ESTIMATE_H_ + +#include <libdirac_common/motion.h> +namespace dirac +{ + + class EncQueue; + + + //! Class to handle the whole motion estimation process. + /*! + + Class to handle the whole motion estimation process, which works in + three stages. + + First a pixel-accurate estimate is formed by looking at the current + picture data and the data from the reference picture(s). Motion vectors + are found for every block. + + Second, these pixel-accurate motion vectors are refined to sub-pixel + accuracy. This means some sort of upconversion needs to be applied to + the reference. This can be done by actually upconverting the reference + to create a bigger picture or by doing some interpolation of values + on the fly. + + Third, mode decisions have to be made. This means choosing which (if + any) reference to use for each block, and whether to use the same + motion vectors for groups of blocks together. A 2x2 group of blocks is + called a sub-MB and a 4x4 group of blocks is a MB (Macroblock). All + the MV data is organised by MB. + */ + class MotionEstimator{ + public: + //! Constructor + MotionEstimator( const EncoderParams& encp ); + //! Destructor + ~MotionEstimator(){} + + //! Do the motion estimation + void DoME( EncQueue& my_buffer , int pic_num ); + + private: + //! Copy constructor: private, body-less - class should not be copied + MotionEstimator( const MotionEstimator& cpy ); + + //! Assignment= : //private, body-less - class should not be assigned + MotionEstimator& operator=( const MotionEstimator& rhs ); + + //! Go through all the intra blocks and extract the chroma dc values to be coded + void SetChromaDC( EncQueue& my_buffer, int pic_num); + + //! Called by previous fn for each component + void SetChromaDC(const PicArray& pic_data, MEData& me_data,CompSort csort); + + //! Called by previous fn for each block + ValueType GetChromaBlockDC(const PicArray& pic_data, int xloc,int yloc,int split); + + // Member variables + + //! A local reference to the encoder parameters + const EncoderParams& m_encparams; + }; + +} // namespace dirac + +#endif diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/pixel_match.cpp b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/pixel_match.cpp new file mode 100644 index 000000000..7ac7f74ed --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/pixel_match.cpp @@ -0,0 +1,380 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: pixel_match.cpp,v 1.20 2008/10/01 01:26:47 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copm_yright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author), +* Tim Borer +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#include <libdirac_motionest/pixel_match.h> +#include <libdirac_motionest/block_match.h> +#include <libdirac_common/motion.h> +#include <libdirac_encoder/enc_queue.h> +#include <libdirac_motionest/downconvert.h> +#include <libdirac_motionest/me_mode_decn.h> +#include <libdirac_motionest/me_subpel.h> +using namespace dirac; + +#include <cmath> +#include <vector> + +using std::vector; +using std::log; + +PixelMatcher::PixelMatcher( const EncoderParams& encp): + m_encparams(encp) +{} + + +void PixelMatcher::DoSearch( EncQueue& my_buffer, int pic_num ) +{ + m_predparams = &(my_buffer.GetPicture(pic_num).GetMEData().GetPicPredParams() ); + + //does an initial search using hierarchical matching to get guide vectors + + // Picture numbers of references + int ref1,ref2; + + // Use the luminance only for motion estimating + const PicArray& pic_data = my_buffer.GetPicture( pic_num ).DataForME(m_encparams.CombinedME()); + + const vector<int>& refs = my_buffer.GetPicture( pic_num ).GetPparams().Refs(); + ref1 = refs[0]; + + if (refs.size()>1) + ref2 = refs[1]; + else + ref2 = ref1; + + // Record temporal distances + m_tdiff[0] = std::abs( ref1 - pic_num ); + m_tdiff[1] = std::abs( ref2 - pic_num ); + + // Obtain C++ references to the reference picture luma components + const PicArray& ref1_data = my_buffer.GetPicture(ref1).DataForME(m_encparams.CombinedME()); + const PicArray& ref2_data = my_buffer.GetPicture(ref2).DataForME(m_encparams.CombinedME()); + + // Determine the picture sort - this affects the motion estimation Lagrangian parameter + m_psort = my_buffer.GetPicture(pic_num).GetPparams().PicSort(); + + + if ( m_encparams.FullSearch() == false ) + { + // Set the number of downconversion levels - not too many or we run out of picture! + m_depth = ( int) std::min( log(((double) pic_data.LengthX())/12.0)/log(2.0) , + log(((double) pic_data.LengthY())/12.0)/log(2.0) ); + + // These arrays will contain the downconverted picture and MvData hierarchy + OneDArray<PicArray*> ref1_down( Range( 1 , m_depth ) ); + OneDArray<PicArray*> ref2_down( Range( 1 , m_depth ) ); + OneDArray<PicArray*> pic_down( Range( 1 , m_depth ) ); + OneDArray<MEData*> me_data_set( Range( 1 , m_depth ) ); + + // Populate the hierarchies + MakePicHierarchy( pic_data , pic_down ); + MakePicHierarchy( ref1_data , ref1_down ); + if (ref1 != ref2) + MakePicHierarchy( ref2_data , ref2_down ); + + MakeMEDataHierarchy( pic_down , me_data_set ); + + // Now do the work! // + ////////////////////// + + // Start with motion estimating at the very lowest level + m_level = m_depth; + + MatchPic( *(pic_down[m_depth]) , *(ref1_down[m_depth]) , *(me_data_set[m_depth]) , + *(me_data_set[m_depth]) , 1 ); + if ( ref1 != ref2 ) + MatchPic( *(pic_down[m_depth]) , *(ref2_down[m_depth]) , *(me_data_set[m_depth]) , + *(me_data_set[m_depth]) , 2 ); + + // Do the intervening levels - here we can have a genuine set of guide vectors + for ( m_level=m_depth-1 ; m_level>=1 ; --m_level ) + { + MatchPic( *(pic_down[m_level]) , *(ref1_down[m_level]) , *(me_data_set[m_level]) , + *(me_data_set[m_level+1]) , 1 ); + if (ref1!=ref2) + MatchPic( *(pic_down[m_level]) , *(ref2_down[m_level]) , *(me_data_set[m_level]) , + *(me_data_set[m_level+1]) , 2 ); + }// level + + // Finally, do the top level, with the pictures themselves + m_level = 0; + MEData& me_data = my_buffer.GetPicture(pic_num).GetMEData(); + MatchPic( pic_data , ref1_data, me_data , *(me_data_set[1]) , 1 ); + if ( ref1 != ref2 ) + MatchPic( pic_data , ref2_data , me_data , *(me_data_set[1]) , 2 ); + + // Now we're finished, tidy everything up ... + TidyPics( pic_down ); + TidyPics( ref1_down ); + if (ref1 != ref2) + TidyPics( ref2_down ); + TidyMEData( me_data_set ); + } + else + { + m_depth = 0; + m_level = 0; + MEData& me_data = my_buffer.GetPicture(pic_num).GetMEData(); + MatchPic( pic_data , ref1_data, me_data , me_data , 1 ); + if ( ref1 != ref2 ) + MatchPic( pic_data , ref2_data , me_data , me_data , 2 ); + } + +} + +void PixelMatcher::MakePicHierarchy(const PicArray& data , + OneDArray< PicArray* >& down_data) +{ + + DownConverter mydcon; + + // Allocate + int scale_factor = 1; + for (int i=1 ; i<=m_depth;++i) + { + // Dimensions of pic_down[i] will be shrunk by a factor 2**i + scale_factor*=2; + down_data[i] = new PicArray( data.LengthY()/scale_factor , data.LengthX()/scale_factor); + } + + //do all the downconversions + if (m_depth>0) + { + mydcon.DoDownConvert( data , *(down_data[1]) ); + + for (int i=1 ; i<m_depth ; ++i) + mydcon.DoDownConvert( *(down_data[i]) , *(down_data[i+1]) ); + + } +} + +void PixelMatcher::MakeMEDataHierarchy(const OneDArray< PicArray*>& down_data, + OneDArray< MEData* >& me_data_set ) +{ + + int xnumblocks , ynumblocks; + const OLBParams bparams = m_predparams->LumaBParams(2); + + // We might not have an integral number of Macroblocks and blocks in + // a picture. So we go start of with the number of macroblocks in the + // full size picture and calculate the number of in the downsized pics + // from this. + xnumblocks = m_predparams->XNumBlocks(); + ynumblocks = m_predparams->YNumBlocks(); + + PicturePredParams predparams = *m_predparams; + predparams.SetXNumSB(0); + predparams.SetYNumSB(0); + for (int i=1 ; i<=m_depth;++i) + { + + xnumblocks = xnumblocks>>1; + ynumblocks = ynumblocks>>1; + + if (( down_data[i]->LengthX() )%bparams.Xbsep() != 0) + xnumblocks++; + + if (( down_data[i]->LengthY() )%bparams.Ybsep() != 0) + ynumblocks++; + + predparams.SetXNumBlocks( xnumblocks ); + predparams.SetYNumBlocks( ynumblocks ); + + me_data_set[i] = new MEData( predparams, 2 ); + }// i + +} + +void PixelMatcher::TidyPics( OneDArray< PicArray*>& down_data ) +{ + for (int i=1 ; i <= m_depth ; ++i) + { + delete down_data[i]; + }// i + +} + +void PixelMatcher::TidyMEData( OneDArray< MEData*>& me_data_set ) +{ + for (int i=1 ; i <= m_depth ; ++i) + { + delete me_data_set[i]; + }// i + +} + + + +void PixelMatcher::MatchPic(const PicArray& pic_data , const PicArray& ref_data , MEData& me_data , + const MvData& guide_data, const int ref_id) +{ + + // Initialisation // + //////////////////// + + m_big_xr = std::min( m_tdiff[ref_id-1], 3 )*m_encparams.XRangeME(); + m_big_yr = std::min( m_tdiff[ref_id-1], 3 )*m_encparams.YRangeME(); + + // Set the search ranges according to the level + if ( m_encparams.FullSearch() == false ) + { + m_cost_mean = 0.0; + m_cost_mean_sq = 0.0; + + m_xr = std::min( m_level+1, 5); + m_yr = std::min( m_level+1, 5); + } + else + { + m_xr = m_big_xr; + m_yr = m_big_yr; + } + + // Provide aliases for the appropriate motion vector data components + + MvArray& mv_array = me_data.Vectors( ref_id ); + const MvArray& guide_array = guide_data.Vectors( ref_id ); + TwoDArray<MvCostData>& pred_costs = me_data.PredCosts( ref_id ); + + // Initialise the arrays + for (int y=0; y<mv_array.LengthY(); ++y) + { + for (int x=0; x<mv_array.LengthX(); ++x) + { + mv_array[y][x].x = 0; + mv_array[y][x].y = 0; + pred_costs[y][x].total = 10000000.0f; + }// x + }// y + + // Provide a block matching object to do the work + BlockMatcher my_bmatch( pic_data , ref_data , + m_predparams->LumaBParams(2) , m_predparams->MVPrecision() , + mv_array , pred_costs ); + + // Do the work - loop over all the blocks, finding the best match // + //////////////////////////////////////////////////////////////////// + + /* + The idea is for each block construct a list of candidate vectors,which will + be tested. This list is actually a list of lists, implemented as a C++ + vector of C++ vectors. This is so that FindBestMatch can shorten the + search process by looking at the beginning of each sublist and + discarding that sub-list if it's too far off. + */ + + // Make a zero-based list that is always used + m_cand_list.clear(); + MVector zero_mv( 0 , 0 ); + + AddNewVlist( m_cand_list , zero_mv , m_xr , m_yr); + + // Now loop over the blocks and find the best matches. + // The loop is unrolled because predictions are different at picture edges. + // The purpose of the loop is to create appropriate candidate lists, and then + // call the DoBlock() function which does the actual work. + + // First do TL corner + + // Set the prediction as the zero vector + m_mv_prediction = zero_mv; + + DoBlock(0, 0 , guide_array , my_bmatch); + + // The rest of the first row + for ( int xpos=1 ; xpos<mv_array.LengthX() ; ++xpos ) + { + m_mv_prediction = mv_array[0][xpos-1]; + DoBlock(xpos, 0 , guide_array , my_bmatch); + }// xpos + + // All the remaining rows except the last + for ( int ypos=1 ; ypos<mv_array.LengthY() ; ++ypos ) + { + + // The first element of each row + m_mv_prediction = mv_array[ypos-1][0]; + DoBlock(0, ypos , guide_array , my_bmatch ); + + // The middle elements of each row + for ( int xpos=1 ; xpos<mv_array.LastX() ; ++xpos ) + { + m_mv_prediction = MvMedian( mv_array[ypos][xpos-1], + mv_array[ypos-1][xpos], + mv_array[ypos-1][xpos+1]); + DoBlock(xpos, ypos , guide_array , my_bmatch ); + + }// xpos + + // The last element in each row + m_mv_prediction = MvMean( mv_array[ypos-1][ mv_array.LastX() ], + mv_array[ypos][ mv_array.LastX()-1 ]); + DoBlock(mv_array.LastX() , ypos , guide_array , my_bmatch ); + }//ypos + +} + +void PixelMatcher::DoBlock(const int xpos, const int ypos , + const MvArray& guide_array, + BlockMatcher& block_match) +{ + // Find the best match for each block ... + + // Use guide from lower down if one exists + if ( m_level<m_depth ) + { + int xdown = BChk(xpos>>1, guide_array.LengthX()); + int ydown = BChk(ypos>>1, guide_array.LengthY()); + AddNewVlist( m_cand_list , guide_array[ydown][xdown] * 2 , m_xr , m_yr ); + + } + + // use the spatial prediction, also, as a guide + if (m_encparams.FullSearch()==false ) + AddNewVlist( m_cand_list , m_mv_prediction , m_xr , m_yr ); + else + AddNewVlist( m_cand_list , m_mv_prediction , 1 , 1); + + // Find the best motion vector // + ///////////////////////////////// + + block_match.FindBestMatchPel( xpos , ypos , m_cand_list, m_mv_prediction, 0 ); + + // Reset the lists ready for the next block (don't erase the first sublist as + // this is a neighbourhood of zero, which we always look at) + m_cand_list.erase( m_cand_list.begin()+1 , m_cand_list.end() ); +} diff --git a/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/pixel_match.h b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/pixel_match.h new file mode 100644 index 000000000..f860882fb --- /dev/null +++ b/src/filters/parser/DiracSplitter/libdirac/libdirac_motionest/pixel_match.h @@ -0,0 +1,157 @@ +/* ***** BEGIN LICENSE BLOCK ***** +* +* $Id: pixel_match.h,v 1.11 2008/08/27 00:20:52 asuraparaju Exp $ $Name: $ +* +* Version: MPL 1.1/GPL 2.0/LGPL 2.1 +* +* The contents of this file are subject to the Mozilla Public License +* Version 1.1 (the "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* http://www.mozilla.org/MPL/ +* +* Software distributed under the License is distributed on an "AS IS" basis, +* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +* the specific language governing rights and limitations under the License. +* +* The Original Code is BBC Research and Development code. +* +* The Initial Developer of the Original Code is the British Broadcasting +* Corporation. +* Portions created by the Initial Developer are Copyright (C) 2004. +* All Rights Reserved. +* +* Contributor(s): Thomas Davies (Original Author) +* +* Alternatively, the contents of this file may be used under the terms of +* the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser +* Public License Version 2.1 (the "LGPL"), in which case the provisions of +* the GPL or the LGPL are applicable instead of those above. If you wish to +* allow use of your version of this file only under the terms of the either +* the GPL or LGPL and not to allow others to use your version of this file +* under the MPL, indicate your decision by deleting the provisions above +* and replace them with the notice and other provisions required by the GPL +* or LGPL. If you do not delete the provisions above, a recipient may use +* your version of this file under the terms of any one of the MPL, the GPL +* or the LGPL. +* ***** END LICENSE BLOCK ***** */ + +#ifndef _PIXEL_MATCH_H_ +#define _PIXEL_MATCH_H_ + +/* ************************************************************************* +* +* Class for getting motion vectors to pixel-accuracy +* +* The class could be implemented in any number of ways. The approach taken +* has been to do hierarchical matching, which means doing block matching +* on smaller, downcoverted versions of the pictures in order to get a wider +* effective search range. At each level of searching the vectors discovered +* can be used as guides to the next level of searching, and in this way +* large motions can be detected easily. The danger is that the motions of +* small objects can be overlooked. +* +* *************************************************************************/ + +#include <libdirac_common/common.h> +#include <libdirac_common/motion.h> +#include <libdirac_motionest/block_match.h> +namespace dirac +{ + class EncQueue; + class MvData; + class EncoderParams; + class PicArray; + + + class PixelMatcher + { + public: + + //! Constructor + PixelMatcher( const EncoderParams& encp); + + //! Do the actual search + /* Do the searching. + + \param my_buffer the buffer of pictures from which pictures are taken + \param pic_num the number of the picture for which motion is to be estimated + \param mv_data class in which the measured motion vectors are stored, together with costs + + */ + void DoSearch( EncQueue& my_buffer, int pic_num ); + + private: + + // Member variables + + //! Local reference to the encoder params + const EncoderParams& m_encparams; + + //! Local reference to the picture pred params + const PicturePredParams* m_predparams; + + // the depth of the hierarchical match + int m_depth; + + // the level we're at (from 0 to depth) + int m_level; + + // the search-range sizes for the hierarchical match + int m_xr, m_yr; + + // the search-range sizes for when hierarchical match fails + int m_big_xr, m_big_yr; + + // the temporal distances to the reference pictures + int m_tdiff[2]; + + // the picture sort - I, L1 or L2 + PictureSort m_psort; + + // list of candidate vectors for checking + CandidateList m_cand_list; + + // Prediction used for each block. This is derived from neighbouring blocks + // and is used to control the variation in the motion vector field. + MVector m_mv_prediction; + + // The value used in computing block cost means with a simple recursive filter + double m_rho; + + // The mean of the block cost + double m_cost_mean; + + // The mean of the square of the block cost + double m_cost_mean_sq; + + private: + + // Functions + + //! Make down-converted pictures + void MakePicHierarchy(const PicArray& data, OneDArray< PicArray* >& down_data); + + //! Make a hierarchy of MvData structures + void MakeMEDataHierarchy(const OneDArray< PicArray*>& down_data, + OneDArray< MEData* >& me_data_set ); + + //! Tidy up the allocations made in building the picture hirearchy + void TidyPics( OneDArray< PicArray*>& down_data ); + + //! Tidy up the allocations made in building the MV data hirearchy + void TidyMEData( OneDArray< MEData*>& me_data_set ); + + //! Match the picture data + void MatchPic(const PicArray& ref_data , const PicArray& pic_data , MEData& me_data , + const MvData& guide_data, const int ref_id); + + //! Do a given block + void DoBlock(const int xpos, const int ypos , + const MvArray& guide_array, + BlockMatcher& block_match); + + }; + +} // namespace dirac + +#endif |