From images to ts
Posted: Fri Jan 26, 2018 9:57 am
Hi, all
I wish to encode a list of PNG images (with 4 channels) to a video while streaming it as a TS stream, but when i open the ts file with a general video player, the Last Two frames cannot be shown. But when i open it with StreamEye, all frames can be represented. I don't know what will results it, the C code as following:
Can anybody help me?
Thank you very much and Best regards
I wish to encode a list of PNG images (with 4 channels) to a video while streaming it as a TS stream, but when i open the ts file with a general video player, the Last Two frames cannot be shown. But when i open it with StreamEye, all frames can be represented. I don't know what will results it, the C code as following:
Code: Select all
extern "C"
{
//#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/opt.h"
#include "libavutil/mathematics.h"
#include "libavutil/timestamp.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/imgutils.h"
};
#define PNG_PATH "./tempPNG/"
#define FRAME_NUM 54
#define TS_FPS 1
#define STREAMING_BUFFER_SIZE (188)
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
#define SCALE_FLAGS SWS_BICUBIC
int test_write_buffer(void* opaque, uint8_t* buf, int buf_size)
{
FILE* fp = NULL;
char path[256] = { 0 };
sprintf(path, "%stest123.ts", PNG_PATH);
fp = fopen(path, "ab+");
fwrite(buf, 1, buf_size, fp);
fclose(fp);
return 1;
}
void main()
{
AVFormatContext* pFormatCtx = NULL;
AVOutputFormat* pOutputFmt = NULL;
AVCodec* pCodec = NULL;
AVStream* pStream = NULL;
AVCodecContext* pCodecCtx = NULL;
av_register_all();
/****************************************** Format Setting *****************************************/
avformat_alloc_output_context2(&pFormatCtx, NULL, "mpegts", NULL);
if (!pFormatCtx) {
ffmDug("Could not create output context");
exit(1);
}
ffmDug("Format: %s", pFormatCtx->oformat->long_name);
uint8_t* outbuffer = (uint8_t*)av_malloc(STREAMING_BUFFER_SIZE);
AVIOContext *avio_out = avio_alloc_context(outbuffer, STREAMING_BUFFER_SIZE, 1, NULL, NULL,
temp_write_packet, NULL);
pFormatCtx->pb = avio_out;
pFormatCtx->flags = AVFMT_FLAG_CUSTOM_IO;
/****************************************** Stream setting ***************************************/
// Build output stream
pStream = avformat_new_stream(pFormatCtx, 0);
if (!pStream) {
ffmDug("Failed allocating output stream");
exit(1);
}
// pStream->id = pFormatCtx->nb_streams - 1;
// Find the registered encoder for codec_id(AV_CODEC_ID_*)
pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!pCodec) {
ffmDug("Could not find encoder for H264");
exit(1);
}
// Allocate memory for Codec Context to hold the context for encode process
pCodecCtx = avcodec_alloc_context3(pCodec);
pStream->codec = pCodecCtx;
pStream->codec->codec_tag = 0;
if (pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
pStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
pCodecCtx->width = 1280;
pCodecCtx->height = 720;
pCodecCtx->bit_rate = 400000;
pCodecCtx->codec_id = AV_CODEC_ID_H264;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->time_base = (AVRational){1, TS_FPS};
pStream->time_base = (AVRational){1, TS_FPS};
pStream->r_frame_rate = (AVRational) {1, TS_FPS};
pCodecCtx->gop_size = 5;
pCodecCtx->pix_fmt = STREAM_PIX_FMT;
pCodecCtx->me_range = 16;
pCodecCtx->max_qdiff = 4;
pCodecCtx->qmin = 10;
pCodecCtx->qmax = 51;
pCodecCtx->max_b_frames = 0;
pCodecCtx->refs = 2;
pCodecCtx->qcompress = 0.6;
av_opt_set(pCodecCtx->priv_data,"preset","veryfast", 0);
av_opt_set(pCodecCtx->priv_data,"tune","zerolatency",0);
// Fill CODEC parameter with codec context
int ret = avcodec_parameters_from_context(pStream->codecpar, pCodecCtx);
if (ret < 0)
{
ffmDug("Could not copy the stream parameters\n");
exit(1);
}
// Open codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
ffmDug("Could not open codec\n");
exit(1);
}
av_dump_format(pFormatCtx, 0, "whatever", 1);
// Write format header
ret = avformat_write_header(pFormatCtx, NULL);
if (ret < 0)
{
ffmDug("Error occurred when writing the header\n");
exit(1);
}
// Allocate YUV frame memory
AVFrame* pFrame = av_frame_alloc();
if(!pFrame)
{
ffmDug("Could not allocate video frame\n");
exit(1);
}
pFrame->format = pCodecCtx->pix_fmt;
pFrame->width = pCodecCtx->width;
pFrame->height = pCodecCtx->height;
ret = av_frame_get_buffer(pFrame, 32);
if (ret < 0)
{
ffmDug("Could not allocate raw picture buffer\n");
exit(1);
}
// Allocate BGRA frame memory
AVFrame* pFrame_rgba = av_frame_alloc();
if(!pFrame_rgba)
{
ffmDug("Could not allocate rgba frame\n");
exit(1);
}
pFrame_rgba->format = AV_PIX_FMT_BGRA;
pFrame_rgba->width = pCodecCtx->width;
pFrame_rgba->height = pCodecCtx->height;
ret = av_frame_get_buffer(pFrame_rgba, 32);
if (ret < 0)
{
ffmDug("Could not allocate rgba picture buffer\n");
exit(1);
}
struct SwsContext* sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_BGRA, pCodecCtx->width,
pCodecCtx->height, STREAM_PIX_FMT,
SCALE_FLAGS, NULL, NULL, NULL);
if (!sws_ctx)
{
ffmDug("Could not initialize the conversion context\n");
exit(1);
}
// Build compressed frame variable
AVPacket* pkt = av_packet_alloc();
for (int idx = 0; idx < FRAME_NUM; idx++) {
char picture[256] = { 0 };
sprintf(picture, "%s%d.png", PNG_PATH, idx);
FILE* fp = fopen(picture, "rb");
if (fp == NULL)
{
ffmDug("Failed to open the %d-th image\n", idx);
fclose(fp);
exit(1);
}
get_png_data(pFrame_rgba, fp);
fclose(fp);
sws_scale(sws_ctx, (const uint8_t* const*)pFrame_rgba->data,
pFrame_rgba->linesize, 0, pCodecCtx->height, pFrame->data,
pFrame->linesize);
pFrame->pts = idx;
// Send the raw data frame to encoder, through the codec context
ret = avcodec_send_frame(pCodecCtx, pFrame);
while (ret >= 0) {
// Receive the raw data packet from encoder,
// through the same codec context
ret = avcodec_receive_packet(pCodecCtx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
ffmDug("Error during encoding\n");
exit(1);
}
ffmDug("Write packet %3"PRId64" (size = 5%d)", pkt->pts, pkt->size);
pkt->stream_index = pStream->index;
av_packet_rescale_ts(pkt, pCodecCtx->time_base, pStream->time_base);
av_interleaved_write_frame(pFormatCtx, pkt);
av_packet_unref(pkt);
}
}
av_write_trailer(pFormatCtx);
}
Thank you very much and Best regards