On Wed, Feb 10, 2021 at 12:55 PM laddoe <xy...@hotmail.com> wrote: > I'm trying to encode(h264) a series of .png into a mp4 file. A cv::Mat > holds the png data (BGR) and that is converted to YUV420P which is then > encoded and written to a .mp4 file. I have added a block statement in the > code to store image on the disk (before encoding) and that image is correct > so the frame holds the correct data before it gets passed. The > avcodec_send_frame returns 0 so up to that point everything works. But I > get an mp4 file of 1 MB and I can't open it with vlc. Below is a short > summary of my code > > > ecodec.h > > class ECodec > { > public: > > MovieCodec(); > ~MovieCodec(); > void MatToFrame( cv::Mat& image ); > void encode( AVFrame *frame, AVPacket *pkt ); > > private: > > FILE* m_file; > AVCodec* m_encoder = NULL; > AVCodecContext* m_codecContextOut = NULL; > AVPacket* m_packet = NULL; > > }; > > > ecodec.cpp > > ECodec::ECodec() : > // m_encoder( avcodec_find_encoder_by_name( videoCodec.c_str())) > m_encoder( avcodec_find_encoder( AV_CODEC_ID_H264 )) > { > m_file = fopen( "c:\\tmp\\outputVideo.mp4", "wb"); > } > > > void ECodec::MatToFrame( cv::Mat& image ) > { > int ret( 0 ); > int frameRate( 24 ); > AVFrame *frame = NULL; > > m_encoder( avcodec_find_encoder( AV_CODEC_ID_H264 )) > m_codecContextOut = avcodec_alloc_context3( m_encoder ); > > m_codecContextOut->width = 800; > m_codecContextOut->height = 640; > m_codecContextOut->bit_rate = 400000;//m_codecContextOut->width * > m_codecContextOut->height * 3; > m_codecContextOut->time_base = (AVRational){1, 24}; > m_codecContextOut->framerate = (AVRational){24, 1}; > m_codecContextOut->codec_tag = AV_CODEC_ID_H264; > m_codecContextOut->pix_fmt = AV_PIX_FMT_YUV420P; > m_codecContextOut->codec_type = AVMEDIA_TYPE_VIDEO; > m_codecContextOut->gop_size = 1; > m_codecContextOut->max_b_frames = 1; > > av_log_set_level(AV_LOG_VERBOSE); > > ret = av_opt_set(m_codecContextOut->priv_data, "preset", "slow", 0); > > ret = avcodec_open2(m_codecContextOut, m_encoder, NULL); > > frame = av_frame_alloc(); > > frame->format = AV_PIX_FMT_YUV420P; > frame->width = image.cols(); > frame->height = image.rows(); > > > ret = av_image_alloc(frame->data, frame->linesize, frame->width, > frame->height, AV_PIX_FMT_YUV420P, 1); > > if (ret < 0) > { > return; > } > > struct SwsContext *sws_ctx; > sws_ctx = sws_getContext((int)image.cols(), (int)image.rows(), > AV_PIX_FMT_RGB24, > (int)image.cols(), (int)image.rows(), > AV_PIX_FMT_YUV420P, > 0, NULL, NULL, NULL); > > const uint8_t* rgbData[1] = { (uint8_t* )image.getData() }; > int rgbLineSize[1] = { 3 * image.cols() }; > > sws_scale(sws_ctx, rgbData, rgbLineSize, 0, image.rows(), frame->data, > frame->linesize); > > frame->pict_type = AV_PICTURE_TYPE_I; > > cv::Mat yuv420p(frame->height + frame->height/2, frame->width, > CV_8UC1,frame->data[0]); > cv::Mat cvmIm; > cv::cvtColor(yuv420p,cvmIm,CV_YUV420p2BGR); > cv::imwrite("c:\\tmp\\rawimage.png", cvmIm); > //OK > > m_packet = av_packet_alloc(); > ret = av_new_packet( m_packet, m_codecContextOut->width * > m_codecContextOut->height * 3 ); > > /* encode the image */ > encode( frame, m_packet ); > > > avcodec_free_context(&m_codecContextOut); > av_frame_free(&frame); > av_packet_free( &m_packet ); > } > > > void ECodec::encode( AVFrame *frame, AVPacket *pkt ) > { > int ret; > /* send the frame to the encoder */ > ret = avcodec_send_frame( m_codecContextOut, frame); > > if (ret < 0) > { > fprintf(stderr, "Error sending a frame for encoding\n"); > exit(1); > } > > do > { > ret = avcodec_receive_packet(m_codecContextOut, pkt); > if (ret == 0) > { > fwrite(pkt->data, 1, pkt->size, m_file ); >
You are writing raw encoded frames here. You nowhere use mov muxer code for muxing. av_packet_unref(pkt); > > break; > } > else if ((ret < 0) && (ret != AVERROR(EAGAIN))) > { > return; > } > else if (ret == AVERROR(EAGAIN)) > { > ret = avcodec_send_frame(m_codecContextOut, NULL); > if (0 > ret) > { > return; > } > } > } while (ret == 0); > } > _______________________________________________ > ffmpeg-user mailing list > ffmpeg-user@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-user > > To unsubscribe, visit link above, or email > ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-user mailing list ffmpeg-user@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-user To unsubscribe, visit link above, or email ffmpeg-user-requ...@ffmpeg.org with subject "unsubscribe".