Im trying to learn the basics of ffmpeg writing (reading already works), so im just trying to take in an input .ts file and write out/passthrough the exact same h264 stream to a new output file. I dont get any compilation errors, but for some reason i cant figure out why my output file's framerate is very wrong. Also when i read in my output file, i get printouts saying "Packet corrupt (stream = 0, dts = #)"
I followed the instructions in the ffmpeg library comments so im not sure what im missing. I call initOutStream(), then initH264encoder(), then during the reading/decoding readH264Packet() is called repeatedly. (Removed code for readability sake, left relevant sections below);
Edit: If i put my output file through the actuall ffmpeg cmd app, the framerate issue seems to get fixed. Wonder where im messing up
void test::initOutStream() {
//create muxing context
outstreamContext = avformat_alloc_context();
//oformat
AVOutputFormat *guessFormat; //Populate oformat
guessFormat = av_guess_format(NULL, inputVideoUrl.c_str(), NULL);
outstreamContext->oformat = guessFormat;
outstreamContext->oformat->video_codec = AV_CODEC_ID_H264;
//outstreamContext->bit_rate = 400000; //No affect;
//pb
AVIOContext *outAVIOContext = nullptr;
//int result = avio_open(&outAVIOContext, outputVideoUrl.c_str(), AVIO_FLAG_WRITE);
int result = avio_open2(&outAVIOContext, outputVideoUrl.c_str(), AVIO_FLAG_WRITE, NULL, NULL); //Documentain said to use this method
outstreamContext->pb = outAVIOContext;
}
.
void test::initH264encoder() { //Frame -> packet
int result;
h264OutCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
h264OutStream = avformat_new_stream(outstreamContext, h264OutCodec);
h264OutStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
h264OutStream->codecpar->codec_id = AV_CODEC_ID_H264;
h264OutStream->codecpar->width = 640;
h264OutStream->codecpar->height = 480;
h264OutStream->id = H264_STREAM_ID;
h264OutStream->codecpar->color_range = AVCOL_RANGE_MPEG;
//h264OutStream->codecpar->bit_rate = 400000;
h264OutContext = avcodec_alloc_context3(h264OutCodec);
h264OutContext->width = 640;
h264OutContext->height = 480;
h264OutContext->time_base = (AVRational){1,static_cast<int>(29.97)};
h264OutContext->pix_fmt = AV_PIX_FMT_YUV420P;
result = avcodec_open2(h264OutContext, h264OutCodec, nullptr);
//Alloc packet + finish
outPacket = av_packet_alloc();
//Write header
result = avformat_write_header(outstreamContext, NULL);
}
Assume that reading was set up correctly
void test::readH264Packet(__unused uint64_t tick) {
//...av_read_frame(streamContext, inPacket);
//...avcodec_send_packet(h264Context, inPacket);
//...avcodec_receive_frame(h264Context, yuvFrame)
//My passthrough:
if(shouldOutputH264Stream){
result = avcodec_send_frame(h264OutContext, yuvFrame); //1. Encode frame to packet
result = avcodec_receive_packet(h264OutContext, outPacket2); //2. get encoded packet
result = av_interleaved_write_frame(outstreamContext, outPacket2); //3. write packet
//Write trailer and free happens later
}
}