h264 encode video stream ffmpeg c++ - c++

I'm trying to develop A live streaming app that capture video from web cam encode it to H264 video stream and use rtsp to send it to device,
I've looked up some examples and found this:
FFMPEG to send RTSP encoded stream C++
I've been using it as a reference to my program.
However I'm keep getting AVCodec type "MPEG", I've been trying to change filename extension and tried different approaches with avformat_alloc_output_context2
This is the relevant code:
const char *filename = "rtsp://127.0.0.1:7003/live.sdp";
AVOutputFormat *fmt;
AVFormatContext *oc;
AVStream *video_st;
AVCodec *video_codec;
video_st = NULL;
av_register_all();
avformat_network_init();
// format context:
avformat_alloc_output_context2(&oc,NULL,"rtsp",filename);
After calling avformat_alloc_output_context2 oc->oformat->video_codec is generated as MPEG codec.
I've tried changing filename extension to:
const char *filename = "rtsp://127.0.0.1:7003/live.264";
const char *filename = "rtsp://127.0.0.1:7003/live.h264";
and a bunch of other extensions.
How can I generate a H264 stream?

According to the documentation, you need to pass an output format to avformat_alloc_output_context2.
To quote (content in square brackets mine):
[the second parameter is the] format to use for allocating the context, if NULL format_name and filename are used instead
This parameter is a pointer to type AVOutputFormat.
Alternatively, you could continue to pass NULL and infer the output by using H264 as the format name.
Either way, I think you'll need to separate the encoding process from the streaming protocol.
This separation of concerns is useful, as if you find you want to use a different protocol to get the stream, the encoding code does not need to know about it.

Related

How to get format of video stream in ffmpeg (c++)

I have a function that reads frames from a stream. I want to find out what the format of the stream is (I'm testing with H264):
StreamingResult MediaWriter::Open(const AVFormatContext *const inputFormatContext,
const fs::path &destination)
{
// Save input stream data
AVStream *videoStream = inputFormatContext->streams[FindVideoStreamIndex(inputFormatContext)];
//....
}
How can I get the format/codec type from the video stream? I am expecting to receive H264, but other formats will be received in the future.
P.S.: Some good FFMPEG documentation would be appreciated, because I am getting lost in Doxygen generated documentation.
Some good FFMPEG documentation would be appreciated, because I am getting lost in Doxygen generated documentation.
Doxygen is th best ffmpeg documentation there is. Its just ffmpeg is a very large peroject and takes time to learn.
What you are looking for is videoStream->codecpar->codec_id

Media Foundation AMR decode

I have a file with .amr extension, and I want to get it's sample rate and number of channels using Microsoft Media Foundation. Further, I want to decode and get the uncompressed data.
I can successfully get those from .aac .mp4 and other file types but not from from a .amr file (or 3.gp file which contains .amr track).
So, for other types I do:
IMFSourceReader *m_pReader;
IMFMediaType *m_pAudioType;
MFCreateSourceReaderFromURL(filePath, NULL, &m_pReader);
m_pReader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false);
m_pReader->SetStreamSelection(MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
m_pReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &m_pAudioType);
UINT32 numChannels,sampleRate;
m_pAudioType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &numChannels);
m_pAudioType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &sampleRate);
Consider there are no any errors during this code.
For .amr files, some garbage is being written in the numChannels and sampleRate.
Does anyone have experience with this and knows how to recognize and/or get proper channels and sample rate for further decoding?
BTW, Windows Media Player plays this file with no problems.
Thanks in advance.
So I found out that it supports decoding for .amr files not encoding.
Just before we get this properties:
UINT32 numChannels,sampleRate;
m_pAudioType->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &numChannels);
m_pAudioType->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &sampleRate);
We have to set a new media type to our Source Reader
m_pAudioType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio)
m_pAudioType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float)
m_pReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, NULL, m_pAudioType);

How to set the moov atom position when encoding video using ffmpeg in c++

I'm encoding some h264 video into a mp4 container using ffmpeg in c++. But the result videos place the moov atom(or metadata?) at the end of the video file, it's bad for internet streaming.
So how can I set the moov atom position to the front?
MOVMuxContext is an internal header and should not be accessed directly. Its implementation is not part of the API and it can change.
The official way to do it is setting options via an AVDictionary :
AVDictionary* options = nullptr;
av_dict_set( &options, "movflags", "faststart", 0 );
avio_open2(..., &options);
You need to use faststart flag of ffmpeg to place the moov atom in the beginning of the MP4 file, Here is the explanation of the flag. Programatically you need to set the flag in output context, here is the sample code and its working for me,
AVFormatContext *outFormatCtx;
// Write MOOV atom at the begining of the MP4 file
MOVMuxContext *mov = NULL;
mov = (MOVMuxContext *)outFormatCtx->priv_data;
mov->flags |= FF_MOV_FLAG_FASTSTART;

c++ ffmpeg api get video stream from https link

I'm trying to read https video link using the function av_format_open_input() but the function return a negative value.
Here is my code:
av_register_all();
avcodec_register_all();
avformat_network_init();
const char * url = "https://r1---sn ...";
AVFormatContext * pFormatCtx = avformat_alloc_context();
int ret = avformat_open_input(&pFormatCtx, url, NULL, NULL);
This code worked with a local file as url but as soon as I give a https url it doesnt work anymore.
thanks
[edit]
I found only this: ffserver.c
But it uses a .ffm file as input. Any exemple or help on how to implement HttpContext (if HttpContext is needed here) would be great.
[update]
I ended using libvlc which seems to be much easier but the way to do it using ffmpeg could still be interesting. See my other post if interested: Get frame from video with libvlc smem and convert it to opencv Mat. (c++)

Raw Audio File to AAC using Windows Media Foundation on Windows 7

Thanks for taking some time to read my question.
I'm developping a C++ application using Qt and windows API.
I'm recording the microphone output in small 10s audio files in raw format, and I want to convert them to aac format.
I have tried to read as many things as I could, and thought it would be a great idea to start from windows media foundation transcode API.
Problem is, I can't seem to use a .raw or .pcm file in the "CreateObjectFromUrl" function, and so I'm pretty much stuck here for the moment. It keeps on failing. The hr return code equals 3222091460. I have tried to pass an .mp3 file to the function and of course it works, so no url-human-failure involved.
MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
IMFSourceResolver* pSourceResolver = NULL;
IUnknown* pUnkSource = NULL;
// Create the source resolver.
hr = MFCreateSourceResolver(&pSourceResolver);
if (FAILED(hr))
{
qDebug() << "Failed !";
}
// Use the source resolver to create the media source.
hr = pSourceResolver->CreateObjectFromURL(
sURL, // URL of the source.
MF_RESOLUTION_MEDIASOURCE, // Create a source object.
NULL, // Optional property store.
&ObjectType, // Receives the created object type.
&pUnkSource // Receives a pointer to the media source.
);
The MFCreateSourceResolver works fine, but CreateObjectFromURL does not succeed :(
So I have two questions for you folks :
Is it possible to encode raw audio files to aac files using windows media foundation ?
If yes, what should I read to accomplish what I want ?
I want to point out that I can't just use ffmpeg or libav because I can't afford any license for my software, and don't want it to be under the GPL license. But if there are alternatives to windows media foundations to encode raw audio files to aac, I would be glad to hear them.
And finally, sorry for my bad english, this is obviously not my native language and I'm sorry if I made your eyes bleed. (and happy if I made you laugh)
Have a nice day
The hr return code equals 3222091460
Those are HRESULT codes. Use this "ShowHresult" tool to have them conveniently decoded for you. The code means 0xC00D36C4 MF_E_UNSUPPORTED_BYTESTREAM_TYPE "The byte stream type of the given URL is unsupported."
The problem is basically that there is no support for these raw files, .WAV is a good source for raw audio - the file holds both format descriptor and the payload.
You can obviously read data from the raw audio file yourself and compress into AAC using Media Foundation's AAC Encoder via its IMFTransform interface. This is reasonably easy and you have AAC data on the output to e.g. write into raw .AAC.
Alternate options to Media Foundation is DirectShow (there are suitable codecs, though I thought it might be not so easy to start), libfaac, FFmpeg's libavcodec (available under LGPL, not GPL).