Skip to content

Instantly share code, notes, and snippets.

@falsycat
Created June 29, 2022 08:58
Show Gist options
  • Save falsycat/172af198c0a855ef004cd1014d6705ed to your computer and use it in GitHub Desktop.
Save falsycat/172af198c0a855ef004cd1014d6705ed to your computer and use it in GitHub Desktop.
read mp4 video using openh264 + minimp4.h
#include <cassert>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <fstream>
#include <vector>
#define MINIMP4_IMPLEMENTATION
#include "minimp4.h"
#include "../codec/api/wels/codec_api.h"
size_t g_size = 0;
int read_cb(int64_t off, void* buf, size_t size, void* ptr) {
std::ifstream* f = (std::ifstream*) ptr;
size_t n = g_size - off - size;
if (size < n) n = size;
f->seekg(off);
assert(*f);
f->read((char*) buf, n);
assert(*f);
return 0;
}
int main() {
std::ifstream f("hello.mp4", std::ifstream::binary | std::ifstream::ate);
g_size = f.tellg();
assert(f);
// decoder init
ISVCDecoder* dec;
WelsCreateDecoder(&dec);
SDecodingParam dparam = {};
dparam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
dparam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
dparam.eEcActiveIdc = ERROR_CON_SLICE_COPY;
dec->Initialize(&dparam);
int level = WELS_LOG_DEBUG;
dec->SetOption(DECODER_OPTION_TRACE_LEVEL, &level);
uint8_t* yuv[3] = {0};
SBufferInfo frame = {};
// demux
MP4D_demux_t dem = {};
MP4D_open(&dem, read_cb, &f, g_size);
std::vector<uint8_t> temp;
for (int ti = 0; ti < dem.track_count; ++ti) {
const auto& t = dem.track[ti];
if (t.handler_type == MP4D_HANDLER_TYPE_VIDE) {
for (size_t si = 0;; ++si) {
int sz;
auto sps = (uint8_t*) MP4D_read_sps(&dem, ti, si, &sz);
if (!sps) break;
std::cout << "sps#" << si << std::endl;
temp.resize(sz+4);
temp[0] = 0;
temp[1] = 0;
temp[2] = 0;
temp[3] = 1;
std::memcpy(&temp[4], sps, sz);
auto ret = dec->DecodeFrameNoDelay(temp.data(), temp.size(), yuv, &frame);
std::cout << " ret: " << ret << std::endl;
}
for (size_t pi = 0;; ++pi) {
int sz;
auto pps = (uint8_t*) MP4D_read_pps(&dem, ti, pi, &sz);
if (!pps) break;
std::cout << "pps#" << pi << std::endl;
temp.resize(sz+4);
temp[0] = 0;
temp[1] = 0;
temp[2] = 0;
temp[3] = 1;
std::memcpy(&temp[4], pps, sz);
auto ret = dec->DecodeFrameNoDelay(temp.data(), temp.size(), yuv, &frame);
std::cout << " ret: " << ret << std::endl;
}
for (size_t si = 0; si < t.sample_count; ++si) {
unsigned fsz, time, dur;
const auto off = MP4D_frame_offset(&dem, ti, si, &fsz, &time, &dur);
std::cout << "frame#" << si << std::endl;
std::cout << " off: " << off << std::endl;
f.seekg(off);
assert(f);
temp.resize(fsz);
f.read((char*) temp.data(), fsz);
assert(f);
for (size_t i = 0; i < temp.size();) {
uint32_t sz = (temp[i] << 24) | (temp[i+1] << 16) | (temp[i+2] << 8) | temp[i+3];
sz += 4;
temp[0] = 0;
temp[1] = 0;
temp[2] = 0;
temp[3] = 1;
auto ret = dec->DecodeFrameNoDelay(&temp[i], sz, yuv, &frame);
std::cout << " result: " << ret << std::endl;
i += sz;
}
}
} else {
assert(false);
}
}
MP4D_close(&dem);
dec->Uninitialize();
WelsDestroyDecoder(dec);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment