Hi, After encoding an H264 video, the output video has 1 frame only shown with duration of 1 second (That's using VLC media player, it doesn't even play with WMP - Shows corrupt file -), I also get "[libx264 @ 01f60060] non-strictly-monotonic PTS" Warning while encoding frames, so I guess it is a PTS problem. How do I set the PTS/DTS for a packet in H264?
Here is my code: (http://pastebin.com/WibnmKLV) ******************************************** #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" #include "libavutil/avutil.h" #include "libavutil/rational.h" #include <stdio.h> int main() { av_register_all(); //avcodec_register_all(); av_log_set_level(AV_LOG_DEBUG); AVFormatContext *ps = avformat_alloc_context(); AVFormatContext *ps2 = NULL;//avformat_alloc_context(); AVOutputFormat *oF = av_guess_format("mp4", NULL, "video/mp4"); if(avformat_open_input(&ps, "vid.mp4", NULL, NULL) != 0) { printf("Failed to open input file.\n"); return -1; } avformat_alloc_output_context2(&ps2, oF, NULL, "vid2.mp4"); avformat_find_stream_info(ps, NULL); ps2->metadata = ps->metadata; AVCodecContext **pC = (AVCodecContext**)malloc(ps->nb_streams), **p2C = (AVCodecContext**)malloc(ps->nb_streams); AVStream *oStream = NULL; AVStream *iStream = NULL; AVCodec *encoder = NULL; AVCodec *decoder = NULL; AVCodecContext *strCtx = NULL; unsigned int i; avio_open(&ps2->pb, "vid2.mp4", AVIO_FLAG_WRITE); for(i = 0; i < ps->nb_streams; i++) { printf("%d\n", i); iStream = ps->streams[i]; pC[i] = iStream->codec; if(pC[i]->codec_type == AVMEDIA_TYPE_UNKNOWN) { printf("Skipping bad stream\n"); continue; } if(pC[i]->codec_type == AVMEDIA_TYPE_VIDEO || pC[i]->codec_type == AVMEDIA_TYPE_AUDIO) { encoder = avcodec_find_encoder(pC[i]->codec_id); //encoder->init(p2C[i]); if (!encoder) { av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n"); return AVERROR_INVALIDDATA; } oStream = avformat_new_stream(ps2, encoder); strCtx = oStream->codec; //We have to set oStream->codec parameters for write_header to work, //since write_header only relies on the stream parameters. p2C[i] = avcodec_alloc_context3(encoder); AVDictionary *param = NULL; if (pC[i]->codec_type == AVMEDIA_TYPE_VIDEO) { p2C[i]->width = pC[i]->width; p2C[i]->height = pC[i]->height; if (encoder->pix_fmts) p2C[i]->pix_fmt = encoder->pix_fmts[0]; else p2C[i]->pix_fmt = pC[i]->pix_fmt; p2C[i]->sample_rate = pC[i]->sample_rate; p2C[i]->sample_aspect_ratio = pC[i]->sample_aspect_ratio; p2C[i]->frame_size = pC[i]->frame_size; p2C[i]->time_base = pC[i]->time_base; strCtx->width = pC[i]->width; strCtx->height = pC[i]->height; if (encoder->pix_fmts) strCtx->pix_fmt = encoder->pix_fmts[0]; else strCtx->pix_fmt = pC[i]->pix_fmt; strCtx->sample_rate = pC[i]->sample_rate; strCtx->sample_aspect_ratio = pC[i]->sample_aspect_ratio; strCtx->time_base = pC[i]->time_base; strCtx->frame_size = pC[i]->frame_size; } else { p2C[i]->sample_rate = pC[i]->sample_rate; p2C[i]->channel_layout = pC[i]->channel_layout; p2C[i]->channels = av_get_channel_layout_nb_channels(p2C[i]->channel_layout); // take first format from list of supported formats p2C[i]->sample_fmt = encoder->sample_fmts[0]; p2C[i]->time_base = (AVRational){1, p2C[i]->sample_rate}; strCtx->sample_rate = pC[i]->sample_rate; strCtx->channel_layout = pC[i]->channel_layout; strCtx->channels = av_get_channel_layout_nb_channels(strCtx->channel_layout); // take first format from list of supported formats strCtx->sample_fmt = encoder->sample_fmts[0]; strCtx->time_base = (AVRational){1, strCtx->sample_rate}; } //AVCodecParameters *par = avcodec_parameters_alloc(); //avcodec_parameters_from_context(par, pC[i]); //avcodec_parameters_to_context(p2C[i], par); decoder = avcodec_find_decoder(pC[i]->codec_id); if(decoder == NULL) printf("Couldn't find decoder\n"); if(pC[i]->codec_type == AVMEDIA_TYPE_VIDEO) { int ret1 = avcodec_open2(pC[i], decoder, ¶m); int ret2 = avcodec_open2(p2C[i], encoder, ¶m); char err[200]; av_make_error_string(err, 200, ret2); printf("Ret2 %d: %s\n", ret2, err); } else { int ret1 = avcodec_open2(pC[i], decoder, NULL); int ret2 = avcodec_open2(p2C[i], encoder, NULL); printf("Ret1: %d | Ret2: %d\n", ret1, ret2); } //p2C-> = pC[i]->pts; } else if (pC[i]->codec_type == AVMEDIA_TYPE_UNKNOWN) { av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i); //return AVERROR_INVALIDDATA; } else { //avcodec_copy_context(oStream->codec, iStream->codec); printf("BUG\n"); } } printf("done\n"); int ret = avformat_write_header(ps2, NULL); char err[200]; av_make_error_string(err, 200, ret); printf("Write header %d: %s\n", ret, err); unsigned int j = 0; for(;; ++j) { AVPacket *pkts = av_packet_alloc(); pkts->data = NULL; pkts->size = 0; AVPacket *pktr = av_packet_alloc(); pktr->data = NULL; pktr->size = 0; AVFrame *rawFrame = av_frame_alloc(); av_init_packet(pkts); av_init_packet(pktr); if(av_read_frame(ps, pkts) != 0) break; //pkts->pts = av_rescale_q_rnd(pkts->pts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); //pkts->dts = av_rescale_q_rnd(pkts->dts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); //pkts->duration = av_rescale_q(pkts->duration, ps->streams[pkts->stream_index]->time_base, ps->streams[pkts->stream_index]->time_base); //pktr->pts = av_rescale_q_rnd(pkts->pts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); //pktr->dts = av_rescale_q_rnd(pkts->dts, ps->streams[pkts->stream_index]->time_base, ps2->streams[pkts->stream_index]->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); //pktr->duration = av_rescale_q(pkts->duration, ps->streams[pkts->stream_index]->time_base, ps->streams[pkts->stream_index]->time_base); //decoding pktr->stream_index = pkts->stream_index; //decoding int dret = 0, eret = 0; dret = avcodec_send_packet(pC[pkts->stream_index], pkts); if(dret == 0) { if(avcodec_receive_frame(pC[pkts->stream_index], rawFrame) == 0) { //rawFrame->pts = av_frame_get_best_effort_timestamp(rawFrame); //encoding eret = avcodec_send_frame(p2C[pktr->stream_index], rawFrame); if(eret == 0) { if(avcodec_receive_packet(p2C[pktr->stream_index], pktr) == 0) { printf("Succ dec/enc Stream index %d\n", pkts->stream_index); if(av_interleaved_write_frame(ps2, pktr) != 0) { printf("Failed to write packet\n"); break; } //printf("packet written\n"); } else printf("avcodec_receive_packet\n"); } else if(eret == AVERROR(EINVAL)) { avcodec_flush_buffers(p2C[i]); } else if(eret == AVERROR(EAGAIN)) { printf("avcodec_send_frame requires flushing...\n"); avcodec_send_frame(p2C[pkts->stream_index], NULL); while(1) { eret = avcodec_receive_packet(p2C[pktr->stream_index], pktr); if(eret != AVERROR_EOF) break; printf("eret: %d\n", eret); } //avcodec_flush_buffers(pC[pkts->stream_index]); } else { printf("avcodec_send_frame Stream index %d\n", pkts->stream_index); } } else printf("avcodec_receive_frame\n"); } else if(dret == AVERROR(EINVAL)) { avcodec_flush_buffers(pC[i]); } else if(dret == AVERROR(EAGAIN)) { printf("avcodec_send_packet requires flushing...\n"); avcodec_send_packet(pC[pkts->stream_index], NULL); while(1) { dret = avcodec_receive_frame(pC[pkts->stream_index], rawFrame); if(dret == AVERROR_EOF) break; printf("dret: %d\n", dret); } avcodec_flush_buffers(pC[pkts->stream_index]); } else printf("avcodec_send_packet other error.\n"); av_packet_free(&pkts); av_packet_free(&pktr); av_frame_free(&rawFrame); av_frame_unref(rawFrame); } if(av_write_trailer(ps2) == 0) printf("Wrote trailer\n"); } ******************************************** Thanks in advance. _______________________________________________ Libav-user mailing list [email protected] http://ffmpeg.org/mailman/listinfo/libav-user
