Due to an unexpected need in the company project, it is required to extract H.264 from an MP4 file. It is recommended to use the open-source tool Bento4.
In most embedded Linux environments, only pure C source code is supported.
About Bento4:
A fast, modern, open source C++ toolkit for all your MP4 and DASH/HLS/CMAF media format needs.
https://www.bento4.com/downloads/
Import Bento4 to buildroot
- at buildroot/src/package/Config.in
source "package/bento4/Config.in"
- create src/package/bento4 folder
add:
2.1 Config.in
config BR2_PACKAGE_BENTO4
bool "bento4"
depends on BR2_INSTALL_LIBSTDCPP
help
Bento4 is a C++ class library designed to read and write
ISO-MP4 files.
https://www.bento4.com/
comment "bento4 support needs a toolchain with C++"
depends on !BR2_INSTALL_LIBSTDCPP
2.2 bento4.hash
# Locally calculated
sha256 9f3eb912207d7ed9c1e6e05315083404b32a11f8aacd604a9b2bdcb10bf79eb9 bento4-1.6.0-639.tar.gz
sha256 7daae92c8628ada28def8d096fe2fde298b72ec3e2d64a3c408afce38edb361b Documents/LICENSE.txt
2.3 bento4.mk
################################################################################
#
# bento4
#
################################################################################
BENTO4_VERSION = 1.6.0-639
BENTO4_SITE = $(call github,axiomatic-systems,Bento4,v$(BENTO4_VERSION))
BENTO4_INSTALL_STAGING = YES
BENTO4_LICENSE = GPL-2.0+
BENTO4_LICENSE_FILES = Documents/LICENSE.txt
BENTO4_CPE_ID_VENDOR = axiosys
# Source/C++/Core/Ap4Config.h
ifeq ($(BR2_ENDIAN),"BIG")
BENTO4_BYTE_ORDER = 0
else
BENTO4_BYTE_ORDER = 1
endif
BENTO4_CONF_OPTS += \
-DBUILD_APPS=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="$(TARGET_CXXFLAGS) -std=c++11 -fPIC -DAP4_PLATFORM_BYTE_ORDER=$(BENTO4_BYTE_ORDER)"
$(eval $(cmake-package))
- Add all .patch to src/package/bento4/
list
Cover C++ interface to C
My plan is to repackage the MP4 to H264/AAC API into a pure C interface. All I need:
header | extract.h |
src | Mp42Aac_extract.cpp |
src | Mp42Aac_extract.cpp |
Makefile | Makefile |
Header file
src/Mp4Extract/extract.h
#ifndef __EXTRACT_H__
#define __EXTRACT_H__
#ifdef __cplusplus
extern "C" {
#endif
int AVC_extract_avc(int argc, char **argv);
int AVC_getSampleNum(char *file_name, int *num);
int AVC_getFrameData(char *file_name, int index, char *ptr, int *frame_len);
int AVC_releaseExtractor();
int extract_aac(int argc, char **argv);
int AAC_getSampleNum(char *file_name, int *num);
int AAC_getFrameData(int index, char *ptr, int *frame_len);
int AAC_releaseExtractor();
#ifdef __cplusplus
}
#endif
#endif
src/Mp4Extract/Mp42Aac_extract.cpp
/*****************************************************************
|
| AP4 - MP4 to AAC File Converter
|
| Copyright 2002-2008 Axiomatic Systems, LLC
|
|
| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
|
| Unless you have obtained Bento4 under a difference license,
| this version of Bento4 is Bento4|GPL.
| Bento4|GPL is free software; you can redistribute it and/or modify
| it under the terms of the GNU General Public License as published by
| the Free Software Foundation; either version 2, or (at your option)
| any later version.
|
| Bento4|GPL 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 Bento4|GPL; see the file COPYING. If not, write to the
| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
| 02111-1307, USA.
|
****************************************************************/
/*----------------------------------------------------------------------
| includes
+---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include "Ap4.h"
#include "extract.h"
/*----------------------------------------------------------------------
| constants
+---------------------------------------------------------------------*/
#define BANNER \
"MP4 To AAC File Converter - Version 1.0\n" \
"(Bento4 Version " AP4_VERSION_STRING ")\n" \
"(c) 2002-2008 Axiomatic Systems, LLC"
/*----------------------------------------------------------------------
| PrintUsageAndExit
+---------------------------------------------------------------------*/
static void PrintUsageAndExit()
{
fprintf(stderr, BANNER "\n\nusage: mp42aac [options] <input> <output>\n"
" Options:\n"
" --key <hex>: 128-bit decryption key (in hex: 32 chars)\n");
exit(1);
}
/*----------------------------------------------------------------------
| GetSamplingFrequencyIndex
+---------------------------------------------------------------------*/
static unsigned int GetSamplingFrequencyIndex(unsigned int sampling_frequency)
{
switch (sampling_frequency) {
case 96000:
return 0;
case 88200:
return 1;
case 64000:
return 2;
case 48000:
return 3;
case 44100:
return 4;
case 32000:
return 5;
case 24000:
return 6;
case 22050:
return 7;
case 16000:
return 8;
case 12000:
return 9;
case 11025:
return 10;
case 8000:
return 11;
case 7350:
return 12;
default:
return 0;
}
}
/*----------------------------------------------------------------------
| WriteAdtsHeader
+---------------------------------------------------------------------*/
static AP4_Result WriteAdtsHeader(AP4_ByteStream *output, unsigned int frame_size,
unsigned int sampling_frequency_index, unsigned int channel_configuration)
{
unsigned char bits[7];
bits[0] = 0xFF;
bits[1] = 0xF1; // 0xF9 (MPEG2)
#if (1)
channel_configuration = 1; // Mono
bits[2] = 0x40 | (sampling_frequency_index << 2) | (channel_configuration >> 2);
bits[3] = ((channel_configuration & 0x3) << 6) | ((frame_size + 7) >> 11);
bits[4] = ((frame_size + 7) >> 3) & 0xFF;
bits[5] = (((frame_size + 7) << 5) & 0xFF) | 0x1F;
bits[6] = 0xFC;
#else
int profile = 2; // AAC LC
int freqIdx = 11; // 8KHz
int chanCfg = 1; // mono
bits[2] = 0x40 | (freqIdx << 2) | (chanCfg >> 2);
bits[3] = ((chanCfg & 0x3) << 6) | ((frame_size + 7) >> 11);
bits[4] = ((frame_size + 7) >> 3) & 0xFF;
bits[5] = (((frame_size + 7) << 5) & 0xFF) | 0x1F;
#endif
return output->Write(bits, 7);
/*
0: syncword 12 always: '111111111111'
12: ID 1 0: MPEG-4, 1: MPEG-2
13: layer 2 always: '00'
15: protection_absent 1
16: profile 2
18: sampling_frequency_index 4
22: private_bit 1
23: channel_configuration 3
26: original/copy 1
27: home 1
28: emphasis 2 only if ID == 0
ADTS Variable header: these can change from frame to frame
28: copyright_identification_bit 1
29: copyright_identification_start 1
30: aac_frame_length 13 length of the frame including header (in bytes)
43: adts_buffer_fullness 11 0x7FF indicates VBR
54: no_raw_data_blocks_in_frame 2
ADTS Error check
crc_check 16 only if protection_absent == 0
*/
}
static AP4_Result WriteAdtsHeaderPtr(unsigned int frame_size, unsigned int sampling_frequency_index,
unsigned int channel_configuration, char *ptr)
{
unsigned char bits[7];
bits[0] = 0xFF;
bits[1] = 0xF1; // 0xF9 (MPEG2)
channel_configuration = 1; // Mono
bits[2] = 0x40 | (sampling_frequency_index << 2) | (channel_configuration >> 2);
bits[3] = ((channel_configuration & 0x3) << 6) | ((frame_size + 7) >> 11);
bits[4] = ((frame_size + 7) >> 3) & 0xFF;
bits[5] = (((frame_size + 7) << 5) & 0xFF) | 0x1F;
bits[6] = 0xFC;
memcpy(ptr, &bits[0], 7);
return 0;
}
/*----------------------------------------------------------------------
| DecryptAndWriteSamples
+---------------------------------------------------------------------*/
static void DecryptAndWriteSamples(AP4_Track *track, AP4_SampleDescription *sdesc, AP4_Byte *key,
AP4_ByteStream *output)
{
AP4_ProtectedSampleDescription *pdesc = AP4_DYNAMIC_CAST(AP4_ProtectedSampleDescription, sdesc);
if (pdesc ==