mangui / flashls

HLS Flash Plugin/Player (Chromeless,OSMF,FlowPlayer,mediaelement.js,video.js,Clappr)
http://www.flashls.org
Mozilla Public License 2.0
751 stars 264 forks source link

608/708 CC SEI parsing issue #471

Open zuzzurro opened 8 years ago

zuzzurro commented 8 years ago

Hi @mangui and @jlacivita

We tested the 608/708 CC implementation using streams from two different encoders and we are able to display them fine (using OSMFCClib) in one case but not the other one. We spent some time analyzing, researching and debugging and we think we know the reason. First of all here: https://en.wikipedia.org/wiki/CEA-708 you will find this note: NOTE: the SEI depending on the encoder can contain more payloads than just the captions, so one would need to navigate all payloadTypes contained within. Secondly you can see that exoplayer probably had a similar issue:

https://github.com/google/ExoPlayer/issues/295

and implemented a fix for it:

https://github.com/google/ExoPlayer/commit/b5100886896ad35a32e6105a9d005c3209a81a9b

(reading the SEI happen in a while loop after the fix).

https://github.com/google/ExoPlayer/blob/master/library/src/main/java/com/google/android/exoplayer/extractor/ts/SeiReader.java#L47

We have implemented a similar fix and it seems to improve the situation a lot (we start seeing the captions) but not completely. Sometimes we seem to still miss some text (the byte array seems to be corrupted), but it is a very promising start.

Here you can find a test stream that has 608 CC that shows the issue.

http://demo.deltatre.it/cc-test/QualityLevels(1400000)/Manifest(video,format=m3u8-aapl).m3u8

mangui commented 8 years ago

Hi @zuzzurro , if you could share your fix, it might help understanding the issue, as ExoPlayer diff is huge, thanks

steve6 commented 8 years ago

Hi @mangui , here the piece of code about the fix on TSDemuxer:

else if (frame.type == 6) {

                    // We already know it's 6, so skip first byte
                    pes.data.position = frame.start + 1;

                    // get the SEI payload type
                    var payload_type : uint = 0;
                    var payload_size : uint = 0;
                    var end:Boolean= false;
                    while (!end && pes.data.bytesAvailable > 1 /* last byte will be rbsp_trailing_bits */) {
                        // Parse payload type.
                        payload_type= 0;
                        do {
                            if(pes.data.bytesAvailable!=0)
                                payload_type += pes.data.readUnsignedByte();
                        } while (payload_type == 0xFF);
                        // Parse payload size.
                        payload_size = 0;
                        do {
                            if(pes.data.bytesAvailable!=0)
                                payload_size += pes.data.readUnsignedByte();
                        } while (payload_size == 0xFF);
                        // Process the payload. We only support EIA-608 payloads currently.
                        if (payload_type == 4 && pes.data.bytesAvailable!=0) {
                            readCC(pes);
                            end=true;
                        } else {
                            pes.data.position+=payload_size;
                        }
                    }

                }

Where readCC(pes) is the old piece of code:

private function readCC(pes : PES):void
        {
            var country_code : uint = pes.data.readUnsignedByte();

            if (country_code == 181)
            {
                var provider_code : uint = pes.data.readUnsignedShort();

                if (provider_code == 49)
                {
                    var user_structure : uint = pes.data.readUnsignedInt();

                    if (user_structure == 0x47413934) // GA94
                    {
                        var user_data_type : uint = pes.data.readUnsignedByte();

                        // CEA-608 wrapped in 708 ( user_data_type == 4 is raw 608, not handled yet )
                        if (user_data_type == 3)
                        {
                            // cc -- the first 8 bits are 1-Boolean-0 and the 5 bits for the number of CCs
                            var byte:uint = pes.data.readUnsignedByte();

                            // get the total number of cc_datas
                            var total:uint = 31 & byte;
                            var count:uint = 0;

                            // supposedly a flag to process the cc_datas or not
                            // isn't working for me, so i don't use it yet
                            var process:Boolean = !((64 & byte) == 0);

                            var size:uint = total * 3;

                            // em_data, do we need? It's not used for anything, but it's there, so i need to pull it out
                            var otherByte:uint = pes.data.readUnsignedByte();

                            if (pes.data.bytesAvailable >= size)
                            {
                                // ByteArray for onCaptionInfo event
                                var sei : ByteArray = new ByteArray();

                                // onCaptionInfo payloads need to know the size of the binary data
                                // there's two two bytes we just read, plus the cc_datas, which are 3 bytes each
                                sei.writeUnsignedInt(2+3*total);

                                // write those two bytes
                                sei.writeByte(byte);
                                sei.writeByte(otherByte);

                                // write the cc_datas
                                pes.data.readBytes(sei, 6, 3*total);

                                pes.data.position -= total * 3;

                                // onCaptionInfo expects Base64 data...
                                var sei_data:String = Base64.encode(sei);

                                var cc_data:Object = {
                                    type: "708",
                                    data: sei_data
                                };

                                // add a new FLVTag with the onCaptionInfo call
                                var tag:FLVTag = new FLVTag(FLVTag.METADATA, pes.pts, pes.pts, false);

                                var data : ByteArray = new ByteArray();
                                data.objectEncoding = ObjectEncoding.AMF0;
                                data.writeObject("onCaptionInfo");
                                data.objectEncoding = ObjectEncoding.AMF3;
                                data.writeByte(0x11);
                                data.writeObject(cc_data);
                                tag.push(data, 0, data.length);
                                tag.build();
                                _tags.push(tag);
                            }
                            else
                            {
                                CONFIG::LOGGING {
                                    Log.info("not enough bytes!");
                                }
                            }
                        }
                    }
                }
            }
            return;
        }

This solution make CC visible but there are another problem that corrupt text displayed. Sometime payload_type seems be duplicated in the bytearray (I don't know why, I need more time to investigate and maybe you have an idea) but when I made a quix fix to skip this duplicated byte the Closed Caption display correctly.

Thank you Steve

jlacivita commented 8 years ago

Hi @zuzzurro & @steve6,

I tested your fix locally and it looks good. It's actually fixed a bunch of streams I have that weren't working. I had assumed they were just 608, without the 708 headers on them, but turns out they were just "hidden" behind some other SEI packet, as you discovered.

@mangui, we're going to use this fix locally, and i recommend adding it to flashls in the next release.

mangui commented 8 years ago

Great. Just bake a PR

zuzzurro commented 8 years ago

We will do that on monday, but as Steve wrote we are not 100% happy with the fix. I will work with Steve to make it more clear where the patch seem to break. I hope you guys will be able to spot the issue more easily that we do.

On Fri, Jan 8, 2016 at 9:24 PM, Guillaume du Pontavice < notifications@github.com> wrote:

Great. Just bake a PR

— Reply to this email directly or view it on GitHub https://github.com/mangui/flashls/issues/471#issuecomment-170113874.

steve6 commented 8 years ago

Hi @jlacivita thank you for the test. But if you debug with this stream: http://demo.deltatre.it/cc-test/QualityLevels(1400000)/Manifest(video,format=m3u8-aapl).m3u8 you should see the CC on top of the video but the text is corrupted (I have used OSMFCClib for the test). With a first analysy seem that sometime the payload_type byte is duplicated. If I skip this byte the text looks better (we get some wrong letters sometime). Debugging Exoplayer the bytecode of TS looks ok without duplication and errors on text displayed.

Any ideas about this problem? In you test http://demo.deltatre.it/cc-test/QualityLevels(1400000)/Manifest(video,format=m3u8-aapl).m3u8 CC are displayed correctly?

steve6 commented 8 years ago

Hi @jlacivita and @mangui I analyze better the problem with @zuzzurro and this is the result:

SEI data EN :06 010700006600000300 040411b500314741393403c2fffc8080fd8080ff 80
-----------------------------------^^^^ duplicated payloadtype
SEi data FR: 06 0447b500314741393403d4fffce9e3fd8502fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000fa0000ff 80

I have print this with this:

else if (frame.type == 6) {

var ba2 : ByteArray = new ByteArray();
pes.data.position = pes.payload;
pes.data.readBytes(ba2);
trace("PES holding SEI data :" + Hex.fromArray(ba2));
ba2 = new ByteArray();
pes.data.position = frame.start;
pes.data.readBytes(ba2, 0, frame.length);
trace("SEI data :" + Hex.fromArray(ba2));

If you see the log the SEI EN package have CC track on second position, but the payload type is duplicated. After this seem to be ok the count 11hex in decimal is 17 byte payload_size.

SEI FR packgage is OK. Should be that the parse phase of sei make a duplication when read the first part of package?

Steve

steve6 commented 8 years ago

Hi @jlacivita , @mangui I have an update about the problem. Here a new dump of three consecutives sei packages compared with Exo player log:

Sample 1:
FLASH PES HOLDING SEI DATA :00000001093000000001060107000012000008040411B500314741393403C2FFFC8080FD8080FF8000000001419A06316C0433FFE539BBD566B036F80601B0444B675BB419C2FF435BE7DF5223F7561B42EAD1BE00C6F2746FD9039C388E30C640493A9F44A875CE2B72F0BD047F6108D5F5B07AD9E6806119FF54E666D89EE609A6A89547EA45247DEC64723F5FF930FE181D8A9A57073AC2A9FC79270B6B5E6A08D9A606220A9B7EFCF76F85B05EE64A5F26F5119EFB112B118BABF6610CC5EEFF35BA1FAFD0B6F4E2CDCDFB196C3116EABD522528CD464E0CE8EC80AC3C9FFD0BFF9B6EF3233D22CCD888681F6704B2BE697546DA96BFF8423FB582FA26F7D7E5544380AB780AD5A89285A1C8AEC51C2162C2740AE83AD7C79E50C661BF4A11060FD207025E6EBE27B34540CC0672050F1F1799E91CA4F6B1B042B3024DAC78E158C4A1B85D651F594E8C625FC0F24E108652C950D3B16A7DD4FBA351E9105586F95E97BA48A56255473B3534195823984FFF6517B0567A10CC06398347238DA20E9D2F0236CC2722D337EDFE805B49FDC81E6C65561AC01BF9BAF44BFA30CF95FD105401A474F7B67A6C348FDEEEA6085526A50D210E9E2E5C6F6E5B416DB923423929430473E031ADF7C189C2BBF467F1CD90737012714FB9D14910030C8EBA7D51ECE94E5A5989C223619E5CB65BBCFE9BA444F82DDCEA6AF48895E2858CC0EC5E8E6F79846CE3B1AA2AB3923A38719AC2889FCE69B1A837B12093B1E567905A0496FEBA75B1EE53905F349599582173E3A25932B5E0B2ECA6A08002BF576A39BF855A7B5152765906344E17FAD18249B41CEB058C2A6BEC5A492AD86A83FCF316663B765260268001E1ADD1114C270CEEEEE53D14BB5010E00124B1A25F85D51F5314BEBB242B617E23EE90F178FE133B42DAC67AD9E41D25C6BF807680778A37DE5BF3F24DD6D683FA4C3D6C86288AC122A044DEDF26C9D4D7A4C1076B0607DEF1CDA756DAFFFA72362B5689C28B19CAEC434D6497CE03DB4E8BE01F2CE98F6EE6AFA69946821A8F5155BAA769C2850E9F72689AD2B4377C446B2E1B33A2E6D37AEC245245E57636AE488AB8CAF7DCCF850B6D4FBBD0FA410504D72DF241B0CE8594828AB547171DE4D7AA52E059FCC258107965275342D578E179F2FCE44684491889760CDF7851FE79E8D4B1B3738E36B8A009161DA1F718196F613AB46F5255DE952CDAC72A3D26FE91966C4E50E3DFFCA81C8CEC1BB9E1FE58FC41A647AA2042D74E03FF5CF7CF8FF916B83F421E7A76C9388FEEDFC1595A6FFAEF5732CAB583878C9E84A59DBBD35A404D394D8396A1FE3659B395ACFA3E54B958A43F92995BFE3514E3E72EA8D2D6B81E0CAE1DBBE55EEC9CB9C48319CF685FE33AA42AE84685614F62844772D7276CECFF3572B4A8A98D9798BC82EE1459BA5523B0A9802D2100A0CD5BD5AE9A21B66083CA97B0EE1C1C5F77C74BAE26261E34CE3B54E8647ECC51AC0CFF78580BA8A283DCE4E01ED2982809C76AC4BFB11D86CDB933E882D25D19B0E5F92211640062F528CBE2177D2F1964E97E610F9175CA3D9EE194B3E0B9368DF568AE1BEB2CCAAE61064F76B891A28F9606DD7C16B526A16C3C05D740F575A317DDA4ACE4A07273E3AF8B58F4426F169EC72F7485D94259D3A53E617B1BC67162AC53C127855E186EB3BC5BDEDC01CAA7C446AE68955F54D4D521AEFB9B90F5972E66F0D7DC906E815114AC852AE90BA3DD12BAB5632BF3744AF112F08749DC7E1CA4DB7D108EFC1534F1EF819133ECBA443CC9683C30BA28CA32306755BD738FE39E64021DBFC13D428F024F67329F931D3D9FA7C356A81B9468F9D97F54683FFC22A2E288E5A501DF495ADDFB112D5654A7A043D1CB25A32DE807FE1A5BCCD2132DA0A62562FACD35E9EFDD1C484DEF1863C1A4A5BBD8257575792EDB4394036D5ACFF6EB31CF302F939856E1569DE92C953647B73AB0084C6C64C0E33B6312A486C2BE6374E95CC74ED12E2C78AF76E6C959287F645CCEB79806555E1A72E2DDCFC5372063CF71E6C0CB517BBD9995612717F3B82754F8A0345436D73EFA7E7AC0F3A0D3A091B3600872FE06C5A62D62AD31F7024F58085703D8E2874F4FEEBB4661A9DAD3272CB3781B3BCD1830D3DD792BE83CF1BAAA1435A073AFA07F5257A4D86E624048C201B304C5FC83D4F5B39A3E45F7A36BF4A9EF5354FE09FF9F894DEA701F7464AFC5494AA7F4291CDD2BACC01844390F040B066B898CFC82044E4414D449D7C3F20B7E4708607CA34EE8A83DD607BB41BE901963B1D24B1ABF9F7268B79E5528A84D1B80F9E3A133DB839B0003C7A39726E3DAD27F1A9E9E7B3C087363D70C9A919A36C03832E4B351A24254957E779B3CD232BE3C0434F57B4CE9A667787864C85169FE0B6DA49092086AEC96126ACDE7AD171E9CDD02B8848BF43C69414F1BEA4F0D267B5F9D238A874EB2A7E041D4F778A21A7DE17F0C7D111A28E2AF42B8A32D94AD55BDBD4F00AA8FADEC6EDF890B97A2DBEB5559E09F084DD8E63BA0ACAB30B84508B1E357B28FFE6278E29D619CD9EAC357156939C486537E0ECA9B59B6C8FFE287B5C8E52033EADCE1A67D6B43CA7ADDFE3D7EC4E507A976359B44D91043EBA629C5F4217F5D0FDA7DBB72B31E466426B677AF7840CB26C1618AF39CCAB675B3CA619773636942E46F142B37C5E66CDC758B24EFE6C283F633115BB225537E78261BC033CE1C23CCE79F61C855C5BFD3D34DD775B4D673177EC45F926B3BBA6DCE950433C6148762E549B7F4F9D0238916B134859D5E03F2DA79E1C70D8B499D61C9670D244DACB88E52F9CCCE1BCF39567B068B5B5129EB9DAD518C238EC37D444D97E0E39A0D18BA2E248EE884E289B213C11F4A66B835D95D7100EDC71B13497D9F5AA8563A61D9E9EE0936ED4AE077E83AFA73B01861C57DE32D6851EAA497EBC0F0080D6DAD7933C161386F57F117576AFEFF228AE231D4EB7D157E24EDDD0225DA8BB685CD66A12B58F1B3FE9DE2441C6C49DABE687B63973038CF208E4F072E0F880E3E898E7A52A17E9520CF197B8843FBC931A53E83F5E6E61095F01D6DF16C2B5AE77D9EDE295D6C338A19A882FDD0216F69A2E558448CF935767280CBF26C6DBB103B280DF21F8DEFD3E589BDD6A338FC1C198E9EA72D582580EA1C2B6B0307625EE3A00AE6592E5B2449011A13329FE426DB7A14B6829F4C8718B041A42A5151589B1ADCA4F51094B31CFA805DF9430A81F112E9BBFF20F11F449334DECE4FCD8DBE40FF824F716DBC251E3832979A7A670E762F2ED5CFB604DD58ABD312CF5EC75D13A8BD36237A3280AB3E1DD3B4C795D7EADF4AEDBAE1C8D53EF182E40F4D520B1322AE144815B940956BFACDA7F08EFA18D5E99E36781120F9BD67C5C2B6504408E06435AF7368218A6604230DFAB8A4A2E961FDD87F89E0CF87390D9DB7C06EAA69703B7270AF4E48D8FCD6A7A159B839183F1B1A41E28809226743F806E429602A9A192F3373CB0D8EBB5C2FC98BAFE53B5B6A962C8C3B0AD762B31A45DD07FF5B9CD10F40BD9755FC2E3A29CBA389524E233E9F6FAA7AAFCB091E7271FFA93450CB74506CF3306608947970192D836B84F5562C4DCE8B2AF78EDD0209492EC23ECEBEF93E32F856A95E7F64E81147A195CDC42082B212A2C1540EB2922D898625CBC18A2263B3F7502AAD4544335352C283FC00638039117C2E0CB3C5579AB70E27907227969E7EC251758E4678591E19F51B8E7C37146B02C057743AEE2C3F544D9200D4E7D188F8591E81C6A702CEC51B0BB6AE0B60DC4DEC2166058B90F69C97EF7E08E299387C132534542589F392418B4C0E520EDFF7167A7B6AE441033DCA18BE8EC9653348BEB93649062483A31F96D03EB6F6FF3F3ABE9BE0DC3DD86907E314891C7C9777487EB2D1F3ABEE929821B4A94B573C653762519978C020752033AF33D10DD99BA1FF244ABD865F80FCE789759C9D4AA9B6336645DC3F3D0E43E4CD692541476B796DCB2EC1A071CB00E5A07CA1BCABB6664D80B395EFBE612FC5AD11D67B22D287F23D6E3BB5B5E925487EBE5087BBABE982BC50631465FDFBC91374F6EA5C68EE06F52547CABF5D9561BD238A6CF4ED27423D3F84A90F4251337DC5872887BBCC4F69456B5F8673FB43F3F2C945EFE936B2E8D8B5D8730F897B88588C72403FBAFC1367EACF803D07073363803C202060ADAB4046D233C5C9C9893E9C59A5ACD8A07459E7FF4EC751D9E99196791CB05C6955B00E722CD6EDC2323FF7029FC3B2CED405446C781A7F8D62C53A25ACABA27DFD6A074D77DABC0C56F694BD14CACCF59D254254F96126A3FB9A9C7C9105918393CA2BBA58C6D0B163559594F04332FBB35D2CF03980DEBB247FD21CBB876EB0B633830E5C81A8BEFCD09860062E7AC27711ABEA7DA0CB8394AB8F469FDBF52158FA385AFA8FA0770A53AEFB2218BD22DD5A188C00B09672F6AF5FC63DFF338A393C437F05CC8D051948861C53515A346F1F108CDE22924B5A9475263D6F577258125535F241732E082908FFFC4A27BCFBAACDD3621B695A84C75873EEAA2EF0BBAD942DE3DD9FC1227322E0541E7BAD9F095A679FA2B8558CE883E528A50E14CE470054EC4F35E2148E9A517500375571C315AAF83565F9AF9DB549D127721916629807991E72C5729F9F39C0AEAC6F3F905C640467D79BB9DDDCA4802D69BC0014D70829711DFFF6517C0E4A5415AEF15A1B014E3688BFD2BD9C579F37BE340F9ED7591142987EF384C957C9831217E155C3FFA211BD21F96051BBC1900834191DCBEBF48F620169644FC034875AD337CC2D9C6EC6448186DE6D803AFA844750E240A6E8B976A9D7F23FAC6A770FA462758E818C1577260E2F17C0640189824F7C2A02B857C01ADD3B460AE572F898B390B1DECB54E9DE6631F797DC6218836E3B821DF9315EDB1FF63201DD01D0DC9CEA0C3E0CAEF9AC7FD1ED9FCB4977F54B9A85B01377CD0AE234D1253E129375FAAE6F5252A6CD80CEBF2EC92F3461F1568D9EB21FC0DA4D9CAFD5F384085442523B7E188117916B469DFE2ABBE62FE8CD24143BEDE463999779ED99C9DBDE40D40047ECDC2F82D996A3ED29DB07E9ED78E534D84710CFC8C159797E88A2449F3383C0ADEA9BB6F7CB67EDD7AE34631F8917778B2FE833954789FC2353C6FFC5B950E08439EAD668C02E85C3FDFE79E79FE73C21CB076CC39D50B61140C8CF95FD9A4B8590BF5CAE30E5D525F82BC742921A4F9FC47C602C310FB9A4C4EEC0C7AD2AB6D4142772BCC73576F3A429EC5A0A32929513525C506C11C3102704EBE5FD296E60883ACB621DF0F97498392F7897C8AA78B80931AF167B9C2CEC2659671A40C84F0447DA3CC616319E1A65D28B9394DCD018BEF29BBD281E4461AF26FFD7F8D5B5A022FEA64F54E8D0B5AEAF2D18C9FC08061D2C4E4BAB4BB0B9D9636F2F83F39F3821E10CDA89286F759E0AD68EF0E926228D1213BFC1B0951E20E171DF818CD8BD5BA11837BA211CEEBD2DC6D4FB567D99314F2EED08B8C8E41847FE1A876D9902D49A1DC869B6B8CEBD341BD6BC30BAB53C85ACB37352725FF7D17F80ADC47B98FC71A2449265DCAD971F0370B2CBC96EE6EE1384724FF43F257B335832D328E3540AEC3ACCCD21854F742C437B3FA26E4DC8D41CFF55EB19FEB608E95148672CF4010BE5F21F3227A8374141CF55F29873152758DBBE7185628070CDCFFC931DFAF224EEB2D75E0BB7D5964B6D081992353D30C995AB503E99EB24229C0E11C612043A8B984DB2987DBB334D9FB8B8ADE7BCF99A00988E4B2C1745FADA3C82E62141005E48DD7448B4E524D8F640BF200354613548CE36D4936856FA6B053D8EE9AEA418812E6CEF0688741D89BBFE6D70CBFC6101BE9CB10F610C018F4F8F8A8900B09DBE68183A3E281550294DC90583F8F5081AC03D97B809CC7213713CDFB4E13A80E1083A49EACBA9C0EFBDC5B22CD42EE9095660D81F22EE098125C2B089EAE5ADD4EF481648706506FD4907405473B0F55C1797D4C9FFDC5727D108B7FD19E96B4485ED12830828BEDC2996E4032F9F572B3B1A64EBC7ED00B20061778A3EDB505B0C416BC168733BD1184C4DFA0776893B7CFA453EF3F62E9768A0930A164CFA4535A3D733B42113F12562099707849461A7FE321EFA719F2F45D8D5776F29A9C816C167091373496838E3FFC848602E553589DF360862448F4B424CC75AB360104B940CF411133E64C85EC0D45B2B0FED8CB596D3721A6277D51A702B0A8545FF6ADBC337AD9DEBC9D38007B03803515C28BE42D8FB510CC4DBDEDC67C20ECC7B68500E6ED67E0922932C53DBD4BAAACFEA18536890746D5ACA2B84A4A7E02D0E66AA4EC734F4D33C3CD96DD56BDDB83D29BAA186B9A0ADEA51A17B5949C111C95C73119D92A64CF0057514797B6161A1B8A1989A7084BE1967376AACEB3ED91573C581390DA3D876AFA2EB6F0D80C16E8A73879761292A348AC600B14849A27277F513E0C6DFBD9F5F1F7EE97C3270E2DF59F22A136C926B94EA8E72A41AB69DDD3C59F6C37E2B40EC6FAB32296C9F3365F48EB1D3E20D360EB9597BB2177D6EDF0FDBE2AA09883EED589CFDB310DDAFF0A89F1D692AB7AF4E0ABDAA5973914089E2A3566016960F98092DB41B3AC56FF29F6FB36DCA71E0D8B4BD40DF620836E0A2B4CC9A50F22A0EE31DA298E6DD074FBED47E2D2F7042D5462B225701B0EA079BE099C6B9FCFF52AC18459E18C56CD47C8BD741A1753B2082EE2D209F940C327301F4BDC179525F332090285757FFB5ABE00C83B4C69884FB910357D0723E7FCD38AC5CEC4B515DC0BD111F88AD3A68EE7AA653BF0A9C4AB6960DDD163318042507F2084FFD8F8B6A34D02FAC80DF5DAA598D6A8472D34C1F8FE9D800E2FFBDBA1FF5BDD8D96D9FAF181D5B14715296DC91BB4760455BF8917D5806010B3290F41B94D7F7D333BAD142C0A0671C05F61BDA6363D12E538ADDBE7014AD95F43300763B12138369F1A35963316650A1334F36B13D3EE956DCC5CC7E6CAD728172260BB12D654A834CC95BBF92BFC3AD43AFB610CF12F424E0D91BB870DEFD06500F1C36A89708F23EC2FC6AC09B215B6346BEA6FDD908C928500949AFA303CC3F5E528C665DB3793652FA981876BDB9FAE58AFC9A5D8AB02D4089C04214F986D78441ADC4FEFAC5FCA22CCA07FFD496D7A4E4BB57ED7EE292AF1785BCDC8A4A0960E45515029960DBE109785806BD511048813A6DB507B914D403313A9CFB389DA42B2424F69332F664D56102D5AE8523090B95A122C8491AE9D50294F822525C19D56DC133359B653A03032BAEAEC1D491054DF2C2B48C8B26B2237DC5F503E7AEA53928F25CC9E8E12E3E07A9BDB25FA56D222F13EEEDDD32F1E299B33FE17C26366F7A9AF4F36CB2890735C287CBDFFB481C9F9E512137B575A694C106D15C5337EE9FD2A5A75C75136AC715C3DE3B0D4AFC90F0B2351436D675760B54751A6B7737D60126CCDA1CE0D856F32ED4E12B6C6C6087E067648AA1343D6185110DB6649BFBC6C7D27A8C6F379BC513E096AB6D3996CA197E061F830D7563CB4BD2D132D2693FEB3A64A4D63BB03245EC48A122327352CCD190D4451490BD2168C52BD85135A35225C82D85170B881F380CB2E0FBCA8E26F7E4FB447D2160F88C02C894D26893FC893AAC48D02D3CDE3D92FCD18BDFD541E4F37721C8817BCC01C95C37B4B82F22C71574B0C1BAAB94FA4E770D55CB9DBE2EA9FECF4C46FF6BF638D0FC2443BCCDC96EFAC4C46890F309B9A7752A664537AD8BE35C8F9B7839881CE31A560D476E3451D3395839C0CC06B4C46AB2859456182BC59F378056303B12EA74A273AF015EC4EB5E71FCB53C421B0B822779F66294B6BDD0E9B49CADA37679E0F396DD991A373EE72E1CBE65AE3F1504C2BE652B3FC41E207C9ED1083E723C9077E4E76E24C753D2FC8327B58D6DB734C99F64DC0EF14B343151F47C5E16684FB1C758ECA2B9FE957954A4EE8B955A4997566C65F7094B2ACC67EB487C430D0DC58C9D0D39B288003626D5DE1304048073E38DAA3FC2975FED9C632AB459FD861C45A3C9DC80E8DC42415E61D7984C34D35FE3E2507CEDB91198CFC6C012C1457C954CADF6662A661AD2075ED600406208435FB510CC6F27110B6973789F3EF0AC63E85B390316DD39E8954B057EF945A20414EF802F27E04337701C3FBEB0E0155774F64C37D444CFA4331EDE00F0FF52D180CC499ED3BFC330CDAFC53712FCEA9868E2D35164D001901EB4A1FD8A31249C1843F79FCC301E06448E5947876DF71BE400D29C7CC9432D2842A8DDE8199E65294EE73B6DE4E4B29A415381A9AA6106B6845439E9A41A1FBFD5057B014B626989E6D91C56ADDBEE26E187DA506D89B5003302BFBCF2D96E1359171FAA29132CCBAC9FCAB467B9852E33C1D77AD361129EB9F0B80CDDCB9EFD99A31C2D1F13620A38C3CF0353E805C7E359A1A4449A00C745F21271BE22352DA1401333ED57EC615916DBD51A1FB7371CDFD5119B784D7F53F3D7BC6A968FB9C197B501D963A953810E358FA173D0C8A866AF72D8E1B4F885BDB367D4551328F2F68BD7F55B169D158E574964254DF5616A7C29CB91703F3AE429BD6A7DF188F099EA9675E872D0EBFBD55C4CEC6056F65CB8C407B4F52B127C8A724D5E064BFCA5FDF0150DFA22A877A0E6BCFE3DC7FE324ED8E90213964935EE8BE2E32F92C6A55D6BAB866A59246F9D83463A140D25E1A89FA470576CB5B8900BE89B32FB49E5BA2E7DE5A79EEFB4BD3F31C1798A0FDC94006F01DD3ACF544565310157614A3D9A470CB09E9FD066564E97CAE572035E320A478258AE92567305123B17049B5D374C3C39F87BC7526887AD698E87986DD121BCBB1D18CDCD8CEC95019B572F0768A37553CE0FDE82936C4030F70D70CEEFA49D33BF7B31AA2D340F2CC8117D5751875C7CD22E2281270B326E79605318FC454B13B9435067214C9898885E39D71757F0F0281A1AD3BE8CD171BF4D318358E9C33AA30161CD6D608FFBE49989E89DF7E9D5F593C5ADB9BAFE5C7D9513AE9A011A50A574918EA4A58CEDC5EE4ABB3213DCE697DF53ADF722EBA11CE2B8DDC0B3C098AAA6C8E34D705D4B3A6AD9B65BBDD3D277A55CC69BD1CD1E7B36E4559CB650E12D6F30975437B36DCF5F871A9C021004E9BF10F1F4E1007F087F336D16C2CAAE9E70CF55F97162798FA564E9FAA133A43AD94DF02172A140E962338C1D8E92556CDA39C4C8C415C3B8C7276EC82AC92A5CC567F9F27ADD90A7BC5D578A9FBD26269D4CBB020B293122059CFCA7D0C2B80A4FB565D1F425DD1BBE542DB99382B5C9670B17CDB5C83D70FA665C78B34B3004CAA3BFFAF820B647FA5D57C33E3F0D550BC5097E6CE418EDCEBCF69A330A116CE4EA3CE25CE5F549AA66F7E4EDFF8093706546B498BE852FE6949D624805D74F37017299F371E627D57512DFEE176C6682C90E9CCD01ECEAF527378BD2F72079DF684377B20288CD8D06CF2DB638589DC18D24E05EC49FAE2590F235A961F4FA5B55BE8912BDBDCA4891B22348C29B0C4D11E46B0D2B37955C24FA00667BE5764BC1CA92CF45467B18B79F9DDF3E2743001386B103DCABF7590446413B743FD0A424290099A91A75582C7966D4CCAC4D2A5E569007C96629F8713C8D8953477682D74853C14AE1BEF1CF91773FEE1FB8078A837F79C9D31C002D2B2BDC83A7D65A4E4A3785C2D198E4C0178BE7EA786A19542EFBD48295F0BA34A4437A0EDF2EF860E45CD328A5989BEFBF8F714D03047E5EECA1775AF685DAEBEA66A6A8DA1B5D61BBB1FB9D8ACA5CF434A94D526C21E1758678602F45F04CF7EC94D805B724800C4B2E1CFAD4AC97CE59D1B1962714FC2AD4454C4CC636FC0BDAE05AFCAC8935F9B9A8D4CA8CD51451003893BD7ECAF00D6BE8CA0509B2A72B76C57CD93D5D14A8700F023935821EF1AA36FBD3769809041EEAF487F0E60C45A5D8BC597344A662AB1AB56892249643528B3F497E6F83240924C6A017A63ADA5601327743A9591CE234309033830549766F37CAA6D396C326BBDBDBEC7BD73BA7BC9145AA978C41A068FC5563BDA0844DBA8F5DD1B9A1351F683F9B93A9EC631F03C9CCF620AC43D0F69BA60A0BBBD0173942E6F363D14735593AB746964B8946E30FB119BDB18DD31DE96A8825BEDB4F5109A205ACB033B0720CDCED54C901277BAF1A71FEAD21ED4F36289907C7DA66C6C2913131C81C49E6D213B2FC3932C4083661D323DDCF9A9CFAE863CB9B0FD6E7F53021A04B5AA051970645B614DEDE96145EF9C738162BECC81533229687FE812AB683FB7EBFF7E1FE1C6CED680277948455E852082257C9788106CFFF50F24B1DA29350B8FB103D5989BEB89631D524E446670419F5D505D528AFC93A5220283CE25538E251FAA353A4982747B3EB7E010F48D1ACC5E22787DA783E1431B71186A2CD48A1AFE617F8FD420B12D082870BF055800AB078F5D8086545CD04BD389A9F07CC0400812A0193E9EFC3EDBDE4530590F720C7DEFBC1C275A7B8D938A0D0DBAAC530EF1A6992782AD35EADF249C64E040C8D67C32E57110B4689359AC65A3C424285B72F5BC22A05530D99D3E849DD61198AEA7FCDC0AB73F6E0DE5AB36CC2BF321A7BDAD60813C5C6C2ACBA0206D19E1520528C9B60BDEB09CC8B32F528A0AE8589FC89FB1109451923EFB28E786DDB03599BB79F5A52A0F567EFDAC59E31C298342A412C8E86426B81630A7D816E0B7F356DF36FF307A1EE641CF691CFB2020B712531298CC021A9B917A0234ED8A96F4C4652FF8CF6C7A17EFE909E687FEFCDE08EAB26E830DE0601F4C66DB23AEA9E75F4A844D8641F4A3EC19590A45474A4B13371C9BF494B4695246D05A70DA89BFF36CDD103E97BE0A52E16C252D5037619AFC8A05FE25986F82E3E505E03F3E0B5335E8CADE901F82107ED93AA2AE52D992989CF40667569A450746F7D6FF0811FF13ABF96C7F6B27760E4D3BE734C9F6A6A0E71B1D581611F9C7138C9039FF83C70F19B02A57FE6C60138A466E78A9EBB1AD54EF420FA18C20733DCC3F44249240E0B36B010058287F3D3EA90CBA5FBD49FB05EC3A39FE635B462170475CAAAC7E0B02C2B9E891566230EE6178FA84AFD16F0CA835045F11578DB053C0AFEA7FC8C102428BE756CAC60FC094181E34C098655211E71A9DC68CD3B4325E30764646729FD247BDD4880744D94133DC61CA8A903F47B9728DAD143DBEEBC190319AEA3D72978A771647645633A5F977BB0ADDDCFAA331BFCBF0F05FA5DC1FB7D194B8B5BD73F16F5817408315F3A47B0F01EB0B5B4FF55106B68064CC93A5E26CD473402E79F3976A20DC5E937843595BCA3F9F2B37664F3FC29A64B5A5E3EB2F874B662AAC166CA2E64EE84F19933C07326B7FB9E27AEA72C8E11031FEC36B72B7F1043EE0BC987E7684CB534376E2C5DCBDDF87118E56540B9134DD324105CEC255655C72A259EDF55BF3264BA694557503106631B5A9F6BB10EE430FF12D0DEAE593495A07E9983F5D2613FD7E505151E957AF491DCF8E517E57E8983FA6A962326DF00E7F38681166D0C354514E8FB0593EE31CAE6C179707B2069A6293720C22274235AB5159768FFA35D48C6F8119D32E94F9294DC59D16FAF68CAF1D628BC773C3EA3FC0D42F7140B7D3E1E721CEDAE83F73BE40AD315F958D6784DB5267C40274DB395B8174C7AD82C75798A9835A85D58FA96FBA5945CDE1E4AAC85A8D2BD1574328BAF374757C7A75C5D6E3A594AFE3ACBD2BACC1B7149C37C65272336E5ECBEF8D7E6C0551DA46BEAE3BCB9BC2472C0FC8A0A844A736CE621199B66EC0C6C17CD577F8C07A7698E44E00E517E0DFBDCA5F9D5B965E850BF7BFBCFAB7DDCC61F9EF06EA0AA1F32E927F76778BB063053B61ED611623BAD8F17BCBF44C847B9E6DC60ECF7BD1DE4651971F92545AAB867F455E84E61FAE02167726F70C25E52EEE61AC35AFDD14386F5E5965C76883FCC68A9360B4266FAF48B680365F271CC31AD9C742AC33BAF7CEF0034C4C36D36A8D30A1767DC9226288BE4A12003BF8CC039EA362FBE5A0B0D942D1CDB34688264FE9F93EC1E7C4CE5CA09D3D9CEA7E14D3643A40292E7AEFDA6DBDDA784473B39F09623F7C023072DF241EC8FF5A072005CC4D5AC21EFEE12A95F52A180F20118D3967A4F1312F64830658EB323B88B1FC742AF00E3410155E7C3FB0804736B64F2BFB823443198EC553932CFD90587A3CAF7F78193137BB63B1C8A109C976AA925FD8E4EF4819ADC65336AA3FA25A02C29DB97E5A574F5D23CACE733A3CE2E8063F52D362955A0C190D7B75D8F8235FC317CB24E38ED0A83350C1E78239EB8F15D553C74C98C9B028B9C367E53DB1939B2FC316F0081B16866E52807BFC53D6992B979E6981A43EC3F15BEED39FBAEBFF1C922DD6013967CFBD9CA39C5F2F407AADA075E8ED6B58A68C04B553C75738C419677121D9EEBDAB829080626C907A533567293259263A457568F466A357A4BAF58601CA0E5B24638A71A113C156EFD26AC059812F9BB47062B2D55D102E6724DDC7FDDB6724F30A4166E63154AA64BD20390266A7BD3EB236CD3571B6AE13295BB5CDF44D10C07C6813C48CCBC49FD99BC6370E572B2AF209EEFE12AC12AE93C9BAEB9287090FC1DEF5144DD409B59822303917FA4D06EA158FFC5D8200D72A84C463B5F7E5D47D41988F29D9366A80B4FC45A58AD56290F903861423F7A9C329AA8E1EC521514E8D0C4C9082CA77F37D34798B5DB4ECB7ABBDE5D438C340080D32AB449DF1D9068623D12AEAB56C0E24622C149DA71A4E52D0105432A5E4D6ED31D9F4E7A5EB1A468605DFF1E8B5A83671E90E8B40C936D807E327A3D84C35C7C35347EFFC3F18C0C4328C12133C95C5FE880A6870F917242DDCB6BD27680678C924B157F8A78C1BFFF30AF86243E2118B7FA8A2323BE9A2D5D8974A8C9F1D97A5D4DF0BF19A406B822F49C8DDFE258F15BDEE1B29A71D06B1158CE95FAD7E24138C9719AAD97127230B49FE6A26AED3D509026897270F4977657984EC455FB43C1E8407174FE8637CA63C664BB63D8FFAD1D2E12FC870E26721F0DABA1877313AC7D0B4408086EDCC915134FB34DF0D60FC3A9AE22D4355571FCB5AC8A88E335A1588990B0262086A978FB33374BD4D8C7342840BECACC03189A03057A0200C989B96010E2381DA2C5DA69441C0F2EBEC472F5B03F48ED10E8DE1E15B454B50B6A173743BDBDC5405CDC09B71E8637ACBFBFC36913D34B828496D6DA1694B7C73777947EC0E33968412B59BA760D10C45DFAEE54DD13201C22C1CFDE310911204C8EFA5F1D6F5787AA5BDC4C34CCC4A23C6A3DB4622302749793220FD1B0F7E1B56428221165D7323A5F42BDE49A9ABF0866A516A99C6FC44603CD25DAC94DB846D219B54C854228BAF838E195255583EF4E4AF543BC0A638220A9D80912DF0111A616946988579B6B598FE2F8634B90AD7F0177BEA185EE8E67A64D345430EAE0ECF860B8ABC1D29E6368AEBE6675A87299D359BFCFDD9082173035A94FB32E7C637CC315320F313364014BFE0F82D7C007AC54F56D994813052CF9B1FEF28B10B44CA1AF23067490D7AFBE34B8BC5C2CC27B894F8F83504C4F0CFACD59FE75A374CFC694EDF3069E
FLASH SEI DATA : 06 01 07 00001200000804 0411B500314741393403C2FFFC8080FD8080FF80
EXO:             06 01 07 00001200000004 0411B500314741393403C2FFFC8080FD8080FF8000000080FD8080FF8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
------------------------
Sample2:
FLASH PES HOLDING SEI DATA :0000000109500000000106010700001400000300040411B500314741393403C2FFFC8080FD8080FF8000000001019E0824B908FF557DABF48CC1563752F54064A0573932812AB3CFFA7AB214C4FB4C295941873E775C26179FCFA598F921F30EB5966371BDA7F5DEA677EAEE6590B58461C96E0410FC876EF4B18A78408DFB19C6A37697F25CF8175CBA3108D21D1387BCCEC59A024573F4613379DE849782A79E101323F9AE1B6247231692EB7799A496746469D3391609A388E5E32E74B1ACC415FD711922792BA1950F9F04B22CA3D8FE3EF9F00A14D83E2A85F3DE1B7B394300DF22003F3A72F94894931B9D3A3461988ADD90EDF10EBCC9D48D9166966CD5A340AF1BD9F81F589BAD4E62E14FFFF7817AE0D73166C751B2D223B1E6E6E7D873982030E1710448BB1A4AF83F81B311330E031822474BF49FF9EE6F9FEE0240D1B8B9F4571B044D3638D16B8E45B2A95788DE8CBE0C061AB3EB32A8A0288F0A840924FFE1A1076DBD73D5FEC07E159F66AFACD180A644BED777E67A2968B565D2578DEAB28DDA3D1F356F21FA0D0894229E9983B50CE70F44E6AAC310FF8E8D2AD1F7825CD59E81D10B5CC6251DD6FFB1CC894DE3A07EA23B753BA19BAB35E752320ED8A15DB5FFDE8DE6FCC180EB0C57C4D629B94BB1D4B3B898A01AF0FE5743AB49814A53AEED9AB851885B7F80EF28818D39DEA05E80EC8F8D4240F6B3D0DFFAE1CB993622093D3BC347A4D9D4C81909AD47E2E228BE42727412A9187E201F14646055E789CBE2FF5E280D262913EB701E651AD1C61C336A25F43F51BF7FB9EB261CD7B4A6C5A3C409CFDC0686F76AF21B3FFBCB11E529AD9C99B53A11DBC0E397D5E70CC4390E4F81810C36B9A7AE7D1BF9D15C661D75A5A0E95ADC6AA14012FED853A820499B451B6015C3D657FB9B263B86043964104D2BBD90C11D1B8B7F7893FCFC909FAEF5B0F480356FB5846270B006952F59B16090B495EB3717F31A363965A63E4CF04FB5AEBECAB67D20893768AA6477216EB8BA42DD0252A781A22D954FA6313B14952F986678165C90085FFAF31EF77B86284F260E90354C5F11E187B157A394D312063857F0F55B0A07C2B5F934302E1A1E1DD82D66536854AC8AFFFD522F3C681BF2E3A532390DFD2F6C0D9DD41DA56B9990C557595EDD9B11C1F961CD44181373FD90496B927B4AC82ADB677F945BEE866E02C6DDCCED269372377F4BCF0793FA9AF230B4D359EBD372E10B43A1EB6F4E1B5B4F16C8EC371FD83333DE689953E0BC0FE90EA2A0E908904F94FA50A32E2CC10B8AB734EE01C7F09F37B8042E65B0C152E6600551E46805E3631E8923B032604EFF451F3692FFF2E9063072BBEEA2EB807AC0DB4BE30A107653C5F1865A00D877E3A702EF5FFDCC2B58C2EBF409A55814375898F460EE99B1D51D86B632D6835E0C8F1D562766E13FBB3745CDFCF627C4D3441C9E318871F8935A7B110EBD791A0833A76CBEE12905729976BE4052620684341B68013AA4B34C15D3B56AB306DD7E949599D5AE4DD760E475032970016046E8EB2BC2FD91EE0F3C04425E1C4EB84F92DFB5FB0278DB24C9F275678F83756AF3C18FC5C78192DDAD322C66A7935D428768623EF4116CD7CFF907C480FF310DD871D5FA05C4D084CFBB1462F0A9998F2B5C36A486DC9E28DC7347BFD53E896899F2C7054AD98B0BD98110BC976824D31119C329CB67BD5BCF0A8A2D6A1D372235139B5A370927397E92DE0856BAAC46CE89179498892B5B188B5CF5D721AEA91DD0F3D8126AFF9D366CAC7457096FEC56AF01B09198BBD9FE929BA860BBD705C811296C40395B854AE27085C043651624AAB807834AFFA001771B012F4FE65E885DF6DE50EA29F749463CF0A2E413B0FF8DCCD7DEBDE4D8B0ACBF200A6583C1D2B6DABE0ADE4869E6940421CF6FBE71B5A2C342BBE1EC43512EB6FF7810145706CA48C2D9B03D6E43E0ECBE42A9F68F9F108AA84D880846FE6A90BB45D5FEF9C38FC8EE344FD748CAC5A2925B63C75BB7144354192B69B7576345330F442DB16F3F5DC37F77ED208257CA30D07005B7FBB6B36FB5F7C1C7073C67AAB121E28C52C6B00EFC41DCB9365099237B34372589BD0CFC986D688164EE8039EA81FF12097D48B2DEBDB885EE36A6C86B22A2555B120FA17FEEA72406B3FF9116ACEA7EE7E006A3B9436409E6C29ACF77BDCB126CE365F0C2E631F51B6D1833ABD21A436058A1C208440677110BADFA9F1C572138597F673D09172E9692E87C03471B3E65E84AFF36825E0334D137AF417DA216F51F4193B7AD966EF86201177A897500CCDC66B1B98D8717F0F0353C0EEACE1A36D12A2CA29AC0E0B8D4618BD961D09F24A54CD7C7D45B510A303916D592BC678F1AB2D0A3E333E787C3BCB9C84DA4FAB7568FA27894071EFD5D388F7BC673A47C8A3E6767DDCD8BE7A732520B088A509A1B3819FDB9B1E38CF7325E59CF3D0E516F240C844C2C630780A08EC85FEBEA47289EAEEC171C23FEE16322EBD9EA690885D7C154DEBDFDBF910FED0766E93F691BBFA7CE2B686091BDDA736889612DB0EC1C094C1E06A31D8152921007EE532A3498BE034B33DCB5325D247B47F6C75E034BCE3D182254E30C3ACA1109AD5992A939E9B84166E95F8635A9FD067815795079FFAEE69C4DC74707E7D731E956FC2A24D0ED6230063B4492FC4446F8B9CE0E500CB1B222CF27D05194A85CB04D17269D6C531B51BE2A9DF5D67B2B9049FFC0A2FD2173C979C1B6E7869663656ABFF686C0D8EA79A8A562128607F1AFAC2DD7A7F4D825BC2C7F29723BA111052C927282969D8BFE92C54F86C3EEEEB53774D179A6BA2ADFE4C765F94D13A92795E70C45B76F06C01EAB1B8081BD2F922941B9A9FD5145E93135EE5440FDAE222C0909A365E5D79F64852CEA550E183F619984FC9D670FE67562738497FB224612EB666585CABF95AE85C5220380DD5019895B3A0922501773DA94525CDFF13F8239D53543F6845673A5F025EBE3C097232390517595958C8C6EAF58C4EC466DB860860CF99E40FF55C5C0C91B554F5EF387F8DC8E84B41AB2DC7BAB6324752703D7775BCF73D18842DA43F4AC6923DD52C9B7D6518BF2FBD154369448D3B0464342463F8E74976E464B531B6D4671A580F9B357131CC6F377049E6CDC84F576B166E1A1C5D19A2C8BCF1C8F022DE109B1D32D3054B4C26B1061B3C1EC5418CD50D097649B5E525247D91CD03B56C97AE4BBCCC997C9E3DF5C807A31C7DF85B0155FED159771A070EB33BCC11FBDCD1423595F6EF4DBFF3CA9DA01CD64E90D1312C8AD86226FAC8688B561C6212653FF32F2C0B82188448A187B2DBB553CB129236988D2E6DAC3DC2F23385692925579ACED757A12DE811F69ACFF8B889CF8694E5E286C43877E09BD7DFB39F1FB9FF85844D0D0AFDF8E27A1B4ABB1C1A943F218F69A1F47AE828EA39DC21E61A069B3E6BD4638022C0882A16BABDB77DF1282553EBD46ACD4120E7907BAF301B715A1C334E4A3044B6DACCD6B359DE6E0D1534C9FAD3F59E3A564635BF2D9D06A9EED7708B8FE48646FA21640DB3E0EC1A40E5B678AAB5C1B3A6F9AD712A02E6BAC57FD0BE86F8B6336609CD085CBFB1BE36FFBD114C6B86AD2E86BEF932C4D1B362AE5FFFC41C25DB4578B97E9336D6649199946BDCFDCF870
FLASH SEI DATA : 06 01 07 0000140000030004 0411B500314741393403C2FFFC8080FD8080FF80
EXO:             06 01 07 00001400000004   0411B500314741393403C2FFFC8080FD8080FF8000000080FD8080FF8000000000000000000000000000000000000000000
------------------------
Sample 3:
FLASH PES HOLDING SEI DATA :0000000109500000000106010700001600000300040411B500314741393403C2FFFC8080FD8080FF8000000001019E0828B908FF558958B4AF1E2AF753583E00FD47D3C3C3D6D75BAB688B054E3E56C7E79525E038EEC8B906220143458547163076FF385DE7419AA00CA314648114D284E72C090995563A90E9F4B44E729DB71B82817184C1FF028C95C287EDD4537C9FCAC88C4529FDA99124D178B5E0EA4F053925A4DF5D036D83C0E94A525E078942131AF15DAECB05275F0292C14ACED391F5B06C1270C3E369CA9DE2A7FEA60A4382B23B9DF51D21C3E897C62BF04545B87A4AF6906325C62AAA0BBCD275581645364EAA32B5E132363F0F7ED05A15212929B4CBF7DCF4B7127B0A590FB7C2B4589E5F6429894318CDD38172F787413B5E7E56827B7100A9C77C14C7DA7DED9171C2F9D9816C23A6EC0802F40337E5F02DD1453845ADC8FBBCA1009DA6A46285C83B84E9122C21397113067922AE09E0ABB9CAFC43DC69C1760AF08D0D18FFDA16639343FDD84DA953396B824AA6AEFAEFC40202D858C19E3953FF24574636D3035493FD08910AC01644C4031A26889BD8F77EC79AFAA1DD694B2610790E2C6B5864F31976414FFC31DA1CBF93DBD87B27E1868A51D53BD5291A123FF0B20C9656343DF62782FC34D69F6A3C87136AE16F3E795D3CDB99E54BFE83F2A7C69B7D9EF0EE1AC55E110EBEB1854BB169168345122FD5A24911EE96F7B9F66841ACBCBD5EB93F2987573CCA14D73B096CA4693D6A95FB3E5E1C7C7D22B941513D938937B5A67367E514EB469AACC4A6FBCC0E99D70504BF27B1747C6F4CC100A11034D335E23E9D73FA52F963BE54CCD320C3187123FBAEBA0D0C45E0696B08B71D29802F11586D0FC0EC0C2CCFD62B9CBD1E11134916643DD0FC251A25645CECED6643712C0BFF38085DD60F2E6C275BA8DA9A40F84C4F68236BA2724ADE8354EF49482BC07A51F70A26B31C349D877BF239C1C57C16ECF21328C0E3D2CD2B71F18552DF3578CD15A800DB843792ECDDDEDE1E6B357493D15F2B47B67705F53949F91EA313998828324EE858776A335B2C74E1E3C6EDD5F89EAFF47082D314A52E022931AC0E4212CE967ADE11B8D6513EC63E855DE38A32F7C5314EE5B026985F8899E630B3924DD1716F99DE7D1C8C7D91F0CF287A19E425E5E3557CF65664857E51F51766D60C9D6851F8FE171F9039A2F3D59F37A07350E101F5104ED4767B506821D3F3638B3682E011872F391E8BA4193720EB14E334466C4D106AF7900E71498AAC036E5F248FB47894231DD60F6D798503B7D7317E6FE43D320E69A23055074C88341D25D6845C2DA32A8E4B8358D2F6E6E2A13B74EF9974EFAAA2FC93E21B16B4FBBF733DE4629FCFAE3DEDC6D29619471318E62CDE7C40092E8497183D046C20BD160EDB419B6FE84A12423C9B03979A9BACC9FA71786EF0E9FCEE9385904D60F2126DC0FBF2EAF251C2A8D886B3669603E079DFE653CA41FF7F71AF3568C6D57DA4F28B5B0AAABBE71A665366F393F4A1AB05DA24827750DF54D9F1D39F96F88CBFF300260E2F8C15FBE5668AFD8A91BD8299C03F42E53198A3DC90694BF8FF9A0449D0666D478401D184E0EDBA740206451142B24F3B7AA9B48D4836AC920B038FCE961EA07C5C141906D05C2F1A385451247FFBBC05C2837FED970B27EF129FAB63B84C23652A346F53625A009D67B55199ACD5EB6626F0C867F4035F9C0B7B6BDEFBC035D8D097A598863CC1AA5DE9B390463EABA4CCEE813AAF4A3842BE7DDEFF6FF6B351F971780198868AB046581088DED968997E9794AE52CB8242CC883922D91EE9937C7DDC125EB2A1B1E8AFB83B3D8FC328D22E3746A0EE962F3B6799AA5F3BB5F31B546DC4B4388576CA9823B0AB5C112579AF1940C1FDFB0453B6384B5DFFAC3DCF87F849BFE0F64FCB628827A2581061734019270411AF35448F6527D1390A535AC4B32635F0D04B46BB82708D9E1DC4102F850B778BA63521C52A683EF23AB787FB740DED9DEF06091B4BE2DEAE3F624C27A964060D1D56F107BA4B4C0A0C2EBA6CAC5D0BA703A2DC2373836515646332D0EEBB4DE4F2BC9D8013D1B6F2FB8AB45B30EEA99F5094E53E0326820E1538182BE2C9B9C8B96041AE44E53C20417633671CA48DD8D77CF5C2C305E315E098A942DE62DCE43C883DD1534D1685E9F8DF9FB48F9B378048967D95AD29C27B062FE57728BDCE586D4E54550A086FFAE1ED76800C2FAD56C4CCAA658F7A38D528FBDFD126A7A7FE36396C9B45E3B8C88A6A557EDD70029D54E6EA1DF795956CCAB71622C76DD5DAF707B301283197CC9FBF57520C515DB312CA46D9F2B52B5E0FD9B59613025442E676FACFBCF5548A2D62FAD92580A5AFF69B75474496FDF803ED0F021ED51ECA907DE044C3AE1368B9891755830BD046195B31A168D7E13B8E3E4F06E9A0FC8E66DF50BFC7374FBC3136D75A1DCFEDFEF24862816F95AF8288320DC1561F78305858348E74CD7B51679E1540AB3A296855F7800BECBF88A8F2297F90860A1FF82EBFF204107610347335E8748C19637909AB9495317A40042C7300E809E86285B4901B7EBEEAF25492EE7051D077E689EFAE6D7DAB34C99EDBB5917D3EDD17C19AB095B45C91D27F42DB1CB2D09CFE8168F099EBBFC3CAC0EF167058FF28C9D240A0CAC6E0E830CB73D80EC179E75306DBBA52DC2A6BD34DCBBF2B4C6B2419A9948729C0CF8CF441FAF0DC9E99040BE0DEDB6FB4CC15A63242FE754FB0F59E2F463BCFC65CFFED8DE07569E91B6CF9A542590EA1EDE4E13D6BF86ECE76817F7AC06457A8AB94C596F433FF4DE5B3653CAACD7FF6D713F9E00F21756752FDA5508D9489D13C05F995F0584608AFB26DEBCC0FC13E5AC441151C0530F21C83389F5B1BB208C7AE9787192CDB94521121C0627C8679757505344AA8C53A9BBEFCDCF5418F3040D829E99AE81C24289A9AE30A994E10305AC329BFADBC6DCD684AA6A747A9334E352AB071F46D3BDE5CFFC9857B8C7E21F76482EC4C2C326CE7EA0E3CF0DFB466A7446109F35FE553475C59D679ABB9299DDC7D271BDB5ED76185E4C1617F96195E36C033DC2F30FAFBD52C6C977F4D9B149C7734E92208095D60277F5ABD617EC6997F5C83C8BB90A7C0623C5415B47980B2D23AA2AAE2CA9CD062BF0A59AB36350048069B2B0D0395FC243891CA1BE41AFB1505BFBD5963CE974043495840DCD5D2747B0C05975C4429A9AA7B82C07051373C8045CE312CB46F3EED8566EFA78184BFA860AA5AABA8F9A24CAD164173631C688DE43A3A710CFD22F3CB154A1F3DF1259201363F20BAB8AC67CF333A64AF3BDBD6300DA462BA35A448E84FBE17F3800C5630FF2BECF557F61F5A849E5CA9CDC694D84A058DCCEBBA908CDFB96AF6624A9C827ACF27808651E73B060B166C797B78BB4883A8BD67928B05FC1C8D453C6EB3DCB62267258CEA44C4B132338374787F8C2D576F409678C5046E0EE3EA0F417CD8962BC62FB3B9D83B45C0BFEE21DAFFAECFB11A149B72DAFCB81DC33356A6C800D656DB8585C9E06AE6A036DDBCCF75D7B55F61409122D6A871C2C3E05BDBFF5469D66E2C00BC3B927FFB1DC6BF9CDD03360A48E901FB6AC3199E2534E9F16BAB18D7E58043EC8F7E69253B223A42E97C1A59F17532FF926C805F03764E6DFC4479B279AAF81A9DF6D4ADC7CDF612C29D6B6FF92CEFF60A6EC63ED9F49DC01DC0E39039D90C3C997899A86319F8FA0FB2A690605F0691199B8840E203E076996A602703F84BA47F6C4F2690A9A2B109BEE89CB19A49FB67557601BDD4E28E9233E53644BB9CEB78F7112FF1D4DF4394406DC4BFB74E4DEDE36ADF7A4A939B0C3B968670259AC985B7E15FF5B70262CFBAC079388DF732BB09F99063950A93C08F5571E7F72E2F3D21BD7E7C3224DED91DBFADEBA43D8E3EC95140BA326B6A6E5B638AC9069973E99A456ECB1BD0B0A2144B364C2B613BF4B6D4434BC3C2872AD6E7ACF58C1FC1D1B6CC806AD5FCB8E704F769CFAEE2115F5CF1E71FD0AAB43D53696D7FDD779266E7CCD57B6EAE67A76F7F361E94B5A5E1505BF6293FE36210DA3147FE5705CD630FA9EC0E1EBE940D36950EF7A7419FFA73340F672B6D74843BE41DC542730E25089783EA5F1469A9B56D9AFFB48E5E8A0D9C4F29224E433ECD6946E2F66C81977CF87002EE64BAE4D7E4DAAC7FCB2BF2669E26808B0DDD83F0
FLASH SEI DATA : 06 01 07 0000160000030004 0411 B500314741393403C2FFFC 8080FD8080FF80
EXO:             06 01 07 00001600000004   0411 B500314741393403C2FFFC 8080FD8080FF8000000080FD8080FF800000000000000000000000000

As you can see the problem is not that 04 payloadType is duplicated but is that there is a wrong value in the previous package.of type 01.

Could any other logs be helpful?

Thanks Steve

mangui commented 8 years ago

Hi @steve6 I don't see any issue in Flash PES to SEI parsing. one possibility would be that there is an issue in the flash PES packet itself ? do you have a dump of Exoplayer PES packet ? also, what do you mean by wrong value in the previous package of type 01 ? Cheers, Mangui

steve6 commented 8 years ago

Hi @mangui big good news! I think that I found the problem.

The problem is the ‘Emulation Prevention’ byte in Nalu packet. Here more detail about ‘Emulation Prevention’: http://stackoverflow.com/questions/24884827/possible-locations-for-sequence-picture-parameter-sets-for-h-264-stream.

FLASH SEI DATA : 06 01 07 0000160000030004 0411 B500314741393403C2FFFC 8080FD8080FF80 ---------------------------------^^^^^^ emulation prevention bytes

Here the sample code from the Exoplayer solution: https://github.com/google/ExoPlayer/blob/0c060f429f459f1bac2ffa0963cadc45ce35b73a/library/src/main/java/com/google/android/exoplayer/util/NalUnitUtil.java#L60

I don't know if I'll have some free time next days to try to implement this but where is the best place to add this fix?

Cheers, Steve

mangui commented 8 years ago

Great ! Indeed that would explain ... You can put that as a static function in Nalu.as. u can try to just unescape SEI. Not clear if all Nalus should be unescaped ? In theory i would say yes..

zuzzurro commented 8 years ago

According to the stackoverflow document: Start codes work because the four byte sequences 0x000000, 0x000001, 0x000002 and 0x000003 are illegal within a non-RBSP NALU.

jlacivita commented 8 years ago

Great work guys!

jlacivita commented 8 years ago

Edited

Note: i left this out before, but we need to check for 01 - 07, not just 01 - 04. The stack overflow article isn't 100% accurate, because 0x07 (i.e. binary 00000111) could be confused for 0x000001 if doing bit-wise (not byte-wise) parsing.

@mangui: the discardEPB code in your apple-segmenter branch: https://github.com/dailymotion/hls.js/compare/apple-segmenter

I think has a minor bug here:

// Find all Emulation Prevention Bytes while (i < length - 2) { if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03) { EPBPositions.push(i + 2); i += 2; } else { i++; } }

It's assuming that all 0x000003 sequences are emulation prevention bytes, however, it's only an EPB if the next byte is a 0x01, 0x02, 0x03, or 0x04. Any other value, and the 3rd byte is not an EPB, it's just a literal 0x03.

I think you need something like:

// Find all Emulation Prevention Bytes while (i < length - 3) { if (data[i] === 0 && data[i + 1] === 0 && data[i + 2] === 0x03 && (data[i + 3] === 0x01 || data[i + 3] === 0x02 || data[i + 3] === 0x03 || data[i + 3] === 0x04 || data[i + 3] === 0x05 || data[i + 3] === 0x06 || data[i + 3] === 0x07)) { EPBPositions.push(i + 2); i += 3; } else { i++; } }

Then it can possibly be applied to other NALUs

jlacivita commented 8 years ago

I'm going to do some testing, because I can't decide if we need to check the 3rd byte for values 0x00-0x03 or a larger range of 0x00-0x07, but i'm sure we need to be checking the 3rd byte.

jlacivita commented 8 years ago

@mangui I moved the discardEPB() call to happen for every NALU, and i'm not seeing any problems, either with your original version, or my modifications.

Can you point me to an M3U8 that had video playback problems when calling discardEPB() for all NALUs?

mangui commented 8 years ago

tks for the hints @jlacivita I will recheck but definitely if my discardEPB() was discarding too much ... it could explain why it was not working as expected :p

I guess this additional condition should do the trick as well ? (!data[i + 3] && data[i + 3] <= 0x7)

jlacivita commented 8 years ago

Hi guys,

I found an HLS stream that fails to play when calling discardEPB on all NALUs. The code i suggested above doesn't help :(

I looking at Exo, they only call their unescapeStream method for SEI (6) and SPS (7) frames. Not sure why that's the case, perhaps it's just an in-practice thing, not an as-speced thing.

I'm going to move the call back into frame 6 & 7 only in my local builds

jlacivita commented 8 years ago

seems to work for me... content plays, and captions look good

steve6 commented 8 years ago

Good @jlacivita! @mangui about pull request is there any other work to do?