ffmpeg: test if format is seekable - c++

How do i test if a format is seekable?
I have written code against the latest fmmpeg's (4.4) libavformat, libavcodec, etc. My code reads and decodes video files. Now i also want to support reading from avdevices, such as dshow (DirectShow) on Windows. That is possible through the same interface as i have already implemented, it just requires using the dshow format. Super nice! But in my video file reader, i have some seek logic implemented, which is engaged in various instances. The problem is that the dshow format is not seekable (avformat_seek_file() returns -22, invalid argument). How do i detect that a format is not seekable? I know that the AVFormatContext's pb member (AVIOContext) has a seekable field, but the dshow format leaves pb null (as it should be since the AVFMT_NOFILE flag is set for the format). How do i test if a format is seekable (so that if it is not, i can disable the seek logic)? The implementation of avformat_seek_file() and the various functions it calls seems to have various callbacks, so i am not sure if simply this would do the trick: bool isSeekable = !!context->pb && context->pb->seekable!=0.

Related

I called av_probe_input_format3(), now I want to call avcodec_find_decoder(), how do I convert the format in a codec?

So... I'm dealing with a system that has input data coming in buffers (i.e. NOT a file). I want to determine which decoder to create to decompress an audio stream (MP3, WAV, OGG, ...) So obviously I do not know the input format.
I found out that I could determine the format using the av_probe_input_format[23]() functions. That part works great, I get a format pointer that matches the files that I use as input.
AVInputFormat * format(av_probe_input_format3(&pd, true, &score));
I can print the format->name and format->long_name and these are the correct type (so the detection is working as expected).
Now, I'm trying to understand how to convert that AVInputFormat * into a AVCodec * so I can call avcodec_alloc_context3(codec) to create the actual audio decoder.
I found a couple of functions, which I used like so:
AVCodecID const codec_id(av_codec_get_id(format->codec_tag, format->raw_codec_id));
AVCodec * codec(avcodec_find_decoder(codec_id));
Problem 1. the raw_codec_id field is marked as "private" (should not access/use anywhere in your client's code).
Problem 2. the first function always returns AV_CODEC_ID_NONE (0) so of course the second call fails each time.
Am I doing something wrong? Is there is way to instead create a generic decode that will automatically detect the type of audio I have as input? (that is, would that be the only way to make that work?)
Okay, so the fact is that trying to use these functions directly is pretty much futile. The problem I have with the design is that it forces me to actually have a callback and that callback forces me to have a thread (i.e. I have to somehow feed data from a stream, not a file or such!)
So I can use the avformat_open_input() as mentioned by Gyan, only I have to have my own AVIOContext. I was hoping I could just call functions with my incoming data and avoid the pipeline concept. The issue here is some background processes could be servers that use fork() and thus you need to be really careful (i.e. fork() is not friendly with threads).

Copying avcodec parameters

I am trying to use libav to convert an MP4 file to an MP3 file. Basically trying to achieve what ffmpeg -i filename.mp4 filename.mp3 does. I've found this official example. But when I run it with an input MP4 and an output MP3 I get an error:
Invalid audio stream. Exactly one MP3 audio stream is required.
I am not at all familiar with this library but I think I have narrowed the problem down to this line:
ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
It seems to copy all streams for a video file but we only need one for the MP3 file? I am not sure. There doesn't seem to be a function to copy only the parameters relevant to audio. I checked the sources, avcodec_parameters_copy does a simple memcpy.
Questions:
Is this the actual problem?
How do I solve it?
Am I on the right track to achieve the goal of extracting audio from a video file? I've seen this question (and other similar questions like this and this) on here but none seem to have a complete code example. The C API documentation for this library is also a little lacking.
You can have multiple audio tracks in mp4 file, but only one such track in an mp3 file. The easiest fix for the remuxing example would be to replace lines 101-103:
if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
stream_index != 0) {
This, naturally, is relevant only if the output is mp3.
PS, make sure that your input mp4 uses the MP3 audio codec. If it does not (and most have AAC or AC3 these days), it's not enough to remux the file, you also need to decode and re-encode the audio stream.

what is "engineName" property in TI gstreamer plugin TIVidenc1

What is "engineName" property in TI Gstreamer plugin TIVidenc1?
And what values it can be?
(I know only codecServer... what else it can be?)
By documentation of TI(not too much explanation):
Engine name used by codec combo.
Here are some good examples of usage.
I have seen also this value
encode (used in network streaming but also H264 encoding to file)
With element TIVidenc I seen also:
- hmjcp (used with H264 encoding)
You can use gst-inspect TIVidenc1 to check the values (hope they are listed there) if you have installed this plugin/expansion or whatever it is..
also if you are keen you can check the sources

list file extensions supported by OpenCV

In OpenCV, I see imread() and VideoCapture() both take a string to a file path of multiple extensions. Is there a way to get a list of extensions that are supported by them? For example, getting a list of "jpg", "png", "mov", "mpg", etc.? I assume this is system dependent and others have needed to query this at runtime.
Furthermore, how is support determined? If have something like the below code and the Mat I get back always seems partially corrupted (I can see a bit of the image). It doesn't seem to change regardless of the frame number I ask for. I can play this video in my video player "totem", but I'm not even sure if totem and OpenCV are even using the same codec for this file.
Mat fromVideo(std::string _videoPath, int frame) {
VideoCapture capture(_videoPath);
Mat f;
for (int i = 0; i < frame; i++) {
capture >> f;
}
return f;
}
For imread() (more info here):
Windows bitmaps - *.bmp, *.dib (always supported)
JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
JPEG 2000 files - *.jp2 (see the Notes section)
Portable Network Graphics - *.png (see the Notes section)
Portable image format - *.pbm, *.pgm, *.ppm (always supported)
Sun rasters - *.sr, *.ras (always supported)
TIFF files - *.tiff, *.tif (see the Notes section)
For VideoCapture():
AVI files - *.avi
It seems that AVI is the only format with decent cross-platform support. See here for more info.
Use the method cv::VideoCapture::isOpened() to make sure that the constructor was successful in initializing the VideoCapture object.
Note that even if it was possible to get a list of supported container formats from OpenCV (AVI, MKV for instance) with their typical filename extensions, you would still need to know the exact list of supported codecs (and even then the exact file you want to open might be corrupted, etc...). So a list of filename extensions is not enough to accurately describe what is internally supported by OpenCV, and the simplest solution at the OpenCV API level is this isOpened() method.
Just update:
cv::VideoCapture cap("D:\\test.mp4")
works for me.

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).