Newest 'ffmpeg' Questions - Stack Overflow
Les articles publiés sur le site
-
Promise chaining and resolution
23 janvier 2019, par Shourya SharmaI am trying to convert videos one by one with the help of promises. i am using ffmpeg for conversion and multer for uploading multiple files.
multer uploads multiple files at once after which i have to chain the conversions one by one. as of now it just converts the 1st file.
i thought chaining of promises ..like in an array should work but i am confused if i can define new promises in an array as ffmpeg also returns a promise
My router:
const router = require('express').Router(); const multer = require('multer'); const ffmpeg = require('ffmpeg'); let str; const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, './uploads'); }, filename: (req, file, cb) => { str = file.originalname.replace(/\.[^/.]+$/, ""); str = str.replace(/[^a-z0-9+]+/gi, '_') + '.' + file.originalname.replace(/^.*\./, ''); cb(null, str); } }); const upload = multer({ storage: storage }).array('files', 12); router.post('/upload', (req, res, next) => { // req.files is an array of files // req.body will contain the text fields, if there were any function uploadFile() { return new Promise((resolve, reject) => { upload(req, res, (err) => { if (err) { res.send(err) // Pass errors to Express. reject(`Error: Something went wrong!`); } else if (req.files == undefined) { res.send(`No File selected.`); resolve(); } else if (!err && req.files.length > 0) { res.status(201).send(`${req.files.length} File(s): ${req.files} uploaded successfully.`); console.log('uploaded'); resolve(); } }); }); } uploadFile().then(() => { try { var process = new ffmpeg('./uploads/' + str); process.then(function (video) { console.log('The video is ready to be processed'); video.addCommand('-hide_banner', ''); video.addCommand('-y', ''); video.addCommand('-c:a', 'aac'); video.addCommand('-ar', '48000'); video.addCommand('-c:v', 'h264'); video.addCommand('-profile:v', 'main'); video.addCommand('-crf', '20'); video.addCommand('-sc_threshold', '0'); video.addCommand('-g', '50'); video.addCommand('-keyint_min', '50'); video.addCommand('-hls_time', '4'); video.addCommand('-hls_playlist_type', 'vod'); video.addCommand('-vf', 'scale=-2:720'); video.addCommand('-b:v', '1400k'); video.addCommand('-maxrate', '1498k'); video.addCommand('-bufsize', '2100k'); video.addCommand('-b:a', '128k'); video.save('./converted/' + str, function (error, file) { if (!error) console.log('Video file: ' + file); }); }, function (err) { console.log('Error: ' + err); }); } catch (e) { console.log(e.code); console.log(e.msg); } }).catch((err) => { console.log(Error, err); }); }); module.exports = router;
-
Non-monotonous DTS when concatenate slowed down video
23 janvier 2019, par whynotbealionCopy from Video StackExchange
I try to concatenate multiple videos to achieve the following:
All my videos are in mp4 format. One video is first slowed down, then mixed with audio Videos are concatenated in the following order: Normal video, normal video, slowed-down video (output.mp4), normal video ... The video is slowed down with the following command:
ffmpeg -y -i raw.mp4 -filter:v 'setpts=1.3333*PTS' silent.mp4
Audio is added with the following command:
ffmpeg -y -i silent.mp4 -i audio.mp3 -map 0:0 -map 1:0 output.mp4
When I concatenate using the Concat demuxer (https://trac.ffmpeg.org/wiki/Concatenate) the audio of the output is not in sync with the video. During the concatenation I get the "Non-monotonous DTS" error.
I tried the following
Following this suggestion (https://video.stackexchange.com/a/22941/24238) after I created my slowed down and mixed video (output.mp4) I convert all mp4 videos to mts format. After this I concatenate and with
ffmpeg -i fullvideo.mts fullvideo.mp4
I convert the resulting video back to mp4 format. This video plays just fine, but during the convert again I get the following error "Non-monotonous DTS in output stream 0:1; previous: 191803, current: 187633; changing to 191804. This may result in incorrect timestamps in the output file."
My question
Even regardless the error the video plays just fine, even in the browser. Does this solution still have a disadvantage or threat? Is there a better solution where I don't get any DTS error? I am thankful for any help as this is all new for me.
-
HLS Event Stream from Azure Blob Storage
23 janvier 2019, par nemesis_567Alright, so I encode videos of around 30 seconds with ffmpeg, the following flags:
ffmpeg.exe -i \"{filename}\" -f hls -hls_segment_type fmp4 -hls_flags single_file -hls_time 5 -g 1 \"{outname}.m3u8\"
This generates a single playlist with an m4s and m3u8 file:
#EXTM3U #EXT-X-VERSION:7 #EXT-X-TARGETDURATION:5 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-MAP:URI="1e02982a-c455-40f5-8229-1033a640c91c-0.mp4.m4s",BYTERANGE="818@0" #EXTINF:4.781911, #EXT-X-BYTERANGE:1398720@5953584 1e02982a-c455-40f5-8229-1033a640c91c-0.mp4.m4s #EXTINF:5.063200, #EXT-X-BYTERANGE:1490276@7352304 1e02982a-c455-40f5-8229-1033a640c91c-0.mp4.m4s #EXTINF:5.063200, #EXT-X-BYTERANGE:1484824@8842580 1e02982a-c455-40f5-8229-1033a640c91c-0.mp4.m4s #EXTINF:5.063200, #EXT-X-BYTERANGE:1468656@10327404 1e02982a-c455-40f5-8229-1033a640c91c-0.mp4.m4s #EXTINF:1.969022, #EXT-X-BYTERANGE:576408@11796060 1e02982a-c455-40f5-8229-1033a640c91c-0.mp4.m4s #EXT-X-ENDLIST
I take this playlist and append several others that are just the same as they come adding a DIscontinuity tag and between each of them and removing unneeded tags. While doing this I replace the filenames with a working SAS URL for the actual files.
Which results in files of the following type:
#EXTM3U #EXT-X-PLAYLIST-TYPE:EVENT #EXT-X-VERSION:7 #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-MAP:URI="https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/1-frag.m4s?sv=2018-03-28&sr=b&sig=el%2F529BGb4Xjeetiv9kxaHAxGYC%2BwogSYgvCivq1tlc%3D&st=2019-01-10T05%3A09%3A13Z&se=2021-01-10T05%3A14%3A13Z&sp=rw",BYTERANGE="818@0" #EXTINF:4.654771, #EXT-X-BYTERANGE:1474761@4854677 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/1-frag.m4s?sv=2018-03-28&sr=b&sig=el%2F529BGb4Xjeetiv9kxaHAxGYC%2BwogSYgvCivq1tlc%3D&st=2019-01-10T05%3A09%3A13Z&se=2021-01-10T05%3A14%3A13Z&sp=rw #EXTINF:5.430566, #EXT-X-BYTERANGE:1716825@6329438 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/1-frag.m4s?sv=2018-03-28&sr=b&sig=el%2F529BGb4Xjeetiv9kxaHAxGYC%2BwogSYgvCivq1tlc%3D&st=2019-01-10T05%3A09%3A13Z&se=2021-01-10T05%3A14%3A13Z&sp=rw #EXTINF:4.654771, #EXT-X-BYTERANGE:1479725@8046263 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/1-frag.m4s?sv=2018-03-28&sr=b&sig=el%2F529BGb4Xjeetiv9kxaHAxGYC%2BwogSYgvCivq1tlc%3D&st=2019-01-10T05%3A09%3A13Z&se=2021-01-10T05%3A14%3A13Z&sp=rw #EXTINF:5.430566, #EXT-X-BYTERANGE:1710125@9525988 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/1-frag.m4s?sv=2018-03-28&sr=b&sig=el%2F529BGb4Xjeetiv9kxaHAxGYC%2BwogSYgvCivq1tlc%3D&st=2019-01-10T05%3A09%3A13Z&se=2021-01-10T05%3A14%3A13Z&sp=rw #EXTINF:3.103181, #EXT-X-BYTERANGE:200@11236113 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/1-frag.m4s?sv=2018-03-28&sr=b&sig=el%2F529BGb4Xjeetiv9kxaHAxGYC%2BwogSYgvCivq1tlc%3D&st=2019-01-10T05%3A09%3A13Z&se=2021-01-10T05%3A14%3A13Z&sp=rw #EXT-X-DISCONTINUITY #EXT-X-MAP:URI="https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/2-frag.m4s?sv=2018-03-28&sr=b&sig=s3s3R1sjE6lZRgfmaYdOkOGCr7BYkOrygBy%2F90crwvM%3D&st=2019-01-10T05%3A09%3A53Z&se=2021-01-10T05%3A14%3A53Z&sp=rw",BYTERANGE="819@0" #EXTINF:4.897959, #EXT-X-BYTERANGE:1506220@6184008 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/2-frag.m4s?sv=2018-03-28&sr=b&sig=s3s3R1sjE6lZRgfmaYdOkOGCr7BYkOrygBy%2F90crwvM%3D&st=2019-01-10T05%3A09%3A53Z&se=2021-01-10T05%3A14%3A53Z&sp=rw #EXTINF:4.897959, #EXT-X-BYTERANGE:1496289@7690228 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/2-frag.m4s?sv=2018-03-28&sr=b&sig=s3s3R1sjE6lZRgfmaYdOkOGCr7BYkOrygBy%2F90crwvM%3D&st=2019-01-10T05%3A09%3A53Z&se=2021-01-10T05%3A14%3A53Z&sp=rw #EXTINF:4.897959, #EXT-X-BYTERANGE:1516854@9186517 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/2-frag.m4s?sv=2018-03-28&sr=b&sig=s3s3R1sjE6lZRgfmaYdOkOGCr7BYkOrygBy%2F90crwvM%3D&st=2019-01-10T05%3A09%3A53Z&se=2021-01-10T05%3A14%3A53Z&sp=rw #EXTINF:4.897959, #EXT-X-BYTERANGE:1492617@10703371 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/2-frag.m4s?sv=2018-03-28&sr=b&sig=s3s3R1sjE6lZRgfmaYdOkOGCr7BYkOrygBy%2F90crwvM%3D&st=2019-01-10T05%3A09%3A53Z&se=2021-01-10T05%3A14%3A53Z&sp=rw #EXTINF:0.816327, #EXT-X-BYTERANGE:219@12195988 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/2-frag.m4s?sv=2018-03-28&sr=b&sig=s3s3R1sjE6lZRgfmaYdOkOGCr7BYkOrygBy%2F90crwvM%3D&st=2019-01-10T05%3A09%3A53Z&se=2021-01-10T05%3A14%3A53Z&sp=rw #EXT-X-DISCONTINUITY #EXT-X-MAP:URI="https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/3-frag.m4s?sv=2018-03-28&sr=b&sig=O%2B%2FQBnVcyIzn2r3T8S7xq2dic9LKW3q7p2bGSYen%2BbI%3D&st=2019-01-10T05%3A10%3A43Z&se=2021-01-10T05%3A15%3A43Z&sp=rw",BYTERANGE="820@0" #EXTINF:5.000000, #EXT-X-BYTERANGE:1352781@6631869 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/3-frag.m4s?sv=2018-03-28&sr=b&sig=O%2B%2FQBnVcyIzn2r3T8S7xq2dic9LKW3q7p2bGSYen%2BbI%3D&st=2019-01-10T05%3A10%3A43Z&se=2021-01-10T05%3A15%3A43Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1357320@7984650 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/3-frag.m4s?sv=2018-03-28&sr=b&sig=O%2B%2FQBnVcyIzn2r3T8S7xq2dic9LKW3q7p2bGSYen%2BbI%3D&st=2019-01-10T05%3A10%3A43Z&se=2021-01-10T05%3A15%3A43Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1360645@9341970 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/3-frag.m4s?sv=2018-03-28&sr=b&sig=O%2B%2FQBnVcyIzn2r3T8S7xq2dic9LKW3q7p2bGSYen%2BbI%3D&st=2019-01-10T05%3A10%3A43Z&se=2021-01-10T05%3A15%3A43Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1334946@10702615 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/3-frag.m4s?sv=2018-03-28&sr=b&sig=O%2B%2FQBnVcyIzn2r3T8S7xq2dic9LKW3q7p2bGSYen%2BbI%3D&st=2019-01-10T05%3A10%3A43Z&se=2021-01-10T05%3A15%3A43Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:238@12037561 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/3-frag.m4s?sv=2018-03-28&sr=b&sig=O%2B%2FQBnVcyIzn2r3T8S7xq2dic9LKW3q7p2bGSYen%2BbI%3D&st=2019-01-10T05%3A10%3A43Z&se=2021-01-10T05%3A15%3A43Z&sp=rw #EXT-X-DISCONTINUITY #EXT-X-MAP:URI="https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=jPsSq8%2FfNzfjUx5bauJs7mkLu8w%2FYFKLaeLRBu8lPzg%3D&st=2019-01-10T05%3A11%3A25Z&se=2021-01-10T05%3A16%3A25Z&sp=rw",BYTERANGE="820@0" #EXTINF:5.000000, #EXT-X-BYTERANGE:1359259@6647772 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=jPsSq8%2FfNzfjUx5bauJs7mkLu8w%2FYFKLaeLRBu8lPzg%3D&st=2019-01-10T05%3A11%3A25Z&se=2021-01-10T05%3A16%3A25Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1353269@8007031 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=jPsSq8%2FfNzfjUx5bauJs7mkLu8w%2FYFKLaeLRBu8lPzg%3D&st=2019-01-10T05%3A11%3A25Z&se=2021-01-10T05%3A16%3A25Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1359724@9360300 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=jPsSq8%2FfNzfjUx5bauJs7mkLu8w%2FYFKLaeLRBu8lPzg%3D&st=2019-01-10T05%3A11%3A25Z&se=2021-01-10T05%3A16%3A25Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1339437@10720024 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=jPsSq8%2FfNzfjUx5bauJs7mkLu8w%2FYFKLaeLRBu8lPzg%3D&st=2019-01-10T05%3A11%3A25Z&se=2021-01-10T05%3A16%3A25Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:238@12059461 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=jPsSq8%2FfNzfjUx5bauJs7mkLu8w%2FYFKLaeLRBu8lPzg%3D&st=2019-01-10T05%3A11%3A25Z&se=2021-01-10T05%3A16%3A25Z&sp=rw #EXT-X-DISCONTINUITY #EXT-X-MAP:URI="https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=yfgkYvCLFjt384tsDZZ2ahVfPI4XxoCyyWepmux4rvc%3D&st=2019-01-10T05%3A12%3A12Z&se=2021-01-10T05%3A17%3A12Z&sp=rw",BYTERANGE="820@0" #EXTINF:5.000000, #EXT-X-BYTERANGE:1371742@6775319 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=yfgkYvCLFjt384tsDZZ2ahVfPI4XxoCyyWepmux4rvc%3D&st=2019-01-10T05%3A12%3A12Z&se=2021-01-10T05%3A17%3A12Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1389742@8147061 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=yfgkYvCLFjt384tsDZZ2ahVfPI4XxoCyyWepmux4rvc%3D&st=2019-01-10T05%3A12%3A12Z&se=2021-01-10T05%3A17%3A12Z&sp=rw #EXTINF:5.000000, #EXT-X-BYTERANGE:1377900@9536803 https://vsatstreams.blob.core.windows.net/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/75888d6c-41fb-4cb0-9573-0e2ab7a6dc4c/4-frag.m4s?sv=2018-03-28&sr=b&sig=yfgkYvCLFjt384tsDZZ2ahVfPI4XxoCyyWepmux4rvc%3D&st=2019-01-10T05%3A12%3A12Z&se=2021-01-10T05%3A17%3A12Z&sp=rw #EXTINF:5.000000,
This stream does not play in chrome with video.js, and only plays in bitmovin client, but it constantly fails with buffer append/stalled errors. In firefox it plays, but without much reliability.
So what am I doing wrong in this process? I've checked the specification for HLS several times, can't see what I'm doing wrong, or what the player expects.
Please check hls.js player, with the following URL which uses the stream above to see what I'm talking about. HLS.JS Demo Player With My Playlist
-
Dumping Subtitles From AVPicture into ppm Format File
23 janvier 2019, par Rishabh GargIn FFMPEG sofftware, AVPicture is used to store image data using data pointer and linesizes. It means all subtitles are stored in the form of picture inside ffmpeg . Now I want to dump subtitles from AVPicture in .ppm format file.
I have written this code to Dump subtitles with the help of data in AVPicture. May be my red,green,blue pixel data may be wrong in the loop.
w = ctx->sub->rects[0]->w; h = ctx->sub->rects[0]->h; line_size = ctx->sub->rects[0]->linesize[0]; int m,n; FILE *fp = fopen("first.ppm", "wb"); (void) fprintf(fp, "P3\n%d %d\n255\n", w, h); for (m = 0; m < h; ++m) { for (n = 0; n < line_size; ++n) { static int r,g,b,a,z; uint32_t *pallet = ctx->sub->rects[0]->data[1]; z = ctx->sub->rects[0]->data[0][n]; b = pallet[z]&0xFF; g = (pallet[z]>>8) & 0xFF; r = (pallet[z]>>16)& 0xFF; a = (pallet[z]>>24)& 0xFF; fprintf(fp,"%d %d %d %d",b,g,r,a); } fprintf(fp,"\n"); fflush(fp); } (void) fclose(fp);
The program is not dumping subtitles. Only 0 is coming in r,g,b,a by which subtitles are not dumping .
-
ffmpeg avcodec_send_packet/avcodec_receive_frame memory leak
23 janvier 2019, par G HamlinI'm attempting to decode frames, but memory usage grows with every frame (more specifically, with every call to avcodec_send_packet) until finally the code crashes with a bad_alloc. Here's the basic decode loop:
int rfret = 0; while((rfret = av_read_frame(inctx.get(), &packet)) >= 0){ if (packet.stream_index == vstrm_idx) { //std::cout << "Sending Packet" << std::endl; int ret = avcodec_send_packet(ctx.get(), &packet); if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { std::cout << "avcodec_send_packet: " << ret << std::endl; break; } while (ret >= 0) { //std::cout << "Receiving Frame" << std::endl; ret = avcodec_receive_frame(ctx.get(), fr); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { //std::cout << "avcodec_receive_frame: " << ret << std::endl; av_frame_unref(fr); // av_frame_free(&fr); break; } std::cout << "frame: " << ctx->frame_number << std::endl; // eventually do something with the frame here... av_frame_unref(fr); // av_frame_free(&fr); } } else { //std::cout << "Not Video" << std::endl; } av_packet_unref(&packet); }
Memory usage/leakage seems to scale with the resolution of the video I'm decoding. For example, for a 3840x2160 resolution video, the memory usage in windows task manager consistently jumps up by about 8mb (1 byte per pixel??) for each received frame. Do I need to do something besides call av_frame_unref to release the memory?
(more) complete code below
void AVFormatContextDeleter(AVFormatContext* ptr) { if (ptr) { avformat_close_input(&ptr); } } void AVCodecContextDeleter(AVCodecContext* ptr) { if (ptr) { avcodec_free_context(&ptr); } } typedef std::unique_ptr AVFormatContextPtr; typedef std::unique_ptr AVCodecContextPtr; AVCodecContextPtr createAvCodecContext(AVCodec *vcodec) { AVCodecContextPtr ctx(avcodec_alloc_context3(vcodec), AVCodecContextDeleter); return ctx; } AVFormatContextPtr createFormatContext(const std::string& filename) { AVFormatContext* inctxPtr = nullptr; int ret = avformat_open_input(&inctxPtr, filename.c_str(), nullptr, nullptr); // int ret = avformat_open_input(&inctx, "D:/Videos/test.mp4", nullptr, nullptr); if (ret != 0) { inctxPtr = nullptr; } return AVFormatContextPtr(inctxPtr, AVFormatContextDeleter); } int testDecode() { // open input file context AVFormatContextPtr inctx = createFormatContext("D:/Videos/Matt Chapman Hi Greg.MOV"); if (!inctx) { // std::cerr << "fail to avforamt_open_input(\"" << infile << "\"): ret=" << ret; return 1; } // retrieve input stream information int ret = avformat_find_stream_info(inctx.get(), nullptr); if (ret < 0) { //std::cerr << "fail to avformat_find_stream_info: ret=" << ret; return 2; } // find primary video stream AVCodec* vcodec = nullptr; const int vstrm_idx = av_find_best_stream(inctx.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &vcodec, 0); if (vstrm_idx < 0) { //std::cerr << "fail to av_find_best_stream: vstrm_idx=" << vstrm_idx; return 3; } AVCodecParameters* origin_par = inctx->streams[vstrm_idx]->codecpar; if (vcodec == nullptr) { // is this even necessary? vcodec = avcodec_find_decoder(origin_par->codec_id); if (!vcodec) { // Can't find decoder return 4; } } AVCodecContextPtr ctx = createAvCodecContext(vcodec); if (!ctx) { return 5; } ret = avcodec_parameters_to_context(ctx.get(), origin_par); if (ret) { return 6; } ret = avcodec_open2(ctx.get(), vcodec, nullptr); if (ret < 0) { return 7; } //print input video stream informataion std::cout //<< "infile: " << infile << "\n" << "format: " << inctx->iformat->name << "\n" << "vcodec: " << vcodec->name << "\n" << "size: " << origin_par->width << 'x' << origin_par->height << "\n" << "fps: " << av_q2d(ctx->framerate) << " [fps]\n" << "length: " << av_rescale_q(inctx->duration, ctx->time_base, {1,1000}) / 1000. << " [sec]\n" << "pixfmt: " << av_get_pix_fmt_name(ctx->pix_fmt) << "\n" << "frame: " << inctx->streams[vstrm_idx]->nb_frames << "\n" << std::flush; AVPacket packet; av_init_packet(&packet); packet.data = nullptr; packet.size = 0; AVFrame *fr = av_frame_alloc(); if (!fr) { return 8; } int rfret = 0; while((rfret = av_read_frame(inctx.get(), &packet)) >= 0){ if (packet.stream_index == vstrm_idx) { //std::cout << "Sending Packet" << std::endl; int ret = avcodec_send_packet(ctx.get(), &packet); if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { std::cout << "avcodec_send_packet: " << ret << std::endl; break; } while (ret >= 0) { //std::cout << "Receiving Frame" << std::endl; ret = avcodec_receive_frame(ctx.get(), fr); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { //std::cout << "avcodec_receive_frame: " << ret << std::endl; av_frame_unref(fr); // av_frame_free(&fr); break; } std::cout << "frame: " << ctx->frame_number << std::endl; // do something with the frame here... av_frame_unref(fr); // av_frame_free(&fr); } } else { //std::cout << "Not Video" << std::endl; } av_packet_unref(&packet); } std::cout << "RFRET = " << rfret << std::endl; return 0; }
Update 1: (1/21/2019) Compiling on a different machine and running with different video files I am not seeing the memory usage growing without bound. I'll try to narrow down where the difference lies (compiler?, ffmpeg version?, or video encoding?)
Update 2: (1/21/2019) Ok, it looks like there is some interaction occurring between ffmpeg and Qt's QCamera. In my application, I'm using Qt to manage the webcam, but decided to use ffmpeg libraries to handle decoding/encoding since Qt doesn't have as comprehensive support for different codecs. If I have the camera turned on (through Qt), ffmpeg decoding memory consumption grows without bound. If the camera is off, ffmpeg behaves fine. I've tried this both with a physical camera (Logitech C920) and with a virtual camera using OBS-Virtualcam, with the same result. So far I'm baffled as to how the two systems are interacting...