libav c++ raw h264 TCP Stream to opencv Mat











up vote
1
down vote

favorite
1












I writting a software for my classes that receive a h264 stream from a drone and i need to convert the video stream to opencv Mat.



I have no trouble to receive the frame and if i save it to a .264 file i can read the output with VLC.



The drone is sending IDR-Frame and P-Frame , since i don't need to see the video stream juste some frame of it, i was thinking of only using the IDR-Frame to get the image but i have trouble to understand how to use libavcodec from FFMPEG, how can i create a AVFrame from my IDR-Frame and how to convert it to cv::Mat after.



i have try the following code, i have store the full frame in .raw file and i try to decode them , but i get read error when i try to parse the packet to a frame, i don't thing a initialize the buffer of ARPacket the right way :



AVFormatContext* fc = 0;
int vi = -1; // vi veut dire video index


inline cv::Mat avframe_to_mat(const AVFrame* avframe)
{
AVFrame dst;
cv::Mat m;

memset(&dst, 0, sizeof(dst));

int w = avframe->width, h = avframe->height;

m = cv::Mat(h, w, CV_8UC3);
dst.data[0] = (uint8_t*)m.data;

avpicture_fill((AVPicture*)&dst, dst.data[0], AV_PIX_FMT_BGR24, w, h);

struct SwsContext *convert_ctx = NULL;

enum AVPixelFormat src_pixfmt = AV_PIX_FMT_BGR24;
enum AVPixelFormat dst_pixfmt = AV_PIX_FMT_BGR24;

convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);

sws_scale(convert_ctx, avframe->data, avframe->linesize, 0, h, dst.data, dst.linesize);
sws_freeContext(convert_ctx);

return m;

}

inline bool init_stream(unsigned char* data, int len)
{

const char* file = "test.avi";

const AVCodecID codec_id = AV_CODEC_ID_H264;
AVCodec* codec = avcodec_find_encoder(codec_id);
// Crée le container pour le stream
fc = avformat_alloc_context();

/*
AVOutputFormat *of = av_guess_format(0, file, 0);
fc = avformat_alloc_context();
fc->oformat = of;
strcpy(fc->filename, file);
*/
int br = 1000000;
int w = 640;
int h = 360;

int fps = 24;


// ajoute un stream video
AVStream* pst = avformat_new_stream(fc, codec); // Pourquoi je passe pas le codec ici ?
vi = pst->index;

codec_context = avcodec_alloc_context3(codec);

codec_context->bit_rate = br;
codec_context->width = w;
codec_context->height = h;
codec_context->time_base = {1,fps};
codec_context->gop_size = 10; // Emit one intra frame every ten frames
codec_context->max_b_frames = 1;
codec_context->pix_fmt = AV_PIX_FMT_YUV420P;

// Vu quon n'est en h264
av_opt_set(codec_context->priv_data, "preset", "slow", 0);


// Ouvre notre codec
if(avcodec_open2(codec_context, codec,nullptr) < 0)
{
cerr << "Impossible d'ouvrir le codec" << endl;
return false;
}

if (!(fc->oformat->flags & AVFMT_NOFILE))
avio_open(&fc->pb, fc->filename,0);

// avformat_write_header(fc,nullptr);


return true;
}


inline void append_stream(uint8_t* data, int len)
{
if( 0 > vi)
{
cerr << "video index is less than 0" << endl;
return;
}
AVStream* pst = fc->streams[vi];

AVPacket pkt;


// Init un nouveau packet
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.data = data;
pkt.stream_index = pst->index;
pkt.size = len;

pkt.dts = AV_NOPTS_VALUE;
pkt.pts = AV_NOPTS_VALUE;

// ERROR accessing location
av_interleaved_write_frame(fc, &pkt);


}


inline void execute_staging_test(const fs::path& folder, int nbr_trame)
{
fs::path file_name = folder / "stream.bin";
if(!fs::exists(file_name))
{
cerr << "The file " << file_name.string() << " does not exists" << endl;
return;
}

avcodec_register_all();

av_log_set_level(AV_LOG_DEBUG);
int length = 0;
char* buffer;

for(int i = 0; i < nbr_trame;i++)
{
fs::path file = std::to_string(i) + ".raw";
file = folder / file;
cout << "Got frame on " << file.string() << endl;
ifstream ifs(file, ofstream::binary);

// Get la longeur du fichier pour savoir le buffer a prendre
ifs.seekg(0, ios::end);
length = ifs.tellg();
ifs.seekg(0, ios::beg);

if (length == 0) {
std::cerr << "No data in file " << file << std::endl;
return;
}

buffer = new char[length];

std::cout << "File " << file << " length is " << length << std::endl;

ifs.read(buffer, length);

cv::VideoWriter vw;
int codec = cv::VideoWriter::fourcc('X', '2', '6', '4');


if(!fc)
{
if(!init_stream((unsigned char*)buffer, length))
{
return;
}
}
if(fc)
{
append_stream((unsigned char*)buffer, length);
}
}
}


Thanks you very mutch if you can help me , i'm a novice in c++ and i have never deal with video stream. If you want to see the full code its host on github repo to this project










share|improve this question


























    up vote
    1
    down vote

    favorite
    1












    I writting a software for my classes that receive a h264 stream from a drone and i need to convert the video stream to opencv Mat.



    I have no trouble to receive the frame and if i save it to a .264 file i can read the output with VLC.



    The drone is sending IDR-Frame and P-Frame , since i don't need to see the video stream juste some frame of it, i was thinking of only using the IDR-Frame to get the image but i have trouble to understand how to use libavcodec from FFMPEG, how can i create a AVFrame from my IDR-Frame and how to convert it to cv::Mat after.



    i have try the following code, i have store the full frame in .raw file and i try to decode them , but i get read error when i try to parse the packet to a frame, i don't thing a initialize the buffer of ARPacket the right way :



    AVFormatContext* fc = 0;
    int vi = -1; // vi veut dire video index


    inline cv::Mat avframe_to_mat(const AVFrame* avframe)
    {
    AVFrame dst;
    cv::Mat m;

    memset(&dst, 0, sizeof(dst));

    int w = avframe->width, h = avframe->height;

    m = cv::Mat(h, w, CV_8UC3);
    dst.data[0] = (uint8_t*)m.data;

    avpicture_fill((AVPicture*)&dst, dst.data[0], AV_PIX_FMT_BGR24, w, h);

    struct SwsContext *convert_ctx = NULL;

    enum AVPixelFormat src_pixfmt = AV_PIX_FMT_BGR24;
    enum AVPixelFormat dst_pixfmt = AV_PIX_FMT_BGR24;

    convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);

    sws_scale(convert_ctx, avframe->data, avframe->linesize, 0, h, dst.data, dst.linesize);
    sws_freeContext(convert_ctx);

    return m;

    }

    inline bool init_stream(unsigned char* data, int len)
    {

    const char* file = "test.avi";

    const AVCodecID codec_id = AV_CODEC_ID_H264;
    AVCodec* codec = avcodec_find_encoder(codec_id);
    // Crée le container pour le stream
    fc = avformat_alloc_context();

    /*
    AVOutputFormat *of = av_guess_format(0, file, 0);
    fc = avformat_alloc_context();
    fc->oformat = of;
    strcpy(fc->filename, file);
    */
    int br = 1000000;
    int w = 640;
    int h = 360;

    int fps = 24;


    // ajoute un stream video
    AVStream* pst = avformat_new_stream(fc, codec); // Pourquoi je passe pas le codec ici ?
    vi = pst->index;

    codec_context = avcodec_alloc_context3(codec);

    codec_context->bit_rate = br;
    codec_context->width = w;
    codec_context->height = h;
    codec_context->time_base = {1,fps};
    codec_context->gop_size = 10; // Emit one intra frame every ten frames
    codec_context->max_b_frames = 1;
    codec_context->pix_fmt = AV_PIX_FMT_YUV420P;

    // Vu quon n'est en h264
    av_opt_set(codec_context->priv_data, "preset", "slow", 0);


    // Ouvre notre codec
    if(avcodec_open2(codec_context, codec,nullptr) < 0)
    {
    cerr << "Impossible d'ouvrir le codec" << endl;
    return false;
    }

    if (!(fc->oformat->flags & AVFMT_NOFILE))
    avio_open(&fc->pb, fc->filename,0);

    // avformat_write_header(fc,nullptr);


    return true;
    }


    inline void append_stream(uint8_t* data, int len)
    {
    if( 0 > vi)
    {
    cerr << "video index is less than 0" << endl;
    return;
    }
    AVStream* pst = fc->streams[vi];

    AVPacket pkt;


    // Init un nouveau packet
    av_init_packet(&pkt);
    pkt.flags |= AV_PKT_FLAG_KEY;
    pkt.data = data;
    pkt.stream_index = pst->index;
    pkt.size = len;

    pkt.dts = AV_NOPTS_VALUE;
    pkt.pts = AV_NOPTS_VALUE;

    // ERROR accessing location
    av_interleaved_write_frame(fc, &pkt);


    }


    inline void execute_staging_test(const fs::path& folder, int nbr_trame)
    {
    fs::path file_name = folder / "stream.bin";
    if(!fs::exists(file_name))
    {
    cerr << "The file " << file_name.string() << " does not exists" << endl;
    return;
    }

    avcodec_register_all();

    av_log_set_level(AV_LOG_DEBUG);
    int length = 0;
    char* buffer;

    for(int i = 0; i < nbr_trame;i++)
    {
    fs::path file = std::to_string(i) + ".raw";
    file = folder / file;
    cout << "Got frame on " << file.string() << endl;
    ifstream ifs(file, ofstream::binary);

    // Get la longeur du fichier pour savoir le buffer a prendre
    ifs.seekg(0, ios::end);
    length = ifs.tellg();
    ifs.seekg(0, ios::beg);

    if (length == 0) {
    std::cerr << "No data in file " << file << std::endl;
    return;
    }

    buffer = new char[length];

    std::cout << "File " << file << " length is " << length << std::endl;

    ifs.read(buffer, length);

    cv::VideoWriter vw;
    int codec = cv::VideoWriter::fourcc('X', '2', '6', '4');


    if(!fc)
    {
    if(!init_stream((unsigned char*)buffer, length))
    {
    return;
    }
    }
    if(fc)
    {
    append_stream((unsigned char*)buffer, length);
    }
    }
    }


    Thanks you very mutch if you can help me , i'm a novice in c++ and i have never deal with video stream. If you want to see the full code its host on github repo to this project










    share|improve this question
























      up vote
      1
      down vote

      favorite
      1









      up vote
      1
      down vote

      favorite
      1






      1





      I writting a software for my classes that receive a h264 stream from a drone and i need to convert the video stream to opencv Mat.



      I have no trouble to receive the frame and if i save it to a .264 file i can read the output with VLC.



      The drone is sending IDR-Frame and P-Frame , since i don't need to see the video stream juste some frame of it, i was thinking of only using the IDR-Frame to get the image but i have trouble to understand how to use libavcodec from FFMPEG, how can i create a AVFrame from my IDR-Frame and how to convert it to cv::Mat after.



      i have try the following code, i have store the full frame in .raw file and i try to decode them , but i get read error when i try to parse the packet to a frame, i don't thing a initialize the buffer of ARPacket the right way :



      AVFormatContext* fc = 0;
      int vi = -1; // vi veut dire video index


      inline cv::Mat avframe_to_mat(const AVFrame* avframe)
      {
      AVFrame dst;
      cv::Mat m;

      memset(&dst, 0, sizeof(dst));

      int w = avframe->width, h = avframe->height;

      m = cv::Mat(h, w, CV_8UC3);
      dst.data[0] = (uint8_t*)m.data;

      avpicture_fill((AVPicture*)&dst, dst.data[0], AV_PIX_FMT_BGR24, w, h);

      struct SwsContext *convert_ctx = NULL;

      enum AVPixelFormat src_pixfmt = AV_PIX_FMT_BGR24;
      enum AVPixelFormat dst_pixfmt = AV_PIX_FMT_BGR24;

      convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);

      sws_scale(convert_ctx, avframe->data, avframe->linesize, 0, h, dst.data, dst.linesize);
      sws_freeContext(convert_ctx);

      return m;

      }

      inline bool init_stream(unsigned char* data, int len)
      {

      const char* file = "test.avi";

      const AVCodecID codec_id = AV_CODEC_ID_H264;
      AVCodec* codec = avcodec_find_encoder(codec_id);
      // Crée le container pour le stream
      fc = avformat_alloc_context();

      /*
      AVOutputFormat *of = av_guess_format(0, file, 0);
      fc = avformat_alloc_context();
      fc->oformat = of;
      strcpy(fc->filename, file);
      */
      int br = 1000000;
      int w = 640;
      int h = 360;

      int fps = 24;


      // ajoute un stream video
      AVStream* pst = avformat_new_stream(fc, codec); // Pourquoi je passe pas le codec ici ?
      vi = pst->index;

      codec_context = avcodec_alloc_context3(codec);

      codec_context->bit_rate = br;
      codec_context->width = w;
      codec_context->height = h;
      codec_context->time_base = {1,fps};
      codec_context->gop_size = 10; // Emit one intra frame every ten frames
      codec_context->max_b_frames = 1;
      codec_context->pix_fmt = AV_PIX_FMT_YUV420P;

      // Vu quon n'est en h264
      av_opt_set(codec_context->priv_data, "preset", "slow", 0);


      // Ouvre notre codec
      if(avcodec_open2(codec_context, codec,nullptr) < 0)
      {
      cerr << "Impossible d'ouvrir le codec" << endl;
      return false;
      }

      if (!(fc->oformat->flags & AVFMT_NOFILE))
      avio_open(&fc->pb, fc->filename,0);

      // avformat_write_header(fc,nullptr);


      return true;
      }


      inline void append_stream(uint8_t* data, int len)
      {
      if( 0 > vi)
      {
      cerr << "video index is less than 0" << endl;
      return;
      }
      AVStream* pst = fc->streams[vi];

      AVPacket pkt;


      // Init un nouveau packet
      av_init_packet(&pkt);
      pkt.flags |= AV_PKT_FLAG_KEY;
      pkt.data = data;
      pkt.stream_index = pst->index;
      pkt.size = len;

      pkt.dts = AV_NOPTS_VALUE;
      pkt.pts = AV_NOPTS_VALUE;

      // ERROR accessing location
      av_interleaved_write_frame(fc, &pkt);


      }


      inline void execute_staging_test(const fs::path& folder, int nbr_trame)
      {
      fs::path file_name = folder / "stream.bin";
      if(!fs::exists(file_name))
      {
      cerr << "The file " << file_name.string() << " does not exists" << endl;
      return;
      }

      avcodec_register_all();

      av_log_set_level(AV_LOG_DEBUG);
      int length = 0;
      char* buffer;

      for(int i = 0; i < nbr_trame;i++)
      {
      fs::path file = std::to_string(i) + ".raw";
      file = folder / file;
      cout << "Got frame on " << file.string() << endl;
      ifstream ifs(file, ofstream::binary);

      // Get la longeur du fichier pour savoir le buffer a prendre
      ifs.seekg(0, ios::end);
      length = ifs.tellg();
      ifs.seekg(0, ios::beg);

      if (length == 0) {
      std::cerr << "No data in file " << file << std::endl;
      return;
      }

      buffer = new char[length];

      std::cout << "File " << file << " length is " << length << std::endl;

      ifs.read(buffer, length);

      cv::VideoWriter vw;
      int codec = cv::VideoWriter::fourcc('X', '2', '6', '4');


      if(!fc)
      {
      if(!init_stream((unsigned char*)buffer, length))
      {
      return;
      }
      }
      if(fc)
      {
      append_stream((unsigned char*)buffer, length);
      }
      }
      }


      Thanks you very mutch if you can help me , i'm a novice in c++ and i have never deal with video stream. If you want to see the full code its host on github repo to this project










      share|improve this question













      I writting a software for my classes that receive a h264 stream from a drone and i need to convert the video stream to opencv Mat.



      I have no trouble to receive the frame and if i save it to a .264 file i can read the output with VLC.



      The drone is sending IDR-Frame and P-Frame , since i don't need to see the video stream juste some frame of it, i was thinking of only using the IDR-Frame to get the image but i have trouble to understand how to use libavcodec from FFMPEG, how can i create a AVFrame from my IDR-Frame and how to convert it to cv::Mat after.



      i have try the following code, i have store the full frame in .raw file and i try to decode them , but i get read error when i try to parse the packet to a frame, i don't thing a initialize the buffer of ARPacket the right way :



      AVFormatContext* fc = 0;
      int vi = -1; // vi veut dire video index


      inline cv::Mat avframe_to_mat(const AVFrame* avframe)
      {
      AVFrame dst;
      cv::Mat m;

      memset(&dst, 0, sizeof(dst));

      int w = avframe->width, h = avframe->height;

      m = cv::Mat(h, w, CV_8UC3);
      dst.data[0] = (uint8_t*)m.data;

      avpicture_fill((AVPicture*)&dst, dst.data[0], AV_PIX_FMT_BGR24, w, h);

      struct SwsContext *convert_ctx = NULL;

      enum AVPixelFormat src_pixfmt = AV_PIX_FMT_BGR24;
      enum AVPixelFormat dst_pixfmt = AV_PIX_FMT_BGR24;

      convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);

      sws_scale(convert_ctx, avframe->data, avframe->linesize, 0, h, dst.data, dst.linesize);
      sws_freeContext(convert_ctx);

      return m;

      }

      inline bool init_stream(unsigned char* data, int len)
      {

      const char* file = "test.avi";

      const AVCodecID codec_id = AV_CODEC_ID_H264;
      AVCodec* codec = avcodec_find_encoder(codec_id);
      // Crée le container pour le stream
      fc = avformat_alloc_context();

      /*
      AVOutputFormat *of = av_guess_format(0, file, 0);
      fc = avformat_alloc_context();
      fc->oformat = of;
      strcpy(fc->filename, file);
      */
      int br = 1000000;
      int w = 640;
      int h = 360;

      int fps = 24;


      // ajoute un stream video
      AVStream* pst = avformat_new_stream(fc, codec); // Pourquoi je passe pas le codec ici ?
      vi = pst->index;

      codec_context = avcodec_alloc_context3(codec);

      codec_context->bit_rate = br;
      codec_context->width = w;
      codec_context->height = h;
      codec_context->time_base = {1,fps};
      codec_context->gop_size = 10; // Emit one intra frame every ten frames
      codec_context->max_b_frames = 1;
      codec_context->pix_fmt = AV_PIX_FMT_YUV420P;

      // Vu quon n'est en h264
      av_opt_set(codec_context->priv_data, "preset", "slow", 0);


      // Ouvre notre codec
      if(avcodec_open2(codec_context, codec,nullptr) < 0)
      {
      cerr << "Impossible d'ouvrir le codec" << endl;
      return false;
      }

      if (!(fc->oformat->flags & AVFMT_NOFILE))
      avio_open(&fc->pb, fc->filename,0);

      // avformat_write_header(fc,nullptr);


      return true;
      }


      inline void append_stream(uint8_t* data, int len)
      {
      if( 0 > vi)
      {
      cerr << "video index is less than 0" << endl;
      return;
      }
      AVStream* pst = fc->streams[vi];

      AVPacket pkt;


      // Init un nouveau packet
      av_init_packet(&pkt);
      pkt.flags |= AV_PKT_FLAG_KEY;
      pkt.data = data;
      pkt.stream_index = pst->index;
      pkt.size = len;

      pkt.dts = AV_NOPTS_VALUE;
      pkt.pts = AV_NOPTS_VALUE;

      // ERROR accessing location
      av_interleaved_write_frame(fc, &pkt);


      }


      inline void execute_staging_test(const fs::path& folder, int nbr_trame)
      {
      fs::path file_name = folder / "stream.bin";
      if(!fs::exists(file_name))
      {
      cerr << "The file " << file_name.string() << " does not exists" << endl;
      return;
      }

      avcodec_register_all();

      av_log_set_level(AV_LOG_DEBUG);
      int length = 0;
      char* buffer;

      for(int i = 0; i < nbr_trame;i++)
      {
      fs::path file = std::to_string(i) + ".raw";
      file = folder / file;
      cout << "Got frame on " << file.string() << endl;
      ifstream ifs(file, ofstream::binary);

      // Get la longeur du fichier pour savoir le buffer a prendre
      ifs.seekg(0, ios::end);
      length = ifs.tellg();
      ifs.seekg(0, ios::beg);

      if (length == 0) {
      std::cerr << "No data in file " << file << std::endl;
      return;
      }

      buffer = new char[length];

      std::cout << "File " << file << " length is " << length << std::endl;

      ifs.read(buffer, length);

      cv::VideoWriter vw;
      int codec = cv::VideoWriter::fourcc('X', '2', '6', '4');


      if(!fc)
      {
      if(!init_stream((unsigned char*)buffer, length))
      {
      return;
      }
      }
      if(fc)
      {
      append_stream((unsigned char*)buffer, length);
      }
      }
      }


      Thanks you very mutch if you can help me , i'm a novice in c++ and i have never deal with video stream. If you want to see the full code its host on github repo to this project







      c++ opencv libavcodec libav






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 10 at 18:16









      William Quintal

      61




      61





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242005%2flibav-c-raw-h264-tcp-stream-to-opencv-mat%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242005%2flibav-c-raw-h264-tcp-stream-to-opencv-mat%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Florida Star v. B. J. F.

          Danny Elfman

          Lugert, Oklahoma