胡斌

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" {
#define SRC_W 320
#define SRC_H 240
CAVTranscoder::CAVTranscoder():
CAVTranscoder::CAVTranscoder(bool bOne2One):
_start_time(INT64_MAX),
_all_processed(true),
_one2one(true),
_nOutputWidth(320),
_cur_out_v_ts(0),
_cur_out_a_ts(0),
_max_audio(1),
_swsCtx(NULL)
_swsCtx(NULL),
_scaledFrame(NULL)
{
_one2one = bOne2One;
if (_one2one) {
_nOutputHeight = 480;
}
else {
_nOutputHeight = 240;
_swsCtx = sws_getContext(SRC_W, SRC_H, PIX_FMT_YUV420P,
SCALED_W, SCALED_H, PIX_FMT_YUV420P, SWS_BILINEAR,
_swsCtx = sws_getContext(SRC_W, SRC_H, AV_PIX_FMT_YUV420P,
SCALED_W, SCALED_H, AV_PIX_FMT_YUV420P, SWS_BILINEAR,
NULL, NULL, NULL);
_scaledFrame = av_frame_alloc();
_scaledFrame->format = AV_PIX_FMT_YUV420P;
_scaledFrame->width = SCALED_W;
_scaledFrame->height = SCALED_H;
_scaledFrame->pts = 0;
int ret = av_frame_get_buffer(_scaledFrame, 32);
if (ret != 0)
{
printf("Error alloc frame buffer for scaling video frame");
}
}
}
... ... @@ -113,6 +125,10 @@ int CAVTranscoder::close()
sws_freeContext(_swsCtx);
_swsCtx = NULL;
}
if (_scaledFrame) {
av_frame_unref(_scaledFrame);
av_frame_free(&_scaledFrame);
}
flush_encoder(0);
flush_encoder(1);
av_write_trailer(_ofmt_ctx);
... ... @@ -214,7 +230,7 @@ int CAVTranscoder::open_output_file(const char *filename)
enc_ctx->channel_layout = AV_CH_LAYOUT_MONO;
enc_ctx->channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO);
/* take first format from list of supported formats */
enc_ctx->sample_fmt = AV_SAMPLE_FMT_S16; //AV_SAMPLE_FMT_FLTP;
enc_ctx->sample_fmt = PCM_FORMAT_FOR_AAC_ENCODE; //AV_SAMPLE_FMT_FLTP;
enc_ctx->time_base.num = 1;
enc_ctx->time_base.den = enc_ctx->sample_rate;
enc_ctx->bit_rate = 64000;
... ... @@ -264,7 +280,7 @@ int CAVTranscoder::open_output_file(const char *filename)
pDstFrame->nb_samples = 1024;
pDstFrame->channel_layout = AV_CH_LAYOUT_MONO;
pDstFrame->channels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO);
pDstFrame->format = AV_SAMPLE_FMT_S16;
pDstFrame->format = PCM_FORMAT_FOR_AAC_ENCODE;
pDstFrame->sample_rate = 48000;
av_frame_get_buffer(pDstFrame, 0);
... ... @@ -273,8 +289,13 @@ int CAVTranscoder::open_output_file(const char *filename)
for (; it != decoders_got_frame.end(); it++) {
AVFrame * pFrame = (*it)->_cur_a_frame;
if (pFrame) {
#if LIBAVCODEC_VERSION_MAJOR < 58
int16_t * psrc = (int16_t *)pFrame->extended_data[0];
int16_t * pdst = (int16_t *)pDstFrame->extended_data[0];
#else
float * psrc = (float *)pFrame->extended_data[0];
float * pdst = (float *)pDstFrame->extended_data[0];
#endif
for (int i = 0; i < 1024; i++,pdst++,psrc++) {
*pdst += (*psrc/_max_audio);
}
... ... @@ -310,40 +331,42 @@ int CAVTranscoder::open_output_file(const char *filename)
uint8_t *dstbuf = new uint8_t[nDstSize];
avpicture_fill((AVPicture*)pDstFrame, dstbuf, AV_PIX_FMT_YUV420P, _nOutputWidth, _nOutputHeight);
bool fill_pure_color = true;
if (idxTeacher != -1) {
//copy teacher frame to dest frame
CAVDecoder * pDecoder = decoders_got_frame[idxTeacher];
AVFrame * pFrame = pDecoder->_cur_v_frame;
if (pFrame) {
fillDestFrame(pDstFrame, pFrame, 0, 0);
fill_pure_color = false;
pDecoder->free_cur_v_frame();
}
else {//fill with pure color
}
if(fill_pure_color){//fill with pure color
memset(pDstFrame->data[0], 0, _nOutputWidth * _nOutputHeight);
memset(pDstFrame->data[1], 0x80, _nOutputWidth *_nOutputHeight / 4);
memset(pDstFrame->data[2], 0x80, _nOutputWidth * _nOutputHeight / 4);
}
int imageIdx = 0;
for (int i = 0; i < decoders_got_frame.size(); i++){
if (i != idxTeacher) {
//scale eacher frame
//copy each frame to the dest frame
}
CAVDecoder * pDecoder = decoders_got_frame[i];
AVFrame * pFrame = pDecoder->_cur_v_frame;
if (!pFrame) {
continue;
}
int h = sws_scale(_swsCtx, pFrame->data, pFrame->linesize, 0, pFrame->height,
_scaledFrame->data, _scaledFrame->linesize);
if (h <= 0){
printf("scale output 0?");
}
else {
memset(pDstFrame->data[0], 0, _nOutputWidth * _nOutputHeight);
memset(pDstFrame->data[1], 0x80, _nOutputWidth *_nOutputHeight / 4);
memset(pDstFrame->data[2], 0x80, _nOutputWidth * _nOutputHeight / 4);
for (int i = 0; i < decoders_got_frame.size(); i++){
if (i != idxTeacher) {
//scale eacher frame
//copy each frame to the dest frame
}
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);
pDecoder->free_cur_v_frame();
imageIdx++;
}
}
... ... @@ -381,6 +404,19 @@ int CAVTranscoder::open_output_file(const char *filename)
return 0;
}
int CAVTranscoder::fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y, int srcx, int srcy, int w, int h)
{
for (int i = 0; i < h; i++) {
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);
}
for (int i = 0; i < h / 2; i++){
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);
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);
}
return 0;
}
int CAVTranscoder::mix_and_output_one2one_vframe(vector<CAVDecoder *> & decoders_got_frame)
{
//prepare one2one base frame
... ...
... ... @@ -5,7 +5,7 @@
class CAVTranscoder
{
public:
CAVTranscoder();
CAVTranscoder(bool bOne2One);
virtual ~CAVTranscoder();
int add(media_info & info);
... ... @@ -35,12 +35,14 @@ private:
int mix_and_output_one2many_vframe(vector<CAVDecoder *> & decoders_got_frame);
int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int x, int y);
int fillDestFrame(AVFrame * pDstFrame, AVFrame * pSrcFrame, int destx, int desty, int srcx,int srcy,int w,int h);
int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame);
int flush_encoder(unsigned int stream_index);
void * _a_frame_pool;
int _max_audio;
struct SwsContext * _swsCtx;
AVFrame * _scaledFrame;
public:
void set_max_audio(int max_audio);
};
... ...
... ... @@ -123,7 +123,7 @@ int CAudioDecoder::init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,
av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");
goto end;
}
enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16;
enum AVSampleFormat sample_fmt = PCM_FORMAT_FOR_AAC_ENCODE;
ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",
(uint8_t*)&sample_fmt, sizeof(sample_fmt),
AV_OPT_SEARCH_CHILDREN);
... ...
#pragma once
#define __STDC_LIMIT_MACROS
#include <string>
#include <vector>
#include <stdint.h>
... ... @@ -79,3 +79,9 @@ typedef struct FilteringContext {
#define AFRAME_DURATION_MS 21.333333
#define VFRAME_DURATION_MS 50
#if LIBAVCODEC_VERSION_MAJOR < 58
#define PCM_FORMAT_FOR_AAC_ENCODE AV_SAMPLE_FMT_S16
#else
#define PCM_FORMAT_FOR_AAC_ENCODE AV_SAMPLE_FMT_FLTP
#endif
... ...
... ... @@ -954,7 +954,7 @@ int process_av_files()
av_register_all();
avfilter_register_all();
CAVTranscoder videoTranscoder;
CAVTranscoder videoTranscoder(max_audio==2);
videoTranscoder.set_max_audio(max_audio);
int64_t cur_time = 0;
... ...