Transcode.h 4.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
 *
 * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
 *
 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
 */

ziyue committed
11 12 13 14
#ifndef ZLMEDIAKIT_TRANSCODE_H
#define ZLMEDIAKIT_TRANSCODE_H

#if defined(ENABLE_FFMPEG)
15 16 17

#include "Util/TimeTicker.h"
#include "Common/MediaSink.h"
18 19 20 21

#ifdef __cplusplus
extern "C" {
#endif
ziyue committed
22 23 24
#include "libswscale/swscale.h"
#include "libavutil/avutil.h"
#include "libavutil/pixdesc.h"
25 26
#include "libavcodec/avcodec.h"
#include "libswresample/swresample.h"
ziyue committed
27
#include "libavutil/audio_fifo.h"
alexliyu7352 committed
28
#include "libavutil/imgutils.h"
29 30 31 32
#ifdef __cplusplus
}
#endif

ziyue committed
33 34
namespace mediakit {

35 36 37 38 39 40 41 42
class FFmpegFrame {
public:
    using Ptr = std::shared_ptr<FFmpegFrame>;

    FFmpegFrame(std::shared_ptr<AVFrame> frame = nullptr);
    ~FFmpegFrame();

    AVFrame *get() const;
ziyue committed
43
    void fillPicture(AVPixelFormat target_format, int target_width, int target_height);
44 45 46 47 48 49

private:
    char *_data = nullptr;
    std::shared_ptr<AVFrame> _frame;
};

50
class FFmpegSwr {
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
public:
    using Ptr = std::shared_ptr<FFmpegSwr>;

    FFmpegSwr(AVSampleFormat output, int channel, int channel_layout, int samplerate);
    ~FFmpegSwr();
    FFmpegFrame::Ptr inputFrame(const FFmpegFrame::Ptr &frame);

private:
    int _target_channels;
    int _target_channel_layout;
    int _target_samplerate;
    AVSampleFormat _target_format;
    SwrContext *_ctx = nullptr;
};

66 67 68
class TaskManager {
public:
    TaskManager() = default;
ziyue committed
69 70 71 72
    virtual ~TaskManager();

    void setMaxTaskSize(size_t size);
    void stopThread(bool drop_task);
73 74

protected:
夏楚 committed
75
    void startThread(const std::string &name);
ziyue committed
76 77
    bool addEncodeTask(std::function<void()> task);
    bool addDecodeTask(bool key_frame, std::function<void()> task);
78 79 80
    bool isEnabled() const;

private:
夏楚 committed
81
    void onThreadRun(const std::string &name);
82 83 84 85 86 87 88 89 90 91 92

private:
    class ThreadExitException : public std::runtime_error {
    public:
        ThreadExitException() : std::runtime_error("exit") {}
        ~ThreadExitException() = default;
    };

private:
    bool _decode_drop_start = false;
    bool _exit = false;
ziyue committed
93
    size_t _max_task = 30;
夏楚 committed
94 95 96 97
    std::mutex _task_mtx;
    toolkit::semaphore _sem;
    toolkit::List<std::function<void()> > _task;
    std::shared_ptr<std::thread> _thread;
98 99
};

ziyue committed
100
class FFmpegDecoder : public TaskManager {
101 102
public:
    using Ptr = std::shared_ptr<FFmpegDecoder>;
夏楚 committed
103
    using onDec = std::function<void(const FFmpegFrame::Ptr &)>;
104

ziyue committed
105
    FFmpegDecoder(const Track::Ptr &track, int thread_num = 2, const std::vector<std::string> &codec_name = {});
ziyue committed
106
    ~FFmpegDecoder() override;
107

ziyue committed
108
    bool inputFrame(const Frame::Ptr &frame, bool live, bool async, bool enable_merge = true);
109 110 111 112 113 114
    void setOnDecode(onDec cb);
    void flush();
    const AVCodecContext *getContext() const;

private:
    void onDecode(const FFmpegFrame::Ptr &frame);
ziyue committed
115
    bool inputFrame_l(const Frame::Ptr &frame, bool live, bool enable_merge);
ziyue committed
116
    bool decodeFrame(const char *data, size_t size, uint64_t dts, uint64_t pts, bool live, bool key_frame);
117 118

private:
119
    bool _do_merger = false;
夏楚 committed
120
    toolkit::Ticker _ticker;
121 122
    onDec _cb;
    std::shared_ptr<AVCodecContext> _context;
ziyue committed
123
    FrameMerger _merger{FrameMerger::h264_prefix};
124 125
};

ziyue committed
126 127 128
class FFmpegSws {
public:
    using Ptr = std::shared_ptr<FFmpegSws>;
129

ziyue committed
130 131 132 133
    FFmpegSws(AVPixelFormat output, int width, int height);
    ~FFmpegSws();
    FFmpegFrame::Ptr inputFrame(const FFmpegFrame::Ptr &frame);
    int inputFrame(const FFmpegFrame::Ptr &frame, uint8_t *data);
134

ziyue committed
135
private:
ziyue committed
136 137 138 139 140 141 142
    FFmpegFrame::Ptr inputFrame(const FFmpegFrame::Ptr &frame, int &ret, uint8_t *data);

private:
    int _target_width = 0;
    int _target_height = 0;
    int _src_width = 0;
    int _src_height = 0;
ziyue committed
143
    SwsContext *_ctx = nullptr;
ziyue committed
144 145
    AVPixelFormat _src_format = AV_PIX_FMT_NONE;
    AVPixelFormat _target_format = AV_PIX_FMT_NONE;
ziyue committed
146 147 148 149 150
};

}//namespace mediakit
#endif// ENABLE_FFMPEG
#endif //ZLMEDIAKIT_TRANSCODE_H