<div dir="ltr"><div><div><div><div><div><div>Hi All,<br><br></div>I am trying to create video software which should be able to stream files over network and to record the streamed data into file.<br><br></div>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 :-) )<br><br></div>When I use more than 1 object I got NULL pointer on input context<br><br></div>I know my code has a lot things to be done, but my real problem now is the NULL pointer<br></div><br>Here is the code<br><br>extern "C"<br>{<br>#include <libavutil/timestamp.h><br>#include <libavformat/avformat.h><br>}<br><br>#include <iostream><br>#include <unistd.h><br>#include <boost/asio.hpp><br>#include <boost/thread.hpp><br>#include <boost/bind.hpp><br>#include "applicationlog.hpp"<br>#include "channel.hpp"<br><br><br>using namespace std;<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>void worker(boost::asio::io_service *ios)<br>{<br>    ios->run();<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>int main(int argc, char **argv)<br>{<br>    boost::asio::io_service ios;<br>    boost::asio::io_service ios1;<br><br>    Channel *channels[100];<br><br>    channels[0] = new Channel(ios, 9078, atoi(argv[1]));<br>    channels[0]->StartTimer(0);<br><br>    channels[1] = new Channel(ios1, 9079, atoi(argv[1]));<br>    channels[1]->StartTimer(0);<br><br>    boost::thread t(boost::bind(&worker, &ios));<br>    boost::thread t1(boost::bind(&worker, &ios1));<br><br><br>    t.join();<br>    t1.join();<br><br>    CEVLOG_MSG << "done" << std::endl;<br><br>    return 0;<br>}<br><br><br></div>The Channel class implementation<br><br>#include "channel.hpp"<br>#include "utils.hpp"<br>#include "boost/lexical_cast.hpp"<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>Channel::Channel(boost::asio::io_service &ioP, int i, bool to_send):<br>    Runnable(ioP),<br>    work( new boost::asio::io_service::work(ioP) ),<br>    ofmt(NULL),<br>    ifmt_ctx(NULL),<br>    ofmt_ctx(NULL)<br>{<br>    av_register_all();<br>    avformat_network_init();<br><br>    id = i;<br>    sender = to_send;<br><br>    if (sender)<br>    {<br>        input.assign("/home/georgi/Downloads/video/IMG_0019.MOV");<br>        output.assign("rtp://<a href="http://10.101.3.60">10.101.3.60</a>:"); output += boost::lexical_cast<std::string>(id);<br>    }<br>    else<br>    {<br>        input.assign("stream"); input += boost::lexical_cast<std::string>(id); input += ".sdp";<br>        output.assign("test"); output += boost::lexical_cast<std::string>(id); output += ".mp4";<br>    }<br><br>    video_idx = audio_idx = sub_idx = -1;<br><br>    if (OpenInput())<br>    {<br>        if (sender)<br>            OpenOutput(eStreamOutput);<br>        else<br>            OpenOutput(eFileOutput);<br>    }<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>Channel::~Channel()<br>{<br>    av_write_trailer(ofmt_ctx);<br><br>    avformat_close_input(&ifmt_ctx);<br><br>    if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))<br>        avio_closep(&ofmt_ctx->pb);<br><br>    avformat_free_context(ofmt_ctx);<br><br>    work.reset();<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>bool Channel::OpenInput()<br>{<br>    CEVLOG_MSG << "opening " << input << std::endl;<br><br>    int ret;<br>    if ((ret = avformat_open_input(&ifmt_ctx, input.c_str(), 0, 0)) < 0)<br>    {<br>        CEVLOG_ERR << "Could not open input file " << input << std::endl;<br>        return false;<br>    }<br><br>    CEVLOG_MSG << " " << ifmt_ctx << std::endl;<br><br>    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0)<br>    {<br>        CEVLOG_ERR << "Failed to retrieve input stream information" << std::endl;<br>        return false;<br>    }<br><br>    ifmt_ctx->flags |= AVFMT_FLAG_GENPTS;<br><br>    //read and set timestamps to 0<br>    av_read_frame(ifmt_ctx, &pkt);<br>    pkt.pts = pkt.dts = 0;<br><br>    return true;<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>bool Channel::OpenOutput(tOutputType WhatToOpen)<br>{<br>    int SDP_size;<br><br>    switch (WhatToOpen)<br>    {<br>    case eFileOutput:<br>        avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, output.c_str());<br>        break;<br><br>    case eStreamOutput:<br>        avformat_alloc_output_context2(&ofmt_ctx, NULL, "rtp", output.c_str());<br><br>        char SDP[4096];<br>        SDP_size = 4096;<br><br>        av_sdp_create(&ofmt_ctx, 1, SDP, SDP_size);<br>        CEVLOG_DBG << "SDP=" << SDP << std::endl;<br>        break;<br><br>    default:<br>        assert(false);<br>        break;<br>    }<br><br>    if (!ofmt_ctx)<br>    {<br>        CEVLOG_ERR << "Could not create output context" << std::endl;<br>        return false;<br>    }<br><br>    ofmt = ofmt_ctx->oformat;<br><br>    video_idx = FindIndex(AVMEDIA_TYPE_VIDEO);<br><br>    if (!(ofmt->flags & AVFMT_NOFILE))<br>    {<br>        if (avio_open(&ofmt_ctx->pb, output.c_str(), AVIO_FLAG_WRITE) < 0)<br>        {<br>            CEVLOG_ERR << "Could not open output file " << output << std::endl;<br>            return false;<br>        }<br>    }<br><br>    if (avformat_write_header(ofmt_ctx, NULL) < 0)<br>    {<br>        CEVLOG_ERR << "Error occurred when opening output file " << output << std::endl;<br>        return false;<br>    }<br><br>    return true;<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>unsigned int Channel::FindIndex(AVMediaType Type)<br>{<br>    int idx;<br><br>    for (idx = 0; idx < ifmt_ctx->nb_streams; idx++)<br>    {<br>        if (ifmt_ctx->streams[idx]->codec->codec_type == Type)<br>        {<br>            AVStream *in_stream = ifmt_ctx->streams[idx];<br>            AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);<br><br>            if (!out_stream)<br>            {<br>                CEVLOG_ERR << "Failed allocating output stream" << std::endl;<br>                break;<br>            }<br><br>            if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0)<br>            {<br>                CEVLOG_ERR << "Failed to copy context from input to output stream codec context" << std::endl;<br>                break;<br>            }<br><br>            out_stream->codec->codec_tag = 0;<br>            if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)<br>            {<br>                out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;<br>            }<br><br>            break;<br>        }<br>    }<br><br>    return idx;<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>void Channel::Callback()<br>{<br>    if (sender)<br>        SendVideo();<br>    else<br>        RecvVideo();<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>void Channel::SendVideo()<br>{<br>    int ret = av_read_frame(ifmt_ctx, &pkt);<br>    int time_ms = 0;<br><br>    if (ret != 0)<br>    {<br>        av_write_trailer(ofmt_ctx);<br>        work.reset();<br>        return;<br>    }<br><br>    if (pkt.stream_index == video_idx)<br>    {<br>        AVStream *in_stream  = ifmt_ctx->streams[pkt.stream_index];<br>        AVStream *out_stream = ofmt_ctx->streams[pkt.stream_index];<br><br>        AVRational time_base = ifmt_ctx->streams[video_idx]->time_base;<br><br>        char timestamp[100];<br>        time_ms = 1000 * 1000 * strtof(timestamp2char(timestamp, pkt.duration, &time_base), NULL);<br><br>        pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF);<br>        pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF);<br>        pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);<br>        pkt.pos = -1;<br><br>        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);<br><br>        if (ret < 0)<br>        {<br>            CEVLOG_ERR << "Error muxing packet" << std::endl;<br>            return;<br>        }<br>    }<br><br>    av_free_packet(&pkt);<br><br>    StartTimer(time_ms);<br>}<br><br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>//-----------------------------------------------------------------------------<br>void Channel::RecvVideo()<br>{<br>    int ret = av_read_frame(ifmt_ctx, &pkt);<br><br>    if (ret != 0)<br>    {<br>        //Some error or end of stream is detected. Write file trailer<br>        av_write_trailer(ofmt_ctx);<br>        work.reset();<br>        return;<br>    }<br><br>    //if is NOT video just continue reading<br>    if (pkt.stream_index == video_idx)<br>    {<br>        AVStream *in_stream  = ifmt_ctx->streams[pkt.stream_index];<br>        AVStream *out_stream = ofmt_ctx->streams[pkt.stream_index];<br><br>        AVRational time_base = ifmt_ctx->streams[video_idx]->time_base;<br><br>        pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF);<br>        pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF);<br>        pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);<br>        pkt.pos = -1;<br><br>        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);<br>        if (ret < 0)<br>        {<br>            CEVLOG_ERR << "Error muxing packet" << std::endl;<br>            return;<br>        }<br>    }<br><br>    av_free_packet(&pkt);<br><br>    StartTimer(0);<br>}<br><br><br></div>