FFMPEG/C++ How to simply write out/passthrough h264 stream?

Viewed 296

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
    }
}
0 Answers
Related