Вскрытие формата OJD
Кому лень читать интересную историю, вот ссылка на конвертер с инструкциями, как превратить .ojd в .mp4: https://drive.google.com/file/d/1GlMXGss0R2-jYP0TOZ_2Y1xzl9Ugar7l/view?usp=sharing
инструкции в readme.txt применимы к unix/linux, но всё работает и на WSL под виндой.
Ну ладно, а кому не лень и таки интересно, услышьте же охуительную историю о том, как я этот самый конвертер собрал!
Заранее предупреждаю - я нихрена не смыслю в аудио и видео, я просто программист на C. всю инфу про H264 и AAC я нагуглил и вычитал в коде старой версии ffmpeg; если тут есть эксперты, простите меня заранее, если какую-нибудь хуиту скажу.
НАЧАЛО ИСТОРИИ. ТАИНСТВЕННОЕ ВИДЕО НА РЕАКТОРЕ? СКАНДАЛЫ, ИНТРИГИ...
Ну так вот, ушел я тут, значит, в отпуск на пару недель, и тут вижу интересный пост от Иисуса:
http://joyreactor.cc/post/4899255
Удивительная история - файл с видео, который сам Иисус не может открыть!
Вместе с многоуважаемыми пидорами из комментов начал гуглить, с превеликим любопытством - случай и правда таинственный, не находилось вообще ничего толкового. С большим интересом тред пялился на хекс-дампы, которые Иисус предоставил в начале ветки ( http://joyreactor.cc/post/4899255#comment23718856 ), особенно на повторяющееся ASCII слово qbox...
И наконец товарищ http://joyreactor.cc/user/nun-buoy , а затем и товарищ http://joyreactor.cc/user/dadv нашли совпадение - старый проприетарный аппаратный видео/аудио кодек MG1264! Эта штуковина была вроде как сделана с рачетом на мобильные девайсы, что совпадало с инфой от Иисуса (видео со старого телефона).
Сообща нами были найдено следующее:
* Базовые характеристики: https://www.semiconductorstore.com/pdf/newsite/mobilygen/MG1264_Comet3_DS.pdf
* Слитые доки по версии 1.1 кодека: https://manualzz.com/doc/7153241/mg1264
* Чудом сохранившийся кусок самопального муксера на C#: https://csharp.hotexamples.com/site/file?hash=0xed6a386bc80b4638eac9ea030e141c8312db2507c58453306c1ab71598c2b8f2&fullName=VideoStreamCodecs/Formats/QBox.cs&project=ctapang/GPUCyclops (толку от этого в результате не вышло, просто интересно почитать)
* Полностью сохранившаяся либа для работы с аппаратным кодеком: https://tipok.org.ua/node/13, плюс патч для ffmpeg 0.6, включающий в себя демуксер для проприетарного формата qbox: https://gist.github.com/lynxis/3033513 (последнее в результате стало основным столпом решения проблемы)
Ручки уже основательно чесались, так что я скачал те самые доки и стал читать и сравнивать с хекс-дампами из треда.
Те самые qbox-ы оказались форматом контейнеров для AAC и H264 пакетов. В доках был описан формат самих qbox-ов:
Действительно, в хекс-дампах Иисуса прослеживались эти самые qbox-ы, в основном все как описывалось (http://joyreactor.cc/post/4899255#comment23720396), но с одним нюансом. Первые 8 байт файла не являлись частью какого-либо qbox-а. "Ну мало ли, наверное, проприетарный хедер", подумал я. Все казалось достаточно однозначно: ojd файлы - наверняка просто qbox аудио/видео стрим в формате "что энкодер высрал, то в файл и запишем" (в примерах из доков MG1264 такие файлы назывались .qbx), плюс в начало дописаны 8 байт для точной идентификации типа файла или еще чего-то в этом духе. Из интереса я еще некоторые время попытался эти 8 байт нагуглить, проверил пару баз файл хедеров, но это мне ничего не дало.
Стоит отметить, что тут все, блять, все в big-endian. Я раньше никогда с такой херней не работал, так что тут все немножко ломало мой привыкший к little-endian мозг =)
Тут стоит отметить один неприятный нюанс - я это далеко не сразу заметил, но несмотря на то, что те самые доки вроде бы жестко гарантируют, что в первом H264 видео qbox-е будут только NAL-ы SPS-PPS, в реальности тут в первом qbox-е выходит последовательность AUD-SPS-PPS-IDR (это можно увидеть здесь: http://joyreactor.cc/post/4899255#comment23718856 у каждого NAL-а 4 байта стандартного старткода заменено на префикс-размер, так что их можно легко подряд читать, не парясь с полным декодированием).
Для наглядности:
Тут выделены размеры (которыми заменены старткоды). Начинается каждый NAL так: 1 бит == 0, 2 бита == реф индекс (типа группа типов), дальше 5 битов ID (nal_unit_type: 9==AUD, 7==SPS, 8==PPS, 5==IDR), это все гуглится по запросу "ISO/IEC 14496 pdf". Короче, получается, что вместо чистого конфига тут еще и данные видео есть.
Если бы я знал хоть что-то об H264, я наверняка бы заподозрил, что 13744 байта как-то слишком дохуя для одних SPS-PPS. Но я ничего не знал и ничего не заметил, так что подозрений об актуальности и возможной устаревшести дока относительно ojd ко мне в душу не закралось...
КАК Я ЕБАЛСЯ С ФОРМАТОМ OJD
Ну, в общем, охуительно уверенный в себе, я постучался к Иисусу в личку, и он мне скинул .ojd файл. Дальше я нашел github FFmpeg-а, клонировал, и стал тыркаться. Приладить тот патч с tipok.org.ua к современной версии FFmpeg-а оказалось слишком сложно, но благо в репозитории был бранч подходящей версии 0.6.7 (патч писался для 0.6.1), я чекаутнул бранч и приладил на него qbox.c, qbox.h и прочие диффы из патча, нужные для работы демуксера. Нагуглив, как с этим ffmpeg вообще работать (лол), легким движением хвоста... эээ... tail-а я обрубил первые 8 байт файла ojd и попытался скормить результат свежескомпиленному ffmpeg-0.6.7.
Естественно, просто так нихуя не сработало.
Покопавшись в ffmpeg-е (выяснилось, что у него, по крайней мере, в версии 0.6, компилится дебаг-билд ffmpeg_g, который заходит с gdb), выяснил, что первый qbox парсится нормально, но со вторым возникают проблемы. Применив xxd, я обнаружил странное: второй qbox начинался через какой-то промежуток после ожидаемого конца первого.
Для наглядности покажу на изначальном .ojd (без обрубленного начала):
Тут хорошо видно "хедер" в начале, после него qbox с размером 0x35b0, и по-хорошему, если это qbox стрим, как в доках, то следующий qbox должен начаться на 0x8+0x35b0==0x35b8, но вот нихуя, начинается он аж на 0x3690!Изрядно прифигев с такого расклада событий, я тупо пялился на этот хекс-дамп, и тут заметил в нем нечто крайне интересное.
А вы, дорогие мои читатели, заметили это? Заметили, блять, с чего начинается строка 00003600?
0461 00a0 **** 03ff
Практически идентично хедеру в начале файла!!!!
Я охуел. Я сделал grep. Я охуел еще больше.
Это пиздец. Каждые 0x200 (512) байт .ojd файла начинаются с 8-байтного префикса. Байты 5-6, по ходу, какой-то... sequence number? Причем нормальный счет идет только в байте 6, в байте 5 же происходит какая-то полная поебень, но там явная закономерность (36-06-13-02-02-03-21-00 повторяются, но потом меняются с переносом единицы из 6 байта, короче, что-то крайне странное).Я не знаю, что это за наркомания. Я подозреваю, что это след какой-то крайне допотопной (возможно самопальной?) блочной файловой системы родной ОС девайса, на который таинственные видео записывались. Если кто тут узнал-распознал эту херню, объясните мне, пожалуйста, мне очень любопытно!
Кстати, забавный нюанс - в видео Иисуса этот сраный формат немножко поломал конец qbox-стрима, то есть последний qbox, который не влез в последний блок ojd, оказался таки обрезан. Это видно в комменте Иисуса с дампом конца ojd файла здесь, если посчитать размер последнего qbox-а: http://joyreactor.cc/post/4899255#comment23719489 а после конца этих блоков зачем-то идет очень дохуя нулей =) но не буду на этом заостряться.Ну, делать нечего, по-быстрому я написал конвертер, который из каждого 512-байтного блока в файле .ojd выкидывал первые 8 байт и записывал результат в файл .qbx.
Дело пошло веселее. С выкинутыми префиксами блков конец каждого qbox-а стал совпадать с началом следующего, и ffmpeg... послал меня нахуй, потому что что-то оказалось не так с аудио. Оказывается, демуксер не генерировал почему-то аудио-стрима, хотя я точно видел в файле аудио-qbox-ы.Решил я разобраться с этим позже. Путем нехитрых хаков кода, я смог декодировать видео в валидный mp4 файл с... ебаным слайдшоу, судя по частоте кадров. Настроив вручную взятый от балды фреймрейт, я еще раз декодировал видео, и... моему взору предстали обещанные Иисусом ебущиеся карлики! Успех!!!!!!!!!
Ебались они, правда, как-то подозрительно слишком резво, так что я сделал заметочку себе на будущее - разобраться с фреймрейтом ебаным. Но сначала аудио.
И тут меня ждал пиздец.
КАК Я ЕБАЛСЯ С АУДИО
В ебаных доках черным по белому было написано, что первый аудио qbox должен содержать аудио конфиг в формате AudioSpecificConfig из ISO/IEC 14496-3. Но конфиг-флага ни на одном из аудио-qbox-ов не нашел ни демуксер, ни я вручную. Правда, в доках и не было написано, что этот флаг обязательно на qbox-е с аудио-конфигом должен быть... Я решил поэкспериментировать и взять просто первый аудио-qbox и попытаться дешифрануть его как конфиг.
Меня ждало жестокое разочарование.
FFmpeg матерился по-черному, закидывал меня эррорами, говорил мне, что конфиг говно. Поебавшись немного, я горько вздохнул, вбил в гугле "ISO/IEC 14496-3 pdf" и начал вникать.
Как видно, первые 5 бит должны указывать на тип объекта. Судя по докам MG1264, этот тип должен быть 2 (AAC_LC).И тут уже незадача - все содержимое qbox-ов с аудио начиналось на 0x21:
дас ист крайне печально, ведь первые 5 битов 0x21 - это вовсе не 2 (AAC_LC), а очень даже 4 (AAC_LTP), который тот билд ffmpeg-а вообще не поддерживал.Вообще, рассматривая эти qbox-ы, я невольно задумался - а есть ли среди них вообще этот самый AudioSpecificConfig? Даже если проигнорировать первые 5 битов, дальше все равно получалась лютая хуита. В доках было четко сказано, что девайс поддерживает 2-канальное стерео AAC-LC аудио с sample rate 48000, 44100, 32000, 24000, или 22050 Hz.
Крепко задумавшись, я продолжил гуглить и штудировать ISO/IEC 14496-3, как вдруг до меня дошло, что все эти пакеты прекрасно подходят под определение AAC raw data block типа ChannelPairElement!
Здесь ID_CPE==1. CPE - это просто пакеты для двухканального стерео-аудио (это подтвердил и код ffmpeg). Я чувствовал, что я на верном пути!Но мне пришлось смириться с горькой правдой - конфига аудио (AudioSpecificConfig) в этом стриме qbox, по ходу, нет вообще. Возможно, девайс, с которого это было записано, поддерживал только одну настройку аудио, и qbox с аудио из файла ojd специально выкинули? Или же расчет был на то, что какие-то декодеры поумнее ffmpeg 0.6 смогут и без конфига тут разобраться? Мистика, конечно...
Ну, раз конфига нет, то сделаем сами, хуле. Будет у нас свой AudioSpecificConfig с блекджеком и шлюхами. Сначала я просто хакал ffmpeg, а потом уже дописал фальшивый аудио qbox в начало файла. Но это я чуть позже покажу.
Итак, мы имеем audioObjectType==2, 3<=samplingFrequencyIndex<=7, channelConfiguration==2. Если что, кстати, последние 2 значения - индексы в такие массивы (из кода ffmpeg 0.6.7):
После некоторых попыток стал я пробовать различные комбинации и... нихрена. FFmpeg выплевывал тонну ошибок (но файл какой-то все-таки выдавал). В чистое AAC не конвертировалось, а при декодировании в raw audio (wav) мои уши встречал оглушительный пердеж. После некоторой ебли, мне показалось, что на частоте 22050 ошибок вроде выдается меньше, и стал с ней тыркаться.Дальше я взял в руки gdb и стал разбираться, откуда идут ошибки. FFmpeg декодирует каждый channel_pair_element так: сначала общий конфиг, потом левый канал, потом правый. В пакете с данными они идут друг за другом последовательно (в табличке channel_pair_element это видно - там это называется individual_channel_stream).
Удивительно, но все ошибки выдавались при декодировании правого канала.
Почесал я репу, похакал я код ffmpeg-овского декодера aac, чтобы, значит, он игнорил ошибки со второго канала, и с каждого qbox-а брал только один экземпляр данных для первого канала.
Получившееся в результате аудио было... странным. В правом ухе оглушительно пердел сатана. Но в левом, кажется, слышались стоны ебущихся карликов!!!!!!
...но стонали они как-то... ускоренно? Я задумался и сел вчитываться в код ffmpeg. Скорее всего, второй канал не выходило распарсить, потому что плохо парсились данные первого канала. Если его недопарсить до конца, или же наоборот перепарсить, то не попадешь на данные второго канала. В конце первого канала шли спектральные данные, которые парсились каким-то очень сложным кодом... Но на его парсинг влиял sample rate.
Отсюда следует очевидное умозаключение - sample rate неправильный. Но я, как было написано раньше, свято верил слитым докам MG1264, в которых было написано, что самый маленький sample rate для аудио, который поддерживает кодек - 22050 герц.
Но в какой-то момент я от безнадеги таки взял и попробовал 16000 герц (индекс 8).
И ебать-колотить, что же я увидел? Конвертацию аудио без ошибок от ffmpeg! И что же я услышал? Громкие, четкие, стерео стоны ебущихся карликов!!!! Я смог!!!!!
В конвертер для qbox-ов добавилась новая фича - дописывать в начало стрима аудио-qbox с найденным мною конфигом.
КАК Я ЕБАЛСЯ С ФРЕЙМРЕЙТОМ
Последней моей задачей было сделать конвертацию видео с нормальным фреймрейтом. Аудио каким-то образом отконвертилось идеально, но чтобы подогнать к нему по времени видео, пришлось подбирать вручную - выяснилось, что там был фреймрейт 25. Но откуда брался изначальный фреймрейт, который был похож на ебаное слайдшоу? Оказалось, что все дело было в демуксере, который зачем-то рескейлил дефолтные 90000 герц базовой шкалы тайминга на какую-то хуйню. Исправив сей огрех и пошаманив немножко с кодом таймстампов, я получил нормальную комбинацию аудио с видео, нормальный mp4 файлик, который уже можно было отправить заждавшемуся Иисусу!ЗАКЛЮЧЕНИЕ
Ебать это было весело. Я дохрена нового для себя узнал про мир аудио и видео энкодингов. И теперь умею немножко работать с ffmpeg! Ну и в кои-то веки есть что интересного рассказать реактору =) всем бобра, я пошел допроебывать свой отпуск!
Подробнее
The QBOX header is as follows. typedef struct { uint32_t box_size; uint32_t box_type; // "qbox" uint32_t box_flags; // (version << 24 | box_flags) uintl6_t sample_stream_type; uintl6_t sample_stream_id; uint32_t sample_flags; uint32_t sample_cts; uint8_t sample_data[]; } QBox; sample_stream_type is set to 0x0001 for AAC audio, and 0x0002 for AVC video. sample_stream_id is currently set to the same value as Sample_stream_type. box f lags has two flags. Bit 0 is set if there is sample data after the header and bit 1 is set if this is the last sample in the stream. sample f lags is a 32-bit value. Bit 0 is set if the data contains configuration information for the decoder. Bit 1 is set if the CTS field is present and valid. Bit 2 is set if the video frame is a c\/nr‘hrnninnint ^mponino T frcimp fnr W iinH Kit 9 ic cpt if tKp friimp ic rlicnnciiKIp
Размер первого qbox-a ??? (13744 байта, считая magic number этот хедер) ** /
00000000 00000010 00000020 00000030 00000040 00000050 00000060 00000070 00000080 00000090 04 61 00 аО 36 00 03 ff 00 00 35 bO 71 62 6f 73 oo 02 0002001000 07 72 44 ba al 09 10^^^Р^ТЯ27 64 40 le ас 2c а6 eQ_a0 c0 а3 00 °°,U Ifl flfl ee 06 e2 c0|00 00 35 66|25 b3 04 83 7a 29 3f с1б^ГЯа c5 f2 b7 4f Oe dO da 2c a9 bc 05 le ec 77 27 52 ae Oe 7b b7 cc 92 02 cl 76 ae b3 Ob 90 6c 53 71 fO 44 52 46 39 3e 3c Oa aO 7f 18 c3 55 dd d4 a4 bb 16 e2 58 f6 e9 d5 c9 5a 60 05 51 Oc Ob 03 9a cl 00 00 00 01 6a 02 d049 80 20 .a. 6..ÿ..5“qbox ...........rD° ¡ .........*d@.^, j.DI ! à A".... .....(î.âÀ..5ff 4....i.z)?Án_>üA ô -O.DÚl©1'*. . iw * R® .{ -Í..Av®3..lSqö DRF9X. ..ÂUYÔH .âXoéÔÉZ'.Q____
/Downloads/ojd$ xxd test_video.ojd | grep qbox -B 10 -A 10 | head -30 00000000 0461 OOaO 3600 03ff 0000 35b0 7162 00 r*^ 4- • â«*0 5. qbox 00000010 0000 0001 0002 0002 0010 0007 7244 baal .. rD.. 00000020 0000 0002 0910 0000 0018 2764 401e ac2c 'd(a. 00000030 6a02 d049 абеО aOcO a800 OOlf 4000 061a j-.i . . (3 . . . 00000040 8020 0000 0005 28ee 06e2 cOOO 0035 6625 (... ...5f% 00000050 b804 0000 15ec 837a 293f cl6e 5f3e dac5 Z)? . n >.. 00000060 f 2b7 4f0e dOda 2ca9 bc05 leec 7727 52ae . .0 . .w‘ R. 00000070 0e7b b7cc 9202 cl76 aeb3 0b90 6c53 71f0 .{ V. . . .ISq. 00000080 4452 4639 3e3c OaaO 7f 18 c355 ddd4 a4bb DRF9><.... .1). ... 00000090 16e2 58f6 e9d5 c95a 6005 510c 0b03 9acl . .X Z' . Q 000000a0 a99d 41bb 8e93 d261 d8fe 5f41 151d 882a ..A....a.. A. . .* 000035f0 2c8c 08df 0d55 5604 92d3 a836 e5cf 7225 UV... . 6. . r% 00003600 0461 OOaO 021b 03ff aaf 1 c857 e200 2d48 .a .W. .-H 00003610 acd5 eef8 a62f lcfa 4ebc lcc6 666d b247 /.. N. . .fm.G 00003620 15b2 8730 3341 0034 4ec3 8351 9925 e752 ...03A.4N. . 0R 00003630 1ЫЗ 454c 8268 50e7 f b94 fe28 7911 a2a0 ..EL.hP... .(y... 00003640 3a6c 53e9 d523 6110 3672 a8e0 03bc d917 :IS..#a.6r 00003650 e430 65bd d595 a7cc 4131 b8ba f5a6 20f9 .0e A1 • • • • • 00003660 0200 3beb 65b3 5a74 7309 cb4c 4d38 89f3 ..).6.Zts. . LM8.. 00003670 6cb7 36al af5d 5b4d 4adc ЫЗа f039 cc5d 1.6..][MJ. • : -9. ] 00003680 343c lc62 06b8 f b29 1159 9b81 cOOO 0000 4<.b...). Y 00003690 0000 12a8 7162 6f78 0000 0001 0002 0002 .qbox.. ООООЗбаО 0010 0002 7244 c8bl 0000 0002 0930 0000 rD .. .0.. ООООЗбЬО 1285 21e0 2000 3915 c494 e902 dad9 7fcb .. !. .9... ООООЗбсО 30b2 fdef 3d81 b8a5 a09c 657e bd60 lecb 0...= e~. ' .. 000036d0 f f9f ccc3 dbd9 817b 8f40 ell4 cOff 1208 ООООЗбеО 9e37 aa70 044d 58ea f4el 39bf c759 lab3 .7.p.MX... 9. .Y.. 000036f0 76f0 540c 88d9 c2c5 1408 6538 7901 9762 v.T e8y. .b 00003700 e361 8c74 6902 a7c0 0139 dd4d e31d c729 .a. ti 9 .M... )
00000000: 0461 OOaO 3600 03ff 0000 35b0 7162 6f78 .a 00000200: 0461 OOaO 0601 03ff e609 cda5 fd58 2d0b .a 00000400: 0461 OOaO 1302 03ff cc43 2abb 917c 6g37 .a 00000600: 0461 OOaO 0203 03ff 5359 6798 cdc8 GOaO .a 00000800: 0461 OOaO 0204 03ff a9ad lf g6 35Gb 2ef2 .a ОООООаОО: 0461 OOaO 0305 03ff g699 2362 46b0 Gca6 .a OOOOOcOO: 0461 OOaO 2106 03ff 3d06 fe22 527b f4a9 .a ОООООеОО: 0461 OOaO 0007 03ff 4117 3797 15da 0633 .a 00001000: 0461 OOaO 3608 03ff 3ae0 3199 0108 3b3b .a 00001200: 0461 OOaO 0609 03ff 5a25 C6f G a210 7c7a .a 00001400: 0461 OOaO 130a 03ff la9e 3f2d b4d2 d588 .a 00001600: 0461 OOaO 020b 03ff 1400 6bdd 7d9d 48df .a 00001800: 0461 OOaO 020c 03ff 7d96 0f3b bG03 05f8 .a OOOOlaOO: 0461 OOaO 030d 03ff ce91 3742 8364 dbd9 .a OOOOlcOO: 0461 OOaO 210e 03ff 6b23 9bd5 cla4 c45g .a OOOOleOO: 0461 OOaO OOOf 03ff 9cab 445g 9cb0 la85 .a 00002000: 0461 OOaO 3610 03ff 9a81 3619 873b 7dl0 .a 00002200: 0461 OOaO 0611 03ff 2fcd cf 19 158a alaa .a 00002400: 0461 OOaO 1312 03ff f717 7a41 2ed7 1688 .a 00002600: 0461 OOaO 0213 03ff 1c9g b807 aOeb 726d .a
printf("Converting ojd blocks to qbox stream..An"); while (fread(block, INBLK_SIZE, 1, infile)) { int bufval = 0; int i; for (i = 0; i < 8; i++) { bufval |= block[i]; > if (bufval = 0) { // Reached ojd padding at end of file, apparently break; } fwrite(block + 0x8, INBLK_SIZE - 0x8, 1, outfile); } printf("Done! Saved qbox stream to %s\n", outfile_name);
Table 1.13 — Syntax of AudioSpecificConfig() Syntax No. of bits Mnemonic AudioSpecificConfig () { audioObjectType = GetAudioObjectType(); samplingFrequencylndex; 4 bslbf if ( samplingFrequencylndex == Oxf ) { samplingFrequency; } channelConfiguration; 24 uimsbf 4 bslbf sbrPresentFlag = -1; if ( audioObjectType == 5 ) { extensionAudioObjectType = audioObjectType; sbrPresentFlag = 1; extensionSamplingFrequencylndex; 4 uimsbf if ( extensionSamplingFrequencylndex == Oxf ) extensionSamplingFrequency; 24 uimsbf audioObjectType = GetAudioObjectTypeQ; } else { extensionAudioObjectType = 0; } switch (audioObjectType) { Table 1.14 — Syntax of GetAudioObjectTypeQ Syntax No. of bits Mnemonic GetAudioObjectType() { audioObjectType; 5 uimsbf if (audioObjectType == 31) { audioObjectType = 32 + audioObjectTypeExt; } return audioObjectType; } 6 uimsbf
Table 4.3 - Syntax of top level payload for audio object types AAC Main, SSR, LC, and LTP (raw_data_block()) Syntax____________________________________________________No. of bits Mnemonic raw_data_block() { while( (id = id_syn_ele) != ID_END){ 3 uimsbf switch (id) { case ID_SCE: break; single_channel_element(); case ID_CPE: break; channel_pair_element(); case ID_CCE: break; coupling_channel_element(); case ID_LFE: break; lfe_channel_element(); case ID_DSE: break; data_stream_element(); case ID_PCE: break; program_config_element(); case ID FIL: } } byte alignment); } fill_element();
Table 4.5 - Syntax of channel_pair_element() Syntax No. of bits Mnemonic channel pair elemento { element_instance_tag; 4 uimsbf common_window; 1 uimsbf if (common_window) { icsJnfo(); ms_mask_present; 2 uimsbf if ( ms_mask_present == 1 ) { for (g = 0; g < num_window_groups; g++) { for (sfb = 0; sfb < max_sfb; sfb++) { ms_used[g][sfb]; 1 uimsbf } } } } individual_channel_stream(common_window,0); individual_channel_stream(common_window,0); }_______________________________________________
const int ff_mpeg4audio_sample_rates[16] = { 96000, 88200, 64000, 48000, 44100, 32000 57 24000, 22050, 16000, 12000, 11025, 8000, 58 }; 59 const uint8_t ff_mpeg4audio_channels[8] = { 61 0, 1, 2, 3, 4, 5, 6, 8 62 }; 7350
8 // A config audio qbox that we can prepend to a qbox stream from an ojd 9 const char config_audio_qbox[] = { 10 // BEGIN QBOX HEADER 11 0x00, 0x00, 0x00, OxlA, // box_size, 26 bytes 'q', 'b1, 'o', 'x', // box_type, magic number 13 0x00, 0x00, 0x00, 0x01, // box_flags, data-present flag set 14 0x00, 0x01, 0x00, 0x01, // sample_streamtype . sample_stream_id, set to 0x1 for AAC audio 15 0x00, 0x00, 0x00, 0x01, // sampleflags, has SAMPLE_FLAGS_C0NFIGURATI0N_INF0 and nothing else 16 0x00, 0x00, 0x00, 0x00, // sample_cts, not used here (T0D0: is this the right move here?) 17 // END QBOX HEADER 18 // BEGIN AAC AudioSpecificConfig 19 0x14, 0x10, // 5 bits: 0x2==0b00010 (AAC_LC), 4 bits: 0x8==0bl000 (default sample rate = 16000 Hz), 4 bits: 0x2==0bO010 (2-channel stereo), 20 // GASpecificConfig: 1 bit framel_engthFlag==0 (use 1024/128), 1 bit dependsOnCoreCoder==0, 1 bit extensionFlag==0 21 // 00010 1000 0010 000= ObOOOlOlOOOOOlOOOO = 0x1410 22 };
Иисус,Исусе,geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор,программирование,реактор помогающий,много букаф,Истории,длиннопост
Отличный комментарий!