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) {
|
if(res < 0) {
|
||||||
char errStr[260];
|
char errStr[260];
|
||||||
av_strerror(res, 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);
|
AVCodec* dstVCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||||||
if(!dstVCodec) std::cout << "cannot find encoder" << std::endl;
|
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);
|
AVStream* outVideoStream = avformat_new_stream(outFmtCtx, dstVCodec);
|
||||||
if(!outVideoStream) std::cout << "cannot create output video stream" << std::endl;
|
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);
|
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);
|
res = avformat_write_header(outFmtCtx, nullptr);
|
||||||
checkResult(res, "error writing header to output file");
|
checkResult(res, "error writing header to output file");
|
||||||
|
|
||||||
AVPacket packet;
|
|
||||||
packet.data = nullptr;
|
|
||||||
packet.size = 0;
|
|
||||||
AVFrame* frame = nullptr;
|
AVFrame* frame = nullptr;
|
||||||
int gotPicture = 0, gotPacket = 0, decodedFrames = 1;
|
int gotPicture = 0, gotPacket = 0, decodedFrames = 1;
|
||||||
while(true) {
|
while(true) {
|
||||||
|
AVPacket packet;
|
||||||
|
packet.data = nullptr;
|
||||||
|
packet.size = 0;
|
||||||
res = av_read_frame(inFmtCtx, &packet);
|
res = av_read_frame(inFmtCtx, &packet);
|
||||||
if(res < 0) break;
|
if(res < 0) break;
|
||||||
|
|
||||||
@ -99,7 +98,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
if(gotPicture) {
|
if(gotPicture) {
|
||||||
frame->pts = av_frame_get_best_effort_timestamp(frame);
|
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;
|
AVPacket encPacket;
|
||||||
encPacket.data = nullptr;
|
encPacket.data = nullptr;
|
||||||
@ -107,19 +107,12 @@ int main(int argc, char** argv) {
|
|||||||
av_init_packet(&encPacket);
|
av_init_packet(&encPacket);
|
||||||
encPacket.stream_index = 0;
|
encPacket.stream_index = 0;
|
||||||
|
|
||||||
encPacket.pts = decodedFrames;
|
|
||||||
encPacket.dts = decodedFrames;
|
|
||||||
|
|
||||||
res = avcodec_encode_video2(dstVCodecCtx, &encPacket, frame, &gotPacket);
|
res = avcodec_encode_video2(dstVCodecCtx, &encPacket, frame, &gotPacket);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
if(res < 0) break;
|
if(res < 0) break;
|
||||||
if(!gotPacket) continue;
|
if(!gotPacket) continue;
|
||||||
|
|
||||||
AVStream *st = outFmtCtx->streams[encPacket.stream_index];
|
av_packet_rescale_ts(&encPacket, videoStream->time_base, outVideoStream->time_base);
|
||||||
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);
|
|
||||||
|
|
||||||
res = av_interleaved_write_frame(outFmtCtx, &encPacket);
|
res = av_interleaved_write_frame(outFmtCtx, &encPacket);
|
||||||
checkResult(res, "cannot write frame to output file");
|
checkResult(res, "cannot write frame to output file");
|
||||||
@ -130,8 +123,34 @@ int main(int argc, char** argv) {
|
|||||||
av_free_packet(&packet);
|
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)
|
if(codecCtx)
|
||||||
avcodec_close(codecCtx);
|
avcodec_close(codecCtx);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user