937 lines · 20.2 KB · C
RawDownload
/****************************************************************************    MP4 output module     Copyright (C) 2017 Krzysztof Nikiel     This program is free software: you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation, either version 3 of the License, or    (at your option) any later version.     This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.     You should have received a copy of the GNU General Public License    along with this program.  If not, see <http://www.gnu.org/licenses/>.****************************************************************************/ #ifdef HAVE_CONFIG_H#include "config.h"#endif #include <stdlib.h>#include <stdio.h>#ifndef WORDS_BIGENDIAN//#include <byteswap.h>#endif#include <string.h>#include <time.h>#include <unistd.h> #include "mp4write.h" enum ATOM_TYPE{    ATOM_STOP = 0 /* end of atoms */ ,    ATOM_NAME /* plain atom */ ,    ATOM_DESCENT,               /* starts group of children */    ATOM_ASCENT,                /* ends group */    ATOM_DATA,};typedef struct{    uint16_t opcode;    void *data;} creator_t; mp4config_t mp4config = { 0 }; static FILE *g_fout = NULL; static inline uint32_t be32(uint32_t u32){#ifndef WORDS_BIGENDIAN#if defined (__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))    return __builtin_bswap32(u32);#elif defined (_MSC_VER)    return _byteswap_ulong(u32);#else    return (u32 << 24) | ((u32 << 8) & 0xFF0000) | ((u32 >> 8) & 0xFF00) | (u32 >> 24);#endif#else    return u32;#endif} static inline uint16_t be16(uint16_t u16){#ifndef WORDS_BIGENDIAN#if defined (__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)))    return __builtin_bswap16(u16);#elif defined (_MSC_VER)    return _byteswap_ushort(u16);#else    return (u16 << 8) | (u16 >> 8);#endif#else    return u16;#endif} static int dataout(const void *data, int size){    if (fwrite(data, 1, size, g_fout) != size)    {        perror("mp4out");        return -1;    }    return size;} static int stringout(const char *txt){    return dataout(txt, strlen(txt));} static int u32out(uint32_t u32){    u32 = be32(u32);    return dataout(&u32, 4);} static int u16out(uint16_t u16){    u16 = be16(u16);    return dataout(&u16, 2);} static int u8out(uint8_t u8){    if (fwrite(&u8, 1, 1, g_fout) != 1)    {        perror("mp4 out");        return 0;    }    return 1;} static int ftypout(void){    int size = 0;     size += stringout("M4A ");    size += u32out(0);    size += stringout("M4A ");    size += stringout("mp42");    size += stringout("isom");    size += u32out(0);     return size;} enum{ SECSINDAY = 24 * 60 * 60 };static time_t mp4time(void){    int y;    time_t t;     time(&t);     // add some time from the start of 1904 to the start of 1970    for (y = 1904; y < 1970; y++)    {        t += 365 * SECSINDAY;        if (!(y & 3))            t += SECSINDAY;    }     return t;} static int mvhdout(void){    int size = 0;    int cnt;     // version    size += u8out(0);    // flags    size += u8out(0);    size += u16out(0);    // Creation time    size += u32out(mp4time());    // Modification time    size += u32out(mp4time());    // Time scale (samplerate)    size += u32out(mp4config.samplerate);    // Duration    size += u32out(mp4config.samples);    // rate    size += u32out(0x00010000);    // volume    size += u16out(0x0100);    // reserved    size += u16out(0);    size += u32out(0);    size += u32out(0);    // matrix    size += u32out(0x00010000);    size += u32out(0);    size += u32out(0);    size += u32out(0);    size += u32out(0x00010000);    size += u32out(0);    size += u32out(0);    size += u32out(0);    size += u32out(0x40000000);     for (cnt = 0; cnt < 6; cnt++)        size += u32out(0);    // Next track ID    size += u32out(2);     return size;}; static int tkhdout(void){    int size = 0;     // version    size += u8out(0);    // flags    // bits 8-23    size += u16out(0);    // bits 0-7    size += u8out(1 /*track enabled */ );    // Creation time    size += u32out(mp4time());    // Modification time    size += u32out(mp4time());    // Track ID    size += u32out(1);    // Reserved    size += u32out(0);    // Duration    size += u32out(mp4config.samples);    // Reserved    size += u32out(0);    size += u32out(0);    // Layer    size += u16out(0);    // Alternate group    size += u16out(0);    // Volume    size += u16out(0x0100);    // Reserved    size += u16out(0);    // matrix    size += u32out(0x00010000);    size += u32out(0);    size += u32out(0);    size += u32out(0);    size += u32out(0x00010000);    size += u32out(0);    size += u32out(0);    size += u32out(0);    size += u32out(0x40000000);     // Track width    size += u32out(0);    // Track height    size += u32out(0);     return size;}; static int mdhdout(void){    int size = 0;     // version/flags    size += u32out(0);    // Creation time    size += u32out(mp4time());    // Modification time    size += u32out(mp4time());    // Time scale    size += u32out(mp4config.samplerate);    // Duration    size += u32out(mp4config.samples);    // Language    size += u16out(0 /*0=English */ );    // pre_defined    size += u16out(0);     return size;};  static int hdlr1out(void){    int size = 0;     // version/flags    size += u32out(0);    // pre_defined    size += u32out(0);    // Component subtype    size += stringout("soun");    // reserved    size += u32out(0);    size += u32out(0);    size += u32out(0);    // name    // null terminate    size += u8out(0);     return size;}; static int smhdout(void){    int size = 0;     // version/flags    size += u32out(0);    // Balance    size += u16out(0 /*center */ );    // Reserved    size += u16out(0);     return size;}; static int drefout(void){    int size = 0;     // version/flags    size += u32out(0);    // Number of entries    size += u32out(1 /*url reference */ );     return size;}; static int urlout(void){    int size = 0;     size += u32out(1);     return size;}; static int stsdout(void){    int size = 0;     // version/flags    size += u32out(0);    // Number of entries(one 'mp4a')    size += u32out(1);     return size;}; static int mp4aout(void){    int size = 0;    // Reserved (6 bytes)    size += u32out(0);    size += u16out(0);    // Data reference index    size += u16out(1);    // Version    size += u16out(0);    // Revision level    size += u16out(0);    // Vendor    size += u32out(0);    // Number of channels    size += u16out(mp4config.channels);    // Sample size (bits)    size += u16out(mp4config.bits);    // Compression ID    size += u16out(0);    // Packet size    size += u16out(0);    // Sample rate (16.16)    // rate integer part    size += u16out(mp4config.samplerate);    // rate reminder part    size += u16out(0);     return size;} static int esdsout(void){    int size = 0;    // descriptor definitions:    // systems/mp4_file_format/libisomediafile/src/MP4Descriptors.h    // systems/mp4_file_format/libisomediafile/src/MP4Descriptors.c    //    // descriptor tree:    // MP4ES_Descriptor    //   MP4DecoderConfigDescriptor    //      MP4DecSpecificInfoDescriptor    //   MP4SLConfigDescriptor    struct    {        int es;        int dc;                 // DecoderConfig        int dsi;                // DecSpecificInfo        int sl;                 // SLConfig    } dsize;     enum    { TAG_ES = 3, TAG_DC = 4, TAG_DSI = 5, TAG_SLC = 6 };     // calc sizes#define DESCSIZE(x) (x + 5/*.tag+.size*/)    dsize.sl = 1;    dsize.dsi = mp4config.asc.size;    dsize.dc = 13 + DESCSIZE(dsize.dsi);    dsize.es = 3 + DESCSIZE(dsize.dc) + DESCSIZE(dsize.sl);     // output esds atom data    // version/flags ?    size += u32out(0);    // mp4es    size += u8out(TAG_ES);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(dsize.es);    // ESID    size += u16out(0);    // flags(url(bit 6); ocr(5); streamPriority (0-4)):    size += u8out(0);     size += u8out(TAG_DC);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(dsize.dc);    size += u8out(0x40 /*MPEG-4 audio */ );    size += u8out((5 << 2) /* AudioStream */ | 1 /* reserved = 1 */);    // decode buffer size bytes#if 0    size += u16out(mp4config.buffersize >> 8);    size += u8out(mp4config.buffersize && 0xff);#else    size += u8out(0);    size += u8out(0x18);    size += u8out(0);#endif    // bitrate    size += u32out(mp4config.bitrate.max);    size += u32out(mp4config.bitrate.avg);     size += u8out(TAG_DSI);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(dsize.dsi);    // AudioSpecificConfig    size += dataout(mp4config.asc.data, mp4config.asc.size);     size += u8out(TAG_SLC);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(0x80);    size += u8out(dsize.sl);    // "predefined" (no idea)    size += u8out(2);     return size;} static int sttsout(void){    int size = 0;     // version/flags    size += u32out(0);    // Number of entries    size += u32out(1);    // only one entry    // Sample count (number of frames)    size += u32out(mp4config.frame.ents);    // Sample duration (samples per frame)    size += u32out(mp4config.framesamples);     return size;} static int stszout(void){    int size = 0;    int cnt;     // version/flags    size += u32out(0);    // Sample size    size += u32out(0 /*i.e. variable size */ );    // Number of entries    if (!mp4config.frame.ents)        return size;    if (!mp4config.frame.data)        return size;     size += u32out(mp4config.frame.ents);    for (cnt = 0; cnt < mp4config.frame.ents; cnt++)        size += u32out(mp4config.frame.data[cnt]);     return size;} static int stscout(void){    int size = 0;     // version/flags    size += u32out(0);    // Number of entries

Lines 1–500 of 937.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t