0

I am grabbing a video frame from my webcam and trying to stream it live through RTMP (to YouTube specifically). I have been able to successfully grab a YUV420p frame from the camera, encode it in h.264, but when I try to send it to the muxer, it does not encode it to the stream correctly.

I suspect that I have failed to set a important parameter, or have done something in a incorrect order when initializing. I have also tried using both the av_write_frame function and the av_interleaved_write_frame.

To make it easier for testing, I have the output going to a flv file for now. I define FILE_TEST_PATH as the path I want the file saved to.

This is my initialization function:

void rtmp_stream::init(string url, int width, int height)
{
    //if(avio_open2(&formatCtx->pb, url.c_str(), AVIO_FLAG_READ_WRITE , NULL, NULL))
    if(avio_open2(&formatCtx->pb, FILE_TEST_PATH , AVIO_FLAG_WRITE, NULL, NULL))
    {
        printf("Error\n");
    }

    avformat_new_stream(formatCtx, codec);
    formatCtx->streams[0]->codecpar->format=AV_PIX_FMT_YUV420P;
    formatCtx->streams[0]->codecpar->bit_rate=4000000;
    formatCtx->streams[0]->codecpar->width=width;
    formatCtx->streams[0]->codecpar->height=height;
    formatCtx->streams[0]->codecpar->codec_id = codec->id;


    formatCtx->streams[0]->time_base=(AVRational){1,1000};
    strcpy(formatCtx->filename, FILE_TEST_PATH);

    /*
     * It says using stream->codec is depricated but yet it does not populate codecpar
     * without setting these up.
     */

    formatCtx->streams[0]->codec->width=width;
    formatCtx->streams[0]->codec->height=height;
    formatCtx->streams[0]->codec->pix_fmt=AV_PIX_FMT_YUV420P;
    formatCtx->streams[0]->codec->codec_id = codec->id;
    formatCtx->streams[0]->codec->bit_rate=4000000;
    formatCtx->streams[0]->codec->pix_fmt=AV_PIX_FMT_YUV420P;
    formatCtx->streams[0]->codec->max_b_frames=3;


    formatCtx->video_codec_id=formatCtx->streams[0]->codecpar->codec_id;

    codecCtx->bit_rate=4000000;
    codecCtx->bit_rate_tolerance=0;
    codecCtx->framerate=(AVRational){1,1};
    codecCtx->gop_size=12;
    codecCtx->height=height;
    codecCtx->width=width;
    codecCtx->pix_fmt=AV_PIX_FMT_YUV420P;
    codecCtx->time_base=(AVRational){1,25};
    codecCtx->max_b_frames=3;

    avcodec_open2(codecCtx, codec, NULL);
    avformat_write_header(formatCtx, NULL);

}

This is the code that sends the encoded h.264 packet to the muxer

void rtmp_stream::send_packet()
{
    av_packet_rescale_ts(packet, codecCtx->time_base, formatCtx->streams[0]->time_base);
    if(av_write_frame(formatCtx, packet))
        printf("ERROR\n");
}

Additional information: I know the frames from the camera are valid and working. I have dumped the h.264 packets from the encoder to a ".h264" file and played them in VLC and they played fine. I'm also only working with video for now.

I have the code in my git gub account should there be a need to see more code. https://github.com/chrismacias37/Heads-Up-Display

cmacia06
  • 189
  • 1
  • 2
  • 13
  • Set the codec context extradata. – szatmary Sep 20 '16 at 17:16
  • I saw this question, http://stackoverflow.com/questions/32028437/what-are-bitstream-filters-in-ffmpeg . Is this what you mean by set the extra data? If so, what bit stream filter is normally used for an flv stream? – cmacia06 Sep 20 '16 at 18:35
  • It turns out that FLV also needs an audio stream to work correctly. I am not sure this is completely true for the flv muxer but, after adding an audio stream, it is finally working. It may be been that YouTube doesn't like an flv stream without audio? Nonetheless the problem is resolved. – cmacia06 Dec 18 '16 at 23:24

0 Answers0