FFmpeg decoding .mp4 video file - c

I'm working on a project that needs to open .mp4 file format, read it's frames 1 by 1, decode them and encode them with better type of lossless compression and save them into a file.
Please correct me if i'm wrong with order of doing things, because i'm not 100% sure how this particular thing should be done. From my understanding it should go like this:
1. Open input .mp4 file
2. Find stream info -> find video stream index
3. Copy codec pointer of found video stream index into AVCodecContext type pointer
4. Find decoder -> allocate codec context -> open codec
5. Read frame by frame -> decode the frame -> encode the frame -> save it into a file
So far i encountered couple of problems. For example, if i want to save a frame using av_interleaved_write_frame() function, i can't open input .mp4 file using avformat_open_input() since it's gonna populate filename part of the AVFormatContext structure with input file name and therefore i can't "write" into that file. I've tried different solution using av_guess_format() but when i dump format using dump_format() i get nothing so i can't find stream information about which codec is it using.
So if anyone have any suggestions, i would really appreciate them. Thank you in advance.

See the "detailed description" in the muxing docs. You:
set ctx->oformat using av_guess_format
set ctx->pb using avio_open2
call avformat_new_stream for each stream in the output file. If you're re-encoding, this is by adding each stream of the input file into the output file.
call avformat_write_header
call av_interleaved_write_frame in a loop
call av_write_trailer
close the file (avio_close) and clear up all allocated memory

You can convert a video to a sequence of losses images with:
ffmpeg -i video.mp4 image-%05d.png
and then from a series of images back to a video with:
ffmpeg -i image-%05d.png video.mp4
The functionality is also available via wrappers.
You can see a similar question at: Extracting frames from MP4/FLV?

Related

Writing matroska to an append only stream

I need to write a matroška video file to a stream that only supports an append operation (not network streaming, output is a single MKV file for offline playback). Right now I'm using ffmpeg's libavformat to do the muxing, but the resulting video file is not seekable (in a player) at all.
Going through the matroška specs, I figured out a way to create a seekable (in a player) file work with only one (file) seek operation:
SeekHead 1 (without clusters)
...
Clusters
Cues
SeekHead 2 (only clusters)
After the file is written I need to go back to SeekHead 1 and update it with positions of SeekHead 2 and Cues.
My output files can easily get to tens of gigabytes, so buffering the whole thing in memory is not an option.
Is there really no way to create the MKV without seeking in the output file?

HTTP byte range yields a corrupt audio file?

when i open a .m4a or .mp3 file using chrome (or in VLC "open new stream), and skip to a certain time mark, it starts streaming the audio right at that time mark, which means that it downloads a chunk from the audio file starting at that position.
when i check network under chrome dev tools after i click somewhere in the audio player, and copy the cURL request, it contains a range http header, for example:
-H "Range: bytes=26500000-30000000"
when i run that cURL command in the terminal, the output is a corrupt audio file. if i try to convert it using ffmpeg, it logs:
[mov,mp4,m4a,3gp,3g2,mj2 # 00000164d5a3ab40] moov atom not found
the only exception is when i request a byte range starting from 0 (and ending at 300000+) in which case the output file can play.
from what i understand, the headers of the audio file are not downloaded when the byte range is somewhere in the middle or ending of the file.
i tried specifying two ranges, as follows
-H "Range: bytes=0-300000,2000000-4000000"
but the output file is corrupt nevertheless.
how does chrome/vlc deal with this situation, and how can i replicate it? what is the right way to download an audio chunk from a large audio file? i am guessing i would have to make consecutive http requests to build a proper, non-corrupt file, it seems that it is what chrome does.
UPDATE
a "temporary fix" i found to the problem that you might find useful is to use launch VLC through command with a hidden interface, load the audio stream (in this case the audio file url) and transcode the audio to a local file while assigning a start and stop time. an example, with a random podcast:
vlc -Idummy --play-and-exit --sout "#transcode{acodec=s16l,channels=2,samplerate=44100}:std{access=file,mux=wav,dst=C:\audio\output.wav}" --start-time=600 --stop-time=630 "http://traffic.libsyn.com/preview/worldofhardwarestartups/World_of_Hardware_Startups_Podcast_EP01_-_AIR_Ready.mp3"
however, the original issue is still unsolved.

Re-encode with ffmpeg

I am trying to do following work in C code with the help of ffmpeg library
Decode a mp2 audio file.
Write decoded data to a file named test.sw
Read data from test.sw and re-encode it to mp2 audio file.
For 1 and 2, i followed example given in decoding_encoding.c which is working fine. While reading and re-encoding, i can't understand how to read from test.sw file and encode it. Can anybody help me with that? It will help me a lot if anybody can provide me any tutorial regarding this topic.
As I understood your question you want to encode to mp2 format.I suggest to use the encoding technique used for mp2 format and use the library ,You have one library ffmpeg just check is it having for encoding .If yes then just use that function and pass your decoded file.
You can check it
http://ffmpeg.org/doxygen/trunk/encoding-example_8c-source.html

How to write incoming frames to file without touching in ffmpeg?

I am able to read frames from av_open_input_file and decode and reencode it with another codec and save to file.
Now, I want the same thing, except i don't want to decode or reencode. I want to do av_interleaved_write_frame on the just read frame to file. To do this, i need to set AVOutputFormat
AVOutputFormat *fmt;
fmt = av_guess_format(NULL, filename, NULL);
However, i can not supply a filename, because it is a remote stream. So, is there any way to generate AVOutputFormat from the current AVFormatContext which already reads input frames? So i can write the same frame to the output file from any part of it (not necessarily from the beginning) in the correct way.
To summarize: I need to write the just read frame to the file without decoding and reencoding. (I will open that file another time to be able to play that file)
Any ideas?

Save video encoded by libavcodec to an AVI file format

I am able to encode video frames using libavcodec, by calling avcodec_encode_video function. How do I save these encoded frames into an AVI file?
Check this out:
http://forum.doom9.org/archive/index.php/t-112286.html
You must open file for binary write, write header in it, and simultaniosly put binary frames in it, I think.

Resources