使用mp4v2将h264和aac封装成mp4
#include<stdio.h>#include<stdint.h>
#include "mp4v2/mp4v2.h"
#include"AacADTSHeader.h"
#include"NaluParse.h"
uint16_tGetDecoderSpecificInfo(uint8_t audioObjectType, uint8_t sampleRateIndex, uint8_t channelNumber)
{
uint16_t decoderSpecificInfo = 0;
uint8_t* p = (uint8_t*)&decoderSpecificInfo;
p = ((audioObjectType << 3) & 0xf8) | ((sampleRateIndex >> 1) & 0x07);
p = ((sampleRateIndex << 7) & 0x80) | ((channelNumber << 3) & 0x70);
return decoderSpecificInfo;
}
int main(int argc, char* argv[])
{
MP4FileHandle mp4 = NULL;
FILE* h264=NULL;
FILE* aac = NULL;
MP4TrackId videoTrack = MP4_INVALID_TRACK_ID;
MP4TrackId audioTrack = MP4_INVALID_TRACK_ID;
try {
AC::NaluParse naluParse;
AC::Nalu nalu;
AC::AacADTSHeader adtsHeader;
unsigned char bufferFull;
unsigned char* buf = bufferFull + 4;
int size;
int naluType;
unsigned char* aacData;
int aacDataLength;
int width = 576;
int height = 320;
double frameRate = 29.97;
int timeScale = 90000;
int sampling_frequency_set[] = { 6000 ,88200,64000,48000,44100,32000,24000,22050,16000,12000, 11025 , 8000, 7350 };
mp4 = MP4Create("test.mp4", 0);
if (mp4 == MP4_INVALID_FILE_HANDLE)
{
throw std::exception("Create mp4 handle fialed.\n");
}
h264 = fopen("test.h264", "rb+");
if (!h264)
{
throw std::exception("Opene h264 handle fialed.\n");
}
aac = fopen("test.aac", "rb+");
if (!aac)
{
throw std::exception("Opene aac handle fialed.\n");
}
//Ƶ
while (1)
{
size = fread(buf, 1, 1024, h264);
if (size < 1)
break;
naluParse.SendH264Stream(buf, size);
while (naluParse.ReceiveNalu(nalu))
{
bool isIdr = true;
naluType = nalu.GetData() & 0x1F;
switch (naluType)
{
case 01:
case 02:
case 03:
case 04:
isIdr = false;
case 05://idr
{
auto pNalu = nalu.GetData();
pNalu -= 4;
pNalu = (nalu.GetDataLength() >> 24) & 0xFF;
pNalu = (nalu.GetDataLength() >> 16) & 0xFF;
pNalu = (nalu.GetDataLength() >> 8) & 0xFF;
pNalu = (nalu.GetDataLength() >> 0) & 0xFF;
if (!MP4WriteSample(mp4, videoTrack, pNalu, nalu.GetDataLength() + 4, MP4_INVALID_DURATION, 0, isIdr))
{
printf("Error:Can't write sample.\n");
}
}
break;
case 7: // SPS
{
if (videoTrack == MP4_INVALID_TRACK_ID)
{
videoTrack = MP4AddH264VideoTrack
(mp4,
timeScale,
timeScale / frameRate,
width,
height,
nalu.GetData(),
nalu.GetData(),
nalu.GetData(),
3); // 4 bytes length before each NAL unit
if (videoTrack == MP4_INVALID_TRACK_ID)
{
printf("Error:Can't add track.\n");
return -1;
}
MP4SetVideoProfileLevel(mp4, 0x7F);
MP4AddH264SequenceParameterSet(mp4, videoTrack, nalu.GetData(), nalu.GetDataLength());
}
}
break;
case 8: // PPS
{
MP4AddH264PictureParameterSet(mp4, videoTrack, nalu.GetData(), nalu.GetDataLength());
}
break;
}
}
}
//Ƶ
while (1)
{
int size;
size = fread(buf, 1, 7, aac);
if (size < 7)
break;
AC::AacADTSParse::BinaryToHeader(buf, adtsHeader);
size = fread(buf, 1, adtsHeader.aac_frame_length - 7, aac);
if (size != adtsHeader.aac_frame_length - 7)
{
throw std::exception("incorrect length!");
}
if (adtsHeader.protection_absent == 0)
//Уλ
{
aacData = buf + 2;
aacDataLength = size - 2;
//TODO Уλbufferbuffer
}
else
{
aacData = buf;
aacDataLength = size;
}
//TODO ȡaac aacDataaacDataLength
if (audioTrack == MP4_INVALID_TRACK_ID)
{
audioTrack = MP4AddAudioTrack(mp4, sampling_frequency_set, 1024, MP4_MPEG4_AUDIO_TYPE);
if (audioTrack == MP4_INVALID_TRACK_ID)
{
throw std::exception("Add audio track failed!");
}
MP4SetAudioProfileLevel(mp4, 0x02);
auto config = GetDecoderSpecificInfo(adtsHeader.profile + 1, adtsHeader.sampling_frequency_index, adtsHeader.channel_configuration);
if (!MP4SetTrackESConfiguration(mp4, audioTrack, (uint8_t*)&config, 2))
{
throw std::exception("set config failed!");
}
}
MP4WriteSample(mp4, audioTrack, aacData, aacDataLength, MP4_INVALID_DURATION, 0, 1);
}
}
catch (const std::exception& e)
{
printf("%s,\n", e.what());
}
if (aac)
fclose(aac);
if (h264)
fclose(h264);
if (mp4)
MP4Close(mp4);
return 0;
}
/*FILE* f = fopen("test_music.aac", "rb+");
uint8_t buffer;
AC::AacADTSHeader h;
while (1)
{
int size;
size = fread(buffer, 1, 7, f);
if (size < 7)
break;
h.LoadtData(buffer);
h.SaveData(buffer);
AC::AacADTSHeader h2;
h2.LoadtData(buffer);
size = fread(buffer, 1, h2.GetAacFrameLength() - 7, f);
if (size != h2.GetAacFrameLength() - 7)
{
throw;
}
}*/
//int main(int argc, char* argv[])
//{
// GdiScreenCaptureTest();
// MP4FileHandle pHandle = NULL;
// FILE* f;
// MP4TrackId videoId = MP4_INVALID_TRACK_ID;
//
// int width = 1920;
// int height = 1080;
// int frameRate = 20;
// int timeScale = 90000;
// unsigned char fullBuffer = {0,0,0,0,0};
// unsigned char *buffer= fullBuffer+4;
// unsigned char* pNalu;
// unsigned char naluType;
// bool isIdr = true;
// f = fopen("test.h264", "rb+");
// if (!f)
// {
// printf("ERROR:Open h264 file fialed.\n");
// return -1;
// }
// for (int i = 1; i <= 8192; i++)
// {
//
// AC::NaluParse parse;
// pHandle = MP4Create("test1.mp4", 0);
// if (pHandle == MP4_INVALID_FILE_HANDLE)
// {
// printf("ERROR:Create mp4 handle fialed.\n");
// return -1;
// }
// while (1)
// {
// int size = fread(buffer, 1, i, f);
// if (size < 1)
// {
// break;
// }
// parse.SendH264Stream(buffer, size);
// AC::Nalu nalu;
// while (parse.ReceiveNalu(nalu))
// {
// pNalu = nalu.GetData();
// naluType = pNalu & 0x1F;
// switch (naluType)
// {
// case 01:
// case 02:
// case 03:
// case 04:
// isIdr = false;
// case 05://idr
// {
// pNalu -= 4;
// pNalu = (nalu.GetDataLength() >> 24) & 0xFF;
// pNalu = (nalu.GetDataLength() >> 16) & 0xFF;
// pNalu = (nalu.GetDataLength() >> 8) & 0xFF;
// pNalu = (nalu.GetDataLength() >> 0) & 0xFF;
// if (!MP4WriteSample(pHandle, videoId, pNalu, nalu.GetDataLength() + 4, MP4_INVALID_DURATION, 0, isIdr))
// {
// printf("Error:Can't write sample.\n");
// }
// isIdr = true;
// }
// break;
// case 7: // SPS
// {
// if (videoId == MP4_INVALID_TRACK_ID)
// {
// videoId = MP4AddH264VideoTrack
// (pHandle,
// timeScale,
// timeScale / frameRate,
// width,
// height,
// pNalu,
// pNalu,
// pNalu,
// 3);
// if (videoId == MP4_INVALID_TRACK_ID)
// {
// printf("Error:Can't add track.\n");
// return -1;
// }
// MP4AddH264SequenceParameterSet(pHandle, videoId, pNalu, nalu.GetDataLength());
// }
// }
// break;
// case 8: // PPS
// {
// MP4AddH264PictureParameterSet(pHandle, videoId, pNalu, nalu.GetDataLength());
// }
// break;
// default:
// break;
// }
// }
// }
// MP4Close(pHandle);
// fseek(f, 0, SEEK_SET);
// videoId = MP4_INVALID_TRACK_ID;
// if (!FileHelper::Compare("test.mp4", "test1.mp4"))
// {
// throw "error";
// }
// }
//
// return 0;
//
//
//
// try {
// WNDCLASS wndclass;
// wndclass.style = CS_HREDRAW | CS_VREDRAW;
// wndclass.lpfnWndProc = WndProc;
// wndclass.cbClsExtra = 0;
// wndclass.cbWndExtra = 0;
// wndclass.hInstance = GetModuleHandle(NULL);
// wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
// wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
// wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
// wndclass.lpszMenuName = 0;
// wndclass.lpszClassName = L"DemoWindow";
// if (!RegisterClass(&wndclass))
// {
// MessageBox(NULL, TEXT(" ʧ!"), L"", MB_ICONERROR);
// }
// auto title = L" ";
// HWND hwnd = CreateWindow(
// L"DemoWindow",
// title,
// WS_OVERLAPPEDWINDOW,
// 0,
// 0,
// 1280,
// 720,
// NULL,
// NULL,
// GetModuleHandle(NULL),
// NULL
// );
// ShowWindow(hwnd, SW_SHOW);
//
// AC::SdlVideoRender sr;
// sr.SetFormat(AC::PixelFormat::PIXELFORMAT_NV12);
// sr.SetWindow(hwnd);
// sr.Initial();
// while (1)
// {
// auto d = AC::MFCameraCapture::GetDevices();
// AC::MFCameraCapture mcc(d.Id);
// for (auto i : d.SurportForamts)
// {
// if (i.PixelFormat == AC::PixelFormat::PIXELFORMAT_NV12 && i.Width == 1280 && i.Height == 720)
// {
// mcc.SetVideoFormat(i);
// break;
// }
// }
// mcc.PixelDataArrived += [&](auto s, AC::IVideoInput::PixelDataArrivedEventArgs* e) {
// sr.Present(e->Frame.Data, e->Frame.DataLength, e->Frame.Width, e->Frame.Height, 0, 0, e->Frame.Width, e->Frame.Height, 0, 0, e->Frame.Width, e->Frame.Height);
// };
// mcc.Open();
// Sleep(50);
// }
// MSG msg;
// HACCEL hAccelTable = NULL;
// // Ϣѭ:
// while (GetMessage(&msg, NULL, 0, 0))
// {
// if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
// {
// TranslateMessage(&msg);
// DispatchMessage(&msg);
// }
// }
// }
// catch (const std::exception& e) {
// printf("%s", e.what());
// }
// //
//
// //GdiScreenCaptureTest();
//
// return 0;
//}
////
//
//static int getNextNalu(unsigned char* h264Frame, int len, int& offset)
//{
// int oldOffset = offset;
// int spliterLen = 4;
// offset += 3;
// while (offset < len)
// {
// if (h264Frame == 0 && h264Frame == 0 && h264Frame == 1)
// {
// if (offset > 3) {
// if (h264Frame == 0) {
// spliterLen = 4;
// }
// else
// {
// spliterLen = 3;
// }
// }
// else {
// spliterLen = 3;
// }
// break;
// }
// offset++;
// }
//
// return offset - oldOffset - spliterLen;
//}
//double atime = 0;
//
//int GetClock() {
// return atime;
//
//}
//
//MP4FileHandle pHandle = NULL;
//AC::SdlVideoRender sr;
//AC::IntelHardwareEncoder* he;
//MP4TrackId videoId;
//int addStream = 1;
//FILE* fh264 = NULL;
//int64_t _timestamp = 0;
//
//class A :public AC::IVideoCaptureCallback
//{
// // ͨ IVideoCaptureCallback̳
// virtual void OnCaptrue(const unsigned char* buf, int len, int width, int height, AC::PixelFormat format, unsigned int timestamp) override
// {
// //sr.Present(buf, len, width, height, 0, 0, width, height, 0, 0, 640, 360);
// try {
//
// if (!he)
// {
// AC::EncodeParam param;
// param.Bitrate = 1024;
// param.Framerate = 20;
// param.Width = 1920;
// param.Height = 1080;
// //param.Profile = AC::PROFILE_AVC_BASELINE;
// //param.GopSize = 50;
// he = new AC::IntelHardwareEncoder(param);
//
// he->EncodedDataArrived += [&](auto s, auto e) {
//
// if (!fh264)
// fh264 = fopen("test.h264", "wb+");
// fwrite(e->Frame.Data, 1, e->Frame.DataLength, fh264);
// unsigned char* pBuf = e->Frame.Data;
// unsigned char* pNalu = e->Frame.Data;
// unsigned char naluType;
// int len = 0;
// int offset = 0;
// int num = 0;
// int width = 1920;
// int height = 1080;
// int frameRate = 20;
// int timeScale = 90000;
// bool isIdr = true;
// while (1)
// {
// len = getNextNalu(pBuf, e->Frame.DataLength, offset);
// gotNal:
// if (len < 0)
// break;
// pNalu = pBuf + offset;
// naluType = pNalu & 0x1F;
// switch (naluType)
// {
// case 01:
// case 02:
// case 03:
// case 04:
// isIdr = false;
// case 05://idr
// {
// len = e->Frame.DataLength - offset;
// if (offset < 4)
// break;
// pNalu -= 4;
// pNalu = (len >> 24) & 0xFF;
// pNalu = (len >> 16) & 0xFF;
// pNalu = (len >> 8) & 0xFF;
// pNalu = (len >> 0) & 0xFF;
//
//
// auto _duration = e->Frame.Timestamp - _timestamp;
// _timestamp = e->Frame.Timestamp;
// printf("%d \n", _duration * timeScale / 1000);
// if (!MP4WriteSample(pHandle, videoId, pNalu, len + 4, _duration * timeScale / 1000, 0, isIdr))
// {
// printf("err\n");
// }
// offset += len;
// isIdr = true;
// }
// break;
// case 6: // SEI
// {
// int a = 5;
// }
// break;
// case 7: // SPS
// {
// if (addStream)
// {
// videoId = MP4AddH264VideoTrack
// (pHandle,
// timeScale, // һ Ӷ timescale
// timeScale / frameRate, // ÿ֡ жٸ timescale
// width, // width
// height, // height
// pNalu, // sps AVCProfileIndication
// pNalu, // sps profile_compat
// pNalu, // sps AVCLevelIndication
// 3); // 4 bytes length before each NAL unit
// if (videoId == MP4_INVALID_TRACK_ID)
// {
// printf("Error:Can't add track.\n");
// return -1;
// }
// MP4SetVideoProfileLevel(pHandle, 0x7F);
// addStream = 0;
// len = getNextNalu(pBuf, e->Frame.DataLength, offset);
// MP4AddH264SequenceParameterSet(pHandle, videoId, pNalu, len);
// goto gotNal;
// }
//
//
// }
// break;
// case 8: // PPS
// {
// len = getNextNalu(pBuf, e->Frame.DataLength, offset);
// printf("pps(%d)\n", len);
// MP4AddH264PictureParameterSet(pHandle, videoId, pNalu, len);
//
// goto gotNal;
// }
// break;
// case 9: // ֽ
// break;
// case 10: // н
// break;
// default:
//
// break;
// }
// }
// };
// }
// auto buffer = he->GetNV12Buffer();
// buffer.Timestamp = GetClock();
// for (int i = 0; i < height; i++)
// {
// memcpy(buffer.GetY() + i * buffer.GetPitch(), buf + i * width, width);
// }
// for (int i = 0; i < height / 2; i++)
// {
// memcpy(buffer.GetUV() + i * buffer.GetPitch(), buf + width * height + i * width, width);
// }
// buffer.IsForceIdr = false;
// he->Write(buffer);
// }
// catch (const std::exception& e) {
// printf(e.what());
// printf("\n");
// }
// catch (...) {
// printf(" δ֪ 쳣\n");
// }
// }
// virtual void OnCaptrue(const unsigned char* buf, int len, int width, int height, AC::CodingFormat format, unsigned int timestamp) override
// {
//
// }
//};
//
//
//
//
//// ڹ
//static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
//{
//
// switch (msg)
// {
// case WM_DESTROY:
// PostQuitMessage(0);
// break;
// }
//
// return DefWindowProc(hWnd, msg, wParam, lParam);
//}
//void GdiScreenCaptureTest() {
// WNDCLASS wndclass;
// wndclass.style = CS_HREDRAW | CS_VREDRAW;
// wndclass.lpfnWndProc = WndProc;
// wndclass.cbClsExtra = 0;
// wndclass.cbWndExtra = 0;
// wndclass.hInstance = GetModuleHandle(NULL);
// wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
// wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
// wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
// wndclass.lpszMenuName = 0;
// wndclass.lpszClassName = L"DemoWindow";
// if (!RegisterClass(&wndclass))
// {
// MessageBox(NULL, TEXT(" ʧ!"), L"", MB_ICONERROR);
// }
// auto title = L" ";
// HWND hwnd = CreateWindow(
// L"DemoWindow",
// title,
// WS_OVERLAPPEDWINDOW,
// 0,
// 0,
// 1280,
// 720,
// NULL,
// NULL,
// GetModuleHandle(NULL),
// NULL
// );
// ShowWindow(hwnd, SW_SHOW);
// sr.SetWindow(hwnd);
// sr.SetFormat(AC::PIXELFORMAT_NV12);
// sr.Initial();
// AC::GdiScreenCapture gc(NULL, AC::PIXELFORMAT_NV12);
// A a;
// gc.SetCallback(&a);
// gc.SetFramerate(20);
//
//
// AC::SoundCollector sc;
// AC::FdkaacEncoder fe({ 2,44100,16 });
// sc.SetBufferSize(1024);
// fe.SetAudioObjectType(AC::AudioObjectType::AUDIOOBJECTTYPE_AAC_LC);
// fe.SetBitrate(256 * 1024);
// fe.SetChannelMode(AC::ChannelMode::CHANNELMODE_2);
// fe.SetChannelOrder(AC::CHANNELORDER_WAV);
// fe.SetBitrateMode(AC::BitrateModde::BITRATEMODDE_CBR);
// fe.SetTransportType(AC::TRANSPORTTYPE_MP4_RAW);
//
// if (!pHandle)
// {
// pHandle = MP4Create("test.mp4", 0);
// if (pHandle == MP4_INVALID_FILE_HANDLE)
// {
// printf("ERROR:Create mp4 handle fialed.\n");
// return;
// }
// MP4SetTimeScale(pHandle, 90000);
// }
//
// // AAC track
// auto audio = MP4AddAudioTrack(pHandle, 44100, 1024, MP4_MPEG4_AUDIO_TYPE);
// if (audio == MP4_INVALID_TRACK_ID)
// {
// printf("Add audio track failed!\n");
// return;
// }
// FILE* faac = NULL;
// faac = fopen("test.aac", "wb+");
// // Ƶ
// MP4SetAudioProfileLevel(pHandle, 0x02);
// auto si = fe.GetDecoderSpecificInfo();
// auto pSi = (uint8_t*)&si;
// uint8_t temp = pSi;
// pSi = pSi;
// pSi = temp;
// MP4SetTrackESConfiguration(pHandle, audio, (uint8_t*)&si, 2);
//
// int64_t _atimestamp = 0;
// int64_t _aduration = 0;
//
// fe.EncodedDataArrived += [&](auto s, auto e) {
// fwrite(e->Frame.Data, 1, e->Frame.DataLength, faac);
// MP4WriteSample(pHandle, audio, e->Frame.Data, e->Frame.DataLength, MP4_INVALID_DURATION/* _aduration * 44100 / 1000*/, 0, 1);
// };
// bool isRun = false;
// sc.DataArrived += [&](auto s, auto e) {
//
//
// atime += e->DataLength * 1000.0 / (44100 * 16 / 8 * 2);
//
// if (_atimestamp)
// _aduration = clock() - _atimestamp;
// /*_atimestamp = clock();*/
//
// if (!isRun)
// {
// _timestamp = GetClock();
// /*atime = 0;
// gc.Start();*/
// isRun = true;
// }
//
// fe.Write(e->Data, e->DataLength);
// };
// _timestamp = GetClock();
// sc.Start(2, 44100, 16);
// gc.Start();
//
//
// MSG msg;
// HACCEL hAccelTable = NULL;
// // Ϣѭ:
// while (GetMessage(&msg, NULL, 0, 0))
// {
// if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
// {
// TranslateMessage(&msg);
// DispatchMessage(&msg);
// }
// }
// gc.Stop();
// sc.Stop();
// MP4Close(pHandle, 0);
// fclose(faac);
//}
//
//
//
//
//int main(int argc, char* argv[])
//{
// GdiScreenCaptureTest();
//
// return 0;
//}
int main2(int argc, char** argv) {
////std::vector<std::string> files;
////FileHelper::GetFolderFiles("E:\\Download\\Incubus\\IncubusQuest ver10", files);
////for (auto i : files)
////{
//// auto ws = AC::StringHelper::ShifJisToUnicode(i);
//// autos = AC::StringHelper::UnicodeToAnsi(ws);
//// int ret = rename(i.c_str(), s.c_str());
////}
//int d;
//scanf("%d", &d);
//auto ox = AC::StringHelper::Sprintf("%d", 15);
////AC::SoundCollectorTest();
//AC::SoundPlayTest();
//AC::WavFileReader read;
//AC::SoundPlay sp;
//unsigned char buf;
//if (read.OpenWavFile("test_music.wav"))
//{
// int channels, sampleRate, bitsPerSample;
// channels = read.GetChannels();
// sampleRate = read.GetSampleRate();
// bitsPerSample = read.GetBitsPerSample();
// sp.Opened += [&](auto s, auto e) {
// printf("ʼ :Channels %d SampleRate %d BitsPerSample %d\n", e->Format.Channels, e->Format.SampleRate, e->Format.BitsPerSample);
// };
// sp.DataDone += [&](auto s, auto e) {
// printf("%p ݲ : %d\n", e->Data, e->DataLength);
// };
// sp.Closed += [&](auto s, auto e) {
// printf(" رղ \n");
// };
// sp.Error += [&](auto s, auto e) {
// printf("%s\n", e->Message.c_str());
// };
// sp.Open(read.GetChannels(), read.GetSampleRate(), read.GetBitsPerSample());
// int size;
// do
// {
// //ȡƵ
// size = read.ReadData(buf, 1024);
// if (size > 0)
// {
// sp.Write(buf, size);
// }
// } while (size);
//}
////auto _play = acf_play_create();
//////acf_play_set_beginCallback(_play, beginCallback);
//////acf_play_set_renderCallback(_play, renderCallback);
////acf_play_play(_play, "212144271-1-192.mp4", 0);
return 0;
}
页:
[1]