<div dir="ltr">Hi all,<div><br></div><div>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.  </div><div><br></div><div>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.</div><div><br></div><div>Does anyone know of a way to create a shared video buffer between processes?</div><div><br></div><div><br></div><div><br></div><div>Below is my code implementation for my reading process.</div><div><br></div><div>struct FFMPEGData {</div><div>   AVFormatContext   *pFormatCtx;</div><div>   AVCodecContext    *pCodecCtx;</div><div>   AVCodec               *pCodec;</div><div>   AVFrame               *pFrame, dst;</div><div>   AVPacket              *packet;</div><div>   AVPacket* pack = new AVPacket[packetNum];</div><div><br></div><div>   struct SwsContext *convert_ctx;</div><div><br></div><div>   enum PixelFormat dst_pixfmt = PIX_FMT_GRAY8;</div><div><br></div><div>   uint8_t         *out_buffer;</div><div>   int               got_picture, videoindex, restart;</div><div>   char             filepath[15];</div><div>   int               windowName;</div><div><br></div><div>   FFMPEGData()</div><div>   {</div><div>      // Initialize some of the values to defaults.</div><div>      restart = 1;</div><div>      got_picture = 0;</div><div>      videoindex = 0;</div><div>      sprintf_s(filepath, "None");</div><div>   }</div><div><br></div><div>   int startFFMPEG();</div><div>};</div><div><br></div><div>int nodeNumber = 2;</div><div><br></div><div>FFMPEGData* vidData = new FFMPEGData[nodeNumber];</div><div><br></div><div><br></div><div>int FFMPEGData::startFFMPEG()</div><div>{</div><div>   pFormatCtx = avformat_alloc_context();</div><div><br></div><div>   if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) < 0)</div><div>   {</div><div>      printf("Couldn't open input stream.\n");</div><div>      return -1;</div><div>   }</div><div><br></div><div>   if (avformat_find_stream_info(pFormatCtx, NULL) < 0)</div><div>   {</div><div>      printf("Couldn't find stream information.\n");</div><div>      return -1;</div><div>   }</div><div><br></div><div>   videoindex = -1;</div><div>   for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)</div><div>   {</div><div>      if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)</div><div>      {</div><div>         videoindex = i;</div><div>         break;</div><div>      }</div><div>   }</div><div><br></div><div>   if (videoindex == -1)</div><div>   {</div><div>      printf("Didn't find a video stream.\n");</div><div>      return -1;</div><div>   }</div><div><br></div><div>   pCodecCtx = pFormatCtx->streams[videoindex]->codec;</div><div>   pCodec = avcodec_find_decoder(pCodecCtx->codec_id);</div><div><br></div><div>   if (pCodec == NULL)</div><div>   {</div><div>      printf("Codec not found.\n");</div><div>      return -1;</div><div>   }</div><div><br></div><div>   if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)</div><div>   {</div><div>      printf("Could not open codec.\n");</div><div>      return -1;</div><div>   }</div><div><br></div><div>   pFrame = av_frame_alloc();</div><div><br></div><div>   out_buffer = (uint8_t *)av_malloc(avpicture_get_size(dst_pixfmt, pCodecCtx->width, pCodecCtx->height));</div><div><br></div><div>   avpicture_fill((AVPicture *)&dst, out_buffer, dst_pixfmt, pCodecCtx->width, pCodecCtx->height);</div><div><br></div><div>   packet = (AVPacket *)av_malloc(sizeof(AVPacket));</div><div><br></div><div>   //Output Info-----------------------------</div><div>   printf("--------------- File Information ----------------\n");</div><div>   av_dump_format(pFormatCtx, 0, filepath, 0);</div><div>   printf("-------------------------------------------------\n");</div><div><br></div><div>   convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,</div><div>                 pCodecCtx->width, pCodecCtx->height, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);</div><div><br></div><div>   return 0;</div><div>}</div><div><br></div><div><br></div><div>void thread(FFMPEGData &vidData)</div><div>{</div><div>   int counter = 0;</div><div>   // changed this to use member function.</div><div>   if (vidData.startFFMPEG() < 0)</div><div>   {</div><div>      printf("should not get here.\n");</div><div>   }</div><div><br></div><div>   while (true)</div><div>   {</div><div>      // Read frames from the stream.</div><div>      if (av_read_frame(vidData.pFormatCtx, &vidData.pack[counter]) != AVERROR(EAGAIN))</div><div>      {</div><div>         if (counter < packetNum)</div><div>         {</div><div>            counter++;</div><div>         }</div><div>         else</div><div>         {</div><div>            counter = 0;</div><div>         }</div><div>      }</div><div>   }</div><div>}</div><div><br></div><div><br></div><div>using namespace std;</div><div><br></div><div>int main(int argc, char **argv)</div><div>{</div><div>   boost::thread_group reads;</div><div><br></div><div>   av_register_all();</div><div>   avformat_network_init();</div><div><br></div><div>   for (int i = 0; i < nodeNumber; i++)</div><div>   {</div><div><br></div><div>      // Set the sdp file for each node.</div><div>      sprintf_s(vidData[i].filepath, "test%d.sdp", (i + 1));</div><div><br></div><div>      vidData[i].restart = 0;</div><div>      vidData[i].windowName = i;</div><div><br></div><div>      reads.add_thread(new boost::thread(thread, boost::ref(vidData[i])));</div><div>   }</div><div><br></div><div>   reads.join_all();</div><div><br></div><div>   //If the code ever reaches here close the pipe before finishing.</div><div>   delete[] vidData;</div><div>   return 0;</div><div>} </div></div>