Cannot wrie header FFMPEG - c++

I'm working on a Project with FFMPEg, but somehow i cannot creae any media file. I've set the Parameters, codec etc. but when i call avformat_write_header the app just stops working.
Here's my code:
AVOutputFormat *fmt;
AVCodecContext *codecctx;
AVFormatContext *fmtctx;
fmt=av_guess_format(NULL,filename,NULL);
AVCodec *codec = avcodec_find_encoder(fmt->video_codec);
codecctx = avcodec_alloc_context3(codec);
codecctx->codec_id = fmt->video_codec;
codecctx->codec_type = AVMEDIA_TYPE_VIDEO;
codecctx->gop_size = 12;
codecctx->bit_rate = WIDTH*HEIGHT*4;
codecctx->width = WIDTH;
codecctx->height = HEIGHT;
codecctx->time_base.den = 2;
codecctx->time_base.num =1;
//codecctx->time_base =(AVRational){1,FPS};
codecctx->max_b_frames=1;
codecctx->pix_fmt= STREAM_PIX_FMT;
fmtctx = avformat_alloc_context();
fmtctx->oformat = fmt;
fmtctx->video_codec_id = fmt->video_codec;
avcodec_open2(codecctx, codec, NULL);
AVStream *VideoStream = avformat_new_stream(fmtctx,codec);
avformat_write_header(fmtctx,NULL);

The main API functions for muxing are avformat_write_header() for writing the file header, av_write_frame() / av_interleaved_write_frame() for writing the packets and av_write_trailer() for finalizing the file.
check this link
http://ffmpeg.org/doxygen/trunk/group__lavf__encoding.html#details

Related

av_read_frame of ffmpeg in windows always returning random packet.stream_index

I'm using ffmpeg to decode an rtsp stream, the av_read_frame is always returning random value on packet.stream_index.
The stream have only 2 index, 1 video and 1 audio respectively on streams[0] and streams[1].
But when i call av_read_frame, i've random value on packet.stream_index and no data in the packet.
If someone can help me, i'm beginner in FFMPEG.
I add my simplified code to make you an idea of what i do :
AVFormatContext* input_ctx = NULL;
AVStream* video_st = NULL;
AVCodecContext* decoder_ctx = NULL;
AVCodec* decoder;
AVPacket pkt = { 0 };
AVFrame* frame = NULL;
DWORD dwHeight = 576;
DWORD dwWidth = 704;
int ret, i;
input_ctx = avformat_alloc_context();
/* open the input file */
ret = avformat_open_input(&input_ctx, "rtsp://**************************/Streaming/Channels/102?profile=Profile_1", NULL, NULL);
avformat_find_stream_info(input_ctx, NULL);
av_dump_format(input_ctx, 0, "rtsp://**************************/Streaming/Channels/102?profile=Profile_1", 0);
av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, 0, -1, &decoder, 0);
/* find the first H.264 video stream */
for (i = 0; i < input_ctx->nb_streams-1; i++) {
AVStream *st = input_ctx->streams[i];
video_st = st;
}
decoder_ctx = input_ctx->streams[0]->codec;
decoder = avcodec_find_decoder(decoder_ctx->codec_id);
decoder_ctx = avcodec_alloc_context3(decoder);
ret = avcodec_open2(decoder_ctx, NULL, NULL);
frame = av_frame_alloc();
av_read_play(input_ctx);
/* actual decoding */
while (ret >= 0) {
ret = av_read_frame(input_ctx, &pkt);
if (pkt.stream_index == video_st->index) {
if ((avcodec_send_packet != NULL)&&(avcodec_receive_frame!=NULL)) {
ret = avcodec_send_packet(decoder_ctx, pkt);
Thx in advance.

c++ - using FFmpeg encode and UDP with a Webcam

I'm trying to get frames from a Webcam using OpenCV, encode them with FFmpeg and send them using UDP.
I did before a similar project that instead of sending the packets with UDP, it saved them in a video file.
My code is.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
#define WIDTH 640
#define HEIGHT 480
#define CODEC_ID AV_CODEC_ID_H264
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P
static AVFrame *frame, *pFrameBGR;
int main(int argc, char **argv)
{
VideoCapture cap(0);
const char *url = "udp://127.0.0.1:8080";
AVFormatContext *formatContext;
AVStream *stream;
AVCodec *codec;
AVCodecContext *c;
AVDictionary *opts = NULL;
int ret, got_packet;
if (!cap.isOpened())
{
return -1;
}
av_log_set_level(AV_LOG_TRACE);
av_register_all();
avformat_network_init();
avformat_alloc_output_context2(&formatContext, NULL, "h264", url);
if (!formatContext)
{
av_log(NULL, AV_LOG_FATAL, "Could not allocate an output context for '%s'.\n", url);
}
codec = avcodec_find_encoder(CODEC_ID);
if (!codec)
{
av_log(NULL, AV_LOG_ERROR, "Could not find encoder.\n");
}
stream = avformat_new_stream(formatContext, codec);
c = avcodec_alloc_context3(codec);
stream->id = formatContext->nb_streams - 1;
stream->time_base = (AVRational){1, 25};
c->codec_id = CODEC_ID;
c->bit_rate = 400000;
c->width = WIDTH;
c->height = HEIGHT;
c->time_base = stream->time_base;
c->gop_size = 12;
c->pix_fmt = STREAM_PIX_FMT;
if (formatContext->flags & AVFMT_GLOBALHEADER)
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
av_dict_set(&opts, "preset", "fast", 0);
av_dict_set(&opts, "tune", "zerolatency", 0);
ret = avcodec_open2(c, codec, NULL);
if (ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "Could not open video codec.\n");
}
pFrameBGR = av_frame_alloc();
if (!pFrameBGR)
{
av_log(NULL, AV_LOG_ERROR, "Could not allocate video frame.\n");
}
frame = av_frame_alloc();
if (!frame)
{
av_log(NULL, AV_LOG_ERROR, "Could not allocate video frame.\n");
}
frame->format = c->pix_fmt;
frame->width = c->width;
frame->height = c->height;
ret = avcodec_parameters_from_context(stream->codecpar, c);
if (ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "Could not open video codec.\n");
}
av_dump_format(formatContext, 0, url, 1);
ret = avformat_write_header(formatContext, NULL);
if (ret != 0)
{
av_log(NULL, AV_LOG_ERROR, "Failed to connect to '%s'.\n", url);
}
Mat image(Size(HEIGHT, WIDTH), CV_8UC3);
SwsContext *swsctx = sws_getContext(WIDTH, HEIGHT, AV_PIX_FMT_BGR24, WIDTH, HEIGHT, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);
int frame_pts = 0;
while (1)
{
cap >> image;
int numBytesYUV = av_image_get_buffer_size(STREAM_PIX_FMT, WIDTH, HEIGHT, 1);
uint8_t *bufferYUV = (uint8_t *)av_malloc(numBytesYUV * sizeof(uint8_t));
avpicture_fill((AVPicture *)pFrameBGR, image.data, AV_PIX_FMT_BGR24, WIDTH, HEIGHT);
avpicture_fill((AVPicture *)frame, bufferYUV, STREAM_PIX_FMT, WIDTH, HEIGHT);
sws_scale(swsctx, (uint8_t const *const *)pFrameBGR->data, pFrameBGR->linesize, 0, HEIGHT, frame->data, frame->linesize);
AVPacket pkt = {0};
av_init_packet(&pkt);
frame->pts = frame_pts;
ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
if (ret < 0)
{
av_log(NULL, AV_LOG_ERROR, "Error encoding frame\n");
}
if (got_packet)
{
pkt.pts = av_rescale_q_rnd(pkt.pts, c->time_base, stream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, c->time_base, stream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q(pkt.duration, c->time_base, stream->time_base);
pkt.stream_index = stream->index;
return av_interleaved_write_frame(formatContext, &pkt);
cout << "Seguro que si" << endl;
}
frame_pts++;
}
avcodec_free_context(&c);
av_frame_free(&frame);
avformat_free_context(formatContext);
return 0;
}
The code compiles but it returns Segmentation fault in the function av_interleaved_write_frame(). I've tried several implementations or several codecs (in this case I'm using libopenh264, but using mpeg2video returns the same segmentation fault). I tried also with av_write_frame() but it returns the same error.
As I told before, I only want to grab frames from a webcam connected via USB, encode them to H264 and send the packets through UDP to another PC.
My console log when I run the executable is.
[100%] Built target display
[OpenH264] this = 0x0x244b4f0, Info:CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_TRACE_CALLBACK callback = 0x7f0c302a87c0.
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:CWelsH264SVCEncoder::InitEncoder(), openh264 codec version = 5a5c4f1
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:iUsageType = 0,iPicWidth= 640;iPicHeight= 480;iTargetBitrate= 400000;iMaxBitrate= 400000;iRCMode= 0;iPaddingFlag= 0;iTemporalLayerNum= 1;iSpatialLayerNum= 1;fFrameRate= 25.000000f;uiIntraPeriod= 12;eSpsPpsIdStrategy = 0;bPrefixNalAddingCtrl = 0;bSimulcastAVC=0;bEnableDenoise= 0;bEnableBackgroundDetection= 1;bEnableSceneChangeDetect = 1;bEnableAdaptiveQuant= 1;bEnableFrameSkip= 0;bEnableLongTermReference= 0;iLtrMarkPeriod= 30, bIsLosslessLink=0;iComplexityMode = 0;iNumRefFrame = 1;iEntropyCodingModeFlag = 0;uiMaxNalSize = 0;iLTRRefNum = 0;iMultipleThreadIdc = 1;iLoopFilterDisableIdc = 0 (offset(alpha/beta): 0,0;iComplexityMode = 0,iMaxQp = 51;iMinQp = 0)
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:sSpatialLayers[0]: .iVideoWidth= 640; .iVideoHeight= 480; .fFrameRate= 25.000000f; .iSpatialBitrate= 400000; .iMaxSpatialBitrate= 400000; .sSliceArgument.uiSliceMode= 1; .sSliceArgument.iSliceNum= 0; .sSliceArgument.uiSliceSizeConstraint= 1500;uiProfileIdc = 66;uiLevelIdc = 41
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Warning:SliceArgumentValidationFixedSliceMode(), unsupported setting with Resolution and uiSliceNum combination under RC on! So uiSliceNum is changed to 6!
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:Setting MaxSpatialBitrate (400000) the same at SpatialBitrate (400000) will make the actual bit rate lower than SpatialBitrate
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Warning:bEnableFrameSkip = 0,bitrate can't be controlled for RC_QUALITY_MODE,RC_BITRATE_MODE and RC_TIMESTAMP_MODE without enabling skip frame.
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Warning:Change QP Range from(0,51) to (12,42)
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:WELS CPU features/capacities (0x4007fe3f) detected: HTT: Y, MMX: Y, MMXEX: Y, SSE: Y, SSE2: Y, SSE3: Y, SSSE3: Y, SSE4.1: Y, SSE4.2: Y, AVX: Y, FMA: Y, X87-FPU: Y, 3DNOW: N, 3DNOWEX: N, ALTIVEC: N, CMOV: Y, MOVBE: Y, AES: Y, NUMBER OF LOGIC PROCESSORS ON CHIP: 8, CPU CACHE LINE SIZE (BYTES): 64
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:WelsInitEncoderExt() exit, overall memory usage: 4542878 bytes
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Info:WelsInitEncoderExt(), pCtx= 0x0x245a400.
Output #0, h264, to 'udp://192.168.100.39:8080':
Stream #0:0, 0, 1/25: Video: h264 (libopenh264), 1 reference frame, yuv420p, 640x480 (0x0), 0/1, q=2-31, 400 kb/s, 25 tbn
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Debug:RcUpdateIntraComplexity iFrameDqBits = 385808,iQStep= 2016,iIntraCmplx = 777788928
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Debug:[Rc]Layer 0: Frame timestamp = 0, Frame type = 2, encoding_qp = 30, average qp = 30, max qp = 33, min qp = 27, index = 0, iTid = 0, used = 385808, bitsperframe = 16000, target = 64000, remainingbits = -257808, skipbuffersize = 200000
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Debug:WelsEncoderEncodeExt() OutputInfo iLayerNum = 2,iFrameSize = 48252
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Debug:WelsEncoderEncodeExt() OutputInfo iLayerId = 0,iNalType = 0,iNalCount = 2, first Nal Length=18,uiSpatialId = 0,uiTemporalId = 0,iSubSeqId = 0
[libopenh264 # 0x244aa00] [OpenH264] this = 0x0x244b4f0, Debug:WelsEncoderEncodeExt() OutputInfo iLayerId = 1,iNalType = 1,iNalCount = 6, first Nal Length=6057,uiSpatialId = 0,uiTemporalId = 0,iSubSeqId = 0
[libopenh264 # 0x244aa00] 6 slices
./scriptBuild.sh: line 20: 10625 Segmentation fault (core dumped) ./display
As you can see, FFmpeg uses libopenh264 and configures it correctly. However, no matter what. It always returns the same Segmentation fault error...
I've used commands like this.
ffmpeg -s 640x480 -f video4linux2 -i /dev/video0 -r 30 -vcodec libopenh264 -an -f h264 udp://127.0.0.1:8080
And it works perfectly, but I need to process the frames before sending them. Thats why I'm trying to use the libs.
My FFmpeg version is.
ffmpeg version 3.3.6 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
configuration: --disable-yasm --enable-shared --enable-libopenh264 --cc='gcc -fPIC'
libavutil 55. 58.100 / 55. 58.100
libavcodec 57. 89.100 / 57. 89.100
libavformat 57. 71.100 / 57. 71.100
libavdevice 57. 6.100 / 57. 6.100
libavfilter 6. 82.100 / 6. 82.100
libswscale 4. 6.100 / 4. 6.100
libswresample 2. 7.100 / 2. 7.100
I tried to get more information of the error using gbd, but it didn't give me debugging info.
How can I solve this problem? I don't know what else can I try...
Thank you!
avpicture_fill is deprecated. I think this is source of the error. Try with av_image_fill_arrays()
An example line should be:
av_image_fill_arrays(pFrameBGR.data, /* destination */
pFrameBGR.linesize, /* destination */
image.data, /* source */
AV_PIX_FMT_BGR24, /* source */
WIDTH, HEIGHT, 1); /* source w+h & alingment */
Hope that helps.

ffmpeg hangs in avcodec_encode_video2

I encode the video stream using ffmeg. Shell QT Creator. OC Windows 7. The compiler MinGW. H264 codec.
There is a function, which I give to the input frame, and I must return an encoded byte array. Within this function it hangs when calling avcodec_encode_video2, but not on the first call, and at random.
That is, an arbitrary coding frame hangs (100 to 10000).
QByteArray VideoEncoder::createFrameVideoFromImage(QImage picture)
{
AVFrame* frame_source = av_frame_alloc();
avpicture_fill((AVPicture*)frame_source, picture.bits(), AV_PIX_FMT_RGB24, this->width_frame, this->height_frame);
AVFrame* frame_dst = av_frame_alloc();
avpicture_fill((AVPicture*)frame_dst, (uint8_t*)this->inbuffer, AV_PIX_FMT_YUV420P, this->width_frame, this->height_frame);
sws_scale(this->convert_rgb_yuv, frame_source->data, frame_source->linesize,
0, this->ctx_codec_in->height, frame_dst->data, frame_dst->linesize);
AVPacket packet;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
packet.pts = packet.dts = AV_NOPTS_VALUE;
int nOutputSize = 0;
if (avcodec_encode_video2(this->ctx_codec_in, &packet, frame_dst, &nOutputSize) < 0)
{
qDebug() << "VideoEncoder error";
}
this->traffic += packet.size;
QByteArray data_frame = QByteArray((char*)packet.data, packet.size);
av_frame_free(&frame_source);
av_frame_free(&frame_dst);
av_free_packet(&packet);
return data_frame;
}
Thank you in advance!

avcodec_open2 error -542398533 : "Generic error in an external library"

I am encountering an error when trying to open the codec with avcodec_open2(). I have tried the same code without any problems if I specify avi instead of h264 in the av_guess_format() function.
I don't know what to make of it. Has anyone else encountered a similar problem?
The library that I'm using is ffmpeg-20160219-git-98a0053-win32-dev. I would really really appreciate if you could help me out of this confusion.
This is my console output:
Video encoding
[libx264 # 01383460] broken ffmpeg default settings detected
[libx264 # 01383460] use an encoding preset (e.g. -vpre medium)
[libx264 # 01383460] preset usage: -vpre -vpre
[libx264 # 01383460] speed presets are listed in x264 --help
[libx264 # 01383460] profile is optional; x264 defaults to high
Cannot open video codec, -542398533
This is the code that I'm working with:
// Video encoding sample
AVCodec *codec = NULL;
AVCodecContext *codecCtx= NULL;
AVFormatContext *pFormatCtx = NULL;
AVOutputFormat *pOutFormat = NULL;
AVStream * pVideoStream = NULL;;
AVFrame *picture = NULL;;
int i, x, y, ret;
printf("Video encoding\n");
// Register all formats and codecs
av_register_all();
// guess format from file extension
pOutFormat = av_guess_format("h264", NULL, NULL);
if (NULL==pOutFormat){
cerr << "Could not guess output format" << endl;
return -1;
}
// allocate context
pFormatCtx = avformat_alloc_context();
pFormatCtx->oformat = pOutFormat;
memcpy(pFormatCtx->filename,filename,
min(strlen(filename), sizeof(pFormatCtx->filename)));
// Add stream to pFormatCtx
pVideoStream = avformat_new_stream(pFormatCtx, 0);
if (!pVideoStream)
{
printf("Cannot add new video stream\n");
return -1;
}
// Set stream's codec context
codecCtx = pVideoStream->codec;
codecCtx->codec_id = (AVCodecID)pOutFormat->video_codec;
codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
codecCtx->frame_number = 0;
// Put sample parameters.
codecCtx->bit_rate = 2000000;
// Resolution must be a multiple of two.
codecCtx->width = 320;
codecCtx->height = 240;
codecCtx->time_base.den = 10;
codecCtx->time_base.num = 1;
pVideoStream->time_base.den = 10;
pVideoStream->time_base.num = 1;
codecCtx->gop_size = 12; // emit one intra frame every twelve frames at most
codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
if (codecCtx->codec_id == AV_CODEC_ID_H264)
{
// Just for testing, we also add B frames
codecCtx->mb_decision = 2;
}
// Some formats want stream headers to be separate.
if(pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if(codecCtx->codec_id == AV_CODEC_ID_H264)
av_opt_set(codecCtx->priv_data, "preset", "slow", 0);
// Open the codec.
codec = avcodec_find_encoder(codecCtx->codec_id);
if (codec == NULL) {
fprintf(stderr, "Codec not found\n");
return -1;
}
ret = avcodec_open2(codecCtx, codec, NULL); // returns -542398533 here
if (ret < 0)
{
printf("Cannot open video codec, %d\n",ret);
return -1;
}
Your problem is this line:
codecCtx = pVideoStream->codec;
This AVCodecContext was allocated using global defaults, which x264 rejects because they are not optimal. Instead, use avcodec_alloc_context3 to allocate it, which will set x264-specific defaults. At the end of your encoding, don't forget to avcodec_free_context the returned pointer.
you should pass codec param to avformat_new_stream
codec = avcodec_find_encoder(codecCtx->codec_id);
pVideoStream = avformat_new_stream(pFormatCtx, codec);

RTP server for audio stream

I'm in the mid of my project where I'm trying to send the audio data over RTP using ffmpeg in VC++.
but I'm unable to do that.
My start up code is:
setRTPOutputAddr("127.0.0.1");
setRTPOutputPort(9985);
av_register_all();
avformat_network_init();
formatCtx= avformat_alloc_context();
//av_dump_format(formatCtx,0,"rtp",1);
avio_open_dyn_buf(&ioctx);
avio_open(&formatCtx->pb, "rtp", AVIO_FLAG_WRITE);
//av_dump_format(formatCtx,0,"rtp",1);
formatCtx->pb = ioctx;
rtpCtx = avformat_alloc_context();
rtpCtx->oformat = av_guess_format("rtp",0,0);
AVStream *fakeVideo = 0;
fakeVideo = avformat_new_stream(rtpCtx,0);
avcodec_get_context_defaults3(fakeVideo->codec, NULL);
fakeVideo->codec->codec_id = AV_CODEC_ID_MPEG2TS;
rtpCtx->audio_codec_id = AV_CODEC_ID_NONE;
rtpCtx->video_codec_id = AV_CODEC_ID_MPEG2TS;
// avformat_write_header(rtpCtx,0);
char *url = new char[1024];
sprintf(url,"rtp://%s:%d",rtpOutputAddr,rtpOutputPort);
printf("will output to url:%s\n",url);
avio_open(&rtpCtx->pb,url,AVIO_FLAG_WRITE);
avformat_write_header(rtpCtx, NULL);
delete url;
if (avio_open(&formatCtx->pb, "rtp", AVIO_FLAG_WRITE) < 0)
{
fprintf(stderr, "Could not open '%s'\n", formatCtx->filename);
return -1;
}
else
{
printf("succeed \n");
}
Error Here: avformat_write_header(formatCtx, NULL); //program Crashes
Do anyone having any idea where I'm doing wrong?
Thanks!