[Libav-user] How to share data between processes
Loren Garavaglia
loren.garavaglia at gmail.com
Thu Jun 30 04:20:16 CEST 2016
Hi all,
I'm working on simulating a network of security cameras who's video feeds
will be collected and processed at a central node. I simulate the security
cameras by starting an FFMPEG stream through the command line, then my
central node is simulated using network simulation software. In the central
node I currently use the FFMPEG library to read and decode the stream.
Unfortunately the network simulation cannot run in real-time on my computer
so the central node is not able to capture every frame from each stream.
To solve this problem I had the idea of running a process outside of my
simulation that reads from the stream and places the packets in a buffer.
The simulation would then read from the buffer and decode the packets to
get a frame. I have realized that the AVPacket type that I want to place in
the buffer is initialized as a dereferenced pointer and the shared memory
implementations that I am aware of do not allow sharing of pointers.
Correct me if I'm wrong but I think that in order for both processes to
work off of the same stream they would also have to share the format
context and codec context of the stream.
Does anyone know of a way to create a shared video buffer between processes?
Below is my code implementation for my reading process.
struct FFMPEGData {
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, dst;
AVPacket *packet;
AVPacket* pack = new AVPacket[packetNum];
struct SwsContext *convert_ctx;
enum PixelFormat dst_pixfmt = PIX_FMT_GRAY8;
uint8_t *out_buffer;
int got_picture, videoindex, restart;
char filepath[15];
int windowName;
FFMPEGData()
{
// Initialize some of the values to defaults.
restart = 1;
got_picture = 0;
videoindex = 0;
sprintf_s(filepath, "None");
}
int startFFMPEG();
};
int nodeNumber = 2;
FFMPEGData* vidData = new FFMPEGData[nodeNumber];
int FFMPEGData::startFFMPEG()
{
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) < 0)
{
printf("Couldn't open input stream.\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\n");
return -1;
}
videoindex = -1;
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoindex = i;
break;
}
}
if (videoindex == -1)
{
printf("Didn't find a video stream.\n");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoindex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL)
{
printf("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Could not open codec.\n");
return -1;
}
pFrame = av_frame_alloc();
out_buffer = (uint8_t *)av_malloc(avpicture_get_size(dst_pixfmt,
pCodecCtx->width, pCodecCtx->height));
avpicture_fill((AVPicture *)&dst, out_buffer, dst_pixfmt,
pCodecCtx->width, pCodecCtx->height);
packet = (AVPacket *)av_malloc(sizeof(AVPacket));
//Output Info-----------------------------
printf("--------------- File Information ----------------\n");
av_dump_format(pFormatCtx, 0, filepath, 0);
printf("-------------------------------------------------\n");
convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, dst_pixfmt,
SWS_FAST_BILINEAR, NULL, NULL, NULL);
return 0;
}
void thread(FFMPEGData &vidData)
{
int counter = 0;
// changed this to use member function.
if (vidData.startFFMPEG() < 0)
{
printf("should not get here.\n");
}
while (true)
{
// Read frames from the stream.
if (av_read_frame(vidData.pFormatCtx, &vidData.pack[counter]) !=
AVERROR(EAGAIN))
{
if (counter < packetNum)
{
counter++;
}
else
{
counter = 0;
}
}
}
}
using namespace std;
int main(int argc, char **argv)
{
boost::thread_group reads;
av_register_all();
avformat_network_init();
for (int i = 0; i < nodeNumber; i++)
{
// Set the sdp file for each node.
sprintf_s(vidData[i].filepath, "test%d.sdp", (i + 1));
vidData[i].restart = 0;
vidData[i].windowName = i;
reads.add_thread(new boost::thread(thread, boost::ref(vidData[i])));
}
reads.join_all();
//If the code ever reaches here close the pipe before finishing.
delete[] vidData;
return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20160629/6743533d/attachment.html>
More information about the Libav-user
mailing list