[Libav-user] FFmpeg RTP payload 96 instead of 97

Yu Ang Tan yuang86 at gmail.com
Wed Oct 26 04:38:20 EEST 2016


On Thu, Sep 22, 2016 at 11:46 AM Yu Ang Tan <yuang86 at gmail.com> wrote:

> I want to create an rtp audio stream with ffmpeg. When I run my
> application I get the following SDP file configuration:
>
>     Output #0, rtp, to 'rtp://127.0.0.1:8554':
>         Stream #0:0: Audio: pcm_s16be, 8000 Hz, stereo, s16, 256 kb/s
>
>     SDP:
>     v=0
>     o=- 0 0 IN IP4 127.0.0.1
>     s=No Name
>     c=IN IP4 127.0.0.1
>     t=0 0
>     a=tool:libavformat 57.25.101
>     m=audio 8554 RTP/AVP 96
>     b=AS:256
>     a=rtpmap:96 L16/8000/2
>
> However, when I try to read it with `ffplay -i test.sdp
> -protocol_whitelist file,udp,rtp`, it fails,shows the following:
>
>     ffplay version N-78598-g98a0053 Copyright (c) 2003-2016 the FFmpeg
> developers
>       built with gcc 5.3.0 (GCC)
>       configuration: --disable-static --enable-shared --enable-gpl
> --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib
> --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv
> --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca
> --enable-libdcadec --enable-libfreetype --enable-libgme --enable-libgsm
> --enable-libilbc --enable-libmodplug --enable-libmp3lame
> --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg
> --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr
> --enable-libspeex --enable-libtheora --enable-libtwolame
> --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis
> --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264
> --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg
> --enable-lzma --enable-decklink --enable-zlib
>       libavutil      55. 18.100 / 55. 18.100
>       libavcodec     57. 24.103 / 57. 24.103
>       libavformat    57. 25.101 / 57. 25.101
>       libavdevice    57.  0.101 / 57.  0.101
>       libavfilter     6. 34.100 /  6. 34.100
>       libswscale      4.  0.100 /  4.  0.100
>       libswresample   2.  0.101 /  2.  0.101
>       libpostproc    54.  0.100 / 54.  0.100
>         nan    :  0.000 fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0
>         (...waits indefinitely.)
>
> The only way to make it work again is to modify the payload type in the
> SDP file from 96 to 97. Can someone tell me why? Where and how is this
> number defined?
>
>
> Here is my source.
>
>     #include <math.h>
>     extern "C"
>     {
>     #include <libavutil/opt.h>
>     #include <libavcodec/avcodec.h>
>     #include <libavutil/channel_layout.h>
>     #include <libavutil/common.h>
>     #include <libavutil/imgutils.h>
>     #include <libavutil/mathematics.h>
>     #include <libavutil/samplefmt.h>
>     #include <libavformat/avformat.h>
>     }
>
>
>     static int write_frame(AVFormatContext *fmt_ctx, const AVRational
> *time_base, AVStream *st, AVPacket *pkt)
>     {
>         /* rescale output packet timestamp values from codec to stream
> timebase */
>         av_packet_rescale_ts(pkt, *time_base, st->time_base);
>
>         /* Write the compressed frame to the media file. */
>         return av_interleaved_write_frame(fmt_ctx, pkt);
>     }
>
>     /*
>     * Audio encoding example
>     */
>     static void audio_encode_example(const char *filename)
>     {
>         AVPacket pkt;
>         int i, j, k, ret, got_output;
>         int buffer_size;
>
>         uint16_t *samples;
>         float t, tincr;
>
>         AVCodec *outCodec = NULL;
>         AVCodecContext *outCodecCtx = NULL;
>         AVFormatContext *outFormatCtx = NULL;
>         AVStream * outAudioStream = NULL;
>         AVFrame *outFrame = NULL;
>
>         ret = avformat_alloc_output_context2(&outFormatCtx, NULL, "rtp",
> filename);
>         if (!outFormatCtx || ret < 0)
>         {
>             fprintf(stderr, "Could not allocate output context");
>         }
>
>         outFormatCtx->flags |= AVFMT_FLAG_NOBUFFER |
> AVFMT_FLAG_FLUSH_PACKETS;
>         outFormatCtx->oformat->audio_codec = AV_CODEC_ID_PCM_S16BE;
>
>         /* find the encoder */
>         outCodec =
> avcodec_find_encoder(outFormatCtx->oformat->audio_codec);
>         if (!outCodec) {
>             fprintf(stderr, "Codec not found\n");
>             exit(1);
>         }
>
>         outAudioStream = avformat_new_stream(outFormatCtx, outCodec);
>         if (!outAudioStream)
>         {
>             fprintf(stderr, "Cannot add new audio stream\n");
>             exit(1);
>         }
>
>         outAudioStream->id = outFormatCtx->nb_streams - 1;
>         outCodecCtx = outAudioStream->codec;
>         outCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
>
>         /* select other audio parameters supported by the encoder */
>         outCodecCtx->sample_rate = 8000;
>         outCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
>         outCodecCtx->channels = 2;
>
>         /* open it */
>         if (avcodec_open2(outCodecCtx, outCodec, NULL) < 0) {
>             fprintf(stderr, "Could not open codec\n");
>             exit(1);
>         }
>
>         // PCM has no frame, so we have to explicitly specify
>         outCodecCtx->frame_size = 1152;
>
>         av_dump_format(outFormatCtx, 0, filename, 1);
>
>         char buff[10000] = { 0 };
>         ret = av_sdp_create(&outFormatCtx, 1, buff, sizeof(buff));
>         printf("%s", buff);
>
>         ret = avio_open2(&outFormatCtx->pb, filename, AVIO_FLAG_WRITE,
> NULL, NULL);
>         ret = avformat_write_header(outFormatCtx, NULL);
>         printf("ret = %d\n", ret);
>         if (ret <0) {
>             exit(1);
>         }
>
>         /* frame containing input audio */
>         outFrame = av_frame_alloc();
>         if (!outFrame) {
>             fprintf(stderr, "Could not allocate audio frame\n");
>             exit(1);
>         }
>
>         outFrame->nb_samples = outCodecCtx->frame_size;
>         outFrame->format = outCodecCtx->sample_fmt;
>         outFrame->channel_layout = outCodecCtx->channel_layout;
>
>         /* we calculate the size of the samples buffer in bytes */
>         buffer_size = av_samples_get_buffer_size(NULL,
> outCodecCtx->channels, outCodecCtx->frame_size,
>             outCodecCtx->sample_fmt, 0);
>         if (buffer_size < 0) {
>             fprintf(stderr, "Could not get sample buffer size\n");
>             exit(1);
>         }
>         samples = (uint16_t*)av_malloc(buffer_size);
>         if (!samples) {
>             fprintf(stderr, "Could not allocate %d bytes for samples
> buffer\n",
>                 buffer_size);
>             exit(1);
>         }
>         /* setup the data pointers in the AVFrame */
>         ret = avcodec_fill_audio_frame(outFrame, outCodecCtx->channels,
> outCodecCtx->sample_fmt,
>             (const uint8_t*)samples, buffer_size, 0);
>         if (ret < 0) {
>             fprintf(stderr, "Could not setup audio frame\n");
>             exit(1);
>         }
>
>         /* encode a single tone sound */
>         t = 0;
>         int next_pts = 0;
>         tincr = 2 * M_PI * 440.0 / outCodecCtx->sample_rate;
>         for (i = 0; i < 400000; i++) {
>             av_init_packet(&pkt);
>             pkt.data = NULL; // packet data will be allocated by the
> encoder
>             pkt.size = 0;
>
>             for (j = 0; j < outCodecCtx->frame_size; j++) {
>                 samples[2 * j] = (uint16_t)(sin(t) * 10000);
>
>                 for (k = 1; k < outCodecCtx->channels; k++)
>                     samples[2 * j + k] = samples[2 * j];
>                 t += tincr;
>             }
>             t = (t > 50000) ? 0 : t;
>
>             // Sets time stamp
>             next_pts += outFrame->nb_samples;
>             outFrame->pts = next_pts;
>
>             /* encode the samples */
>             ret = avcodec_encode_audio2(outCodecCtx, &pkt, outFrame,
> &got_output);
>             if (ret < 0) {
>                 fprintf(stderr, "Error encoding audio frame\n");
>                 exit(1);
>             }
>             if (got_output) {
>                 write_frame(outFormatCtx, &outCodecCtx->time_base,
> outAudioStream, &pkt);
>                 av_packet_unref(&pkt);
>             }
>
>             printf("i:%d\n", i); // waste some time to avoid over-filling
> jitter buffer
>             printf("Audio: %d\t%d\n", samples[0], samples[1]); // waste
> some time to avoid over-filling jitter buffer
>             printf("t: %f\n", t); // waste some time to avoid over-filling
> jitter buffer
>         }
>
>         /* get the delayed frames */
>         for (got_output = 1; got_output; i++) {
>             ret = avcodec_encode_audio2(outCodecCtx, &pkt, NULL,
> &got_output);
>             if (ret < 0) {
>                 fprintf(stderr, "Error encoding frame\n");
>                 exit(1);
>             }
>
>             if (got_output) {
>                 pkt.pts = AV_NOPTS_VALUE;
>                 write_frame(outFormatCtx, &outCodecCtx->time_base,
> outAudioStream, &pkt);
>                 av_packet_unref(&pkt);
>             }
>         }
>
>         av_freep(&samples);
>         av_frame_free(&outFrame);
>         avcodec_close(outCodecCtx);
>         av_free(outCodecCtx);
>     }
>
>
>     int main(int argc, char **argv)
>     {
>         const char *output;
>
>         av_register_all();
>         avformat_network_init(); // for network streaming
>
>         audio_encode_example("rtp://127.0.0.1:8554");
>
>         return 0;
>     }
>
>
>
Interestingly, the same code when compiled in Linux Ubuntu gives the
following:

Output #0, rtp, to 'rtp://127.0.0.1:8554':
    Stream #0:0: Unknown: none (pcm_s16be)
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 57.48.100
m=application 8554 RTP/AVP 3

I noticed that the Output stream is now labeled as "Unknown". And in the
SDP dump, the media name is switched from audio to application. RTP/AVP is
now 3 instead of 96/97. What's going on?

Would really appreciate it if any of you could shine some light on this.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20161026/241470f4/attachment.html>


More information about the Libav-user mailing list