胡斌

finished most of decode flow

  1 +#include "AVDecoder.h"
  2 +
  3 +
  4 +CAVDecoder::CAVDecoder() :
  5 +_a_start_time_ms(INT64_MAX),
  6 +_v_start_time_ms(INT64_MAX),
  7 +_cur_a_ts_ms(INT64_MAX),
  8 +_cur_v_ts_ms(INT64_MAX),
  9 +_end_time_ms(0),
  10 +_cur_a_frame(NULL),
  11 +_cur_v_frame(NULL)
  12 +{
  13 +}
  14 +
  15 +
  16 +CAVDecoder::~CAVDecoder()
  17 +{
  18 +}
  19 +
  20 +int CAVDecoder::add(media_info &info)
  21 +{
  22 + if (info.m_type == mt_audio) {
  23 + _a_start_time_ms = info.start_time_ms;
  24 + _a_end_time_ms = info.end_time_ms;
  25 + _audio_info.push_back(info);
  26 + _audio_decoder.add(info);
  27 + }
  28 + else {
  29 + _v_start_time_ms = info.start_time_ms;
  30 + _v_end_time_ms = info.end_time_ms;
  31 + _video_info.push_back(info);
  32 + _video_decoder.add(info);
  33 + }
  34 +
  35 + if (_cur_a_ts_ms == INT64_MAX) {
  36 + _cur_a_ts_ms = info.start_time_ms;
  37 + _cur_v_ts_ms = info.start_time_ms;
  38 + }
  39 +
  40 + if (_end_time_ms < info.end_time_ms) {
  41 + _end_time_ms = info.end_time_ms;
  42 + }
  43 +
  44 + return 0;
  45 +}
  46 +
  47 +unsigned int CAVDecoder::getuid()
  48 +{
  49 + return 0;
  50 +}
  51 +
  52 +bool CAVDecoder::get_one_v_frame()
  53 +{
  54 + int64_t ts;
  55 + int ret = -1;
  56 + if (_video_info.size()) {
  57 + ret = _video_decoder.get_one_frame(&_cur_v_frame, ts);
  58 + if (ret == 0) {
  59 + _cur_v_ts_ms = _v_start_time_ms + ts;
  60 + }
  61 + else {
  62 + _video_info.pop_front();
  63 + if (_cur_v_ts_ms < _end_time_ms) {
  64 + _cur_v_ts_ms += 50;//return last v frame
  65 + ret = 0;
  66 + }
  67 + }
  68 + }
  69 +
  70 + if (ret) {//no video decoded
  71 + if (_cur_v_ts_ms < _end_time_ms) {//should have as video frame
  72 + _cur_v_ts_ms += 50;//return last v frame
  73 + ret = 0;
  74 + if (!_cur_v_frame) {
  75 + _cur_v_frame = get_blank_frame();
  76 + }
  77 + }
  78 + }
  79 +
  80 + return ret == 0;
  81 +}
  82 +
  83 +AVFrame * CAVDecoder::get_blank_frame()
  84 +{
  85 + return NULL;
  86 +}
  87 +
  88 +AVFrame * CAVDecoder::get_silence_frame()
  89 +{
  90 + return NULL;
  91 +}
  92 +
  93 +
  94 +
  95 +void CAVDecoder::free_cur_a_frame()
  96 +{
  97 + if (_cur_a_frame) {
  98 + av_frame_free(&_cur_a_frame);
  99 + }
  100 +}
  101 +
  102 +
  103 +void CAVDecoder::free_cur_v_frame()
  104 +{
  105 + if (_cur_v_frame) {
  106 + av_frame_free(&_cur_v_frame);
  107 + }
  108 +}
  109 +
  110 +bool CAVDecoder::get_one_a_frame()
  111 +{
  112 + int64_t ts;
  113 + int ret = -1;
  114 + if (_audio_info.size()) {
  115 + ret = _audio_decoder.get_one_frame(&_cur_v_frame, ts);
  116 + if (ret == 0) {
  117 + _cur_a_ts_ms = _a_start_time_ms + ts;
  118 + }
  119 + else {
  120 + _audio_info.pop_front();
  121 + if (_cur_a_ts_ms < _end_time_ms) {
  122 + _cur_a_ts_ms += AFRAME_DURATION_MS;//return silence frame
  123 + ret = 0;
  124 + }
  125 + }
  126 + }
  127 +
  128 + if (ret) {//no video decoded
  129 + if (_cur_a_ts_ms < _end_time_ms) {//should have a audio frame
  130 + _cur_a_ts_ms += AFRAME_DURATION_MS;//return last a frame
  131 + ret = 0;
  132 + if (!_cur_a_frame) {
  133 + _cur_a_frame = get_silence_frame();
  134 + }
  135 + }
  136 + }
  137 +
  138 + return ret == 0;
  139 +}
  1 +#pragma once
  2 +#include "AudioDecoder.h"
  3 +#include "VideoDecoder.h"
  4 +
  5 +class CAVDecoder
  6 +{
  7 +public:
  8 + CAVDecoder();
  9 + virtual ~CAVDecoder();
  10 +
  11 + int add(media_info &info);
  12 +
  13 + unsigned int getuid();
  14 + bool get_one_a_frame();
  15 + bool get_one_v_frame();
  16 + int64_t _cur_a_ts_ms;
  17 + int64_t _cur_v_ts_ms;
  18 +
  19 +protected:
  20 + list<media_info> _video_info;
  21 + list<media_info> _audio_info;
  22 + CAudioDecoder _audio_decoder;
  23 + CVideoDecoder _video_decoder;
  24 + int64_t _a_start_time_ms;
  25 + int64_t _a_end_time_ms;
  26 + int64_t _v_start_time_ms;
  27 + int64_t _v_end_time_ms;
  28 + int64_t _end_time_ms;
  29 + AVFrame * _cur_a_frame;
  30 + AVFrame * _cur_v_frame;
  31 +private:
  32 + AVFrame * get_blank_frame();
  33 + AVFrame * get_silence_frame();
  34 +public:
  35 + void free_cur_a_frame();
  36 + void free_cur_v_frame();
  37 +};
  38 +
  1 +#include "AVTranscoder.h"
  2 +
  3 +
  4 +CAVTranscoder::CAVTranscoder():
  5 +_start_time(INT64_MAX),
  6 +_all_processed(true)
  7 +{
  8 +}
  9 +
  10 +
  11 +CAVTranscoder::~CAVTranscoder()
  12 +{
  13 +}
  14 +
  15 +int CAVTranscoder::add(media_info & info)
  16 +{
  17 + _all_processed = false;
  18 + if (_start_time == INT64_MAX) {
  19 + _start_time = info.start_time_ms;
  20 + _cur_v_time = _start_time;
  21 + _cur_a_time = _start_time;
  22 + }
  23 + vector < CAVDecoder *>::iterator it = _decoders.begin();
  24 + for (; it != _decoders.end(); it++) {
  25 + if ((*it)->getuid() == info.uid){
  26 + (*it)->add(info);
  27 + break;
  28 + }
  29 + }
  30 + if (it == _decoders.end()) {
  31 + CAVDecoder * pVideoDecoder = new CAVDecoder();
  32 + pVideoDecoder->add(info);
  33 + _decoders.push_back(pVideoDecoder);
  34 + }
  35 + return 0;
  36 +}
  37 +
  38 +int64_t CAVTranscoder::transcode()
  39 +{
  40 + vector<CAVDecoder *> decoders_got_frame;
  41 + vector < CAVDecoder *>::iterator it = _decoders.begin();
  42 + for (; it != _decoders.end();) {
  43 + if((*it)->get_one_v_frame()){
  44 + decoders_got_frame.push_back(*it);
  45 + }
  46 + else {
  47 + it = _decoders.erase(it);
  48 + continue;
  49 + }
  50 + it++;
  51 + }
  52 +
  53 + _all_processed = decoders_got_frame.size() == 0;
  54 + mix_and_output_vframe(decoders_got_frame);
  55 +
  56 + _cur_v_time += 50;
  57 + //sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
  58 +
  59 + while (_cur_a_time < _cur_v_time)
  60 + {
  61 + decoders_got_frame.clear();
  62 + vector < CAVDecoder *>::iterator it = _decoders.begin();
  63 + for (; it != _decoders.end();) {
  64 + if ((*it)->get_one_a_frame()){
  65 + decoders_got_frame.push_back(*it);
  66 + }
  67 + else {
  68 + it = _decoders.erase(it);
  69 + continue;
  70 + }
  71 + it++;
  72 + }
  73 + mix_and_output_aframe(decoders_got_frame);
  74 + _cur_a_time += AFRAME_DURATION_MS;
  75 + }
  76 +
  77 + return _cur_v_time;
  78 +}
  79 +
  80 +bool CAVTranscoder::all_processed()
  81 +{
  82 + return _all_processed;
  83 +}
  84 +
  85 +int CAVTranscoder::close()
  86 +{
  87 + return 0;
  88 +}
  89 +
  90 +
  91 +int CAVTranscoder::open_output_file(const char *filename)
  92 +{
  93 + AVStream *out_stream;
  94 + AVCodecContext *dec_ctx, *enc_ctx;
  95 + AVCodec *encoder;
  96 + int ret;
  97 + unsigned int i;
  98 +
  99 + ofmt_ctx = NULL;
  100 + avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
  101 + if (!ofmt_ctx) {
  102 + av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");
  103 + return AVERROR_UNKNOWN;
  104 + }
  105 +
  106 +
  107 + for (i = 0; i < 2; i++) {
  108 + out_stream = avformat_new_stream(ofmt_ctx, NULL);
  109 + if (!out_stream) {
  110 + av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");
  111 + return AVERROR_UNKNOWN;
  112 + }
  113 +
  114 + enc_ctx = out_stream->codec;
  115 +
  116 + if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
  117 + enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
  118 +
  119 +
  120 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
  121 + || dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  122 + /* in this example, we choose transcoding to same codec */
  123 + encoder = avcodec_find_encoder(dec_ctx->codec_id);
  124 + if (!encoder) {
  125 + av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");
  126 + return AVERROR_INVALIDDATA;
  127 + }
  128 +
  129 + /* In this example, we transcode to same properties (picture size,
  130 + * sample rate etc.). These properties can be changed for output
  131 + * streams easily using filters */
  132 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
  133 + enc_ctx->height = dec_ctx->height;
  134 + enc_ctx->width = dec_ctx->width;
  135 + enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
  136 + /* take first format from list of supported formats */
  137 + enc_ctx->pix_fmt = encoder->pix_fmts[0];
  138 + /* video time_base can be set to whatever is handy and supported by encoder */
  139 + enc_ctx->time_base = dec_ctx->time_base;
  140 +
  141 + enc_ctx->me_range = 16;
  142 + enc_ctx->max_qdiff = 4;
  143 + enc_ctx->qmin = 10;
  144 + enc_ctx->qmax = 30;
  145 + enc_ctx->qcompress = 0.6;
  146 + }
  147 + else {
  148 + enc_ctx->sample_rate = dec_ctx->sample_rate;
  149 + enc_ctx->channel_layout = dec_ctx->channel_layout;
  150 + enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
  151 + /* take first format from list of supported formats */
  152 + enc_ctx->sample_fmt = encoder->sample_fmts[0];
  153 + enc_ctx->time_base.num = 1;
  154 + enc_ctx->time_base.den = enc_ctx->sample_rate;
  155 + }
  156 +
  157 + /* Third parameter can be used to pass settings to encoder */
  158 + ret = avcodec_open2(enc_ctx, encoder, NULL);
  159 + if (ret < 0) {
  160 + av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);
  161 + return ret;
  162 + }
  163 + }
  164 + else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {
  165 + av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);
  166 + return AVERROR_INVALIDDATA;
  167 + }
  168 +#if 0
  169 + else {
  170 + /* if this stream must be remuxed */
  171 + ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,
  172 + ifmt_ctx->streams[i]->codec);
  173 + if (ret < 0) {
  174 + av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");
  175 + return ret;
  176 + }
  177 +#endif
  178 + }
  179 +
  180 +#if 0
  181 + av_dump_format(ofmt_ctx, 0, filename, 1);
  182 +
  183 + if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
  184 + ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
  185 + if (ret < 0) {
  186 + av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename);
  187 + return ret;
  188 + }
  189 + }
  190 +
  191 + /* init muxer, write output file header */
  192 + ret = avformat_write_header(ofmt_ctx, NULL);
  193 + if (ret < 0) {
  194 + av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");
  195 + return ret;
  196 + }
  197 +#endif
  198 + return 0;
  199 +}
  200 +
  201 +
  202 + int CAVTranscoder::mix_and_output_vframe(vector<CAVDecoder *> & decoders_got_frame)
  203 + {
  204 + vector < CAVDecoder *>::iterator it = decoders_got_frame.begin();
  205 + for (; it != decoders_got_frame.end(); it++) {
  206 + (*it)->free_cur_a_frame();
  207 + }
  208 + return 0;
  209 + }
  210 +
  211 + int CAVTranscoder::mix_and_output_aframe(vector<CAVDecoder *> & decoders_got_frame)
  212 + {
  213 + vector < CAVDecoder *>::iterator it = decoders_got_frame.begin();
  214 + for (; it != decoders_got_frame.end(); it++) {
  215 + (*it)->free_cur_v_frame();
  216 + }
  217 + return 0;
  218 + }
  219 +
  220 + int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) {
  221 + int ret;
  222 + int got_frame_local;
  223 + AVPacket enc_pkt;
  224 +#if 0
  225 + int(*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) =
  226 + (ifmt_ctx->streams[stream_index]->codec->codec_type ==
  227 + AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2;
  228 +
  229 + if (!got_frame)
  230 + got_frame = &got_frame_local;
  231 +
  232 + av_log(NULL, AV_LOG_INFO, "Encoding frame\n");
  233 + /* encode filtered frame */
  234 + enc_pkt.data = NULL;
  235 + enc_pkt.size = 0;
  236 + av_init_packet(&enc_pkt);
  237 + ret = enc_func(ofmt_ctx->streams[stream_index]->codec, &enc_pkt,
  238 + filt_frame, got_frame);
  239 + av_frame_free(&filt_frame);
  240 + if (ret < 0)
  241 + return ret;
  242 + if (!(*got_frame))
  243 + return 0;
  244 +
  245 + /* prepare packet for muxing */
  246 + enc_pkt.stream_index = stream_index;
  247 + av_packet_rescale_ts(&enc_pkt,
  248 + ofmt_ctx->streams[stream_index]->codec->time_base,
  249 + ofmt_ctx->streams[stream_index]->time_base);
  250 +
  251 + av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");
  252 + /* mux encoded frame */
  253 + ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
  254 +#endif
  255 + return ret;
  256 +}
  257 +
  258 +#if 0
  259 +static int flush_encoder(unsigned int stream_index)
  260 +{
  261 + int ret;
  262 + int got_frame;
  263 +
  264 + if (!(ofmt_ctx->streams[stream_index]->codec->codec->capabilities &
  265 + CODEC_CAP_DELAY))
  266 + return 0;
  267 +
  268 + while (1) {
  269 + av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);
  270 + ret = encode_write_frame(NULL, stream_index, &got_frame);
  271 + if (ret < 0)
  272 + break;
  273 + if (!got_frame)
  274 + return 0;
  275 + }
  276 + return ret;
  277 +}
  278 +#endif
  1 +#pragma once
  2 +#include "AVDecoder.h"
  3 +
  4 +
  5 +class CAVTranscoder
  6 +{
  7 +public:
  8 + CAVTranscoder();
  9 + virtual ~CAVTranscoder();
  10 +
  11 + int add(media_info & info);
  12 + int64_t transcode();
  13 + bool all_processed();
  14 + int close();
  15 +
  16 +protected:
  17 + int open_output_file(const char *filename);
  18 +
  19 +protected:
  20 + vector < CAVDecoder *> _decoders;
  21 +
  22 + AVFormatContext *ofmt_ctx;
  23 + int64_t _start_time;
  24 + int64_t _cur_a_time;
  25 + int64_t _cur_v_time;
  26 +private:
  27 + int mix_and_output_vframe(vector<CAVDecoder *> & decoders_got_frame);
  28 + int mix_and_output_aframe(vector<CAVDecoder *> & decoders_got_frame);
  29 + bool _all_processed;
  30 +};
  31 +
  1 +#include "AudioDecoder.h"
  2 +AVRational timebase_ms = { 1, 1000 };
  3 +
  4 +CAudioDecoder::CAudioDecoder() :
  5 +_start_time(-10.0),
  6 +_is_finished(false)
  7 +{
  8 +
  9 +}
  10 +
  11 +CAudioDecoder::~CAudioDecoder()
  12 +{
  13 +}
  14 +
  15 +int CAudioDecoder::add(media_info &info)
  16 +{
  17 + if (_start_time < -1.0) {//the the start time of this decoder
  18 + _start_time = info.start_time;
  19 + }
  20 + _info.push_back(info);
  21 +
  22 + int ret;
  23 +
  24 + do{
  25 + if ((ret = open_input_file(info.name.c_str())) < 0)
  26 + break;
  27 +
  28 + if ((ret = init_filters()) < 0)
  29 + break;
  30 +
  31 + _is_finished = false;
  32 + } while (0);
  33 +
  34 + return ret ? 1 : 0;
  35 +}
  36 +
  37 +
  38 +
  39 +int CAudioDecoder::init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
  40 + const char *filter_spec)
  41 +{
  42 + char args[512];
  43 + int ret = 0;
  44 + AVFilter *buffersrc = NULL;
  45 + AVFilter *buffersink = NULL;
  46 + AVFilterContext *buffersrc_ctx = NULL;
  47 + AVFilterContext *buffersink_ctx = NULL;
  48 + AVFilterInOut *outputs = avfilter_inout_alloc();
  49 + AVFilterInOut *inputs = avfilter_inout_alloc();
  50 + AVFilterGraph *filter_graph = avfilter_graph_alloc();
  51 +
  52 + if (!outputs || !inputs || !filter_graph) {
  53 + ret = AVERROR(ENOMEM);
  54 + goto end;
  55 + }
  56 +
  57 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
  58 + buffersrc = avfilter_get_by_name("buffer");
  59 + buffersink = avfilter_get_by_name("buffersink");
  60 + if (!buffersrc || !buffersink) {
  61 + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
  62 + ret = AVERROR_UNKNOWN;
  63 + goto end;
  64 + }
  65 +
  66 + snprintf(args, sizeof(args),
  67 + "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
  68 + dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
  69 + dec_ctx->time_base.num, dec_ctx->time_base.den,
  70 + dec_ctx->sample_aspect_ratio.num,
  71 + dec_ctx->sample_aspect_ratio.den);
  72 +
  73 + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  74 + args, NULL, filter_graph);
  75 + if (ret < 0) {
  76 + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
  77 + goto end;
  78 + }
  79 +
  80 + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  81 + NULL, NULL, filter_graph);
  82 + if (ret < 0) {
  83 + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
  84 + goto end;
  85 + }
  86 +
  87 + AVPixelFormat fmt = AV_PIX_FMT_YUV420P;
  88 + ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",
  89 + (uint8_t*)&fmt, sizeof(AVPixelFormat),
  90 + AV_OPT_SEARCH_CHILDREN);
  91 + if (ret < 0) {
  92 + av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
  93 + goto end;
  94 + }
  95 + }
  96 + else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  97 + buffersrc = avfilter_get_by_name("abuffer");
  98 + buffersink = avfilter_get_by_name("abuffersink");
  99 + if (!buffersrc || !buffersink) {
  100 + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
  101 + ret = AVERROR_UNKNOWN;
  102 + goto end;
  103 + }
  104 +
  105 + if (!dec_ctx->channel_layout)
  106 + dec_ctx->channel_layout =
  107 + av_get_default_channel_layout(dec_ctx->channels);
  108 + sprintf(args, //sizeof(args),
  109 + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
  110 + dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,
  111 + av_get_sample_fmt_name(dec_ctx->sample_fmt),
  112 + dec_ctx->channel_layout);
  113 + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  114 + args, NULL, filter_graph);
  115 + if (ret < 0) {
  116 + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
  117 + goto end;
  118 + }
  119 +
  120 + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  121 + NULL, NULL, filter_graph);
  122 + if (ret < 0) {
  123 + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
  124 + goto end;
  125 + }
  126 + enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
  127 + ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",
  128 + (uint8_t*)&sample_fmt, sizeof(sample_fmt),
  129 + AV_OPT_SEARCH_CHILDREN);
  130 + if (ret < 0) {
  131 + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
  132 + goto end;
  133 + }
  134 +
  135 + uint64_t channel_layout = AV_CH_LAYOUT_MONO;
  136 + ret = av_opt_set_bin(buffersink_ctx, "channel_layouts",
  137 + (uint8_t*)&channel_layout,
  138 + sizeof(channel_layout), AV_OPT_SEARCH_CHILDREN);
  139 + if (ret < 0) {
  140 + av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
  141 + goto end;
  142 + }
  143 +
  144 + int sample_rate = 46000;
  145 + ret = av_opt_set_bin(buffersink_ctx, "sample_rates",
  146 + (uint8_t*)&sample_rate, sizeof(sample_rate),
  147 + AV_OPT_SEARCH_CHILDREN);
  148 + if (ret < 0) {
  149 + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
  150 + goto end;
  151 + }
  152 + }
  153 + else {
  154 + ret = AVERROR_UNKNOWN;
  155 + goto end;
  156 + }
  157 +
  158 + /* Endpoints for the filter graph. */
  159 + outputs->name = av_strdup("in");
  160 + outputs->filter_ctx = buffersrc_ctx;
  161 + outputs->pad_idx = 0;
  162 + outputs->next = NULL;
  163 +
  164 + inputs->name = av_strdup("out");
  165 + inputs->filter_ctx = buffersink_ctx;
  166 + inputs->pad_idx = 0;
  167 + inputs->next = NULL;
  168 +
  169 + if (!outputs->name || !inputs->name) {
  170 + ret = AVERROR(ENOMEM);
  171 + goto end;
  172 + }
  173 +
  174 + if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,
  175 + &inputs, &outputs, NULL)) < 0)
  176 + goto end;
  177 +
  178 + if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
  179 + goto end;
  180 +
  181 + /* Fill FilteringContext */
  182 + fctx->buffersrc_ctx = buffersrc_ctx;
  183 + fctx->buffersink_ctx = buffersink_ctx;
  184 + fctx->filter_graph = filter_graph;
  185 +
  186 +end:
  187 + avfilter_inout_free(&inputs);
  188 + avfilter_inout_free(&outputs);
  189 +
  190 + return ret;
  191 +}
  192 +
  193 +int CAudioDecoder::init_filters(void)
  194 +{
  195 + const char *filter_spec;
  196 + unsigned int i;
  197 + int ret;
  198 + filter_ctx = (FilteringContext *)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));
  199 + if (!filter_ctx)
  200 + return AVERROR(ENOMEM);
  201 +
  202 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  203 + filter_ctx[i].buffersrc_ctx = NULL;
  204 + filter_ctx[i].buffersink_ctx = NULL;
  205 + filter_ctx[i].filter_graph = NULL;
  206 + if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
  207 + || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
  208 + continue;
  209 +
  210 +
  211 + if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  212 + filter_spec = "fps=fps=20"; /* passthrough (dummy) filter for video */
  213 + _codec_timebase.num = 1;
  214 + _codec_timebase.den = 20;
  215 + }
  216 + else
  217 + filter_spec = "anull"; /* passthrough (dummy) filter for audio */
  218 + ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec,
  219 + filter_spec);
  220 + if (ret)
  221 + return ret;
  222 + }
  223 + return 0;
  224 +}
  225 +
  226 +int CAudioDecoder::open_input_file(const char *filename)
  227 +{
  228 + int ret;
  229 + unsigned int i;
  230 +
  231 + ifmt_ctx = NULL;
  232 + if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {
  233 + av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
  234 + return ret;
  235 + }
  236 +
  237 + if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
  238 + av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
  239 + return ret;
  240 + }
  241 +
  242 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  243 + AVStream *stream;
  244 + AVCodecContext *codec_ctx;
  245 + stream = ifmt_ctx->streams[i];
  246 + codec_ctx = stream->codec;
  247 + /* Reencode video & audio and remux subtitles etc. */
  248 + if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
  249 + || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  250 + /* Open decoder */
  251 + ret = avcodec_open2(codec_ctx,
  252 + avcodec_find_decoder(codec_ctx->codec_id), NULL);
  253 + if (ret < 0) {
  254 + av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
  255 + return ret;
  256 + }
  257 + }
  258 + }
  259 +
  260 + av_dump_format(ifmt_ctx, 0, filename, 0);
  261 + return 0;
  262 +}
  263 +
  264 +
  265 +int CAudioDecoder::filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
  266 +{
  267 + int ret;
  268 + AVFrame *filt_frame;
  269 +
  270 + //av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");
  271 + /* push the decoded frame into the filtergraph */
  272 + ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,
  273 + frame, 0);
  274 + if (ret < 0) {
  275 + av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
  276 + return ret;
  277 + }
  278 +
  279 + /* pull filtered frames from the filtergraph */
  280 + while (1) {
  281 + filt_frame = av_frame_alloc();
  282 + if (!filt_frame) {
  283 + ret = AVERROR(ENOMEM);
  284 + break;
  285 + }
  286 + //av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");
  287 + ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,
  288 + filt_frame);
  289 + if (ret < 0) {
  290 + /* if no more frames for output - returns AVERROR(EAGAIN)
  291 + * if flushed and no more frames for output - returns AVERROR_EOF
  292 + * rewrite retcode to 0 to show it as normal procedure completion
  293 + */
  294 + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  295 + ret = 0;
  296 + av_frame_free(&filt_frame);
  297 + break;
  298 + }
  299 +
  300 + filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
  301 + //todo: callback filted frame
  302 + _decoded_frames.push_back(filt_frame);
  303 + }
  304 +
  305 + return ret;
  306 +}
  307 +
  308 +unsigned int CAudioDecoder::getuid()
  309 +{
  310 + return 0;
  311 +}
  312 +
  313 +int CAudioDecoder::get_one_frame(AVFrame ** pFrame, int64_t & ts)
  314 +{
  315 + int ret;
  316 + AVPacket packet;
  317 + AVFrame *frame = NULL;
  318 + enum AVMediaType type;
  319 + unsigned int stream_index;
  320 + unsigned int i;
  321 + int got_frame;
  322 +
  323 + if (_decoded_frames.size() > 0) {
  324 + *pFrame = _decoded_frames.front();
  325 + ts = av_rescale_q((*pFrame)->pts, _codec_timebase, timebase_ms);
  326 + _decoded_frames.pop_front();
  327 +
  328 + return 0;
  329 + }
  330 +
  331 + if (_is_finished){
  332 + return -1;
  333 + }
  334 +
  335 + int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
  336 + memset(&packet, 0, sizeof(AVPacket));
  337 +
  338 + /* read all packets */
  339 + while (1) {
  340 + if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
  341 + break;
  342 + stream_index = packet.stream_index;
  343 + type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;
  344 + av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",
  345 + stream_index);
  346 +
  347 + if (filter_ctx[stream_index].filter_graph) {
  348 + av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
  349 + frame = av_frame_alloc();
  350 + if (!frame) {
  351 + ret = AVERROR(ENOMEM);
  352 + break;
  353 + }
  354 +
  355 + av_packet_rescale_ts(&packet,
  356 + ifmt_ctx->streams[stream_index]->time_base,
  357 + ifmt_ctx->streams[stream_index]->codec->time_base);
  358 + dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :
  359 + avcodec_decode_audio4;
  360 + ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame,
  361 + &got_frame, &packet);
  362 + if (ret < 0) {
  363 + av_frame_free(&frame);
  364 + av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
  365 + break;
  366 + }
  367 +
  368 + if (got_frame) {
  369 + frame->pts = av_frame_get_best_effort_timestamp(frame);
  370 + ret = filter_encode_write_frame(frame, stream_index);
  371 + if (_decoded_frames.size() > 0) {
  372 + *pFrame = _decoded_frames.front();
  373 + _decoded_frames.pop_front();
  374 + ts = av_rescale_q((*pFrame)->pts, _codec_timebase, timebase_ms);
  375 + return 0;
  376 + }
  377 + if (ret < 0)
  378 + goto end;
  379 + }
  380 + else {
  381 + av_frame_free(&frame);
  382 + }
  383 + }
  384 + av_packet_unref(&packet);
  385 +
  386 + }
  387 +
  388 + /* flush filters and encoders */
  389 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  390 + /* flush filter */
  391 + if (!filter_ctx[i].filter_graph)
  392 + continue;
  393 + ret = filter_encode_write_frame(NULL, i);
  394 + if (ret < 0) {
  395 + av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
  396 + goto end;
  397 + }
  398 +
  399 + }
  400 +end:;
  401 + av_packet_unref(&packet);
  402 + av_frame_free(&frame);
  403 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  404 + avcodec_close(ifmt_ctx->streams[i]->codec);
  405 + if (filter_ctx && filter_ctx[i].filter_graph)
  406 + avfilter_graph_free(&filter_ctx[i].filter_graph);
  407 + }
  408 + av_free(filter_ctx);
  409 + avformat_close_input(&ifmt_ctx);
  410 + _is_finished = true;
  411 +
  412 + return 0;
  413 +}
  1 +#pragma once
  2 +#include "media_info.h"
  3 +#include <list>
  4 +class CAudioDecoder
  5 +{
  6 +public:
  7 + CAudioDecoder();
  8 + virtual ~CAudioDecoder();
  9 +
  10 + int add(media_info &info);
  11 +
  12 + unsigned int getuid();
  13 +
  14 + int get_one_frame(AVFrame ** pFrame, int64_t & ts);
  15 +
  16 +protected:
  17 + int open_input_file(const char *filename);
  18 + int init_filters(void);
  19 + int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, const char *filter_spec);
  20 + int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index);
  21 +
  22 +protected:
  23 + vector<media_info> _info;
  24 + list<AVFrame * > _decoded_frames;
  25 + float _start_time;
  26 +
  27 + AVFormatContext *ifmt_ctx;
  28 +
  29 + FilteringContext *filter_ctx;
  30 +
  31 + bool _is_finished;
  32 + AVRational _codec_timebase;
  33 +};
  1 +#include "AudioEncoder.h"
  2 +
  3 +
  4 +CAudioEncoder::CAudioEncoder()
  5 +{
  6 +}
  7 +
  8 +
  9 +CAudioEncoder::~CAudioEncoder()
  10 +{
  11 +}
  1 +#pragma once
  2 +class CAudioEncoder
  3 +{
  4 +public:
  5 + CAudioEncoder();
  6 + virtual ~CAudioEncoder();
  7 +};
  8 +
1 #include "VideoDecoder.h" 1 #include "VideoDecoder.h"
  2 +extern AVRational timebase_ms;
2 3
3 -CVideoDecoder::CVideoDecoder() 4 +CVideoDecoder::CVideoDecoder() :
  5 +_start_time(-10.0),
  6 +_is_finished(false)
4 { 7 {
5 8
6 } 9 }
@@ -11,10 +14,400 @@ CVideoDecoder::~CVideoDecoder() @@ -11,10 +14,400 @@ CVideoDecoder::~CVideoDecoder()
11 14
12 int CVideoDecoder::add(media_info &info) 15 int CVideoDecoder::add(media_info &info)
13 { 16 {
  17 + if (_start_time < -1.0) {//the the start time of this decoder
  18 + _start_time = info.start_time;
  19 + }
  20 + _info.push_back(info);
  21 +
  22 + int ret;
  23 +
  24 + do{
  25 + if ((ret = open_input_file(info.name.c_str())) < 0)
  26 + break;
  27 +
  28 + if ((ret = init_filters()) < 0)
  29 + break;
  30 +
  31 + _is_finished = false;
  32 + } while (0);
  33 +
  34 + return ret ? 1 : 0;
  35 +}
  36 +
  37 +
  38 +
  39 +int CVideoDecoder::init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
  40 + const char *filter_spec)
  41 +{
  42 + char args[512];
  43 + int ret = 0;
  44 + AVFilter *buffersrc = NULL;
  45 + AVFilter *buffersink = NULL;
  46 + AVFilterContext *buffersrc_ctx = NULL;
  47 + AVFilterContext *buffersink_ctx = NULL;
  48 + AVFilterInOut *outputs = avfilter_inout_alloc();
  49 + AVFilterInOut *inputs = avfilter_inout_alloc();
  50 + AVFilterGraph *filter_graph = avfilter_graph_alloc();
  51 +
  52 + if (!outputs || !inputs || !filter_graph) {
  53 + ret = AVERROR(ENOMEM);
  54 + goto end;
  55 + }
  56 +
  57 + if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
  58 + buffersrc = avfilter_get_by_name("buffer");
  59 + buffersink = avfilter_get_by_name("buffersink");
  60 + if (!buffersrc || !buffersink) {
  61 + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
  62 + ret = AVERROR_UNKNOWN;
  63 + goto end;
  64 + }
  65 +
  66 + snprintf(args, sizeof(args),
  67 + "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
  68 + dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
  69 + dec_ctx->time_base.num, dec_ctx->time_base.den,
  70 + dec_ctx->sample_aspect_ratio.num,
  71 + dec_ctx->sample_aspect_ratio.den);
  72 +
  73 + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  74 + args, NULL, filter_graph);
  75 + if (ret < 0) {
  76 + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
  77 + goto end;
  78 + }
  79 +
  80 + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  81 + NULL, NULL, filter_graph);
  82 + if (ret < 0) {
  83 + av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
  84 + goto end;
  85 + }
  86 +
  87 + AVPixelFormat fmt = AV_PIX_FMT_YUV420P;
  88 + ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",
  89 + (uint8_t*)&fmt, sizeof(AVPixelFormat),
  90 + AV_OPT_SEARCH_CHILDREN);
  91 + if (ret < 0) {
  92 + av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");
  93 + goto end;
  94 + }
  95 + }
  96 +#if 0
  97 + else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  98 + buffersrc = avfilter_get_by_name("abuffer");
  99 + buffersink = avfilter_get_by_name("abuffersink");
  100 + if (!buffersrc || !buffersink) {
  101 + av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
  102 + ret = AVERROR_UNKNOWN;
  103 + goto end;
  104 + }
  105 +
  106 + if (!dec_ctx->channel_layout)
  107 + dec_ctx->channel_layout =
  108 + av_get_default_channel_layout(dec_ctx->channels);
  109 + sprintf(args, //sizeof(args),
  110 + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
  111 + dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,
  112 + av_get_sample_fmt_name(dec_ctx->sample_fmt),
  113 + dec_ctx->channel_layout);
  114 + ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  115 + args, NULL, filter_graph);
  116 + if (ret < 0) {
  117 + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");
  118 + goto end;
  119 + }
  120 +
  121 + ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  122 + NULL, NULL, filter_graph);
  123 + if (ret < 0) {
  124 + av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
  125 + goto end;
  126 + }
  127 +
  128 + ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",
  129 + (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt),
  130 + AV_OPT_SEARCH_CHILDREN);
  131 + if (ret < 0) {
  132 + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");
  133 + goto end;
  134 + }
  135 +
  136 + ret = av_opt_set_bin(buffersink_ctx, "channel_layouts",
  137 + (uint8_t*)&enc_ctx->channel_layout,
  138 + sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN);
  139 + if (ret < 0) {
  140 + av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");
  141 + goto end;
  142 + }
  143 +
  144 + ret = av_opt_set_bin(buffersink_ctx, "sample_rates",
  145 + (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate),
  146 + AV_OPT_SEARCH_CHILDREN);
  147 + if (ret < 0) {
  148 + av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");
  149 + goto end;
  150 + }
  151 + }
  152 +#endif
  153 + else {
  154 + ret = AVERROR_UNKNOWN;
  155 + goto end;
  156 + }
  157 +
  158 + /* Endpoints for the filter graph. */
  159 + outputs->name = av_strdup("in");
  160 + outputs->filter_ctx = buffersrc_ctx;
  161 + outputs->pad_idx = 0;
  162 + outputs->next = NULL;
  163 +
  164 + inputs->name = av_strdup("out");
  165 + inputs->filter_ctx = buffersink_ctx;
  166 + inputs->pad_idx = 0;
  167 + inputs->next = NULL;
  168 +
  169 + if (!outputs->name || !inputs->name) {
  170 + ret = AVERROR(ENOMEM);
  171 + goto end;
  172 + }
  173 +
  174 + if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,
  175 + &inputs, &outputs, NULL)) < 0)
  176 + goto end;
  177 +
  178 + if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
  179 + goto end;
  180 +
  181 + /* Fill FilteringContext */
  182 + fctx->buffersrc_ctx = buffersrc_ctx;
  183 + fctx->buffersink_ctx = buffersink_ctx;
  184 + fctx->filter_graph = filter_graph;
  185 +
  186 +end:
  187 + avfilter_inout_free(&inputs);
  188 + avfilter_inout_free(&outputs);
  189 +
  190 + return ret;
  191 +}
  192 +
  193 +int CVideoDecoder::init_filters(void)
  194 +{
  195 + const char *filter_spec;
  196 + unsigned int i;
  197 + int ret;
  198 + filter_ctx = (FilteringContext *)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));
  199 + if (!filter_ctx)
  200 + return AVERROR(ENOMEM);
  201 +
  202 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  203 + filter_ctx[i].buffersrc_ctx = NULL;
  204 + filter_ctx[i].buffersink_ctx = NULL;
  205 + filter_ctx[i].filter_graph = NULL;
  206 + if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
  207 + || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))
  208 + continue;
  209 +
  210 +
  211 + if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  212 + filter_spec = "fps=fps=20"; /* passthrough (dummy) filter for video */
  213 + _codec_timebase.num = 1;
  214 + _codec_timebase.den = 20;
  215 + }
  216 + else
  217 + filter_spec = "anull"; /* passthrough (dummy) filter for audio */
  218 + ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec,
  219 + filter_spec);
  220 + if (ret)
  221 + return ret;
  222 + }
14 return 0; 223 return 0;
15 } 224 }
16 225
  226 +int CVideoDecoder::open_input_file(const char *filename)
  227 +{
  228 + int ret;
  229 + unsigned int i;
  230 +
  231 + ifmt_ctx = NULL;
  232 + if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {
  233 + av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
  234 + return ret;
  235 + }
  236 +
  237 + if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
  238 + av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
  239 + return ret;
  240 + }
  241 +
  242 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  243 + AVStream *stream;
  244 + AVCodecContext *codec_ctx;
  245 + stream = ifmt_ctx->streams[i];
  246 + codec_ctx = stream->codec;
  247 + /* Reencode video & audio and remux subtitles etc. */
  248 + if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
  249 + || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
  250 + /* Open decoder */
  251 + ret = avcodec_open2(codec_ctx,
  252 + avcodec_find_decoder(codec_ctx->codec_id), NULL);
  253 + if (ret < 0) {
  254 + av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
  255 + return ret;
  256 + }
  257 + }
  258 + }
  259 +
  260 + av_dump_format(ifmt_ctx, 0, filename, 0);
  261 + return 0;
  262 +}
  263 +
  264 +
  265 +int CVideoDecoder::filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
  266 +{
  267 + int ret;
  268 + AVFrame *filt_frame;
  269 +
  270 + //av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");
  271 + /* push the decoded frame into the filtergraph */
  272 + ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,
  273 + frame, 0);
  274 + if (ret < 0) {
  275 + av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");
  276 + return ret;
  277 + }
  278 +
  279 + /* pull filtered frames from the filtergraph */
  280 + while (1) {
  281 + filt_frame = av_frame_alloc();
  282 + if (!filt_frame) {
  283 + ret = AVERROR(ENOMEM);
  284 + break;
  285 + }
  286 + //av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");
  287 + ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,
  288 + filt_frame);
  289 + if (ret < 0) {
  290 + /* if no more frames for output - returns AVERROR(EAGAIN)
  291 + * if flushed and no more frames for output - returns AVERROR_EOF
  292 + * rewrite retcode to 0 to show it as normal procedure completion
  293 + */
  294 + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  295 + ret = 0;
  296 + av_frame_free(&filt_frame);
  297 + break;
  298 + }
  299 +
  300 + filt_frame->pict_type = AV_PICTURE_TYPE_NONE;
  301 + //todo: callback filted frame
  302 + _decoded_frames.push_back(filt_frame);
  303 + }
  304 +
  305 + return ret;
  306 +}
  307 +
17 unsigned int CVideoDecoder::getuid() 308 unsigned int CVideoDecoder::getuid()
18 { 309 {
19 return 0; 310 return 0;
20 } 311 }
  312 +
  313 +int CVideoDecoder::get_one_frame(AVFrame ** pFrame, int64_t & ts)
  314 +{
  315 + int ret;
  316 + AVPacket packet;
  317 + AVFrame *frame = NULL;
  318 + enum AVMediaType type;
  319 + unsigned int stream_index;
  320 + unsigned int i;
  321 + int got_frame;
  322 +
  323 + if (_decoded_frames.size() > 0) {
  324 + *pFrame = _decoded_frames.front();
  325 + ts = av_rescale_q((*pFrame)->pts, _codec_timebase, timebase_ms);
  326 + _decoded_frames.pop_front();
  327 +
  328 + return 0;
  329 + }
  330 +
  331 + if (_is_finished){
  332 + return -1;
  333 + }
  334 +
  335 + int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
  336 + memset(&packet, 0, sizeof(AVPacket));
  337 +
  338 + /* read all packets */
  339 + while (1) {
  340 + if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
  341 + break;
  342 + stream_index = packet.stream_index;
  343 + type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;
  344 + av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",
  345 + stream_index);
  346 +
  347 + if (filter_ctx[stream_index].filter_graph) {
  348 + av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
  349 + frame = av_frame_alloc();
  350 + if (!frame) {
  351 + ret = AVERROR(ENOMEM);
  352 + break;
  353 + }
  354 +
  355 + av_packet_rescale_ts(&packet,
  356 + ifmt_ctx->streams[stream_index]->time_base,
  357 + ifmt_ctx->streams[stream_index]->codec->time_base);
  358 + dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :
  359 + avcodec_decode_audio4;
  360 + ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame,
  361 + &got_frame, &packet);
  362 + if (ret < 0) {
  363 + av_frame_free(&frame);
  364 + av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
  365 + break;
  366 + }
  367 +
  368 + if (got_frame) {
  369 + frame->pts = av_frame_get_best_effort_timestamp(frame);
  370 + ret = filter_encode_write_frame(frame, stream_index);
  371 + if (_decoded_frames.size() > 0) {
  372 + *pFrame = _decoded_frames.front();
  373 + _decoded_frames.pop_front();
  374 + ts = av_rescale_q((*pFrame)->pts, _codec_timebase, timebase_ms);
  375 + return 0;
  376 + }
  377 + if (ret < 0)
  378 + goto end;
  379 + }
  380 + else {
  381 + av_frame_free(&frame);
  382 + }
  383 + }
  384 + av_packet_unref(&packet);
  385 +
  386 + }
  387 +
  388 + /* flush filters and encoders */
  389 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  390 + /* flush filter */
  391 + if (!filter_ctx[i].filter_graph)
  392 + continue;
  393 + ret = filter_encode_write_frame(NULL, i);
  394 + if (ret < 0) {
  395 + av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");
  396 + goto end;
  397 + }
  398 +
  399 + }
  400 +end:;
  401 + av_packet_unref(&packet);
  402 + av_frame_free(&frame);
  403 + for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  404 + avcodec_close(ifmt_ctx->streams[i]->codec);
  405 + if (filter_ctx && filter_ctx[i].filter_graph)
  406 + avfilter_graph_free(&filter_ctx[i].filter_graph);
  407 + }
  408 + av_free(filter_ctx);
  409 + avformat_close_input(&ifmt_ctx);
  410 + _is_finished = true;
  411 +
  412 + return 0;
  413 +}
1 #pragma once 1 #pragma once
2 -#include <string>  
3 -#include <vector>  
4 -using namespace std;  
5 -  
6 -enum media_type{  
7 - mt_audio = 0,  
8 - mt_video = 1,  
9 - mt_av = 3,  
10 -};  
11 -  
12 -enum media_role {  
13 - mr_teacher = 0,  
14 - mr_student = 1,  
15 -};  
16 -  
17 -enum timestamp_type{  
18 - tt_start = 0,  
19 - tt_end = 1,  
20 -};  
21 -  
22 -class media_info {  
23 -public:  
24 - float type_time;//the time for start or end according to the m_type  
25 - float start_time;  
26 - float end_time;  
27 - string name;  
28 - int rotate;  
29 -  
30 - float duration;  
31 - int index;  
32 - unsigned int uid;  
33 - media_type m_type;  
34 - media_role m_role;  
35 - timestamp_type t_type;  
36 -};  
37 - 2 +#include "media_info.h"
  3 +#include <list>
38 class CVideoDecoder 4 class CVideoDecoder
39 { 5 {
40 public: 6 public:
@@ -45,7 +11,24 @@ public: @@ -45,7 +11,24 @@ public:
45 11
46 unsigned int getuid(); 12 unsigned int getuid();
47 13
  14 + int get_one_frame(AVFrame ** pFrame, int64_t & ts);
  15 +
  16 +protected:
  17 + int open_input_file(const char *filename);
  18 + int init_filters(void);
  19 + int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, const char *filter_spec);
  20 + int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index);
  21 +
48 protected: 22 protected:
49 vector<media_info> _info; 23 vector<media_info> _info;
  24 + list<AVFrame * > _decoded_frames;
  25 + float _start_time;
  26 +
  27 + AVFormatContext *ifmt_ctx;
  28 +
  29 + FilteringContext *filter_ctx;
  30 +
  31 + bool _is_finished;
  32 + AVRational _codec_timebase;
50 }; 33 };
51 34
  1 +#include "VideoEncoder.h"
  2 +
  3 +
  4 +CVideoEncoder::CVideoEncoder()
  5 +{
  6 +}
  7 +
  8 +
  9 +CVideoEncoder::~CVideoEncoder()
  10 +{
  11 +}
  1 +#pragma once
  2 +class CVideoEncoder
  3 +{
  4 +public:
  5 + CVideoEncoder();
  6 + virtual ~CVideoEncoder();
  7 +};
  8 +
1 -#include "VideoTranscoder.h"  
2 -  
3 -  
4 -CVideoTranscoder::CVideoTranscoder()  
5 -{  
6 -}  
7 -  
8 -  
9 -CVideoTranscoder::~CVideoTranscoder()  
10 -{  
11 -}  
12 -  
13 -int CVideoTranscoder::add(media_info & info)  
14 -{  
15 - vector < CVideoDecoder *>::iterator it = _decoders.begin();  
16 - for (; it != _decoders.end(); it++) {  
17 - if ((*it)->getuid() == info.uid){  
18 - (*it)->add(info);  
19 - break;  
20 - }  
21 - }  
22 - if (it == _decoders.end()) {  
23 - CVideoDecoder * pVideoDecoder = new CVideoDecoder();  
24 - pVideoDecoder->add(info);  
25 - _decoders.push_back(pVideoDecoder);  
26 - }  
27 - return 0;  
28 -}  
29 -  
30 -float CVideoTranscoder::transcode()  
31 -{  
32 - throw std::logic_error("The method or operation is not implemented.");  
33 -}  
34 -  
35 -bool CVideoTranscoder::all_processed()  
36 -{  
37 - throw std::logic_error("The method or operation is not implemented.");  
38 -}  
39 -  
40 -int CVideoTranscoder::close()  
41 -{  
42 - throw std::logic_error("The method or operation is not implemented.");  
43 -}  
1 -#pragma once  
2 -#include "VideoDecoder.h"  
3 -  
4 -  
5 -class CVideoTranscoder  
6 -{  
7 -public:  
8 - CVideoTranscoder();  
9 - virtual ~CVideoTranscoder();  
10 -  
11 - int add(media_info & info);  
12 - float transcode();  
13 - bool all_processed();  
14 - int close();  
15 -  
16 -protected:  
17 - vector < CVideoDecoder *> _decoders;  
18 -};  
19 -  
  1 +#pragma once
  2 +
  3 +#include <string>
  4 +#include <vector>
  5 +#include <stdint.h>
  6 +using namespace std;
  7 +
  8 +enum media_type{
  9 + mt_audio = 0,
  10 + mt_video = 1,
  11 + mt_av = 3,
  12 +};
  13 +
  14 +enum media_role {
  15 + mr_teacher = 0,
  16 + mr_student = 1,
  17 +};
  18 +
  19 +enum timestamp_type{
  20 + tt_start = 0,
  21 + tt_end = 1,
  22 +};
  23 +
  24 +class media_info {
  25 +public:
  26 + float type_time;//the time for start or end according to the m_type
  27 + float start_time;
  28 + int64_t start_time_ms;
  29 + float end_time;
  30 + int64_t end_time_ms;
  31 + string name;
  32 + int rotate;
  33 +
  34 + float duration;
  35 + int index;
  36 + unsigned int uid;
  37 + media_type m_type;
  38 + media_role m_role;
  39 + timestamp_type t_type;
  40 +};
  41 +
  42 +#define __STDC_FORMAT_MACROS
  43 +#include <stdint.h>
  44 +#include <inttypes.h>
  45 +extern "C" {
  46 +#include <libavcodec/avcodec.h>
  47 +#include <libavformat/avformat.h>
  48 +#include <libavfilter/avfiltergraph.h>
  49 +#include <libavfilter/buffersink.h>
  50 +#include <libavfilter/buffersrc.h>
  51 +#include <libavutil/opt.h>
  52 +#include <libavutil/pixdesc.h>
  53 +}
  54 +#ifdef WIN32
  55 +#pragma comment(lib, "avcodec.lib")
  56 +#pragma comment(lib, "avdevice.lib")
  57 +#pragma comment(lib, "avfilter.lib")
  58 +#pragma comment(lib, "avformat.lib")
  59 +#pragma comment(lib, "avutil.lib")
  60 +#pragma comment(lib, "postproc.lib")
  61 +#pragma comment(lib, "swresample.lib")
  62 +#pragma comment(lib, "swscale.lib")
  63 +#endif
  64 +
  65 +#if _MSC_VER
  66 +#define snprintf _snprintf
  67 +#define PRIu64 "I64u"
  68 +#define PRId64 "I64d"
  69 +#define PRIx64 "I64x"
  70 +#define PRIX64 "I64X"
  71 +#endif
  72 +
  73 +typedef struct FilteringContext {
  74 + AVFilterContext *buffersink_ctx;
  75 + AVFilterContext *buffersrc_ctx;
  76 + AVFilterGraph *filter_graph;
  77 +} FilteringContext;
  78 +
  79 +
  80 +#define AFRAME_DURATION_MS 20
  81 +#define VFRAME_DURATION_MS 50
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 #include <list> 8 #include <list>
9 #include <deque> 9 #include <deque>
10 #include "tools.h" 10 #include "tools.h"
11 -#include "VideoTranscoder.h" 11 +#include "AVTranscoder.h"
12 12
13 bool only_print = false; 13 bool only_print = false;
14 bool keep_tmp_files = false; 14 bool keep_tmp_files = false;
@@ -594,6 +594,8 @@ void add_media_infos() @@ -594,6 +594,8 @@ void add_media_infos()
594 m.rotate = f.rotate; 594 m.rotate = f.rotate;
595 m.m_role = f.m_role; 595 m.m_role = f.m_role;
596 m.uid = f.uid; 596 m.uid = f.uid;
  597 + m.start_time_ms = f.start_time * 1000;
  598 + m.end_time_ms = f.end_time * 1000;
597 add_media_info(m); 599 add_media_info(m);
598 m.t_type = tt_end; 600 m.t_type = tt_end;
599 m.type_time = m.end_time; 601 m.type_time = m.end_time;
@@ -871,608 +873,22 @@ int load_record_info(char * record_info) @@ -871,608 +873,22 @@ int load_record_info(char * record_info)
871 873
872 874
873 875
874 -#define __STDC_FORMAT_MACROS  
875 -#include <stdint.h>  
876 -#include <inttypes.h>  
877 -extern "C" {  
878 -#include <libavcodec/avcodec.h>  
879 -#include <libavformat/avformat.h>  
880 -#include <libavfilter/avfiltergraph.h>  
881 -#include <libavfilter/buffersink.h>  
882 -#include <libavfilter/buffersrc.h>  
883 -#include <libavutil/opt.h>  
884 -#include <libavutil/pixdesc.h>  
885 -}  
886 -#ifdef WIN32  
887 -#pragma comment(lib, "avcodec.lib")  
888 -#pragma comment(lib, "avdevice.lib")  
889 -#pragma comment(lib, "avfilter.lib")  
890 -#pragma comment(lib, "avformat.lib")  
891 -#pragma comment(lib, "avutil.lib")  
892 -#pragma comment(lib, "postproc.lib")  
893 -#pragma comment(lib, "swresample.lib")  
894 -#pragma comment(lib, "swscale.lib")  
895 -#endif  
896 -  
897 -#if _MSC_VER  
898 -#define snprintf _snprintf  
899 -#define PRIu64 "I64u"  
900 -#define PRId64 "I64d"  
901 -#define PRIx64 "I64x"  
902 -#define PRIX64 "I64X"  
903 -#endif  
904 -  
905 -  
906 -static AVFormatContext *ifmt_ctx;  
907 -static AVFormatContext *ofmt_ctx;  
908 -typedef struct FilteringContext {  
909 - AVFilterContext *buffersink_ctx;  
910 - AVFilterContext *buffersrc_ctx;  
911 - AVFilterGraph *filter_graph;  
912 -} FilteringContext;  
913 -static FilteringContext *filter_ctx;  
914 -  
915 -static int open_input_file(const char *filename)  
916 -{  
917 - int ret;  
918 - unsigned int i;  
919 -  
920 - ifmt_ctx = NULL;  
921 - if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {  
922 - av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");  
923 - return ret;  
924 - }  
925 -  
926 - if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {  
927 - av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");  
928 - return ret;  
929 - }  
930 -  
931 - for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
932 - AVStream *stream;  
933 - AVCodecContext *codec_ctx;  
934 - stream = ifmt_ctx->streams[i];  
935 - codec_ctx = stream->codec;  
936 - /* Reencode video & audio and remux subtitles etc. */  
937 - if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO  
938 - || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {  
939 - /* Open decoder */  
940 - ret = avcodec_open2(codec_ctx,  
941 - avcodec_find_decoder(codec_ctx->codec_id), NULL);  
942 - if (ret < 0) {  
943 - av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);  
944 - return ret;  
945 - }  
946 - }  
947 - }  
948 -  
949 - av_dump_format(ifmt_ctx, 0, filename, 0);  
950 - return 0;  
951 -}  
952 -  
953 -static int open_output_file(const char *filename)  
954 -{  
955 - AVStream *out_stream;  
956 - AVStream *in_stream;  
957 - AVCodecContext *dec_ctx, *enc_ctx;  
958 - AVCodec *encoder;  
959 - int ret;  
960 - unsigned int i;  
961 -  
962 - ofmt_ctx = NULL;  
963 - avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);  
964 - if (!ofmt_ctx) {  
965 - av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");  
966 - return AVERROR_UNKNOWN;  
967 - }  
968 -  
969 -  
970 - for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
971 - out_stream = avformat_new_stream(ofmt_ctx, NULL);  
972 - if (!out_stream) {  
973 - av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");  
974 - return AVERROR_UNKNOWN;  
975 - }  
976 -  
977 - in_stream = ifmt_ctx->streams[i];  
978 - dec_ctx = in_stream->codec;  
979 - enc_ctx = out_stream->codec;  
980 -  
981 - if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  
982 - enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;  
983 -  
984 -  
985 - if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO  
986 - || dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {  
987 - /* in this example, we choose transcoding to same codec */  
988 - encoder = avcodec_find_encoder(dec_ctx->codec_id);  
989 - if (!encoder) {  
990 - av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");  
991 - return AVERROR_INVALIDDATA;  
992 - }  
993 -  
994 - /* In this example, we transcode to same properties (picture size,  
995 - * sample rate etc.). These properties can be changed for output  
996 - * streams easily using filters */  
997 - if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {  
998 - enc_ctx->height = dec_ctx->height;  
999 - enc_ctx->width = dec_ctx->width;  
1000 - enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;  
1001 - /* take first format from list of supported formats */  
1002 - enc_ctx->pix_fmt = encoder->pix_fmts[0];  
1003 - /* video time_base can be set to whatever is handy and supported by encoder */  
1004 - enc_ctx->time_base = dec_ctx->time_base;  
1005 -  
1006 - enc_ctx->me_range = 16;  
1007 - enc_ctx->max_qdiff = 4;  
1008 - enc_ctx->qmin = 10;  
1009 - enc_ctx->qmax = 30;  
1010 - enc_ctx->qcompress = 0.6;  
1011 - }  
1012 - else {  
1013 - enc_ctx->sample_rate = dec_ctx->sample_rate;  
1014 - enc_ctx->channel_layout = dec_ctx->channel_layout;  
1015 - enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);  
1016 - /* take first format from list of supported formats */  
1017 - enc_ctx->sample_fmt = encoder->sample_fmts[0];  
1018 - enc_ctx->time_base.num = 1;  
1019 - enc_ctx->time_base.den = enc_ctx->sample_rate;  
1020 - }  
1021 -  
1022 - /* Third parameter can be used to pass settings to encoder */  
1023 - ret = avcodec_open2(enc_ctx, encoder, NULL);  
1024 - if (ret < 0) {  
1025 - av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);  
1026 - return ret;  
1027 - }  
1028 - }  
1029 - else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {  
1030 - av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);  
1031 - return AVERROR_INVALIDDATA;  
1032 - }  
1033 - else {  
1034 - /* if this stream must be remuxed */  
1035 - ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,  
1036 - ifmt_ctx->streams[i]->codec);  
1037 - if (ret < 0) {  
1038 - av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");  
1039 - return ret;  
1040 - }  
1041 - }  
1042 - }  
1043 - av_dump_format(ofmt_ctx, 0, filename, 1);  
1044 -  
1045 - if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {  
1046 - ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);  
1047 - if (ret < 0) {  
1048 - av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename);  
1049 - return ret;  
1050 - }  
1051 - }  
1052 -  
1053 - /* init muxer, write output file header */  
1054 - ret = avformat_write_header(ofmt_ctx, NULL);  
1055 - if (ret < 0) {  
1056 - av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");  
1057 - return ret;  
1058 - }  
1059 -  
1060 - return 0;  
1061 -}  
1062 -  
1063 -static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,  
1064 - AVCodecContext *enc_ctx, const char *filter_spec)  
1065 -{  
1066 - char args[512];  
1067 - int ret = 0;  
1068 - AVFilter *buffersrc = NULL;  
1069 - AVFilter *buffersink = NULL;  
1070 - AVFilterContext *buffersrc_ctx = NULL;  
1071 - AVFilterContext *buffersink_ctx = NULL;  
1072 - AVFilterInOut *outputs = avfilter_inout_alloc();  
1073 - AVFilterInOut *inputs = avfilter_inout_alloc();  
1074 - AVFilterGraph *filter_graph = avfilter_graph_alloc();  
1075 -  
1076 - if (!outputs || !inputs || !filter_graph) {  
1077 - ret = AVERROR(ENOMEM);  
1078 - goto end;  
1079 - }  
1080 -  
1081 - if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {  
1082 - buffersrc = avfilter_get_by_name("buffer");  
1083 - buffersink = avfilter_get_by_name("buffersink");  
1084 - if (!buffersrc || !buffersink) {  
1085 - av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");  
1086 - ret = AVERROR_UNKNOWN;  
1087 - goto end;  
1088 - }  
1089 -  
1090 - snprintf(args, sizeof(args),  
1091 - "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",  
1092 - dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,  
1093 - dec_ctx->time_base.num, dec_ctx->time_base.den,  
1094 - dec_ctx->sample_aspect_ratio.num,  
1095 - dec_ctx->sample_aspect_ratio.den);  
1096 -  
1097 - ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",  
1098 - args, NULL, filter_graph);  
1099 - if (ret < 0) {  
1100 - av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");  
1101 - goto end;  
1102 - }  
1103 -  
1104 - ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",  
1105 - NULL, NULL, filter_graph);  
1106 - if (ret < 0) {  
1107 - av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");  
1108 - goto end;  
1109 - }  
1110 -  
1111 - ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",  
1112 - (uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt),  
1113 - AV_OPT_SEARCH_CHILDREN);  
1114 - if (ret < 0) {  
1115 - av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");  
1116 - goto end;  
1117 - }  
1118 - }  
1119 - else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {  
1120 - buffersrc = avfilter_get_by_name("abuffer");  
1121 - buffersink = avfilter_get_by_name("abuffersink");  
1122 - if (!buffersrc || !buffersink) {  
1123 - av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");  
1124 - ret = AVERROR_UNKNOWN;  
1125 - goto end;  
1126 - }  
1127 -  
1128 - if (!dec_ctx->channel_layout)  
1129 - dec_ctx->channel_layout =  
1130 - av_get_default_channel_layout(dec_ctx->channels);  
1131 - sprintf(args, //sizeof(args),  
1132 - "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,  
1133 - dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,  
1134 - av_get_sample_fmt_name(dec_ctx->sample_fmt),  
1135 - dec_ctx->channel_layout);  
1136 - ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",  
1137 - args, NULL, filter_graph);  
1138 - if (ret < 0) {  
1139 - av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");  
1140 - goto end;  
1141 - }  
1142 -  
1143 - ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",  
1144 - NULL, NULL, filter_graph);  
1145 - if (ret < 0) {  
1146 - av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");  
1147 - goto end;  
1148 - }  
1149 -  
1150 - ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",  
1151 - (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt),  
1152 - AV_OPT_SEARCH_CHILDREN);  
1153 - if (ret < 0) {  
1154 - av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");  
1155 - goto end;  
1156 - }  
1157 -  
1158 - ret = av_opt_set_bin(buffersink_ctx, "channel_layouts",  
1159 - (uint8_t*)&enc_ctx->channel_layout,  
1160 - sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN);  
1161 - if (ret < 0) {  
1162 - av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");  
1163 - goto end;  
1164 - }  
1165 -  
1166 - ret = av_opt_set_bin(buffersink_ctx, "sample_rates",  
1167 - (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate),  
1168 - AV_OPT_SEARCH_CHILDREN);  
1169 - if (ret < 0) {  
1170 - av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");  
1171 - goto end;  
1172 - }  
1173 - }  
1174 - else {  
1175 - ret = AVERROR_UNKNOWN;  
1176 - goto end;  
1177 - }  
1178 -  
1179 - /* Endpoints for the filter graph. */  
1180 - outputs->name = av_strdup("in");  
1181 - outputs->filter_ctx = buffersrc_ctx;  
1182 - outputs->pad_idx = 0;  
1183 - outputs->next = NULL;  
1184 -  
1185 - inputs->name = av_strdup("out");  
1186 - inputs->filter_ctx = buffersink_ctx;  
1187 - inputs->pad_idx = 0;  
1188 - inputs->next = NULL;  
1189 -  
1190 - if (!outputs->name || !inputs->name) {  
1191 - ret = AVERROR(ENOMEM);  
1192 - goto end;  
1193 - }  
1194 -  
1195 - if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,  
1196 - &inputs, &outputs, NULL)) < 0)  
1197 - goto end;  
1198 -  
1199 - if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)  
1200 - goto end;  
1201 -  
1202 - /* Fill FilteringContext */  
1203 - fctx->buffersrc_ctx = buffersrc_ctx;  
1204 - fctx->buffersink_ctx = buffersink_ctx;  
1205 - fctx->filter_graph = filter_graph;  
1206 -  
1207 -end:  
1208 - avfilter_inout_free(&inputs);  
1209 - avfilter_inout_free(&outputs);  
1210 -  
1211 - return ret;  
1212 -}  
1213 -  
1214 -static int init_filters(void)  
1215 -{  
1216 - const char *filter_spec;  
1217 - unsigned int i;  
1218 - int ret;  
1219 - filter_ctx = (FilteringContext *)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));  
1220 - if (!filter_ctx)  
1221 - return AVERROR(ENOMEM);  
1222 -  
1223 - for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
1224 - filter_ctx[i].buffersrc_ctx = NULL;  
1225 - filter_ctx[i].buffersink_ctx = NULL;  
1226 - filter_ctx[i].filter_graph = NULL;  
1227 - if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO  
1228 - || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))  
1229 - continue;  
1230 -  
1231 -  
1232 - if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)  
1233 - filter_spec = "null"; /* passthrough (dummy) filter for video */  
1234 - else  
1235 - filter_spec = "anull"; /* passthrough (dummy) filter for audio */  
1236 - ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec,  
1237 - ofmt_ctx->streams[i]->codec, filter_spec);  
1238 - if (ret)  
1239 - return ret;  
1240 - }  
1241 - return 0;  
1242 -}  
1243 -  
1244 -static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) {  
1245 - int ret;  
1246 - int got_frame_local;  
1247 - AVPacket enc_pkt;  
1248 - int(*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) =  
1249 - (ifmt_ctx->streams[stream_index]->codec->codec_type ==  
1250 - AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2;  
1251 -  
1252 - if (!got_frame)  
1253 - got_frame = &got_frame_local;  
1254 -  
1255 - av_log(NULL, AV_LOG_INFO, "Encoding frame\n");  
1256 - /* encode filtered frame */  
1257 - enc_pkt.data = NULL;  
1258 - enc_pkt.size = 0;  
1259 - av_init_packet(&enc_pkt);  
1260 - ret = enc_func(ofmt_ctx->streams[stream_index]->codec, &enc_pkt,  
1261 - filt_frame, got_frame);  
1262 - av_frame_free(&filt_frame);  
1263 - if (ret < 0)  
1264 - return ret;  
1265 - if (!(*got_frame))  
1266 - return 0;  
1267 -  
1268 - /* prepare packet for muxing */  
1269 - enc_pkt.stream_index = stream_index;  
1270 - av_packet_rescale_ts(&enc_pkt,  
1271 - ofmt_ctx->streams[stream_index]->codec->time_base,  
1272 - ofmt_ctx->streams[stream_index]->time_base);  
1273 -  
1274 - av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  
1275 - /* mux encoded frame */  
1276 - ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);  
1277 - return ret;  
1278 -}  
1279 -  
1280 -static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)  
1281 -{  
1282 - int ret;  
1283 - AVFrame *filt_frame;  
1284 -  
1285 - av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");  
1286 - /* push the decoded frame into the filtergraph */  
1287 - ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,  
1288 - frame, 0);  
1289 - if (ret < 0) {  
1290 - av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");  
1291 - return ret;  
1292 - }  
1293 -  
1294 - /* pull filtered frames from the filtergraph */  
1295 - while (1) {  
1296 - filt_frame = av_frame_alloc();  
1297 - if (!filt_frame) {  
1298 - ret = AVERROR(ENOMEM);  
1299 - break;  
1300 - }  
1301 - av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");  
1302 - ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,  
1303 - filt_frame);  
1304 - if (ret < 0) {  
1305 - /* if no more frames for output - returns AVERROR(EAGAIN)  
1306 - * if flushed and no more frames for output - returns AVERROR_EOF  
1307 - * rewrite retcode to 0 to show it as normal procedure completion  
1308 - */  
1309 - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)  
1310 - ret = 0;  
1311 - av_frame_free(&filt_frame);  
1312 - break;  
1313 - }  
1314 -  
1315 - filt_frame->pict_type = AV_PICTURE_TYPE_NONE;  
1316 - ret = encode_write_frame(filt_frame, stream_index, NULL);  
1317 - if (ret < 0)  
1318 - break;  
1319 - }  
1320 -  
1321 - return ret;  
1322 -}  
1323 -  
1324 -static int flush_encoder(unsigned int stream_index)  
1325 -{  
1326 - int ret;  
1327 - int got_frame;  
1328 -  
1329 - if (!(ofmt_ctx->streams[stream_index]->codec->codec->capabilities &  
1330 - CODEC_CAP_DELAY))  
1331 - return 0;  
1332 -  
1333 - while (1) {  
1334 - av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);  
1335 - ret = encode_write_frame(NULL, stream_index, &got_frame);  
1336 - if (ret < 0)  
1337 - break;  
1338 - if (!got_frame)  
1339 - return 0;  
1340 - }  
1341 - return ret;  
1342 -}  
1343 -  
1344 -int transcode(const char * input){  
1345 - int ret;  
1346 - AVPacket packet;  
1347 - AVFrame *frame = NULL;  
1348 - enum AVMediaType type;  
1349 - unsigned int stream_index;  
1350 - unsigned int i;  
1351 - int got_frame;  
1352 - int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);  
1353 - memset(&packet, 0, sizeof(AVPacket));  
1354 -  
1355 - char output[1024];  
1356 - get_output_file_name(input, "pip_", output);  
1357 -  
1358 - if ((ret = open_input_file(input)) < 0)  
1359 - goto end;  
1360 - if ((ret = open_output_file(output)) < 0)  
1361 - goto end;  
1362 - if ((ret = init_filters()) < 0)  
1363 - goto end;  
1364 -  
1365 - /* read all packets */  
1366 - while (1) {  
1367 - if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)  
1368 - break;  
1369 - stream_index = packet.stream_index;  
1370 - type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;  
1371 - av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",  
1372 - stream_index);  
1373 -  
1374 - if (filter_ctx[stream_index].filter_graph) {  
1375 - av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");  
1376 - frame = av_frame_alloc();  
1377 - if (!frame) {  
1378 - ret = AVERROR(ENOMEM);  
1379 - break;  
1380 - }  
1381 - av_packet_rescale_ts(&packet,  
1382 - ifmt_ctx->streams[stream_index]->time_base,  
1383 - ifmt_ctx->streams[stream_index]->codec->time_base);  
1384 - dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :  
1385 - avcodec_decode_audio4;  
1386 - ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame,  
1387 - &got_frame, &packet);  
1388 - if (ret < 0) {  
1389 - av_frame_free(&frame);  
1390 - av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");  
1391 - break;  
1392 - }  
1393 -  
1394 - if (got_frame) {  
1395 - frame->pts = av_frame_get_best_effort_timestamp(frame);  
1396 - ret = filter_encode_write_frame(frame, stream_index);  
1397 - av_frame_free(&frame);  
1398 - if (ret < 0)  
1399 - goto end;  
1400 - }  
1401 - else {  
1402 - av_frame_free(&frame);  
1403 - }  
1404 - }  
1405 - else {  
1406 - /* remux this frame without reencoding */  
1407 - av_packet_rescale_ts(&packet,  
1408 - ifmt_ctx->streams[stream_index]->time_base,  
1409 - ofmt_ctx->streams[stream_index]->time_base);  
1410 -  
1411 - ret = av_interleaved_write_frame(ofmt_ctx, &packet);  
1412 - if (ret < 0)  
1413 - goto end;  
1414 - }  
1415 - av_packet_unref(&packet);  
1416 - }  
1417 -  
1418 - /* flush filters and encoders */  
1419 - for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
1420 - /* flush filter */  
1421 - if (!filter_ctx[i].filter_graph)  
1422 - continue;  
1423 - ret = filter_encode_write_frame(NULL, i);  
1424 - if (ret < 0) {  
1425 - av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");  
1426 - goto end;  
1427 - }  
1428 -  
1429 - /* flush encoder */  
1430 - ret = flush_encoder(i);  
1431 - if (ret < 0) {  
1432 - av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");  
1433 - goto end;  
1434 - }  
1435 - }  
1436 -  
1437 - av_write_trailer(ofmt_ctx);  
1438 -end:  
1439 - av_packet_unref(&packet);  
1440 - av_frame_free(&frame);  
1441 - for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
1442 - avcodec_close(ifmt_ctx->streams[i]->codec);  
1443 - if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && ofmt_ctx->streams[i]->codec)  
1444 - avcodec_close(ofmt_ctx->streams[i]->codec);  
1445 - if (filter_ctx && filter_ctx[i].filter_graph)  
1446 - avfilter_graph_free(&filter_ctx[i].filter_graph);  
1447 - }  
1448 - av_free(filter_ctx);  
1449 - avformat_close_input(&ifmt_ctx);  
1450 - if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))  
1451 - avio_closep(&ofmt_ctx->pb);  
1452 - avformat_free_context(ofmt_ctx);  
1453 -  
1454 - //if (ret < 0)  
1455 - // av_log(NULL, AV_LOG_ERROR, "Error occurred: %s\n", av_err2str(ret));  
1456 -  
1457 - return ret ? 1 : 0;  
1458 -}  
1459 -  
1460 -#define MIN_TIME_INTERVAL 0.2 876 +#define MIN_TIME_INTERVAL 25
1461 877
1462 int process_av_files() 878 int process_av_files()
1463 { 879 {
1464 av_register_all(); 880 av_register_all();
1465 avfilter_register_all(); 881 avfilter_register_all();
1466 882
1467 - CVideoTranscoder videoTranscoder; 883 + CAVTranscoder videoTranscoder;
1468 884
1469 - float cur_time = 0.0; 885 + int64_t cur_time = 0;
1470 bool has_file = sorted_media.size(); 886 bool has_file = sorted_media.size();
1471 while (has_file){ 887 while (has_file){
1472 while (has_file){ 888 while (has_file){
1473 media_info info = sorted_media.front(); 889 media_info info = sorted_media.front();
1474 890
1475 - if (info.start_time - cur_time < MIN_TIME_INTERVAL) { 891 + if (info.start_time_ms - cur_time < MIN_TIME_INTERVAL) {
1476 sorted_media.pop_front(); 892 sorted_media.pop_front();
1477 videoTranscoder.add(info); 893 videoTranscoder.add(info);
1478 } 894 }
@@ -82,14 +82,23 @@ @@ -82,14 +82,23 @@
82 <Text Include="ReadMe.txt" /> 82 <Text Include="ReadMe.txt" />
83 </ItemGroup> 83 </ItemGroup>
84 <ItemGroup> 84 <ItemGroup>
  85 + <ClCompile Include="AudioDecoder.cpp" />
  86 + <ClCompile Include="AudioEncoder.cpp" />
  87 + <ClCompile Include="AVDecoder.cpp" />
85 <ClCompile Include="merge_pip.cpp" /> 88 <ClCompile Include="merge_pip.cpp" />
86 <ClCompile Include="tools.cpp" /> 89 <ClCompile Include="tools.cpp" />
87 <ClCompile Include="VideoDecoder.cpp" /> 90 <ClCompile Include="VideoDecoder.cpp" />
88 - <ClCompile Include="VideoTranscoder.cpp" /> 91 + <ClCompile Include="AVTranscoder.cpp" />
  92 + <ClCompile Include="VideoEncoder.cpp" />
89 </ItemGroup> 93 </ItemGroup>
90 <ItemGroup> 94 <ItemGroup>
  95 + <ClInclude Include="AudioDecoder.h" />
  96 + <ClInclude Include="AudioEncoder.h" />
  97 + <ClInclude Include="AVDecoder.h" />
  98 + <ClInclude Include="media_info.h" />
91 <ClInclude Include="VideoDecoder.h" /> 99 <ClInclude Include="VideoDecoder.h" />
92 - <ClInclude Include="VideoTranscoder.h" /> 100 + <ClInclude Include="AVTranscoder.h" />
  101 + <ClInclude Include="VideoEncoder.h" />
93 </ItemGroup> 102 </ItemGroup>
94 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 103 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
95 <ImportGroup Label="ExtensionTargets"> 104 <ImportGroup Label="ExtensionTargets">
@@ -24,18 +24,45 @@ @@ -24,18 +24,45 @@
24 <ClCompile Include="merge_pip.cpp"> 24 <ClCompile Include="merge_pip.cpp">
25 <Filter>源文件</Filter> 25 <Filter>源文件</Filter>
26 </ClCompile> 26 </ClCompile>
27 - <ClCompile Include="VideoTranscoder.cpp"> 27 + <ClCompile Include="VideoDecoder.cpp">
28 <Filter>源文件</Filter> 28 <Filter>源文件</Filter>
29 </ClCompile> 29 </ClCompile>
30 - <ClCompile Include="VideoDecoder.cpp"> 30 + <ClCompile Include="AVDecoder.cpp">
  31 + <Filter>源文件</Filter>
  32 + </ClCompile>
  33 + <ClCompile Include="AudioDecoder.cpp">
  34 + <Filter>源文件</Filter>
  35 + </ClCompile>
  36 + <ClCompile Include="AVTranscoder.cpp">
  37 + <Filter>源文件</Filter>
  38 + </ClCompile>
  39 + <ClCompile Include="VideoEncoder.cpp">
  40 + <Filter>源文件</Filter>
  41 + </ClCompile>
  42 + <ClCompile Include="AudioEncoder.cpp">
31 <Filter>源文件</Filter> 43 <Filter>源文件</Filter>
32 </ClCompile> 44 </ClCompile>
33 </ItemGroup> 45 </ItemGroup>
34 <ItemGroup> 46 <ItemGroup>
35 - <ClInclude Include="VideoTranscoder.h"> 47 + <ClInclude Include="VideoDecoder.h">
36 <Filter>头文件</Filter> 48 <Filter>头文件</Filter>
37 </ClInclude> 49 </ClInclude>
38 - <ClInclude Include="VideoDecoder.h"> 50 + <ClInclude Include="AVDecoder.h">
  51 + <Filter>头文件</Filter>
  52 + </ClInclude>
  53 + <ClInclude Include="AudioDecoder.h">
  54 + <Filter>头文件</Filter>
  55 + </ClInclude>
  56 + <ClInclude Include="media_info.h">
  57 + <Filter>头文件</Filter>
  58 + </ClInclude>
  59 + <ClInclude Include="AVTranscoder.h">
  60 + <Filter>头文件</Filter>
  61 + </ClInclude>
  62 + <ClInclude Include="VideoEncoder.h">
  63 + <Filter>头文件</Filter>
  64 + </ClInclude>
  65 + <ClInclude Include="AudioEncoder.h">
39 <Filter>头文件</Filter> 66 <Filter>头文件</Filter>
40 </ClInclude> 67 </ClInclude>
41 </ItemGroup> 68 </ItemGroup>