胡斌

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
@@ -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;