|
1 | 1 | /*
|
2 |
| - * FLV muxer |
3 |
| - * Copyright (c) 2003 The FFmpeg Project |
| 2 | + * WebRTC muxer |
| 3 | + * Copyright (c) 2023 The FFmpeg Project |
4 | 4 | *
|
5 | 5 | * This file is part of FFmpeg.
|
6 | 6 | *
|
|
28 | 28 | #include "internal.h"
|
29 | 29 | #include "mux.h"
|
30 | 30 | #include "libavutil/opt.h"
|
| 31 | +#include "libavcodec/avcodec.h" |
31 | 32 |
|
32 | 33 | typedef struct RTCContext {
|
33 | 34 | AVClass *av_class;
|
| 35 | + |
| 36 | + /* Input audio and video codec parameters */ |
| 37 | + AVCodecParameters *audio_par; |
| 38 | + AVCodecParameters *video_par; |
34 | 39 | } RTCContext;
|
35 | 40 |
|
36 |
| -static int rtc_init(struct AVFormatContext *s) |
| 41 | +/** |
| 42 | + * Only support video(h264) and audio(opus) for now. Note that only baseline |
| 43 | + * and constrained baseline of h264 are supported. |
| 44 | + */ |
| 45 | +static int check_codec(AVFormatContext *s) |
| 46 | +{ |
| 47 | + int i; |
| 48 | + RTCContext *rtc = s->priv_data; |
| 49 | + |
| 50 | + for (i = 0; i < s->nb_streams; i++) { |
| 51 | + AVCodecParameters *par = s->streams[i]->codecpar; |
| 52 | + const AVCodecDescriptor *desc = avcodec_descriptor_get(par->codec_id); |
| 53 | + switch (par->codec_type) { |
| 54 | + case AVMEDIA_TYPE_VIDEO: |
| 55 | + if (rtc->video_par) { |
| 56 | + av_log(s, AV_LOG_ERROR, |
| 57 | + "Only one video stream is supported by RTC\n"); |
| 58 | + return AVERROR(EINVAL); |
| 59 | + } |
| 60 | + rtc->video_par = par; |
| 61 | + |
| 62 | + if (par->codec_id != AV_CODEC_ID_H264) { |
| 63 | + av_log(s, AV_LOG_ERROR, |
| 64 | + "Unsupported video codec %s by RTC, choose h264\n", |
| 65 | + desc ? desc->name : "unknown"); |
| 66 | + return AVERROR(EINVAL); |
| 67 | + } |
| 68 | + if ((par->profile & ~FF_PROFILE_H264_CONSTRAINED) != FF_PROFILE_H264_BASELINE) { |
| 69 | + av_log(s, AV_LOG_ERROR, |
| 70 | + "Profile %d of stream %d is not baseline, currently unsupported by RTC\n", |
| 71 | + par->profile, i); |
| 72 | + return AVERROR(EINVAL); |
| 73 | + } |
| 74 | + break; |
| 75 | + case AVMEDIA_TYPE_AUDIO: |
| 76 | + if (rtc->audio_par) { |
| 77 | + av_log(s, AV_LOG_ERROR, |
| 78 | + "Only one audio stream is supported by RTC\n"); |
| 79 | + return AVERROR(EINVAL); |
| 80 | + } |
| 81 | + rtc->audio_par = par; |
| 82 | + |
| 83 | + if (par->codec_id != AV_CODEC_ID_OPUS) { |
| 84 | + av_log(s, AV_LOG_ERROR, |
| 85 | + "Unsupported audio codec %s by RTC, choose opus\n", |
| 86 | + desc ? desc->name : "unknown"); |
| 87 | + return AVERROR(EINVAL); |
| 88 | + } |
| 89 | + |
| 90 | + if (par->ch_layout.nb_channels != 2) { |
| 91 | + av_log(s, AV_LOG_ERROR, |
| 92 | + "Unsupported audio channels %d by RTC, choose stereo\n", |
| 93 | + par->ch_layout.nb_channels); |
| 94 | + return AVERROR(EINVAL); |
| 95 | + } |
| 96 | + |
| 97 | + if (par->sample_rate != 48000) { |
| 98 | + av_log(s, AV_LOG_ERROR, |
| 99 | + "Unsupported audio sample rate %d by RTC, choose 48000\n", |
| 100 | + par->sample_rate); |
| 101 | + return AVERROR(EINVAL); |
| 102 | + } |
| 103 | + break; |
| 104 | + default: |
| 105 | + av_log(s, AV_LOG_ERROR, |
| 106 | + "Codec type '%s' for stream %d is not supported by RTC\n", |
| 107 | + av_get_media_type_string(par->codec_type), i); |
| 108 | + return AVERROR(EINVAL); |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + return 0; |
| 113 | +} |
| 114 | + |
| 115 | +static int rtc_init(AVFormatContext *s) |
37 | 116 | {
|
| 117 | + int ret; |
| 118 | + |
| 119 | + if ((ret = check_codec(s)) < 0) |
| 120 | + return ret; |
| 121 | + |
38 | 122 | return 0;
|
39 | 123 | }
|
40 | 124 |
|
41 |
| -static int rtc_write_header(struct AVFormatContext *s) |
| 125 | +static int rtc_write_header(AVFormatContext *s) |
42 | 126 | {
|
43 | 127 | return 0;
|
44 | 128 | }
|
45 | 129 |
|
46 |
| -static int rtc_write_packet(struct AVFormatContext *s, AVPacket *pkt) |
| 130 | +static int rtc_write_packet(AVFormatContext *s, AVPacket *pkt) |
47 | 131 | {
|
48 | 132 | return 0;
|
49 | 133 | }
|
50 | 134 |
|
51 |
| -static int rtc_write_trailer(struct AVFormatContext *s) |
| 135 | +static int rtc_write_trailer(AVFormatContext *s) |
52 | 136 | {
|
53 | 137 | return 0;
|
54 | 138 | }
|
55 | 139 |
|
56 |
| -static void rtc_deinit(struct AVFormatContext *s) |
| 140 | +static void rtc_deinit(AVFormatContext *s) |
57 | 141 | {
|
58 | 142 | }
|
59 | 143 |
|
|
0 commit comments