Video transcoding kind of works (at least if input video frames has correct pts/dts)
This commit is contained in:
parent
c4a6e2f0bf
commit
141e8bdd4c
77
main.cpp
77
main.cpp
@ -8,7 +8,7 @@ void checkResult(int res, const char* msg) {
|
||||
if(res < 0) {
|
||||
char errStr[260];
|
||||
av_strerror(res, errStr, 260);
|
||||
std::cout << msg << ": " << errStr << std::endl;
|
||||
std::cerr << msg << ": " << errStr << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,21 +49,6 @@ int main(int argc, char** argv) {
|
||||
AVCodec* dstVCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||||
if(!dstVCodec) std::cout << "cannot find encoder" << std::endl;
|
||||
|
||||
AVCodecContext* dstVCodecCtx = avcodec_alloc_context3(dstVCodec);
|
||||
if(!dstVCodecCtx) std::cout << "cannot allocate context" << std::endl;
|
||||
|
||||
dstVCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
dstVCodecCtx->width = codecCtx->width;
|
||||
dstVCodecCtx->height = codecCtx->height;
|
||||
dstVCodecCtx->time_base = codecCtx->time_base;
|
||||
outFmtCtx->duration = inFmtCtx->duration;
|
||||
|
||||
res = avcodec_open2(dstVCodecCtx, dstVCodec, nullptr);
|
||||
checkResult(res, "cannot open codec for encoding");
|
||||
|
||||
if(outFmtCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
dstVCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
AVStream* outVideoStream = avformat_new_stream(outFmtCtx, dstVCodec);
|
||||
if(!outVideoStream) std::cout << "cannot create output video stream" << std::endl;
|
||||
|
||||
@ -74,15 +59,29 @@ int main(int argc, char** argv) {
|
||||
|
||||
av_dump_format(outFmtCtx, 0, argv[2], 1);
|
||||
|
||||
AVCodecContext* dstVCodecCtx = outVideoStream->codec;
|
||||
dstVCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
dstVCodecCtx->width = codecCtx->width;
|
||||
dstVCodecCtx->height = codecCtx->height;
|
||||
//dstVCodecCtx->time_base = codecCtx->time_base;
|
||||
outVideoStream->time_base = codecCtx->time_base;
|
||||
outFmtCtx->duration = inFmtCtx->duration;
|
||||
|
||||
if(outFmtCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
dstVCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
res = avcodec_open2(dstVCodecCtx, dstVCodec, nullptr);
|
||||
checkResult(res, "cannot open codec for encoding");
|
||||
|
||||
res = avformat_write_header(outFmtCtx, nullptr);
|
||||
checkResult(res, "error writing header to output file");
|
||||
|
||||
AVPacket packet;
|
||||
packet.data = nullptr;
|
||||
packet.size = 0;
|
||||
AVFrame* frame = nullptr;
|
||||
int gotPicture = 0, gotPacket = 0, decodedFrames = 1;
|
||||
while(true) {
|
||||
AVPacket packet;
|
||||
packet.data = nullptr;
|
||||
packet.size = 0;
|
||||
res = av_read_frame(inFmtCtx, &packet);
|
||||
if(res < 0) break;
|
||||
|
||||
@ -99,7 +98,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
if(gotPicture) {
|
||||
frame->pts = av_frame_get_best_effort_timestamp(frame);
|
||||
std::cout << "decoded frame: " << decodedFrames++ << std::endl;
|
||||
frame->pict_type = AV_PICTURE_TYPE_NONE;
|
||||
//std::cout << "decoded frame: " << decodedFrames++ << " pts: " << frame->pts << ", dts: " << frame->pkt_dts << std::endl;
|
||||
|
||||
AVPacket encPacket;
|
||||
encPacket.data = nullptr;
|
||||
@ -107,19 +107,12 @@ int main(int argc, char** argv) {
|
||||
av_init_packet(&encPacket);
|
||||
encPacket.stream_index = 0;
|
||||
|
||||
encPacket.pts = decodedFrames;
|
||||
encPacket.dts = decodedFrames;
|
||||
|
||||
res = avcodec_encode_video2(dstVCodecCtx, &encPacket, frame, &gotPacket);
|
||||
av_frame_free(&frame);
|
||||
if(res < 0) break;
|
||||
if(!gotPacket) continue;
|
||||
|
||||
AVStream *st = outFmtCtx->streams[encPacket.stream_index];
|
||||
auto x = st->codec->has_b_frames;
|
||||
auto y = st->codec->max_b_frames;
|
||||
|
||||
//av_packet_rescale_ts(&encPacket, st->codec->time_base, st->time_base);
|
||||
av_packet_rescale_ts(&encPacket, videoStream->time_base, outVideoStream->time_base);
|
||||
|
||||
res = av_interleaved_write_frame(outFmtCtx, &encPacket);
|
||||
checkResult(res, "cannot write frame to output file");
|
||||
@ -130,8 +123,34 @@ int main(int argc, char** argv) {
|
||||
av_free_packet(&packet);
|
||||
}
|
||||
|
||||
av_write_trailer(outFmtCtx);
|
||||
// flush encoder
|
||||
if(dstVCodecCtx->codec->capabilities & AV_CODEC_CAP_DELAY) {
|
||||
std::cout << "flushing encoder" << std::endl;
|
||||
int gotFrame = 0;
|
||||
while (1) {
|
||||
AVPacket encPacket;
|
||||
encPacket.data = nullptr;
|
||||
encPacket.size = 0;
|
||||
av_init_packet(&encPacket);
|
||||
encPacket.stream_index = 0;
|
||||
res = avcodec_encode_video2(dstVCodecCtx, &encPacket, nullptr, &gotFrame);
|
||||
if (res < 0) {
|
||||
std::cout << "avcodec_encode_video2 failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
if (gotFrame) {
|
||||
//std::cout << "extra frame" << std::endl;
|
||||
av_packet_rescale_ts(&encPacket, videoStream->time_base, outVideoStream->time_base);
|
||||
res = av_interleaved_write_frame(outFmtCtx, &encPacket);
|
||||
checkResult(res, "[flush encoder] cannot write frame to output file");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res = av_write_trailer(outFmtCtx);
|
||||
checkResult(res, "error writing trailer to output file");
|
||||
|
||||
if(codecCtx)
|
||||
avcodec_close(codecCtx);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user