[Libav-user] NULL pointer using boost asio and many streaming object

Georgi Rosenov Stefanov georgi.rosenov at gmail.com
Tue Apr 7 14:22:00 CEST 2015


Hi All,

I am trying to create video software which should be able to stream files
over network and to record the streamed data into file.

To realize this I create an object for every stream ( I call it channel)
and another object for recording the stream to file (I call it channel
again :-) )

When I use more than 1 object I got NULL pointer on input context

I know my code has a lot things to be done, but my real problem now is the
NULL pointer

Here is the code

extern "C"
{
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
}

#include <iostream>
#include <unistd.h>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include "applicationlog.hpp"
#include "channel.hpp"


using namespace std;

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void worker(boost::asio::io_service *ios)
{
    ios->run();
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
    boost::asio::io_service ios;
    boost::asio::io_service ios1;

    Channel *channels[100];

    channels[0] = new Channel(ios, 9078, atoi(argv[1]));
    channels[0]->StartTimer(0);

    channels[1] = new Channel(ios1, 9079, atoi(argv[1]));
    channels[1]->StartTimer(0);

    boost::thread t(boost::bind(&worker, &ios));
    boost::thread t1(boost::bind(&worker, &ios1));


    t.join();
    t1.join();

    CEVLOG_MSG << "done" << std::endl;

    return 0;
}


The Channel class implementation

#include "channel.hpp"
#include "utils.hpp"
#include "boost/lexical_cast.hpp"
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Channel::Channel(boost::asio::io_service &ioP, int i, bool to_send):
    Runnable(ioP),
    work( new boost::asio::io_service::work(ioP) ),
    ofmt(NULL),
    ifmt_ctx(NULL),
    ofmt_ctx(NULL)
{
    av_register_all();
    avformat_network_init();

    id = i;
    sender = to_send;

    if (sender)
    {
        input.assign("/home/georgi/Downloads/video/IMG_0019.MOV");
        output.assign("rtp://10.101.3.60:"); output +=
boost::lexical_cast<std::string>(id);
    }
    else
    {
        input.assign("stream"); input +=
boost::lexical_cast<std::string>(id); input += ".sdp";
        output.assign("test"); output +=
boost::lexical_cast<std::string>(id); output += ".mp4";
    }

    video_idx = audio_idx = sub_idx = -1;

    if (OpenInput())
    {
        if (sender)
            OpenOutput(eStreamOutput);
        else
            OpenOutput(eFileOutput);
    }
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Channel::~Channel()
{
    av_write_trailer(ofmt_ctx);

    avformat_close_input(&ifmt_ctx);

    if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
        avio_closep(&ofmt_ctx->pb);

    avformat_free_context(ofmt_ctx);

    work.reset();
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool Channel::OpenInput()
{
    CEVLOG_MSG << "opening " << input << std::endl;

    int ret;
    if ((ret = avformat_open_input(&ifmt_ctx, input.c_str(), 0, 0)) < 0)
    {
        CEVLOG_ERR << "Could not open input file " << input << std::endl;
        return false;
    }

    CEVLOG_MSG << " " << ifmt_ctx << std::endl;

    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0)
    {
        CEVLOG_ERR << "Failed to retrieve input stream information" <<
std::endl;
        return false;
    }

    ifmt_ctx->flags |= AVFMT_FLAG_GENPTS;

    //read and set timestamps to 0
    av_read_frame(ifmt_ctx, &pkt);
    pkt.pts = pkt.dts = 0;

    return true;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool Channel::OpenOutput(tOutputType WhatToOpen)
{
    int SDP_size;

    switch (WhatToOpen)
    {
    case eFileOutput:
        avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL,
output.c_str());
        break;

    case eStreamOutput:
        avformat_alloc_output_context2(&ofmt_ctx, NULL, "rtp",
output.c_str());

        char SDP[4096];
        SDP_size = 4096;

        av_sdp_create(&ofmt_ctx, 1, SDP, SDP_size);
        CEVLOG_DBG << "SDP=" << SDP << std::endl;
        break;

    default:
        assert(false);
        break;
    }

    if (!ofmt_ctx)
    {
        CEVLOG_ERR << "Could not create output context" << std::endl;
        return false;
    }

    ofmt = ofmt_ctx->oformat;

    video_idx = FindIndex(AVMEDIA_TYPE_VIDEO);

    if (!(ofmt->flags & AVFMT_NOFILE))
    {
        if (avio_open(&ofmt_ctx->pb, output.c_str(), AVIO_FLAG_WRITE) < 0)
        {
            CEVLOG_ERR << "Could not open output file " << output <<
std::endl;
            return false;
        }
    }

    if (avformat_write_header(ofmt_ctx, NULL) < 0)
    {
        CEVLOG_ERR << "Error occurred when opening output file " << output
<< std::endl;
        return false;
    }

    return true;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
unsigned int Channel::FindIndex(AVMediaType Type)
{
    int idx;

    for (idx = 0; idx < ifmt_ctx->nb_streams; idx++)
    {
        if (ifmt_ctx->streams[idx]->codec->codec_type == Type)
        {
            AVStream *in_stream = ifmt_ctx->streams[idx];
            AVStream *out_stream = avformat_new_stream(ofmt_ctx,
in_stream->codec->codec);

            if (!out_stream)
            {
                CEVLOG_ERR << "Failed allocating output stream" <<
std::endl;
                break;
            }

            if (avcodec_copy_context(out_stream->codec, in_stream->codec) <
0)
            {
                CEVLOG_ERR << "Failed to copy context from input to output
stream codec context" << std::endl;
                break;
            }

            out_stream->codec->codec_tag = 0;
            if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
            {
                out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
            }

            break;
        }
    }

    return idx;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Channel::Callback()
{
    if (sender)
        SendVideo();
    else
        RecvVideo();
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Channel::SendVideo()
{
    int ret = av_read_frame(ifmt_ctx, &pkt);
    int time_ms = 0;

    if (ret != 0)
    {
        av_write_trailer(ofmt_ctx);
        work.reset();
        return;
    }

    if (pkt.stream_index == video_idx)
    {
        AVStream *in_stream  = ifmt_ctx->streams[pkt.stream_index];
        AVStream *out_stream = ofmt_ctx->streams[pkt.stream_index];

        AVRational time_base = ifmt_ctx->streams[video_idx]->time_base;

        char timestamp[100];
        time_ms = 1000 * 1000 * strtof(timestamp2char(timestamp,
pkt.duration, &time_base), NULL);

        pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base,
out_stream->time_base, AV_ROUND_NEAR_INF);
        pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base,
out_stream->time_base, AV_ROUND_NEAR_INF);
        pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base,
out_stream->time_base);
        pkt.pos = -1;

        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);

        if (ret < 0)
        {
            CEVLOG_ERR << "Error muxing packet" << std::endl;
            return;
        }
    }

    av_free_packet(&pkt);

    StartTimer(time_ms);
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void Channel::RecvVideo()
{
    int ret = av_read_frame(ifmt_ctx, &pkt);

    if (ret != 0)
    {
        //Some error or end of stream is detected. Write file trailer
        av_write_trailer(ofmt_ctx);
        work.reset();
        return;
    }

    //if is NOT video just continue reading
    if (pkt.stream_index == video_idx)
    {
        AVStream *in_stream  = ifmt_ctx->streams[pkt.stream_index];
        AVStream *out_stream = ofmt_ctx->streams[pkt.stream_index];

        AVRational time_base = ifmt_ctx->streams[video_idx]->time_base;

        pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base,
out_stream->time_base, AV_ROUND_NEAR_INF);
        pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base,
out_stream->time_base, AV_ROUND_NEAR_INF);
        pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base,
out_stream->time_base);
        pkt.pos = -1;

        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
        if (ret < 0)
        {
            CEVLOG_ERR << "Error muxing packet" << std::endl;
            return;
        }
    }

    av_free_packet(&pkt);

    StartTimer(0);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20150407/beb070e0/attachment.html>


More information about the Libav-user mailing list