1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840 |
- /********************************************************************
- * *
- * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
- * by the Xiph.Org Foundation http://www.xiph.org/ *
- * *
- ********************************************************************
- function:
- last mod: $Id$
- ********************************************************************/
- #include <stdlib.h>
- #include <string.h>
- #include "encint.h"
- #include "dequant.h"
- /*The default quantization parameters used by VP3.1.*/
- static const int OC_VP31_RANGE_SIZES[1]={63};
- static const th_quant_base OC_VP31_BASES_INTRA_Y[2]={
- {
- 16, 11, 10, 16, 24, 40, 51, 61,
- 12, 12, 14, 19, 26, 58, 60, 55,
- 14, 13, 16, 24, 40, 57, 69, 56,
- 14, 17, 22, 29, 51, 87, 80, 62,
- 18, 22, 37, 58, 68,109,103, 77,
- 24, 35, 55, 64, 81,104,113, 92,
- 49, 64, 78, 87,103,121,120,101,
- 72, 92, 95, 98,112,100,103, 99
- },
- {
- 16, 11, 10, 16, 24, 40, 51, 61,
- 12, 12, 14, 19, 26, 58, 60, 55,
- 14, 13, 16, 24, 40, 57, 69, 56,
- 14, 17, 22, 29, 51, 87, 80, 62,
- 18, 22, 37, 58, 68,109,103, 77,
- 24, 35, 55, 64, 81,104,113, 92,
- 49, 64, 78, 87,103,121,120,101,
- 72, 92, 95, 98,112,100,103, 99
- }
- };
- static const th_quant_base OC_VP31_BASES_INTRA_C[2]={
- {
- 17, 18, 24, 47, 99, 99, 99, 99,
- 18, 21, 26, 66, 99, 99, 99, 99,
- 24, 26, 56, 99, 99, 99, 99, 99,
- 47, 66, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99
- },
- {
- 17, 18, 24, 47, 99, 99, 99, 99,
- 18, 21, 26, 66, 99, 99, 99, 99,
- 24, 26, 56, 99, 99, 99, 99, 99,
- 47, 66, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99
- }
- };
- static const th_quant_base OC_VP31_BASES_INTER[2]={
- {
- 16, 16, 16, 20, 24, 28, 32, 40,
- 16, 16, 20, 24, 28, 32, 40, 48,
- 16, 20, 24, 28, 32, 40, 48, 64,
- 20, 24, 28, 32, 40, 48, 64, 64,
- 24, 28, 32, 40, 48, 64, 64, 64,
- 28, 32, 40, 48, 64, 64, 64, 96,
- 32, 40, 48, 64, 64, 64, 96,128,
- 40, 48, 64, 64, 64, 96,128,128
- },
- {
- 16, 16, 16, 20, 24, 28, 32, 40,
- 16, 16, 20, 24, 28, 32, 40, 48,
- 16, 20, 24, 28, 32, 40, 48, 64,
- 20, 24, 28, 32, 40, 48, 64, 64,
- 24, 28, 32, 40, 48, 64, 64, 64,
- 28, 32, 40, 48, 64, 64, 64, 96,
- 32, 40, 48, 64, 64, 64, 96,128,
- 40, 48, 64, 64, 64, 96,128,128
- }
- };
- const th_quant_info TH_VP31_QUANT_INFO={
- {
- 220,200,190,180,170,170,160,160,
- 150,150,140,140,130,130,120,120,
- 110,110,100,100, 90, 90, 90, 80,
- 80, 80, 70, 70, 70, 60, 60, 60,
- 60, 50, 50, 50, 50, 40, 40, 40,
- 40, 40, 30, 30, 30, 30, 30, 30,
- 30, 20, 20, 20, 20, 20, 20, 20,
- 20, 10, 10, 10, 10, 10, 10, 10
- },
- {
- 500,450,400,370,340,310,285,265,
- 245,225,210,195,185,180,170,160,
- 150,145,135,130,125,115,110,107,
- 100, 96, 93, 89, 85, 82, 75, 74,
- 70, 68, 64, 60, 57, 56, 52, 50,
- 49, 45, 44, 43, 40, 38, 37, 35,
- 33, 32, 30, 29, 28, 25, 24, 22,
- 21, 19, 18, 17, 15, 13, 12, 10
- },
- {
- 30,25,20,20,15,15,14,14,
- 13,13,12,12,11,11,10,10,
- 9, 9, 8, 8, 7, 7, 7, 7,
- 6, 6, 6, 6, 5, 5, 5, 5,
- 4, 4, 4, 4, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- },
- {
- {
- {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_Y},
- {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C},
- {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTRA_C}
- },
- {
- {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER},
- {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER},
- {1,OC_VP31_RANGE_SIZES,OC_VP31_BASES_INTER}
- }
- }
- };
- /*The current default quantization parameters.*/
- static const int OC_DEF_QRANGE_SIZES[3]={32,16,15};
- static const th_quant_base OC_DEF_BASES_INTRA_Y[4]={
- {
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- },
- {
- 15, 12, 12, 15, 18, 20, 20, 21,
- 13, 13, 14, 17, 18, 21, 21, 20,
- 14, 14, 15, 18, 20, 21, 21, 21,
- 14, 16, 17, 19, 20, 21, 21, 21,
- 16, 17, 20, 21, 21, 21, 21, 21,
- 18, 19, 20, 21, 21, 21, 21, 21,
- 20, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21
- },
- {
- 16, 12, 11, 16, 20, 25, 27, 28,
- 13, 13, 14, 18, 21, 28, 28, 27,
- 14, 13, 16, 20, 25, 28, 28, 28,
- 14, 16, 19, 22, 27, 29, 29, 28,
- 17, 19, 25, 28, 28, 30, 30, 29,
- 20, 24, 27, 28, 29, 30, 30, 29,
- 27, 28, 29, 29, 30, 30, 30, 30,
- 29, 29, 29, 29, 30, 30, 30, 29
- },
- {
- 16, 11, 10, 16, 24, 40, 51, 61,
- 12, 12, 14, 19, 26, 58, 60, 55,
- 14, 13, 16, 24, 40, 57, 69, 56,
- 14, 17, 22, 29, 51, 87, 80, 62,
- 18, 22, 37, 58, 68,109,103, 77,
- 24, 35, 55, 64, 81,104,113, 92,
- 49, 64, 78, 87,103,121,120,101,
- 72, 92, 95, 98,112,100,103, 99
- }
- };
- static const th_quant_base OC_DEF_BASES_INTRA_C[4]={
- {
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19
- },
- {
- 18, 18, 21, 25, 26, 26, 26, 26,
- 18, 20, 22, 26, 26, 26, 26, 26,
- 21, 22, 25, 26, 26, 26, 26, 26,
- 25, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26
- },
- {
- 17, 18, 22, 31, 36, 36, 36, 36,
- 18, 20, 24, 34, 36, 36, 36, 36,
- 22, 24, 33, 36, 36, 36, 36, 36,
- 31, 34, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36
- },
- {
- 17, 18, 24, 47, 99, 99, 99, 99,
- 18, 21, 26, 66, 99, 99, 99, 99,
- 24, 26, 56, 99, 99, 99, 99, 99,
- 47, 66, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99
- }
- };
- static const th_quant_base OC_DEF_BASES_INTER[4]={
- {
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21
- },
- {
- 18, 18, 18, 21, 23, 24, 25, 27,
- 18, 18, 21, 23, 24, 25, 27, 28,
- 18, 21, 23, 24, 25, 27, 28, 29,
- 21, 23, 24, 25, 27, 28, 29, 29,
- 23, 24, 25, 27, 28, 29, 29, 29,
- 24, 25, 27, 28, 29, 29, 29, 30,
- 25, 27, 28, 29, 29, 29, 30, 30,
- 27, 28, 29, 29, 29, 30, 30, 30
- },
- {
- 17, 17, 17, 20, 23, 26, 28, 32,
- 17, 17, 20, 23, 26, 28, 32, 34,
- 17, 20, 23, 26, 28, 32, 34, 37,
- 20, 23, 26, 28, 32, 34, 37, 37,
- 23, 26, 28, 32, 34, 37, 37, 37,
- 26, 28, 32, 34, 37, 37, 37, 41,
- 28, 32, 34, 37, 37, 37, 41, 42,
- 32, 34, 37, 37, 37, 41, 42, 42
- },
- {
- 16, 16, 16, 20, 24, 28, 32, 40,
- 16, 16, 20, 24, 28, 32, 40, 48,
- 16, 20, 24, 28, 32, 40, 48, 64,
- 20, 24, 28, 32, 40, 48, 64, 64,
- 24, 28, 32, 40, 48, 64, 64, 64,
- 28, 32, 40, 48, 64, 64, 64, 96,
- 32, 40, 48, 64, 64, 64, 96,128,
- 40, 48, 64, 64, 64, 96,128,128
- }
- };
- const th_quant_info TH_DEF_QUANT_INFO={
- {
- 365,348,333,316,300,287,277,265,
- 252,240,229,219,206,197,189,180,
- 171,168,160,153,146,139,132,127,
- 121,115,110,107,101, 97, 94, 89,
- 85, 83, 78, 73, 72, 67, 66, 62,
- 60, 59, 56, 53, 52, 48, 47, 43,
- 42, 40, 36, 35, 34, 33, 31, 30,
- 28, 25, 24, 22, 20, 17, 14, 10
- },
- {
- 365,348,333,316,300,287,277,265,
- 252,240,229,219,206,197,189,180,
- 171,168,160,153,146,139,132,127,
- 121,115,110,107,101, 97, 94, 89,
- 85, 83, 78, 73, 72, 67, 66, 62,
- 60, 59, 56, 53, 52, 48, 47, 43,
- 42, 40, 36, 35, 34, 33, 31, 30,
- 28, 25, 24, 22, 20, 17, 14, 10
- },
- {
- 15,12, 9, 8, 6, 6, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 4, 4, 4, 4, 4, 4, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- },
- {
- {
- {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_Y},
- {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_C},
- {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTRA_C}
- },
- {
- {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER},
- {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER},
- {3,OC_DEF_QRANGE_SIZES,OC_DEF_BASES_INTER}
- }
- }
- };
- /*The Huffman codes used for macro block modes.*/
- const unsigned char OC_MODE_BITS[2][OC_NMODES]={
- /*Codebook 0: a maximally skewed prefix code.*/
- {1,2,3,4,5,6,7,7},
- /*Codebook 1: a fixed-length code.*/
- {3,3,3,3,3,3,3,3}
- };
- static const unsigned char OC_MODE_CODES[2][OC_NMODES]={
- /*Codebook 0: a maximally skewed prefix code.*/
- {0x00,0x02,0x06,0x0E,0x1E,0x3E,0x7E,0x7F},
- /*Codebook 1: a fixed-length code.*/
- {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}
- };
- /*The Huffman codes used for motion vectors.*/
- const unsigned char OC_MV_BITS[2][64]={
- /*Codebook 0: VLC code.*/
- {
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,7,7,7,7,7,7,7,7,6,6,6,6,4,4,3,
- 3,
- 3,4,4,6,6,6,6,7,7,7,7,7,7,7,7,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- },
- /*Codebook 1: (5 bit magnitude, 1 bit sign).
- This wastes a code word (0x01, negative zero), or a bit (0x00, positive
- zero, requires only 5 bits to uniquely decode), but is hopefully not used
- very often.*/
- {
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
- }
- };
- static const unsigned char OC_MV_CODES[2][64]={
- /*Codebook 0: VLC code.*/
- {
- 0xFF,0xFD,0xFB,0xF9,0xF7,0xF5,0xF3,
- 0xF1,0xEF,0xED,0xEB,0xE9,0xE7,0xE5,0xE3,
- 0xE1,0x6F,0x6D,0x6B,0x69,0x67,0x65,0x63,
- 0x61,0x2F,0x2D,0x2B,0x29,0x09,0x07,0x02,
- 0x00,
- 0x01,0x06,0x08,0x28,0x2A,0x2C,0x2E,0x60,
- 0x62,0x64,0x66,0x68,0x6A,0x6C,0x6E,0xE0,
- 0xE2,0xE4,0xE6,0xE8,0xEA,0xEC,0xEE,0xF0,
- 0xF2,0xF4,0xF6,0xF8,0xFA,0xFC,0xFE
- },
- /*Codebook 1: (5 bit magnitude, 1 bit sign).*/
- {
- 0x3F,0x3D,0x3B,0x39,0x37,0x35,0x33,
- 0x31,0x2F,0x2D,0x2B,0x29,0x27,0x25,0x23,
- 0x21,0x1F,0x1D,0x1B,0x19,0x17,0x15,0x13,
- 0x11,0x0F,0x0D,0x0B,0x09,0x07,0x05,0x03,
- 0x00,
- 0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,0x10,
- 0x12,0x14,0x16,0x18,0x1A,0x1C,0x1E,0x20,
- 0x22,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30,
- 0x32,0x34,0x36,0x38,0x3A,0x3C,0x3E
- }
- };
- /*Super block run coding scheme:
- Codeword Run Length
- 0 1
- 10x 2-3
- 110x 4-5
- 1110xx 6-9
- 11110xxx 10-17
- 111110xxxx 18-33
- 111111xxxxxxxxxxxx 34-4129*/
- const ogg_uint16_t OC_SB_RUN_VAL_MIN[8]={1,2,4,6,10,18,34,4130};
- static const unsigned OC_SB_RUN_CODE_PREFIX[7]={
- 0,4,0xC,0x38,0xF0,0x3E0,0x3F000
- };
- const unsigned char OC_SB_RUN_CODE_NBITS[7]={1,3,4,6,8,10,18};
- /*Writes the bit pattern for the run length of a super block run to the given
- oggpack_buffer.
- _opb: The buffer to write to.
- _run_count: The length of the run, which must be positive.
- _flag: The current flag.
- _done: Whether or not more flags are to be encoded.*/
- static void oc_sb_run_pack(oggpack_buffer *_opb,ptrdiff_t _run_count,
- int _flag,int _done){
- int i;
- if(_run_count>=4129){
- do{
- oggpackB_write(_opb,0x3FFFF,18);
- _run_count-=4129;
- if(_run_count>0)oggpackB_write(_opb,_flag,1);
- else if(!_done)oggpackB_write(_opb,!_flag,1);
- }
- while(_run_count>=4129);
- if(_run_count<=0)return;
- }
- for(i=0;_run_count>=OC_SB_RUN_VAL_MIN[i+1];i++);
- oggpackB_write(_opb,OC_SB_RUN_CODE_PREFIX[i]+_run_count-OC_SB_RUN_VAL_MIN[i],
- OC_SB_RUN_CODE_NBITS[i]);
- }
- /*Block run coding scheme:
- Codeword Run Length
- 0x 1-2
- 10x 3-4
- 110x 5-6
- 1110xx 7-10
- 11110xx 11-14
- 11111xxxx 15-30*/
- const unsigned char OC_BLOCK_RUN_CODE_NBITS[30]={
- 2,2,3,3,4,4,6,6,6,6,7,7,7,7,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9
- };
- static const ogg_uint16_t OC_BLOCK_RUN_CODE_PATTERN[30]={
- 0x000,0x001,0x004,0x005,0x00C,0x00D,0x038,
- 0x039,0x03A,0x03B,0x078,0x079,0x07A,0x07B,0x1F0,
- 0x1F1,0x1F2,0x1F3,0x1F4,0x1F5,0x1F6,0x1F7,0x1F8,
- 0x1F9,0x1FA,0x1FB,0x1FC,0x1FD,0x1FE,0x1FF
- };
- /*Writes the bit pattern for the run length of a block run to the given
- oggpack_buffer.
- _opb: The buffer to write to.
- _run_count: The length of the run.
- This must be positive, and no more than 30.*/
- static void oc_block_run_pack(oggpack_buffer *_opb,int _run_count){
- oggpackB_write(_opb,OC_BLOCK_RUN_CODE_PATTERN[_run_count-1],
- OC_BLOCK_RUN_CODE_NBITS[_run_count-1]);
- }
- static void oc_enc_frame_header_pack(oc_enc_ctx *_enc){
- /*Mark this as a data packet.*/
- oggpackB_write(&_enc->opb,0,1);
- /*Output the frame type (key frame or delta frame).*/
- oggpackB_write(&_enc->opb,_enc->state.frame_type,1);
- /*Write out the current qi list.*/
- oggpackB_write(&_enc->opb,_enc->state.qis[0],6);
- if(_enc->state.nqis>1){
- oggpackB_write(&_enc->opb,1,1);
- oggpackB_write(&_enc->opb,_enc->state.qis[1],6);
- if(_enc->state.nqis>2){
- oggpackB_write(&_enc->opb,1,1);
- oggpackB_write(&_enc->opb,_enc->state.qis[2],6);
- }
- else oggpackB_write(&_enc->opb,0,1);
- }
- else oggpackB_write(&_enc->opb,0,1);
- if(_enc->state.frame_type==OC_INTRA_FRAME){
- /*Key frames have 3 unused configuration bits, holdovers from the VP3 days.
- Most of the other unused bits in the VP3 headers were eliminated.
- Monty kept these to leave us some wiggle room for future expansion,
- though a single bit in all frames would have been far more useful.*/
- oggpackB_write(&_enc->opb,0,3);
- }
- }
- /*Writes the bit flags for whether or not each super block is partially coded
- or not.
- These flags are run-length encoded, with the flag value alternating between
- each run.
- Return: The number partially coded SBs.*/
- static unsigned oc_enc_partial_sb_flags_pack(oc_enc_ctx *_enc){
- const oc_sb_flags *sb_flags;
- unsigned nsbs;
- unsigned sbi;
- unsigned npartial;
- int flag;
- sb_flags=_enc->state.sb_flags;
- nsbs=_enc->state.nsbs;
- flag=sb_flags[0].coded_partially;
- oggpackB_write(&_enc->opb,flag,1);
- sbi=npartial=0;
- do{
- unsigned run_count;
- for(run_count=0;sbi<nsbs;sbi++){
- if(sb_flags[sbi].coded_partially!=flag)break;
- run_count++;
- npartial+=flag;
- }
- oc_sb_run_pack(&_enc->opb,run_count,flag,sbi>=nsbs);
- flag=!flag;
- }
- while(sbi<nsbs);
- return npartial;
- }
- /*Writes the coded/not coded flags for each super block that is not partially
- coded.
- These flags are run-length encoded, with the flag value altenating between
- each run.*/
- static void oc_enc_coded_sb_flags_pack(oc_enc_ctx *_enc){
- const oc_sb_flags *sb_flags;
- unsigned nsbs;
- unsigned sbi;
- int flag;
- sb_flags=_enc->state.sb_flags;
- nsbs=_enc->state.nsbs;
- /*Skip partially coded super blocks; their flags have already been coded.*/
- for(sbi=0;sb_flags[sbi].coded_partially;sbi++);
- flag=sb_flags[sbi].coded_fully;
- oggpackB_write(&_enc->opb,flag,1);
- do{
- unsigned run_count;
- for(run_count=0;sbi<nsbs;sbi++){
- if(sb_flags[sbi].coded_partially)continue;
- if(sb_flags[sbi].coded_fully!=flag)break;
- run_count++;
- }
- oc_sb_run_pack(&_enc->opb,run_count,flag,sbi>=nsbs);
- flag=!flag;
- }
- while(sbi<nsbs);
- }
- static void oc_enc_coded_flags_pack(oc_enc_ctx *_enc){
- const oc_sb_map *sb_maps;
- const oc_sb_flags *sb_flags;
- unsigned nsbs;
- const oc_fragment *frags;
- unsigned npartial;
- int run_count;
- int flag;
- int pli;
- unsigned sbi;
- npartial=oc_enc_partial_sb_flags_pack(_enc);
- if(npartial<_enc->state.nsbs)oc_enc_coded_sb_flags_pack(_enc);
- sb_maps=(const oc_sb_map *)_enc->state.sb_maps;
- sb_flags=_enc->state.sb_flags;
- nsbs=_enc->state.nsbs;
- frags=_enc->state.frags;
- for(sbi=0;sbi<nsbs&&!sb_flags[sbi].coded_partially;sbi++);
- /*If there's at least one partial SB, store individual coded block flags.*/
- if(sbi<nsbs){
- flag=frags[sb_maps[sbi][0][0]].coded;
- oggpackB_write(&_enc->opb,flag,1);
- run_count=0;
- nsbs=sbi=0;
- for(pli=0;pli<3;pli++){
- nsbs+=_enc->state.fplanes[pli].nsbs;
- for(;sbi<nsbs;sbi++){
- int quadi;
- int bi;
- ptrdiff_t fragi;
- if(sb_flags[sbi].coded_partially){
- for(quadi=0;quadi<4;quadi++){
- for(bi=0;bi<4;bi++){
- fragi=sb_maps[sbi][quadi][bi];
- if(fragi>=0){
- if(frags[fragi].coded!=flag){
- oc_block_run_pack(&_enc->opb,run_count);
- flag=!flag;
- run_count=1;
- }
- else run_count++;
- }
- }
- }
- }
- }
- }
- /*Flush any trailing block coded run.*/
- if(run_count>0)oc_block_run_pack(&_enc->opb,run_count);
- }
- }
- static void oc_enc_mb_modes_pack(oc_enc_ctx *_enc){
- const unsigned char *mode_codes;
- const unsigned char *mode_bits;
- const unsigned char *mode_ranks;
- unsigned *coded_mbis;
- size_t ncoded_mbis;
- const signed char *mb_modes;
- unsigned mbii;
- int scheme;
- int mb_mode;
- scheme=_enc->chooser.scheme_list[0];
- /*Encode the best scheme.*/
- oggpackB_write(&_enc->opb,scheme,3);
- /*If the chosen scheme is scheme 0, send the mode frequency ordering.*/
- if(scheme==0){
- for(mb_mode=0;mb_mode<OC_NMODES;mb_mode++){
- oggpackB_write(&_enc->opb,_enc->chooser.scheme0_ranks[mb_mode],3);
- }
- }
- mode_ranks=_enc->chooser.mode_ranks[scheme];
- mode_bits=OC_MODE_BITS[scheme+1>>3];
- mode_codes=OC_MODE_CODES[scheme+1>>3];
- coded_mbis=_enc->coded_mbis;
- ncoded_mbis=_enc->ncoded_mbis;
- mb_modes=_enc->state.mb_modes;
- for(mbii=0;mbii<ncoded_mbis;mbii++){
- int rank;
- rank=mode_ranks[mb_modes[coded_mbis[mbii]]];
- oggpackB_write(&_enc->opb,mode_codes[rank],mode_bits[rank]);
- }
- }
- static void oc_enc_mv_pack(oc_enc_ctx *_enc,int _mv_scheme,oc_mv _mv){
- int dx;
- int dy;
- dx=OC_MV_X(_mv);
- dy=OC_MV_Y(_mv);
- oggpackB_write(&_enc->opb,
- OC_MV_CODES[_mv_scheme][dx+31],OC_MV_BITS[_mv_scheme][dx+31]);
- oggpackB_write(&_enc->opb,
- OC_MV_CODES[_mv_scheme][dy+31],OC_MV_BITS[_mv_scheme][dy+31]);
- }
- static void oc_enc_mvs_pack(oc_enc_ctx *_enc){
- const unsigned *coded_mbis;
- size_t ncoded_mbis;
- const oc_mb_map *mb_maps;
- const signed char *mb_modes;
- const oc_fragment *frags;
- const oc_mv *frag_mvs;
- unsigned mbii;
- int mv_scheme;
- /*Choose the coding scheme.*/
- mv_scheme=_enc->mv_bits[1]<_enc->mv_bits[0];
- oggpackB_write(&_enc->opb,mv_scheme,1);
- /*Encode the motion vectors.
- Macro blocks are iterated in Hilbert scan order, but the MVs within the
- macro block are coded in raster order.*/
- coded_mbis=_enc->coded_mbis;
- ncoded_mbis=_enc->ncoded_mbis;
- mb_modes=_enc->state.mb_modes;
- mb_maps=(const oc_mb_map *)_enc->state.mb_maps;
- frags=_enc->state.frags;
- frag_mvs=_enc->state.frag_mvs;
- for(mbii=0;mbii<ncoded_mbis;mbii++){
- ptrdiff_t fragi;
- unsigned mbi;
- int bi;
- mbi=coded_mbis[mbii];
- switch(mb_modes[mbi]){
- case OC_MODE_INTER_MV:
- case OC_MODE_GOLDEN_MV:{
- for(bi=0;;bi++){
- fragi=mb_maps[mbi][0][bi];
- if(frags[fragi].coded){
- oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]);
- /*Only code a single MV for this macro block.*/
- break;
- }
- }
- }break;
- case OC_MODE_INTER_MV_FOUR:{
- for(bi=0;bi<4;bi++){
- fragi=mb_maps[mbi][0][bi];
- if(frags[fragi].coded){
- oc_enc_mv_pack(_enc,mv_scheme,frag_mvs[fragi]);
- /*Keep coding all the MVs for this macro block.*/
- }
- }
- }break;
- }
- }
- }
- static void oc_enc_block_qis_pack(oc_enc_ctx *_enc){
- const oc_fragment *frags;
- ptrdiff_t *coded_fragis;
- ptrdiff_t ncoded_fragis;
- ptrdiff_t fragii;
- ptrdiff_t run_count;
- ptrdiff_t nqi0;
- int flag;
- if(_enc->state.nqis<=1)return;
- ncoded_fragis=_enc->state.ntotal_coded_fragis;
- if(ncoded_fragis<=0)return;
- coded_fragis=_enc->state.coded_fragis;
- frags=_enc->state.frags;
- flag=!!frags[coded_fragis[0]].qii;
- oggpackB_write(&_enc->opb,flag,1);
- nqi0=0;
- for(fragii=0;fragii<ncoded_fragis;){
- for(run_count=0;fragii<ncoded_fragis;fragii++){
- if(!!frags[coded_fragis[fragii]].qii!=flag)break;
- run_count++;
- nqi0+=!flag;
- }
- oc_sb_run_pack(&_enc->opb,run_count,flag,fragii>=ncoded_fragis);
- flag=!flag;
- }
- if(_enc->state.nqis<3||nqi0>=ncoded_fragis)return;
- for(fragii=0;!frags[coded_fragis[fragii]].qii;fragii++);
- flag=frags[coded_fragis[fragii]].qii-1;
- oggpackB_write(&_enc->opb,flag,1);
- while(fragii<ncoded_fragis){
- for(run_count=0;fragii<ncoded_fragis;fragii++){
- int qii;
- qii=frags[coded_fragis[fragii]].qii;
- if(!qii)continue;
- if(qii-1!=flag)break;
- run_count++;
- }
- oc_sb_run_pack(&_enc->opb,run_count,flag,fragii>=ncoded_fragis);
- flag=!flag;
- }
- }
- /*Counts the tokens of each type used for the given range of coefficient
- indices in zig-zag order.
- _zzi_start: The first zig-zag index to include.
- _zzi_end: The first zig-zag index to not include.
- _token_counts_y: Returns the token counts for the Y' plane.
- _token_counts_c: Returns the token counts for the Cb and Cr planes.*/
- static void oc_enc_count_tokens(oc_enc_ctx *_enc,int _zzi_start,int _zzi_end,
- ptrdiff_t _token_counts_y[32],ptrdiff_t _token_counts_c[32]){
- const unsigned char *dct_tokens;
- ptrdiff_t ndct_tokens;
- int pli;
- int zzi;
- ptrdiff_t ti;
- memset(_token_counts_y,0,32*sizeof(*_token_counts_y));
- memset(_token_counts_c,0,32*sizeof(*_token_counts_c));
- for(zzi=_zzi_start;zzi<_zzi_end;zzi++){
- dct_tokens=_enc->dct_tokens[0][zzi];
- ndct_tokens=_enc->ndct_tokens[0][zzi];
- for(ti=_enc->dct_token_offs[0][zzi];ti<ndct_tokens;ti++){
- _token_counts_y[dct_tokens[ti]]++;
- }
- }
- for(pli=1;pli<3;pli++){
- for(zzi=_zzi_start;zzi<_zzi_end;zzi++){
- dct_tokens=_enc->dct_tokens[pli][zzi];
- ndct_tokens=_enc->ndct_tokens[pli][zzi];
- for(ti=_enc->dct_token_offs[pli][zzi];ti<ndct_tokens;ti++){
- _token_counts_c[dct_tokens[ti]]++;
- }
- }
- }
- }
- /*Computes the number of bits used for each of the potential Huffman code for
- the given list of token counts.
- The bits are added to whatever the current bit counts are.*/
- static void oc_enc_count_bits(oc_enc_ctx *_enc,int _hgi,
- const ptrdiff_t _token_counts[32],size_t _bit_counts[16]){
- int huffi;
- int huff_offs;
- int token;
- huff_offs=_hgi<<4;
- for(huffi=0;huffi<16;huffi++){
- for(token=0;token<32;token++){
- _bit_counts[huffi]+=
- _token_counts[token]*_enc->huff_codes[huffi+huff_offs][token].nbits;
- }
- }
- }
- /*Returns the Huffman index using the fewest number of bits.*/
- static int oc_select_huff_idx(size_t _bit_counts[16]){
- int best_huffi;
- int huffi;
- best_huffi=0;
- for(huffi=1;huffi<16;huffi++)if(_bit_counts[huffi]<_bit_counts[best_huffi]){
- best_huffi=huffi;
- }
- return best_huffi;
- }
- static void oc_enc_huff_group_pack(oc_enc_ctx *_enc,
- int _zzi_start,int _zzi_end,const int _huff_idxs[2]){
- int zzi;
- for(zzi=_zzi_start;zzi<_zzi_end;zzi++){
- int pli;
- for(pli=0;pli<3;pli++){
- const unsigned char *dct_tokens;
- const ogg_uint16_t *extra_bits;
- ptrdiff_t ndct_tokens;
- const th_huff_code *huff_codes;
- ptrdiff_t ti;
- dct_tokens=_enc->dct_tokens[pli][zzi];
- extra_bits=_enc->extra_bits[pli][zzi];
- ndct_tokens=_enc->ndct_tokens[pli][zzi];
- huff_codes=_enc->huff_codes[_huff_idxs[pli+1>>1]];
- for(ti=_enc->dct_token_offs[pli][zzi];ti<ndct_tokens;ti++){
- int token;
- int neb;
- token=dct_tokens[ti];
- oggpackB_write(&_enc->opb,huff_codes[token].pattern,
- huff_codes[token].nbits);
- neb=OC_DCT_TOKEN_EXTRA_BITS[token];
- if(neb)oggpackB_write(&_enc->opb,extra_bits[ti],neb);
- }
- }
- }
- }
- static void oc_enc_residual_tokens_pack(oc_enc_ctx *_enc){
- static const unsigned char OC_HUFF_GROUP_MIN[6]={0,1,6,15,28,64};
- static const unsigned char *OC_HUFF_GROUP_MAX=OC_HUFF_GROUP_MIN+1;
- ptrdiff_t token_counts_y[32];
- ptrdiff_t token_counts_c[32];
- size_t bits_y[16];
- size_t bits_c[16];
- int huff_idxs[2];
- int frame_type;
- int hgi;
- frame_type=_enc->state.frame_type;
- /*Choose which Huffman tables to use for the DC token list.*/
- oc_enc_count_tokens(_enc,0,1,token_counts_y,token_counts_c);
- memset(bits_y,0,sizeof(bits_y));
- memset(bits_c,0,sizeof(bits_c));
- oc_enc_count_bits(_enc,0,token_counts_y,bits_y);
- oc_enc_count_bits(_enc,0,token_counts_c,bits_c);
- huff_idxs[0]=oc_select_huff_idx(bits_y);
- huff_idxs[1]=oc_select_huff_idx(bits_c);
- /*Write the DC token list with the chosen tables.*/
- oggpackB_write(&_enc->opb,huff_idxs[0],4);
- oggpackB_write(&_enc->opb,huff_idxs[1],4);
- _enc->huff_idxs[frame_type][0][0]=(unsigned char)huff_idxs[0];
- _enc->huff_idxs[frame_type][0][1]=(unsigned char)huff_idxs[1];
- oc_enc_huff_group_pack(_enc,0,1,huff_idxs);
- /*Choose which Huffman tables to use for the AC token lists.*/
- memset(bits_y,0,sizeof(bits_y));
- memset(bits_c,0,sizeof(bits_c));
- for(hgi=1;hgi<5;hgi++){
- oc_enc_count_tokens(_enc,OC_HUFF_GROUP_MIN[hgi],OC_HUFF_GROUP_MAX[hgi],
- token_counts_y,token_counts_c);
- oc_enc_count_bits(_enc,hgi,token_counts_y,bits_y);
- oc_enc_count_bits(_enc,hgi,token_counts_c,bits_c);
- }
- huff_idxs[0]=oc_select_huff_idx(bits_y);
- huff_idxs[1]=oc_select_huff_idx(bits_c);
- /*Write the AC token lists using the chosen tables.*/
- oggpackB_write(&_enc->opb,huff_idxs[0],4);
- oggpackB_write(&_enc->opb,huff_idxs[1],4);
- _enc->huff_idxs[frame_type][1][0]=(unsigned char)huff_idxs[0];
- _enc->huff_idxs[frame_type][1][1]=(unsigned char)huff_idxs[1];
- for(hgi=1;hgi<5;hgi++){
- huff_idxs[0]+=16;
- huff_idxs[1]+=16;
- oc_enc_huff_group_pack(_enc,
- OC_HUFF_GROUP_MIN[hgi],OC_HUFF_GROUP_MAX[hgi],huff_idxs);
- }
- }
- /*Packs an explicit drop frame, instead of using the more efficient 0-byte
- packet.
- This is only enabled in VP3-compatibility mode, even though it is not
- strictly required for VP3 compatibility (VP3 could be encoded in AVI, which
- also supports dropping frames by inserting 0 byte packets).
- However, almost every _Theora_ player used to get this wrong (and many still
- do), and it wasn't until we started shipping a post-VP3 encoder that
- actually used non-VP3 features that this began to be discovered and fixed,
- despite being in the standard since 2004.
- The pack buffer must be reset before calling this function.*/
- static void oc_enc_drop_frame_pack(oc_enc_ctx *_enc){
- unsigned nsbs;
- /*Mark this as a data packet.*/
- oggpackB_write(&_enc->opb,0,1);
- /*Output the frame type (key frame or delta frame).*/
- oggpackB_write(&_enc->opb,OC_INTER_FRAME,1);
- /*Write out the current qi list.
- We always use just 1 qi, to avoid wasting bits on the others.*/
- oggpackB_write(&_enc->opb,_enc->state.qis[0],6);
- oggpackB_write(&_enc->opb,0,1);
- /*Coded block flags: everything is uncoded.*/
- nsbs=_enc->state.nsbs;
- /*No partially coded SBs.*/
- oggpackB_write(&_enc->opb,0,1);
- oc_sb_run_pack(&_enc->opb,nsbs,0,1);
- /*No fully coded SBs.*/
- oggpackB_write(&_enc->opb,0,1);
- oc_sb_run_pack(&_enc->opb,nsbs,0,1);
- /*MB modes: just need write which scheme to use.
- Since we have no coded MBs, we can pick any of them except 0, which would
- require writing out an additional mode list.*/
- oggpackB_write(&_enc->opb,7,3);
- /*MVs: just need write which scheme to use.
- We can pick either one, since we have no MVs.*/
- oggpackB_write(&_enc->opb,1,1);
- /*Write the chosen DC token tables.*/
- oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][0],4);
- oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][0][1],4);
- /*Write the chosen AC token tables.*/
- oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][0],4);
- oggpackB_write(&_enc->opb,_enc->huff_idxs[OC_INTER_FRAME][1][1],4);
- }
- static void oc_enc_frame_pack(oc_enc_ctx *_enc){
- /*musl libc malloc()/realloc() calls might use floating point, so make sure
- we've cleared the MMX state for them.*/
- oc_restore_fpu(&_enc->state);
- oggpackB_reset(&_enc->opb);
- /*Only proceed if we have some coded blocks.*/
- if(_enc->state.ntotal_coded_fragis>0){
- oc_enc_frame_header_pack(_enc);
- if(_enc->state.frame_type==OC_INTER_FRAME){
- /*Coded block flags, MB modes, and MVs are only needed for delta frames.*/
- oc_enc_coded_flags_pack(_enc);
- oc_enc_mb_modes_pack(_enc);
- oc_enc_mvs_pack(_enc);
- }
- oc_enc_block_qis_pack(_enc);
- oc_enc_tokenize_finish(_enc);
- oc_enc_residual_tokens_pack(_enc);
- }
- /*If there are no coded blocks, we can drop this frame simply by emitting a
- 0 byte packet.
- We emit an inter frame with no coded blocks in VP3-compatibility mode.*/
- else if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc);
- /*Success: Mark the packet as ready to be flushed.*/
- _enc->packet_state=OC_PACKET_READY;
- #if defined(OC_COLLECT_METRICS)
- oc_enc_mode_metrics_collect(_enc);
- #endif
- }
- void oc_enc_accel_init_c(oc_enc_ctx *_enc){
- /*The implementations prefixed with oc_enc_ are encoder-specific.
- The rest we re-use from the decoder.*/
- # if defined(OC_ENC_USE_VTABLE)
- _enc->opt_vtable.frag_sub=oc_enc_frag_sub_c;
- _enc->opt_vtable.frag_sub_128=oc_enc_frag_sub_128_c;
- _enc->opt_vtable.frag_sad=oc_enc_frag_sad_c;
- _enc->opt_vtable.frag_sad_thresh=oc_enc_frag_sad_thresh_c;
- _enc->opt_vtable.frag_sad2_thresh=oc_enc_frag_sad2_thresh_c;
- _enc->opt_vtable.frag_intra_sad=oc_enc_frag_intra_sad_c;
- _enc->opt_vtable.frag_satd=oc_enc_frag_satd_c;
- _enc->opt_vtable.frag_satd2=oc_enc_frag_satd2_c;
- _enc->opt_vtable.frag_intra_satd=oc_enc_frag_intra_satd_c;
- _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_c;
- _enc->opt_vtable.frag_border_ssd=oc_enc_frag_border_ssd_c;
- _enc->opt_vtable.frag_copy2=oc_enc_frag_copy2_c;
- _enc->opt_vtable.enquant_table_init=oc_enc_enquant_table_init_c;
- _enc->opt_vtable.enquant_table_fixup=oc_enc_enquant_table_fixup_c;
- _enc->opt_vtable.quantize=oc_enc_quantize_c;
- _enc->opt_vtable.frag_recon_intra=oc_frag_recon_intra_c;
- _enc->opt_vtable.frag_recon_inter=oc_frag_recon_inter_c;
- _enc->opt_vtable.fdct8x8=oc_enc_fdct8x8_c;
- # endif
- _enc->opt_data.enquant_table_size=64*sizeof(oc_iquant);
- _enc->opt_data.enquant_table_alignment=16;
- }
- /*Initialize the macro block neighbor lists for MC analysis.
- This assumes that the entire mb_info memory region has been initialized with
- zeros.*/
- static void oc_enc_mb_info_init(oc_enc_ctx *_enc){
- oc_mb_enc_info *embs;
- const signed char *mb_modes;
- unsigned nhsbs;
- unsigned nvsbs;
- unsigned nhmbs;
- unsigned nvmbs;
- unsigned sby;
- mb_modes=_enc->state.mb_modes;
- embs=_enc->mb_info;
- nhsbs=_enc->state.fplanes[0].nhsbs;
- nvsbs=_enc->state.fplanes[0].nvsbs;
- nhmbs=_enc->state.nhmbs;
- nvmbs=_enc->state.nvmbs;
- for(sby=0;sby<nvsbs;sby++){
- unsigned sbx;
- for(sbx=0;sbx<nhsbs;sbx++){
- int quadi;
- for(quadi=0;quadi<4;quadi++){
- /*Because of the Hilbert curve ordering the macro blocks are
- visited in, the available neighbors change depending on where in
- a super block the macro block is located.
- Only the first three vectors are used in the median calculation
- for the optimal predictor, and so the most important should be
- listed first.
- Additional vectors are used, so there will always be at least 3,
- except for in the upper-left most macro block.*/
- /*The number of current neighbors for each macro block position.*/
- static const unsigned char NCNEIGHBORS[4]={4,3,2,4};
- /*The offset of each current neighbor in the X direction.*/
- static const signed char CDX[4][4]={
- {-1,0,1,-1},
- {-1,0,-1,},
- {-1,-1},
- {-1,0,0,1}
- };
- /*The offset of each current neighbor in the Y direction.*/
- static const signed char CDY[4][4]={
- {0,-1,-1,-1},
- {0,-1,-1},
- {0,-1},
- {0,-1,1,-1}
- };
- /*The offset of each previous neighbor in the X direction.*/
- static const signed char PDX[4]={-1,0,1,0};
- /*The offset of each previous neighbor in the Y direction.*/
- static const signed char PDY[4]={0,-1,0,1};
- unsigned mbi;
- int mbx;
- int mby;
- unsigned nmbi;
- int nmbx;
- int nmby;
- int ni;
- mbi=(sby*nhsbs+sbx<<2)+quadi;
- if(mb_modes[mbi]==OC_MODE_INVALID)continue;
- mbx=2*sbx+(quadi>>1);
- mby=2*sby+(quadi+1>>1&1);
- /*Fill in the neighbors with current motion vectors available.*/
- for(ni=0;ni<NCNEIGHBORS[quadi];ni++){
- nmbx=mbx+CDX[quadi][ni];
- nmby=mby+CDY[quadi][ni];
- if(nmbx<0||nmbx>=nhmbs||nmby<0||nmby>=nvmbs)continue;
- nmbi=(nmby&~1)*nhmbs+((nmbx&~1)<<1)+OC_MB_MAP[nmby&1][nmbx&1];
- if(mb_modes[nmbi]==OC_MODE_INVALID)continue;
- embs[mbi].cneighbors[embs[mbi].ncneighbors++]=nmbi;
- }
- /*Fill in the neighbors with previous motion vectors available.*/
- for(ni=0;ni<4;ni++){
- nmbx=mbx+PDX[ni];
- nmby=mby+PDY[ni];
- if(nmbx<0||nmbx>=nhmbs||nmby<0||nmby>=nvmbs)continue;
- nmbi=(nmby&~1)*nhmbs+((nmbx&~1)<<1)+OC_MB_MAP[nmby&1][nmbx&1];
- if(mb_modes[nmbi]==OC_MODE_INVALID)continue;
- embs[mbi].pneighbors[embs[mbi].npneighbors++]=nmbi;
- }
- }
- }
- }
- }
- static int oc_enc_set_huffman_codes(oc_enc_ctx *_enc,
- const th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){
- int ret;
- if(_enc==NULL)return TH_EFAULT;
- if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
- if(_codes==NULL)_codes=TH_VP31_HUFF_CODES;
- /*Validate the codes.*/
- oggpackB_reset(&_enc->opb);
- ret=oc_huff_codes_pack(&_enc->opb,_codes);
- if(ret<0)return ret;
- memcpy(_enc->huff_codes,_codes,sizeof(_enc->huff_codes));
- return 0;
- }
- static void oc_enc_enquant_tables_init(oc_enc_ctx *_enc,
- const th_quant_info *_qinfo){
- unsigned char *etd;
- size_t ets;
- int align;
- int qii;
- int qi;
- int pli;
- int qti;
- for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
- _enc->state.dequant_tables[qi][pli][qti]=
- _enc->state.dequant_table_data[qi][pli][qti];
- }
- /*Initialize the dequantization tables.*/
- oc_dequant_tables_init(_enc->state.dequant_tables,NULL,_qinfo);
- /*And save off the DC values.*/
- for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
- _enc->dequant_dc[qi][pli][qti]=_enc->state.dequant_tables[qi][pli][qti][0];
- }
- /*Set up storage for the quantization tables.*/
- etd=_enc->enquant_table_data;
- ets=_enc->opt_data.enquant_table_size;
- align=-(etd-(unsigned char *)0)&_enc->opt_data.enquant_table_alignment-1;
- etd+=align;
- /*Set up the main tables.*/
- for(qi=0;qi<64;qi++)for(pli=0;pli<3;pli++)for(qti=0;qti<2;qti++){
- _enc->enquant_tables[qi][pli][qti]=etd;
- oc_enc_enquant_table_init(_enc,etd,
- _enc->state.dequant_tables[qi][pli][qti]);
- etd+=ets;
- }
- /*Set up storage for the local copies we modify for each frame.*/
- for(pli=0;pli<3;pli++)for(qii=0;qii<3;qii++)for(qti=0;qti<2;qti++){
- _enc->enquant[pli][qii][qti]=etd;
- etd+=ets;
- }
- }
- /*Updates the encoder state after the quantization parameters have been
- changed.*/
- static void oc_enc_quant_params_updated(oc_enc_ctx *_enc,
- const th_quant_info *_qinfo){
- oc_enc_enquant_tables_init(_enc,_qinfo);
- memcpy(_enc->state.loop_filter_limits,_qinfo->loop_filter_limits,
- sizeof(_enc->state.loop_filter_limits));
- oc_enquant_qavg_init(_enc->log_qavg,_enc->log_plq,_enc->chroma_rd_scale,
- _enc->state.dequant_tables,_enc->state.info.pixel_fmt);
- }
- /*Sets the quantization parameters to use.
- This may only be called before the setup header is written.
- If it is called multiple times, only the last call has any effect.
- _qinfo: The quantization parameters.
- These are described in more detail in theoraenc.h.
- This can be NULL, in which case the default quantization parameters
- will be used.*/
- static int oc_enc_set_quant_params(oc_enc_ctx *_enc,
- const th_quant_info *_qinfo){
- th_quant_info old_qinfo;
- int ret;
- if(_enc==NULL)return TH_EFAULT;
- if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
- if(_qinfo==NULL)_qinfo=&TH_DEF_QUANT_INFO;
- memcpy(&old_qinfo,&_enc->qinfo,sizeof(old_qinfo));
- ret=oc_quant_params_clone(&_enc->qinfo,_qinfo);
- if(ret<0){
- oc_quant_params_clear(&_enc->qinfo);
- memcpy(&_enc->qinfo,&old_qinfo,sizeof(old_qinfo));
- return ret;
- }
- else oc_quant_params_clear(&old_qinfo);
- oc_enc_quant_params_updated(_enc,_qinfo);
- return 0;
- }
- static void oc_enc_clear(oc_enc_ctx *_enc);
- static int oc_enc_init(oc_enc_ctx *_enc,const th_info *_info){
- th_info info;
- size_t mcu_nmbs;
- ptrdiff_t mcu_ncfrags;
- ptrdiff_t mcu_nfrags;
- int hdec;
- int vdec;
- int ret;
- int pli;
- /*Clean up the requested settings.*/
- memcpy(&info,_info,sizeof(info));
- info.version_major=TH_VERSION_MAJOR;
- info.version_minor=TH_VERSION_MINOR;
- info.version_subminor=TH_VERSION_SUB;
- if(info.quality>63)info.quality=63;
- if(info.quality<0)info.quality=32;
- if(info.target_bitrate<0)info.target_bitrate=0;
- /*Initialize the shared encoder/decoder state.*/
- ret=oc_state_init(&_enc->state,&info,6);
- if(ret<0)return ret;
- oc_enc_accel_init(_enc);
- _enc->mb_info=_ogg_calloc(_enc->state.nmbs,sizeof(*_enc->mb_info));
- _enc->frag_dc=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_dc));
- _enc->coded_mbis=
- (unsigned *)_ogg_malloc(_enc->state.nmbs*sizeof(*_enc->coded_mbis));
- hdec=!(_enc->state.info.pixel_fmt&1);
- vdec=!(_enc->state.info.pixel_fmt&2);
- /*If chroma is sub-sampled in the vertical direction, we have to encode two
- super block rows of Y' for each super block row of Cb and Cr.*/
- _enc->mcu_nvsbs=1<<vdec;
- mcu_nmbs=_enc->mcu_nvsbs*_enc->state.fplanes[0].nhsbs*(size_t)4;
- mcu_ncfrags=mcu_nmbs<<3-(hdec+vdec);
- mcu_nfrags=4*mcu_nmbs+mcu_ncfrags;
- _enc->mcu_skip_ssd=(unsigned *)_ogg_malloc(
- mcu_nfrags*sizeof(*_enc->mcu_skip_ssd));
- _enc->mcu_rd_scale=(ogg_uint16_t *)_ogg_malloc(
- (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_scale));
- _enc->mcu_rd_iscale=(ogg_uint16_t *)_ogg_malloc(
- (mcu_ncfrags>>1)*sizeof(*_enc->mcu_rd_iscale));
- for(pli=0;pli<3;pli++){
- _enc->dct_tokens[pli]=(unsigned char **)oc_malloc_2d(64,
- _enc->state.fplanes[pli].nfrags,sizeof(**_enc->dct_tokens));
- _enc->extra_bits[pli]=(ogg_uint16_t **)oc_malloc_2d(64,
- _enc->state.fplanes[pli].nfrags,sizeof(**_enc->extra_bits));
- }
- #if defined(OC_COLLECT_METRICS)
- _enc->frag_sad=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_sad));
- _enc->frag_satd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_satd));
- _enc->frag_ssd=_ogg_calloc(_enc->state.nfrags,sizeof(*_enc->frag_ssd));
- #endif
- _enc->enquant_table_data=(unsigned char *)_ogg_malloc(
- (64+3)*3*2*_enc->opt_data.enquant_table_size
- +_enc->opt_data.enquant_table_alignment-1);
- _enc->keyframe_frequency_force=1<<_enc->state.info.keyframe_granule_shift;
- _enc->state.qis[0]=_enc->state.info.quality;
- _enc->state.nqis=1;
- _enc->activity_avg=90<<12;
- _enc->luma_avg=128<<8;
- oc_rc_state_init(&_enc->rc,_enc);
- oggpackB_writeinit(&_enc->opb);
- memcpy(_enc->huff_codes,TH_VP31_HUFF_CODES,sizeof(_enc->huff_codes));
- memset(_enc->qinfo.qi_ranges,0,sizeof(_enc->qinfo.qi_ranges));
- /*Reset the packet-out state machine.*/
- _enc->packet_state=OC_PACKET_INFO_HDR;
- _enc->dup_count=0;
- _enc->nqueued_dups=0;
- _enc->prev_dup_count=0;
- /*Enable speed optimizations up through early skip by default.*/
- _enc->sp_level=OC_SP_LEVEL_EARLY_SKIP;
- /*Disable VP3 compatibility by default.*/
- _enc->vp3_compatible=0;
- /*No INTER frames coded yet.*/
- _enc->coded_inter_frame=0;
- if(_enc->mb_info==NULL||_enc->frag_dc==NULL||_enc->coded_mbis==NULL
- ||_enc->mcu_skip_ssd==NULL||_enc->dct_tokens[0]==NULL
- ||_enc->dct_tokens[1]==NULL||_enc->dct_tokens[2]==NULL
- ||_enc->extra_bits[0]==NULL||_enc->extra_bits[1]==NULL
- ||_enc->extra_bits[2]==NULL
- #if defined(OC_COLLECT_METRICS)
- ||_enc->frag_sad==NULL||_enc->frag_satd==NULL||_enc->frag_ssd==NULL
- #endif
- ||oc_enc_set_quant_params(_enc,NULL)<0){
- oc_enc_clear(_enc);
- return TH_EFAULT;
- }
- oc_mode_scheme_chooser_init(&_enc->chooser);
- oc_enc_mb_info_init(_enc);
- memset(_enc->huff_idxs,0,sizeof(_enc->huff_idxs));
- return 0;
- }
- static void oc_enc_clear(oc_enc_ctx *_enc){
- int pli;
- oc_rc_state_clear(&_enc->rc);
- oggpackB_writeclear(&_enc->opb);
- oc_quant_params_clear(&_enc->qinfo);
- _ogg_free(_enc->enquant_table_data);
- #if defined(OC_COLLECT_METRICS)
- /*Save the collected metrics from this run.
- Use tools/process_modedec_stats to actually generate modedec.h from the
- resulting file.*/
- oc_mode_metrics_dump();
- _ogg_free(_enc->frag_ssd);
- _ogg_free(_enc->frag_satd);
- _ogg_free(_enc->frag_sad);
- #endif
- for(pli=3;pli-->0;){
- oc_free_2d(_enc->extra_bits[pli]);
- oc_free_2d(_enc->dct_tokens[pli]);
- }
- _ogg_free(_enc->mcu_rd_iscale);
- _ogg_free(_enc->mcu_rd_scale);
- _ogg_free(_enc->mcu_skip_ssd);
- _ogg_free(_enc->coded_mbis);
- _ogg_free(_enc->frag_dc);
- _ogg_free(_enc->mb_info);
- oc_state_clear(&_enc->state);
- }
- static void oc_enc_drop_frame(th_enc_ctx *_enc){
- /*Use the previous frame's reconstruction.*/
- _enc->state.ref_frame_idx[OC_FRAME_SELF]=
- _enc->state.ref_frame_idx[OC_FRAME_PREV];
- _enc->state.ref_frame_data[OC_FRAME_SELF]=
- _enc->state.ref_frame_data[OC_FRAME_PREV];
- /*Flag motion vector analysis about the frame drop.*/
- _enc->prevframe_dropped=1;
- /*Zero the packet.*/
- oggpackB_reset(&_enc->opb);
- /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/
- if(_enc->vp3_compatible)oc_enc_drop_frame_pack(_enc);
- }
- static void oc_enc_compress_keyframe(oc_enc_ctx *_enc,int _recode){
- if(_enc->state.info.target_bitrate>0){
- _enc->state.qis[0]=oc_enc_select_qi(_enc,OC_INTRA_FRAME,
- _enc->state.curframe_num>0);
- _enc->state.nqis=1;
- }
- oc_enc_calc_lambda(_enc,OC_INTRA_FRAME);
- oc_enc_analyze_intra(_enc,_recode);
- oc_enc_frame_pack(_enc);
- /*On the first frame, the previous call was an initial dry-run to prime
- feed-forward statistics.*/
- if(!_recode&&_enc->state.curframe_num==0){
- if(_enc->state.info.target_bitrate>0){
- oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
- OC_INTRA_FRAME,_enc->state.qis[0],1,0);
- }
- oc_enc_compress_keyframe(_enc,1);
- }
- }
- static void oc_enc_compress_frame(oc_enc_ctx *_enc,int _recode){
- if(_enc->state.info.target_bitrate>0){
- _enc->state.qis[0]=oc_enc_select_qi(_enc,OC_INTER_FRAME,1);
- _enc->state.nqis=1;
- }
- oc_enc_calc_lambda(_enc,OC_INTER_FRAME);
- if(oc_enc_analyze_inter(_enc,_enc->rc.twopass!=2,_recode)){
- /*Mode analysis thinks this should have been a keyframe; start over.*/
- oc_enc_compress_keyframe(_enc,1);
- }
- else{
- oc_enc_frame_pack(_enc);
- if(!_enc->coded_inter_frame){
- /*On the first INTER frame, the previous call was an initial dry-run to
- prime feed-forward statistics.*/
- _enc->coded_inter_frame=1;
- if(_enc->state.info.target_bitrate>0){
- /*Rate control also needs to prime.*/
- oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
- OC_INTER_FRAME,_enc->state.qis[0],1,0);
- }
- oc_enc_compress_frame(_enc,1);
- }
- }
- }
- /*Set the granule position for the next packet to output based on the current
- internal state.*/
- static void oc_enc_set_granpos(oc_enc_ctx *_enc){
- unsigned dup_offs;
- /*Add an offset for the number of duplicate frames we've emitted so far.*/
- dup_offs=_enc->prev_dup_count-_enc->nqueued_dups;
- /*If the current frame was a keyframe, use it for the high part.*/
- if(_enc->state.frame_type==OC_INTRA_FRAME){
- _enc->state.granpos=(_enc->state.curframe_num+_enc->state.granpos_bias<<
- _enc->state.info.keyframe_granule_shift)+dup_offs;
- }
- /*Otherwise use the last keyframe in the high part and put the current frame
- in the low part.*/
- else{
- _enc->state.granpos=
- (_enc->state.keyframe_num+_enc->state.granpos_bias<<
- _enc->state.info.keyframe_granule_shift)
- +_enc->state.curframe_num-_enc->state.keyframe_num+dup_offs;
- }
- }
- th_enc_ctx *th_encode_alloc(const th_info *_info){
- oc_enc_ctx *enc;
- if(_info==NULL)return NULL;
- enc=oc_aligned_malloc(sizeof(*enc),16);
- if(enc==NULL||oc_enc_init(enc,_info)<0){
- oc_aligned_free(enc);
- return NULL;
- }
- return enc;
- }
- void th_encode_free(th_enc_ctx *_enc){
- if(_enc!=NULL){
- oc_enc_clear(_enc);
- oc_aligned_free(_enc);
- }
- }
- int th_encode_ctl(th_enc_ctx *_enc,int _req,void *_buf,size_t _buf_sz){
- switch(_req){
- case TH_ENCCTL_SET_HUFFMAN_CODES:{
- if(_buf==NULL&&_buf_sz!=0||
- _buf!=NULL&&_buf_sz!=sizeof(th_huff_table)*TH_NHUFFMAN_TABLES){
- return TH_EINVAL;
- }
- return oc_enc_set_huffman_codes(_enc,(const th_huff_table *)_buf);
- }break;
- case TH_ENCCTL_SET_QUANT_PARAMS:{
- if(_buf==NULL&&_buf_sz!=0||
- _buf!=NULL&&_buf_sz!=sizeof(th_quant_info)){
- return TH_EINVAL;
- }
- return oc_enc_set_quant_params(_enc,(th_quant_info *)_buf);
- }break;
- case TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE:{
- ogg_uint32_t keyframe_frequency_force;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(keyframe_frequency_force))return TH_EINVAL;
- keyframe_frequency_force=*(ogg_uint32_t *)_buf;
- if(keyframe_frequency_force<=0)keyframe_frequency_force=1;
- if(_enc->packet_state==OC_PACKET_INFO_HDR){
- /*It's still early enough to enlarge keyframe_granule_shift.*/
- _enc->state.info.keyframe_granule_shift=OC_CLAMPI(
- _enc->state.info.keyframe_granule_shift,
- OC_ILOG_32(keyframe_frequency_force-1),31);
- }
- _enc->keyframe_frequency_force=OC_MINI(keyframe_frequency_force,
- (ogg_uint32_t)1U<<_enc->state.info.keyframe_granule_shift);
- *(ogg_uint32_t *)_buf=_enc->keyframe_frequency_force;
- return 0;
- }break;
- case TH_ENCCTL_SET_VP3_COMPATIBLE:{
- int vp3_compatible;
- int ret;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(vp3_compatible))return TH_EINVAL;
- /*Try this before we change anything else, because it can fail.*/
- ret=oc_enc_set_quant_params(_enc,&TH_VP31_QUANT_INFO);
- /*If we can't allocate enough memory, don't change any of the state.*/
- if(ret==TH_EFAULT)return ret;
- vp3_compatible=*(int *)_buf;
- _enc->vp3_compatible=vp3_compatible;
- if(oc_enc_set_huffman_codes(_enc,TH_VP31_HUFF_CODES)<0)vp3_compatible=0;
- if(ret<0)vp3_compatible=0;
- if(_enc->state.info.pixel_fmt!=TH_PF_420||
- _enc->state.info.pic_width<_enc->state.info.frame_width||
- _enc->state.info.pic_height<_enc->state.info.frame_height||
- /*If we have more than 4095 super blocks, VP3's RLE coding might
- overflow.
- We could overcome this by ensuring we flip the coded/not-coded flags on
- at least one super block in the frame, but we pick the simple solution
- of just telling the user the stream will be incompatible instead.
- It's unlikely the old VP3 codec would be able to decode streams at this
- resolution in real time in the first place.*/
- _enc->state.nsbs>4095){
- vp3_compatible=0;
- }
- *(int *)_buf=vp3_compatible;
- return 0;
- }break;
- case TH_ENCCTL_GET_SPLEVEL_MAX:{
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(int))return TH_EINVAL;
- *(int *)_buf=OC_SP_LEVEL_MAX;
- return 0;
- }break;
- case TH_ENCCTL_SET_SPLEVEL:{
- int speed;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(speed))return TH_EINVAL;
- speed=*(int *)_buf;
- if(speed<0||speed>OC_SP_LEVEL_MAX)return TH_EINVAL;
- _enc->sp_level=speed;
- return 0;
- }break;
- case TH_ENCCTL_GET_SPLEVEL:{
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(int))return TH_EINVAL;
- *(int *)_buf=_enc->sp_level;
- return 0;
- }
- case TH_ENCCTL_SET_DUP_COUNT:{
- int dup_count;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(dup_count))return TH_EINVAL;
- dup_count=*(int *)_buf;
- if(dup_count>=_enc->keyframe_frequency_force)return TH_EINVAL;
- _enc->dup_count=OC_MAXI(dup_count,0);
- return 0;
- }break;
- case TH_ENCCTL_SET_QUALITY:{
- int qi;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_enc->state.info.target_bitrate>0)return TH_EINVAL;
- qi=*(int *)_buf;
- if(qi<0||qi>63)return TH_EINVAL;
- _enc->state.info.quality=qi;
- _enc->state.qis[0]=(unsigned char)qi;
- _enc->state.nqis=1;
- return 0;
- }break;
- case TH_ENCCTL_SET_BITRATE:{
- long bitrate;
- int reset;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- bitrate=*(long *)_buf;
- if(bitrate<=0)return TH_EINVAL;
- reset=_enc->state.info.target_bitrate<=0;
- _enc->state.info.target_bitrate=bitrate>INT_MAX?INT_MAX:bitrate;
- if(reset)oc_rc_state_init(&_enc->rc,_enc);
- else oc_enc_rc_resize(_enc);
- return 0;
- }break;
- case TH_ENCCTL_SET_RATE_FLAGS:{
- int set;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(set))return TH_EINVAL;
- if(_enc->state.info.target_bitrate<=0)return TH_EINVAL;
- set=*(int *)_buf;
- _enc->rc.drop_frames=set&TH_RATECTL_DROP_FRAMES;
- _enc->rc.cap_overflow=set&TH_RATECTL_CAP_OVERFLOW;
- _enc->rc.cap_underflow=set&TH_RATECTL_CAP_UNDERFLOW;
- return 0;
- }break;
- case TH_ENCCTL_SET_RATE_BUFFER:{
- int set;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_buf_sz!=sizeof(set))return TH_EINVAL;
- if(_enc->state.info.target_bitrate<=0)return TH_EINVAL;
- set=*(int *)_buf;
- _enc->rc.buf_delay=set;
- oc_enc_rc_resize(_enc);
- *(int *)_buf=_enc->rc.buf_delay;
- return 0;
- }break;
- case TH_ENCCTL_2PASS_OUT:{
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_enc->state.info.target_bitrate<=0||
- _enc->state.curframe_num>=0&&_enc->rc.twopass!=1||
- _buf_sz!=sizeof(unsigned char *)){
- return TH_EINVAL;
- }
- return oc_enc_rc_2pass_out(_enc,(unsigned char **)_buf);
- }break;
- case TH_ENCCTL_2PASS_IN:{
- if(_enc==NULL)return TH_EFAULT;
- if(_enc->state.info.target_bitrate<=0||
- _enc->state.curframe_num>=0&&_enc->rc.twopass!=2){
- return TH_EINVAL;
- }
- return oc_enc_rc_2pass_in(_enc,_buf,_buf_sz);
- }break;
- case TH_ENCCTL_SET_COMPAT_CONFIG:{
- unsigned char buf[7];
- oc_pack_buf opb;
- th_quant_info qinfo;
- th_huff_code huff_codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS];
- int ret;
- int i;
- if(_enc==NULL||_buf==NULL)return TH_EFAULT;
- if(_enc->packet_state>OC_PACKET_SETUP_HDR)return TH_EINVAL;
- oc_pack_readinit(&opb,_buf,_buf_sz);
- /*Validate the setup packet header.*/
- for(i=0;i<7;i++)buf[i]=(unsigned char)oc_pack_read(&opb,8);
- if(!(buf[0]&0x80)||memcmp(buf+1,"theora",6)!=0)return TH_ENOTFORMAT;
- if(buf[0]!=0x82)return TH_EBADHEADER;
- /*Reads its contents.*/
- ret=oc_quant_params_unpack(&opb,&qinfo);
- if(ret<0){
- oc_quant_params_clear(&qinfo);
- return ret;
- }
- ret=oc_huff_codes_unpack(&opb,huff_codes);
- if(ret<0){
- oc_quant_params_clear(&qinfo);
- return ret;
- }
- /*Install the new state.*/
- oc_quant_params_clear(&_enc->qinfo);
- memcpy(&_enc->qinfo,&qinfo,sizeof(qinfo));
- oc_enc_quant_params_updated(_enc,&qinfo);
- memcpy(_enc->huff_codes,huff_codes,sizeof(_enc->huff_codes));
- return 0;
- }
- #if defined(OC_COLLECT_METRICS)
- case TH_ENCCTL_SET_METRICS_FILE:{
- OC_MODE_METRICS_FILENAME=(const char *)_buf;
- return 0;
- }
- #endif
- default:return TH_EIMPL;
- }
- }
- int th_encode_flushheader(th_enc_ctx *_enc,th_comment *_tc,ogg_packet *_op){
- if(_enc==NULL)return TH_EFAULT;
- return oc_state_flushheader(&_enc->state,&_enc->packet_state,&_enc->opb,
- &_enc->qinfo,(const th_huff_table *)_enc->huff_codes,th_version_string(),
- _tc,_op);
- }
- static void oc_img_plane_copy_pad(th_img_plane *_dst,th_img_plane *_src,
- ogg_int32_t _pic_x,ogg_int32_t _pic_y,
- ogg_int32_t _pic_width,ogg_int32_t _pic_height){
- unsigned char *dst;
- int dstride;
- ogg_uint32_t frame_width;
- ogg_uint32_t frame_height;
- ogg_uint32_t y;
- frame_width=_dst->width;
- frame_height=_dst->height;
- /*If we have _no_ data, just encode a dull green.*/
- if(_pic_width==0||_pic_height==0){
- dst=_dst->data;
- dstride=_dst->stride;
- for(y=0;y<frame_height;y++){
- memset(dst,0,frame_width*sizeof(*dst));
- dst+=dstride;
- }
- }
- /*Otherwise, copy what we do have, and add our own padding.*/
- else{
- unsigned char *dst_data;
- unsigned char *src_data;
- unsigned char *src;
- int sstride;
- ogg_uint32_t x;
- /*Step 1: Copy the data we do have.*/
- dstride=_dst->stride;
- sstride=_src->stride;
- dst_data=_dst->data;
- src_data=_src->data;
- dst=dst_data+_pic_y*(ptrdiff_t)dstride+_pic_x;
- src=src_data+_pic_y*(ptrdiff_t)sstride+_pic_x;
- for(y=0;y<_pic_height;y++){
- memcpy(dst,src,_pic_width);
- dst+=dstride;
- src+=sstride;
- }
- /*Step 2: Perform a low-pass extension into the padding region.*/
- /*Left side.*/
- for(x=_pic_x;x-->0;){
- dst=dst_data+_pic_y*(ptrdiff_t)dstride+x;
- for(y=0;y<_pic_height;y++){
- dst[0]=(dst[1]<<1)+(dst-(dstride&-(y>0)))[1]
- +(dst+(dstride&-(y+1<_pic_height)))[1]+2>>2;
- dst+=dstride;
- }
- }
- /*Right side.*/
- for(x=_pic_x+_pic_width;x<frame_width;x++){
- dst=dst_data+_pic_y*(ptrdiff_t)dstride+x-1;
- for(y=0;y<_pic_height;y++){
- dst[1]=(dst[0]<<1)+(dst-(dstride&-(y>0)))[0]
- +(dst+(dstride&-(y+1<_pic_height)))[0]+2>>2;
- dst+=dstride;
- }
- }
- /*Top.*/
- dst=dst_data+_pic_y*(ptrdiff_t)dstride;
- for(y=_pic_y;y-->0;){
- for(x=0;x<frame_width;x++){
- (dst-dstride)[x]=(dst[x]<<1)+dst[x-(x>0)]
- +dst[x+(x+1<frame_width)]+2>>2;
- }
- dst-=dstride;
- }
- /*Bottom.*/
- dst=dst_data+(_pic_y+_pic_height)*(ptrdiff_t)dstride;
- for(y=_pic_y+_pic_height;y<frame_height;y++){
- for(x=0;x<frame_width;x++){
- dst[x]=((dst-dstride)[x]<<1)+(dst-dstride)[x-(x>0)]
- +(dst-dstride)[x+(x+1<frame_width)]+2>>2;
- }
- dst+=dstride;
- }
- }
- }
- int th_encode_ycbcr_in(th_enc_ctx *_enc,th_ycbcr_buffer _img){
- th_ycbcr_buffer img;
- int frame_width;
- int frame_height;
- int pic_width;
- int pic_height;
- int pic_x;
- int pic_y;
- int cframe_width;
- int cframe_height;
- int cpic_width;
- int cpic_height;
- int cpic_x;
- int cpic_y;
- int hdec;
- int vdec;
- int pli;
- int refi;
- int drop;
- /*Step 1: validate parameters.*/
- if(_enc==NULL||_img==NULL)return TH_EFAULT;
- if(_enc->packet_state==OC_PACKET_DONE)return TH_EINVAL;
- if(_enc->rc.twopass&&_enc->rc.twopass_buffer_bytes==0)return TH_EINVAL;
- hdec=!(_enc->state.info.pixel_fmt&1);
- vdec=!(_enc->state.info.pixel_fmt&2);
- frame_width=_enc->state.info.frame_width;
- frame_height=_enc->state.info.frame_height;
- pic_x=_enc->state.info.pic_x;
- pic_y=_enc->state.info.pic_y;
- pic_width=_enc->state.info.pic_width;
- pic_height=_enc->state.info.pic_height;
- cframe_width=frame_width>>hdec;
- cframe_height=frame_height>>vdec;
- cpic_x=pic_x>>hdec;
- cpic_y=pic_y>>vdec;
- cpic_width=(pic_x+pic_width+hdec>>hdec)-cpic_x;
- cpic_height=(pic_y+pic_height+vdec>>vdec)-cpic_y;
- /*Flip the input buffer upside down.*/
- oc_ycbcr_buffer_flip(img,_img);
- if(img[0].width!=frame_width||img[0].height!=frame_height||
- img[1].width!=cframe_width||img[2].width!=cframe_width||
- img[1].height!=cframe_height||img[2].height!=cframe_height){
- /*The buffer does not match the frame size.
- Check to see if it matches the picture size.*/
- if(img[0].width!=pic_width||img[0].height!=pic_height||
- img[1].width!=cpic_width||img[2].width!=cpic_width||
- img[1].height!=cpic_height||img[2].height!=cpic_height){
- /*It doesn't; we don't know how to handle it.*/
- return TH_EINVAL;
- }
- /*Adjust the pointers to address a full frame.
- We still only use the picture region, however.*/
- img[0].data-=pic_y*(ptrdiff_t)img[0].stride+pic_x;
- img[1].data-=cpic_y*(ptrdiff_t)img[1].stride+cpic_x;
- img[2].data-=cpic_y*(ptrdiff_t)img[2].stride+cpic_x;
- }
- /*Step 2: Update the buffer state.*/
- if(_enc->state.ref_frame_idx[OC_FRAME_SELF]>=0){
- _enc->state.ref_frame_idx[OC_FRAME_PREV]=
- _enc->state.ref_frame_idx[OC_FRAME_SELF];
- _enc->state.ref_frame_data[OC_FRAME_PREV]=
- _enc->state.ref_frame_data[OC_FRAME_SELF];
- if(_enc->state.frame_type==OC_INTRA_FRAME){
- /*The new frame becomes both the previous and gold reference frames.*/
- _enc->state.keyframe_num=_enc->state.curframe_num;
- _enc->state.ref_frame_idx[OC_FRAME_GOLD]=
- _enc->state.ref_frame_idx[OC_FRAME_SELF];
- _enc->state.ref_frame_data[OC_FRAME_GOLD]=
- _enc->state.ref_frame_data[OC_FRAME_SELF];
- }
- }
- if(_enc->state.ref_frame_idx[OC_FRAME_IO]>=0&&_enc->prevframe_dropped==0){
- _enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG]=
- _enc->state.ref_frame_idx[OC_FRAME_IO];
- _enc->state.ref_frame_data[OC_FRAME_PREV_ORIG]=
- _enc->state.ref_frame_data[OC_FRAME_IO];
- if(_enc->state.frame_type==OC_INTRA_FRAME){
- /*The new input frame becomes both the previous and gold
- original-reference frames.*/
- _enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]=
- _enc->state.ref_frame_idx[OC_FRAME_IO];
- _enc->state.ref_frame_data[OC_FRAME_GOLD_ORIG]=
- _enc->state.ref_frame_data[OC_FRAME_IO];
- }
- }
- /*Select a free buffer to use for the incoming frame*/
- for(refi=3;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD_ORIG]||
- refi==_enc->state.ref_frame_idx[OC_FRAME_PREV_ORIG];refi++);
- _enc->state.ref_frame_idx[OC_FRAME_IO]=refi;
- _enc->state.ref_frame_data[OC_FRAME_IO]=
- _enc->state.ref_frame_bufs[refi][0].data;
- /*Step 3: Copy the input to our internal buffer.
- This lets us add padding, so we don't have to worry about dereferencing
- possibly invalid addresses, and allows us to use the same strides and
- fragment offsets for both the input frame and the reference frames.*/
- oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+0,img+0,
- pic_x,pic_y,pic_width,pic_height);
- oc_state_borders_fill_rows(&_enc->state,refi,0,0,frame_height);
- oc_state_borders_fill_caps(&_enc->state,refi,0);
- for(pli=1;pli<3;pli++){
- oc_img_plane_copy_pad(_enc->state.ref_frame_bufs[refi]+pli,img+pli,
- cpic_x,cpic_y,cpic_width,cpic_height);
- oc_state_borders_fill_rows(&_enc->state,refi,pli,0,cframe_height);
- oc_state_borders_fill_caps(&_enc->state,refi,pli);
- }
- /*Select a free buffer to use for the reconstructed version of this frame.*/
- for(refi=0;refi==_enc->state.ref_frame_idx[OC_FRAME_GOLD]||
- refi==_enc->state.ref_frame_idx[OC_FRAME_PREV];refi++);
- _enc->state.ref_frame_idx[OC_FRAME_SELF]=refi;
- _enc->state.ref_frame_data[OC_FRAME_SELF]=
- _enc->state.ref_frame_bufs[refi][0].data;
- _enc->state.curframe_num+=_enc->prev_dup_count+1;
- /*Step 4: Compress the frame.*/
- /*Start with a keyframe, and don't allow the generation of invalid files that
- overflow the keyframe_granule_shift.*/
- if(_enc->rc.twopass_force_kf||_enc->state.curframe_num==0||
- _enc->state.curframe_num-_enc->state.keyframe_num+_enc->dup_count>=
- _enc->keyframe_frequency_force){
- oc_enc_compress_keyframe(_enc,0);
- drop=0;
- }
- else{
- oc_enc_compress_frame(_enc,0);
- drop=1;
- }
- oc_restore_fpu(&_enc->state);
- /*drop currently indicates if the frame is droppable.*/
- if(_enc->state.info.target_bitrate>0){
- drop=oc_enc_update_rc_state(_enc,oggpackB_bytes(&_enc->opb)<<3,
- _enc->state.frame_type,_enc->state.qis[0],0,drop);
- }
- else drop=0;
- /*drop now indicates if the frame was dropped.*/
- if(drop)oc_enc_drop_frame(_enc);
- else _enc->prevframe_dropped=0;
- _enc->packet_state=OC_PACKET_READY;
- _enc->prev_dup_count=_enc->nqueued_dups=_enc->dup_count;
- _enc->dup_count=0;
- #if defined(OC_DUMP_IMAGES)
- oc_enc_set_granpos(_enc);
- oc_state_dump_frame(&_enc->state,OC_FRAME_IO,"src");
- oc_state_dump_frame(&_enc->state,OC_FRAME_SELF,"rec");
- #endif
- return 0;
- }
- int th_encode_packetout(th_enc_ctx *_enc,int _last_p,ogg_packet *_op){
- unsigned char *packet;
- if(_enc==NULL||_op==NULL)return TH_EFAULT;
- if(_enc->packet_state==OC_PACKET_READY){
- _enc->packet_state=OC_PACKET_EMPTY;
- if(_enc->rc.twopass!=1){
- packet=oggpackB_get_buffer(&_enc->opb);
- /*If there's no packet, malloc failed while writing; it's lost forever.*/
- if(packet==NULL)return TH_EFAULT;
- _op->packet=packet;
- _op->bytes=oggpackB_bytes(&_enc->opb);
- }
- /*For the first pass in 2-pass mode, don't emit any packet data.*/
- else{
- _op->packet=NULL;
- _op->bytes=0;
- }
- }
- else if(_enc->packet_state==OC_PACKET_EMPTY){
- if(_enc->nqueued_dups>0){
- _enc->nqueued_dups--;
- /*Emit an inter frame with no coded blocks in VP3-compatibility mode.*/
- if(_enc->vp3_compatible){
- oggpackB_reset(&_enc->opb);
- oc_enc_drop_frame_pack(_enc);
- packet=oggpackB_get_buffer(&_enc->opb);
- /*If there's no packet, malloc failed while writing; it's lost
- forever.*/
- if(packet==NULL)return TH_EFAULT;
- _op->packet=packet;
- _op->bytes=oggpackB_bytes(&_enc->opb);
- }
- /*Otherwise emit a 0-byte packet.*/
- else{
- _op->packet=NULL;
- _op->bytes=0;
- }
- }
- else{
- if(_last_p)_enc->packet_state=OC_PACKET_DONE;
- return 0;
- }
- }
- else return 0;
- _last_p=_last_p&&_enc->nqueued_dups<=0;
- _op->b_o_s=0;
- _op->e_o_s=_last_p;
- oc_enc_set_granpos(_enc);
- _op->packetno=th_granule_frame(_enc,_enc->state.granpos)+3;
- _op->granulepos=_enc->state.granpos;
- if(_last_p)_enc->packet_state=OC_PACKET_DONE;
- return 1+_enc->nqueued_dups;
- }
|