| /* |
| * Copyright (C) 2020-2021 Savoir-faire Linux Inc. |
| * |
| * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| */ |
| |
| #ifndef MEDIASTREAM_H |
| #define MEDIASTREAM_H |
| |
| #include <media/libav_deps.h> |
| #include <rational.h> |
| |
| #include "audioFormat.h" |
| |
| #include <string> |
| |
| namespace jami { |
| |
| struct MediaStream |
| { |
| std::string name {}; |
| int format {-1}; |
| bool isVideo {false}; |
| rational<int> timeBase; |
| int64_t firstTimestamp {0}; |
| int width {0}; |
| int height {0}; |
| int bitrate; |
| rational<int> frameRate; |
| int sampleRate {0}; |
| int nbChannels {0}; |
| int frameSize {0}; |
| |
| MediaStream() {} |
| |
| MediaStream(const std::string& streamName, |
| int fmt, |
| rational<int> tb, |
| int w, |
| int h, |
| int br, |
| rational<int> fr) |
| : name(streamName) |
| , format(fmt) |
| , isVideo(true) |
| , timeBase(tb) |
| , width(w) |
| , height(h) |
| , bitrate(br) |
| , frameRate(fr) |
| {} |
| |
| MediaStream( |
| const std::string& streamName, int fmt, rational<int> tb, int sr, int channels, int size) |
| : name(streamName) |
| , format(fmt) |
| , isVideo(false) |
| , timeBase(tb) |
| , sampleRate(sr) |
| , nbChannels(channels) |
| , frameSize(size) |
| {} |
| |
| MediaStream(const std::string& streamName, AudioFormat fmt) |
| : MediaStream(streamName, fmt, 0) |
| {} |
| |
| MediaStream(const std::string& streamName, AudioFormat fmt, int64_t startTimestamp) |
| : name(streamName) |
| , format(fmt.sampleFormat) |
| , isVideo(false) |
| , timeBase(1, fmt.sample_rate) |
| , firstTimestamp(startTimestamp) |
| , sampleRate(fmt.sample_rate) |
| , nbChannels(fmt.nb_channels) |
| , frameSize(fmt.sample_rate / 50) // standard frame size for our encoder is 20 ms |
| {} |
| |
| MediaStream(const std::string& streamName, AVCodecContext* c) |
| : MediaStream(streamName, c, 0) |
| {} |
| |
| MediaStream(const std::string& streamName, AVCodecContext* c, int64_t startTimestamp) |
| : name(streamName) |
| , firstTimestamp(startTimestamp) |
| { |
| if (c) { |
| timeBase = c->time_base; |
| switch (c->codec_type) { |
| case AVMEDIA_TYPE_VIDEO: |
| format = c->pix_fmt; |
| isVideo = true; |
| width = c->width; |
| height = c->height; |
| bitrate = c->bit_rate; |
| frameRate = c->framerate; |
| break; |
| case AVMEDIA_TYPE_AUDIO: |
| format = c->sample_fmt; |
| isVideo = false; |
| sampleRate = c->sample_rate; |
| nbChannels = c->channels; |
| frameSize = c->frame_size; |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| MediaStream(const MediaStream& other) = default; |
| |
| bool isValid() const |
| { |
| if (format < 0) |
| return false; |
| if (isVideo) |
| return width > 0 && height > 0; |
| else |
| return sampleRate > 0 && nbChannels > 0; |
| } |
| |
| void update(AVFrame* f) |
| { |
| // update all info possible (AVFrame has no fps or bitrate data) |
| format = f->format; |
| if (isVideo) { |
| width = f->width; |
| height = f->height; |
| } else { |
| sampleRate = f->sample_rate; |
| nbChannels = f->channels; |
| timeBase = rational<int>(1, f->sample_rate); |
| if (!frameSize) |
| frameSize = f->nb_samples; |
| } |
| } |
| }; |
| |
| inline std::ostream& |
| operator<<(std::ostream& os, const MediaStream& ms) |
| { |
| if (ms.isVideo) { |
| auto formatName = av_get_pix_fmt_name(static_cast<AVPixelFormat>(ms.format)); |
| os << (ms.name.empty() ? "(null)" : ms.name) << ": " |
| << (formatName ? formatName : "(unknown format)") << " video, " << ms.width << "x" |
| << ms.height << ", " << ms.frameRate << " fps (" << ms.timeBase << ")"; |
| if (ms.bitrate > 0) |
| os << ", " << ms.bitrate << " kb/s"; |
| } else { |
| os << (ms.name.empty() ? "(null)" : ms.name) << ": " |
| << av_get_sample_fmt_name(static_cast<AVSampleFormat>(ms.format)) << " audio, " |
| << ms.nbChannels << " channel(s), " << ms.sampleRate << " Hz (" << ms.timeBase << "), " |
| << ms.frameSize << " samples per frame"; |
| } |
| if (ms.firstTimestamp > 0) |
| os << ", start: " << ms.firstTimestamp; |
| return os; |
| } |
| }; // namespace jami |
| |
| #endif // MEDIASTREAM_H |