1.support one to many,only tested using one student
2.add macro to support using ffmpeg codec version 58,which need pcm format using AV_SAMPLE_FMT_FLTP when encoding aac
正在显示
5 个修改的文件
包含
78 行增加
和
34 行删除
| @@ -11,24 +11,36 @@ extern "C" { | @@ -11,24 +11,36 @@ extern "C" { | ||
| 11 | #define SRC_W 320 | 11 | #define SRC_W 320 |
| 12 | #define SRC_H 240 | 12 | #define SRC_H 240 |
| 13 | 13 | ||
| 14 | -CAVTranscoder::CAVTranscoder(): | 14 | +CAVTranscoder::CAVTranscoder(bool bOne2One): |
| 15 | _start_time(INT64_MAX), | 15 | _start_time(INT64_MAX), |
| 16 | _all_processed(true), | 16 | _all_processed(true), |
| 17 | -_one2one(true), | ||
| 18 | _nOutputWidth(320), | 17 | _nOutputWidth(320), |
| 19 | _cur_out_v_ts(0), | 18 | _cur_out_v_ts(0), |
| 20 | _cur_out_a_ts(0), | 19 | _cur_out_a_ts(0), |
| 21 | _max_audio(1), | 20 | _max_audio(1), |
| 22 | -_swsCtx(NULL) | 21 | +_swsCtx(NULL), |
| 22 | +_scaledFrame(NULL) | ||
| 23 | { | 23 | { |
| 24 | + _one2one = bOne2One; | ||
| 24 | if (_one2one) { | 25 | if (_one2one) { |
| 25 | _nOutputHeight = 480; | 26 | _nOutputHeight = 480; |
| 26 | } | 27 | } |
| 27 | else { | 28 | else { |
| 28 | _nOutputHeight = 240; | 29 | _nOutputHeight = 240; |
| 29 | - _swsCtx = sws_getContext(SRC_W, SRC_H, PIX_FMT_YUV420P, | ||
| 30 | - SCALED_W, SCALED_H, PIX_FMT_YUV420P, SWS_BILINEAR, | 30 | + _swsCtx = sws_getContext(SRC_W, SRC_H, AV_PIX_FMT_YUV420P, |
| 31 | + SCALED_W, SCALED_H, AV_PIX_FMT_YUV420P, SWS_BILINEAR, | ||
| 31 | NULL, NULL, NULL); | 32 | NULL, NULL, NULL); |
| 33 | + _scaledFrame = av_frame_alloc(); | ||
| 34 | + _scaledFrame->format = AV_PIX_FMT_YUV420P; | ||
| 35 | + _scaledFrame->width = SCALED_W; | ||
| 36 | + _scaledFrame->height = SCALED_H; | ||
| 37 | + _scaledFrame->pts = 0; | ||
| 38 | + | ||
| 39 | + int ret = av_frame_get_buffer(_scaledFrame, 32); | ||
| 40 | + if (ret != 0) | ||
| 41 | + { | ||
| 42 | + printf("Error alloc frame buffer for scaling video frame"); | ||
| 43 | + } | ||
| 32 | } | 44 | } |
| 33 | } | 45 | } |
| 34 | 46 | ||
| @@ -113,6 +125,10 @@ int CAVTranscoder::close() | @@ -113,6 +125,10 @@ int CAVTranscoder::close() | ||
| 113 | sws_freeContext(_swsCtx); | 125 | sws_freeContext(_swsCtx); |
| 114 | _swsCtx = NULL; | 126 | _swsCtx = NULL; |
| 115 | } | 127 | } |
| 128 | + if (_scaledFrame) { | ||
| 129 | + av_frame_unref(_scaledFrame); | ||
| 130 | + av_frame_free(&_scaledFrame); | ||
| 131 | + } | ||
| 116 | flush_encoder(0); | 132 | flush_encoder(0); |
| 117 | flush_encoder(1); | 133 | flush_encoder(1); |
| 118 | av_write_trailer(_ofmt_ctx); | 134 | av_write_trailer(_ofmt_ctx); |
| @@ -214,7 +230,7 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -214,7 +230,7 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 214 | enc_ctx->channel_layout = AV_CH_LAYOUT_MONO; | 230 | enc_ctx->channel_layout = AV_CH_LAYOUT_MONO; |
| 215 | enc_ctx->channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO); | 231 | enc_ctx->channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO); |
| 216 | /* take first format from list of supported formats */ | 232 | /* take first format from list of supported formats */ |
| 217 | - enc_ctx->sample_fmt = AV_SAMPLE_FMT_S16; //AV_SAMPLE_FMT_FLTP; | 233 | + enc_ctx->sample_fmt = PCM_FORMAT_FOR_AAC_ENCODE; //AV_SAMPLE_FMT_FLTP; |
| 218 | enc_ctx->time_base.num = 1; | 234 | enc_ctx->time_base.num = 1; |
| 219 | enc_ctx->time_base.den = enc_ctx->sample_rate; | 235 | enc_ctx->time_base.den = enc_ctx->sample_rate; |
| 220 | enc_ctx->bit_rate = 64000; | 236 | enc_ctx->bit_rate = 64000; |
| @@ -264,7 +280,7 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -264,7 +280,7 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 264 | pDstFrame->nb_samples = 1024; | 280 | pDstFrame->nb_samples = 1024; |
| 265 | pDstFrame->channel_layout = AV_CH_LAYOUT_MONO; | 281 | pDstFrame->channel_layout = AV_CH_LAYOUT_MONO; |
| 266 | pDstFrame->channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO); | 282 | pDstFrame->channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO); |
| 267 | - pDstFrame->format = AV_SAMPLE_FMT_S16; | 283 | + pDstFrame->format = PCM_FORMAT_FOR_AAC_ENCODE; |
| 268 | pDstFrame->sample_rate = 48000; | 284 | pDstFrame->sample_rate = 48000; |
| 269 | 285 | ||
| 270 | av_frame_get_buffer(pDstFrame, 0); | 286 | av_frame_get_buffer(pDstFrame, 0); |
| @@ -273,8 +289,13 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -273,8 +289,13 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 273 | for (; it != decoders_got_frame.end(); it++) { | 289 | for (; it != decoders_got_frame.end(); it++) { |
| 274 | AVFrame * pFrame = (*it)->_cur_a_frame; | 290 | AVFrame * pFrame = (*it)->_cur_a_frame; |
| 275 | if (pFrame) { | 291 | if (pFrame) { |
| 292 | +#if LIBAVCODEC_VERSION_MAJOR < 58 | ||
| 276 | int16_t * psrc = (int16_t *)pFrame->extended_data[0]; | 293 | int16_t * psrc = (int16_t *)pFrame->extended_data[0]; |
| 277 | int16_t * pdst = (int16_t *)pDstFrame->extended_data[0]; | 294 | int16_t * pdst = (int16_t *)pDstFrame->extended_data[0]; |
| 295 | +#else | ||
| 296 | + float * psrc = (float *)pFrame->extended_data[0]; | ||
| 297 | + float * pdst = (float *)pDstFrame->extended_data[0]; | ||
| 298 | +#endif | ||
| 278 | for (int i = 0; i < 1024; i++,pdst++,psrc++) { | 299 | for (int i = 0; i < 1024; i++,pdst++,psrc++) { |
| 279 | *pdst += (*psrc/_max_audio); | 300 | *pdst += (*psrc/_max_audio); |
| 280 | } | 301 | } |
| @@ -310,41 +331,43 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -310,41 +331,43 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 310 | uint8_t *dstbuf = new uint8_t[nDstSize]; | 331 | uint8_t *dstbuf = new uint8_t[nDstSize]; |
| 311 | avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight); | 332 | avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight); |
| 312 | 333 | ||
| 334 | + bool fill_pure_color = true; | ||
| 313 | if (idxTeacher != -1) { | 335 | if (idxTeacher != -1) { |
| 314 | //copy teacher frame to dest frame | 336 | //copy teacher frame to dest frame |
| 315 | CAVDecoder * pDecoder = decoders_got_frame[idxTeacher]; | 337 | CAVDecoder * pDecoder = decoders_got_frame[idxTeacher]; |
| 316 | AVFrame * pFrame = pDecoder->_cur_v_frame; | 338 | AVFrame * pFrame = pDecoder->_cur_v_frame; |
| 317 | if (pFrame) { | 339 | if (pFrame) { |
| 318 | fillDestFrame(pDstFrame, pFrame, 0, 0); | 340 | fillDestFrame(pDstFrame, pFrame, 0, 0); |
| 341 | + fill_pure_color = false; | ||
| 342 | + pDecoder->free_cur_v_frame(); | ||
| 319 | } | 343 | } |
| 320 | - else {//fill with pure color | 344 | + } |
| 345 | + if(fill_pure_color){//fill with pure color | ||
| 321 | memset(pDstFrame->data[0], 0, _nOutputWidth * _nOutputHeight); | 346 | memset(pDstFrame->data[0], 0, _nOutputWidth * _nOutputHeight); |
| 322 | memset(pDstFrame->data[1], 0x80, _nOutputWidth *_nOutputHeight / 4); | 347 | memset(pDstFrame->data[1], 0x80, _nOutputWidth *_nOutputHeight / 4); |
| 323 | memset(pDstFrame->data[2], 0x80, _nOutputWidth * _nOutputHeight / 4); | 348 | memset(pDstFrame->data[2], 0x80, _nOutputWidth * _nOutputHeight / 4); |
| 324 | - } | ||
| 325 | - | ||
| 326 | - for (int i = 0; i < decoders_got_frame.size(); i++){ | ||
| 327 | - if (i != idxTeacher) { | ||
| 328 | - //scale eacher frame | ||
| 329 | - | ||
| 330 | - //copy each frame to the dest frame | ||
| 331 | - | ||
| 332 | - } | ||
| 333 | - } | ||
| 334 | } | 349 | } |
| 335 | - else { | ||
| 336 | - memset(pDstFrame->data[0], 0, _nOutputWidth * _nOutputHeight); | ||
| 337 | - memset(pDstFrame->data[1], 0x80, _nOutputWidth *_nOutputHeight / 4); | ||
| 338 | - memset(pDstFrame->data[2], 0x80, _nOutputWidth * _nOutputHeight / 4); | ||
| 339 | 350 | ||
| 340 | - for (int i = 0; i < decoders_got_frame.size(); i++){ | ||
| 341 | - if (i != idxTeacher) { | ||
| 342 | - //scale eacher frame | ||
| 343 | - | ||
| 344 | - //copy each frame to the dest frame | ||
| 345 | - | ||
| 346 | - } | 351 | + int imageIdx = 0; |
| 352 | + for (int i = 0; i < decoders_got_frame.size(); i++){ | ||
| 353 | + if (i != idxTeacher) { | ||
| 354 | + //scale eacher frame | ||
| 355 | + CAVDecoder * pDecoder = decoders_got_frame[i]; | ||
| 356 | + AVFrame * pFrame = pDecoder->_cur_v_frame; | ||
| 357 | + if (!pFrame) { | ||
| 358 | + continue; | ||
| 347 | } | 359 | } |
| 360 | + int h = sws_scale(_swsCtx, pFrame->data, pFrame->linesize, 0, pFrame->height, | ||
| 361 | + _scaledFrame->data, _scaledFrame->linesize); | ||
| 362 | + if (h <= 0){ | ||
| 363 | + printf("scale output 0?"); | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + //copy each frame to the dest frame | ||
| 367 | + fillDestFrame(pDstFrame, _scaledFrame, SRC_W - SCALED_H - ((imageIdx % 4) * SCALED_H), SRC_H - SCALED_H - (SCALED_H + 8)*imageIdx / 4, (SCALED_W - SCALED_H) / 2, 0, SCALED_H, SCALED_H); | ||
| 368 | + pDecoder->free_cur_v_frame(); | ||
| 369 | + imageIdx++; | ||
| 370 | + } | ||
| 348 | } | 371 | } |
| 349 | 372 | ||
| 350 | //fill the timestamp of dest frame | 373 | //fill the timestamp of dest frame |
| @@ -381,6 +404,19 @@ int CAVTranscoder::open_output_file(const char *filename) | @@ -381,6 +404,19 @@ int CAVTranscoder::open_output_file(const char *filename) | ||
| 381 | return 0; | 404 | return 0; |
| 382 | } | 405 | } |
| 383 | 406 | ||
| 407 | + int CAVTranscoder::fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y, int srcx, int srcy, int w, int h) | ||
| 408 | + { | ||
| 409 | + for (int i = 0; i < h; i++) { | ||
| 410 | + memcpy(pDstFrame->data[0] + (y + i)*pDstFrame->linesize[0] + x, pSrcFrame->data[0] + (i+srcy) * pSrcFrame->linesize[0] + srcx, pSrcFrame->linesize[0] > 0 ? w : -w); | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + for (int i = 0; i < h / 2; i++){ | ||
| 414 | + memcpy(pDstFrame->data[1] + (y / 2 + i)*pDstFrame->linesize[1] + x / 2, pSrcFrame->data[1] + (i + srcy/2) * pSrcFrame->linesize[1], pSrcFrame->linesize[1] > 0 ? w/2 : -w/2); | ||
| 415 | + memcpy(pDstFrame->data[2] + (y / 2 + i)*pDstFrame->linesize[2] + x / 2, pSrcFrame->data[2] + (i + srcy/2) * pSrcFrame->linesize[2], pSrcFrame->linesize[2] > 0 ? w/2 : -w/2); | ||
| 416 | + } | ||
| 417 | + return 0; | ||
| 418 | + } | ||
| 419 | + | ||
| 384 | int CAVTranscoder::mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame) | 420 | int CAVTranscoder::mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame) |
| 385 | { | 421 | { |
| 386 | //prepare one2one base frame | 422 | //prepare one2one base frame |
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | class CAVTranscoder | 5 | class CAVTranscoder |
| 6 | { | 6 | { |
| 7 | public: | 7 | public: |
| 8 | - CAVTranscoder(); | 8 | + CAVTranscoder(bool bOne2One); |
| 9 | virtual ~CAVTranscoder(); | 9 | virtual ~CAVTranscoder(); |
| 10 | 10 | ||
| 11 | int add(media_info & info); | 11 | int add(media_info & info); |
| @@ -35,12 +35,14 @@ private: | @@ -35,12 +35,14 @@ private: | ||
| 35 | int mix_and_output_one2many_vframe(vector<CAVDecoder *> & decoders_got_frame); | 35 | int mix_and_output_one2many_vframe(vector<CAVDecoder *> & decoders_got_frame); |
| 36 | 36 | ||
| 37 | int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y); | 37 | int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y); |
| 38 | + int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int destx, int desty, int srcx,int srcy,int w,int h); | ||
| 38 | int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame); | 39 | int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame); |
| 39 | int flush_encoder(unsigned int stream_index); | 40 | int flush_encoder(unsigned int stream_index); |
| 40 | 41 | ||
| 41 | void * _a_frame_pool; | 42 | void * _a_frame_pool; |
| 42 | int _max_audio; | 43 | int _max_audio; |
| 43 | struct SwsContext * _swsCtx; | 44 | struct SwsContext * _swsCtx; |
| 45 | + AVFrame * _scaledFrame; | ||
| 44 | public: | 46 | public: |
| 45 | void set_max_audio(int max_audio); | 47 | void set_max_audio(int max_audio); |
| 46 | }; | 48 | }; |
| @@ -123,7 +123,7 @@ int CAudioDecoder::init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, | @@ -123,7 +123,7 @@ int CAudioDecoder::init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, | ||
| 123 | av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n"); | 123 | av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n"); |
| 124 | goto end; | 124 | goto end; |
| 125 | } | 125 | } |
| 126 | - enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16; | 126 | + enum AVSampleFormat sample_fmt = PCM_FORMAT_FOR_AAC_ENCODE; |
| 127 | ret = av_opt_set_bin(buffersink_ctx, "sample_fmts", | 127 | ret = av_opt_set_bin(buffersink_ctx, "sample_fmts", |
| 128 | (uint8_t*)&sample_fmt, sizeof(sample_fmt), | 128 | (uint8_t*)&sample_fmt, sizeof(sample_fmt), |
| 129 | AV_OPT_SEARCH_CHILDREN); | 129 | AV_OPT_SEARCH_CHILDREN); |
| 1 | #pragma once | 1 | #pragma once |
| 2 | - | 2 | +#define __STDC_LIMIT_MACROS |
| 3 | #include <string> | 3 | #include <string> |
| 4 | #include <vector> | 4 | #include <vector> |
| 5 | #include <stdint.h> | 5 | #include <stdint.h> |
| @@ -78,4 +78,10 @@ typedef struct FilteringContext { | @@ -78,4 +78,10 @@ typedef struct FilteringContext { | ||
| 78 | 78 | ||
| 79 | 79 | ||
| 80 | #define AFRAME_DURATION_MS 21.333333 | 80 | #define AFRAME_DURATION_MS 21.333333 |
| 81 | -#define VFRAME_DURATION_MS 50 | ||
| 81 | +#define VFRAME_DURATION_MS 50 | ||
| 82 | + | ||
| 83 | +#if LIBAVCODEC_VERSION_MAJOR < 58 | ||
| 84 | +#define PCM_FORMAT_FOR_AAC_ENCODE AV_SAMPLE_FMT_S16 | ||
| 85 | +#else | ||
| 86 | +#define PCM_FORMAT_FOR_AAC_ENCODE AV_SAMPLE_FMT_FLTP | ||
| 87 | +#endif |
| @@ -954,7 +954,7 @@ int process_av_files() | @@ -954,7 +954,7 @@ int process_av_files() | ||
| 954 | av_register_all(); | 954 | av_register_all(); |
| 955 | avfilter_register_all(); | 955 | avfilter_register_all(); |
| 956 | 956 | ||
| 957 | - CAVTranscoder videoTranscoder; | 957 | + CAVTranscoder videoTranscoder(max_audio==2); |
| 958 | videoTranscoder.set_max_audio(max_audio); | 958 | videoTranscoder.set_max_audio(max_audio); |
| 959 | 959 | ||
| 960 | int64_t cur_time = 0; | 960 | int64_t cur_time = 0; |
-
请 注册 或 登录 后发表评论