static int run_test(AVCodec *enc, AVCodec *dec, AVCodecContext *enc_ctx, AVCodecContext *dec_ctx) { AVPacket enc_pkt; AVFrame *in_frame, *out_frame; uint8_t *raw_in = NULL, *raw_out = NULL; int in_offset = 0, out_offset = 0; int result = 0; int got_output = 0; int i = 0; int in_frame_bytes, out_frame_bytes; in_frame = av_frame_alloc(); if (!in_frame) { av_log(NULL, AV_LOG_ERROR, "Can't allocate input frame\n"); return AVERROR(ENOMEM); } in_frame->nb_samples = enc_ctx->frame_size; in_frame->format = enc_ctx->sample_fmt; in_frame->channel_layout = enc_ctx->channel_layout; if (av_frame_get_buffer(in_frame, 32) != 0) { av_log(NULL, AV_LOG_ERROR, "Can't allocate a buffer for input frame\n"); return AVERROR(ENOMEM); } out_frame = av_frame_alloc(); if (!out_frame) { av_log(NULL, AV_LOG_ERROR, "Can't allocate output frame\n"); return AVERROR(ENOMEM); } raw_in = av_malloc(in_frame->linesize[0] * NUMBER_OF_FRAMES); if (!raw_in) { av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for raw_in\n"); return AVERROR(ENOMEM); } raw_out = av_malloc(in_frame->linesize[0] * NUMBER_OF_FRAMES); if (!raw_out) { av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for raw_out\n"); return AVERROR(ENOMEM); } for (i = 0; i < NUMBER_OF_FRAMES; i++) { av_init_packet(&enc_pkt); enc_pkt.data = NULL; enc_pkt.size = 0; generate_raw_frame((uint16_t*)(in_frame->data[0]), i, enc_ctx->sample_rate, enc_ctx->channels, enc_ctx->frame_size); in_frame_bytes = in_frame->nb_samples * av_frame_get_channels(in_frame) * sizeof(uint16_t); if (in_frame_bytes > in_frame->linesize[0]) { av_log(NULL, AV_LOG_ERROR, "Incorrect value of input frame linesize\n"); return 1; } memcpy(raw_in + in_offset, in_frame->data[0], in_frame_bytes); in_offset += in_frame_bytes; result = avcodec_encode_audio2(enc_ctx, &enc_pkt, in_frame, &got_output); if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Error encoding audio frame\n"); return result; } /* if we get an encoded packet, feed it straight to the decoder */ if (got_output) { result = avcodec_decode_audio4(dec_ctx, out_frame, &got_output, &enc_pkt); if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding audio packet\n"); return result; } if (got_output) { if (result != enc_pkt.size) { av_log(NULL, AV_LOG_INFO, "Decoder consumed only part of a packet, it is allowed to do so -- need to update this test\n"); return AVERROR_UNKNOWN; } if (in_frame->nb_samples != out_frame->nb_samples) { av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different number of samples\n"); return AVERROR_UNKNOWN; } if (in_frame->channel_layout != out_frame->channel_layout) { av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different channel layout\n"); return AVERROR_UNKNOWN; } if (in_frame->format != out_frame->format) { av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different sample format\n"); return AVERROR_UNKNOWN; } out_frame_bytes = out_frame->nb_samples * av_frame_get_channels(out_frame) * sizeof(uint16_t); if (out_frame_bytes > out_frame->linesize[0]) { av_log(NULL, AV_LOG_ERROR, "Incorrect value of output frame linesize\n"); return 1; } memcpy(raw_out + out_offset, out_frame->data[0], out_frame_bytes); out_offset += out_frame_bytes; } } av_free_packet(&enc_pkt); } if (memcmp(raw_in, raw_out, out_frame_bytes * NUMBER_OF_FRAMES) != 0) { av_log(NULL, AV_LOG_ERROR, "Output differs\n"); return 1; } av_log(NULL, AV_LOG_INFO, "OK\n"); av_freep(&raw_in); av_freep(&raw_out); av_frame_free(&in_frame); av_frame_free(&out_frame); return 0; }
bool AudioEncoder::EncodeFrame(AVFrameWrapper* frame) { if(frame != NULL) { #if SSR_USE_AVFRAME_NB_SAMPLES assert((unsigned int) frame->GetFrame()->nb_samples == GetFrameSize()); #endif #if SSR_USE_AVFRAME_CHANNELS assert(frame->GetFrame()->channels == GetCodecContext()->channels); #endif #if SSR_USE_AVFRAME_SAMPLE_RATE assert(frame->GetFrame()->sample_rate == GetCodecContext()->sample_rate); #endif #if SSR_USE_AVFRAME_FORMAT assert(frame->GetFrame()->format == GetCodecContext()->sample_fmt); #endif } #if SSR_USE_AVCODEC_SEND_RECEIVE // send a frame AVFrame *avframe = (frame == NULL)? NULL : frame->Release(); try { if(avcodec_send_frame(GetCodecContext(), avframe) < 0) { Logger::LogError("[AudioEncoder::EncodeFrame] " + Logger::tr("Error: Sending of audio frame failed!")); throw LibavException(); } } catch(...) { av_frame_free(&avframe); throw; } av_frame_free(&avframe); // try to receive a packet for( ; ; ) { std::unique_ptr<AVPacketWrapper> packet(new AVPacketWrapper()); int res = avcodec_receive_packet(GetCodecContext(), packet->GetPacket()); if(res == 0) { // we have a packet, send the packet to the muxer GetMuxer()->AddPacket(GetStream()->index, std::move(packet)); IncrementPacketCounter(); } else if(res == AVERROR(EAGAIN)) { // we have no packet return true; } else if(res == AVERROR_EOF) { // this is the end of the stream return false; } else { Logger::LogError("[AudioEncoder::EncodeFrame] " + Logger::tr("Error: Receiving of audio packet failed!")); throw LibavException(); } } #elif SSR_USE_AVCODEC_ENCODE_AUDIO2 // allocate a packet std::unique_ptr<AVPacketWrapper> packet(new AVPacketWrapper()); // encode the frame int got_packet; if(avcodec_encode_audio2(GetCodecContext(), packet->GetPacket(), (frame == NULL)? NULL : frame->GetFrame(), &got_packet) < 0) { Logger::LogError("[AudioEncoder::EncodeFrame] " + Logger::tr("Error: Encoding of audio frame failed!")); throw LibavException(); } // do we have a packet? if(got_packet) { // send the packet to the muxer GetMuxer()->AddPacket(GetStream()->index, std::move(packet)); IncrementPacketCounter(); return true; } else { return false; } #else // encode the frame short *data = (frame == NULL)? NULL : (short*) frame->GetFrame()->data[0]; int bytes_encoded = avcodec_encode_audio(GetCodecContext(), m_temp_buffer.data(), m_temp_buffer.size(), data); if(bytes_encoded < 0) { Logger::LogError("[AudioEncoder::EncodeFrame] " + Logger::tr("Error: Encoding of audio frame failed!")); throw LibavException(); } // do we have a packet? if(bytes_encoded > 0) { // allocate a packet std::unique_ptr<AVPacketWrapper> packet(new AVPacketWrapper(bytes_encoded)); // copy the data memcpy(packet->GetPacket()->data, m_temp_buffer.data(), bytes_encoded); // set the timestamp // note: pts will be rescaled and stream_index will be set by Muxer if(GetCodecContext()->coded_frame != NULL && GetCodecContext()->coded_frame->pts != (int64_t) AV_NOPTS_VALUE) packet->GetPacket()->pts = GetCodecContext()->coded_frame->pts; // send the packet to the muxer GetMuxer()->AddPacket(GetStream()->index, std::move(packet)); IncrementPacketCounter(); return true; } else { return false; } #endif }
AUD_NAMESPACE_BEGIN void FFMPEGWriter::encode() { sample_t* data = m_input_buffer.getBuffer(); if(m_deinterleave) { m_deinterleave_buffer.assureSize(m_input_buffer.getSize()); sample_t* dbuf = m_deinterleave_buffer.getBuffer(); // deinterleave int single_size = sizeof(sample_t); for(int channel = 0; channel < m_specs.channels; channel++) { for(int i = 0; i < m_input_buffer.getSize() / AUD_SAMPLE_SIZE(m_specs); i++) { std::memcpy(((data_t*)dbuf) + (m_input_samples * channel + i) * single_size, ((data_t*)data) + ((m_specs.channels * i) + channel) * single_size, single_size); } } // convert first if(m_input_size) m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(dbuf), m_input_samples * m_specs.channels); else std::memcpy(data, dbuf, m_input_buffer.getSize()); } else // convert first if(m_input_size) m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_samples * m_specs.channels); AVPacket packet; packet.data = nullptr; packet.size = 0; av_init_packet(&packet); AVFrame* frame = av_frame_alloc(); av_frame_unref(frame); int got_packet; frame->nb_samples = m_input_samples; frame->format = m_codecCtx->sample_fmt; frame->channel_layout = m_codecCtx->channel_layout; if(avcodec_fill_audio_frame(frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0) AUD_THROW(FileException, "File couldn't be written, filling the audio frame failed with ffmpeg."); AVRational sample_time = { 1, static_cast<int>(m_specs.rate) }; frame->pts = av_rescale_q(m_position - m_input_samples, m_codecCtx->time_base, sample_time); if(avcodec_encode_audio2(m_codecCtx, &packet, frame, &got_packet)) { av_frame_free(&frame); AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg."); } if(got_packet) { packet.flags |= AV_PKT_FLAG_KEY; packet.stream_index = m_stream->index; if(av_write_frame(m_formatCtx, &packet) < 0) { av_free_packet(&packet); av_frame_free(&frame); AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg."); } av_free_packet(&packet); } av_frame_free(&frame); }
static bool encode_audio(ffmpeg_t *handle, AVPacket *pkt, bool dry) { av_init_packet(pkt); pkt->data = handle->audio.outbuf; pkt->size = handle->audio.outbuf_size; AVFrame *frame = av_frame_alloc(); if (!frame) return false; frame->nb_samples = handle->audio.frames_in_buffer; frame->format = handle->audio.codec->sample_fmt; frame->channel_layout = handle->audio.codec->channel_layout; frame->pts = handle->audio.frame_cnt; planarize_audio(handle); int samples_size = av_samples_get_buffer_size(NULL, handle->audio.codec->channels, handle->audio.frames_in_buffer, handle->audio.codec->sample_fmt, 0); avcodec_fill_audio_frame(frame, handle->audio.codec->channels, handle->audio.codec->sample_fmt, handle->audio.is_planar ? (uint8_t*)handle->audio.planar_buf : handle->audio.buffer, samples_size, 0); int got_packet = 0; if (avcodec_encode_audio2(handle->audio.codec, pkt, dry ? NULL : frame, &got_packet) < 0) { av_frame_free(&frame); return false; } if (!got_packet) { pkt->size = 0; pkt->pts = AV_NOPTS_VALUE; pkt->dts = AV_NOPTS_VALUE; av_frame_free(&frame); return true; } if (pkt->pts != (int64_t)AV_NOPTS_VALUE) { pkt->pts = av_rescale_q(pkt->pts, handle->audio.codec->time_base, handle->muxer.astream->time_base); } if (pkt->dts != (int64_t)AV_NOPTS_VALUE) { pkt->dts = av_rescale_q(pkt->dts, handle->audio.codec->time_base, handle->muxer.astream->time_base); } av_frame_free(&frame); pkt->stream_index = handle->muxer.astream->index; return true; }
MediaRecorder::MediaRecorder(const char * outfile,int width, int height) { audiofailed = false; /* INIT SOUND RECORDING */ debug_samples_out = fopen("audiosamples.s16","wb"); audio_samples_written = 0; pa_context* pactx; pa_mainloop * m = pa_mainloop_new(); m_api = pa_mainloop_get_api(m); pactx = pa_context_new(m_api,"Rec1"); if ( pa_context_connect(pactx,NULL,(pa_context_flags_t)0,NULL) < 0 ) printf("Cannot connect to pulseaudio\n"); int ret; pa_context_set_state_callback(pactx, context_state_callback, this); pa_mainloop_run(m,&ret); std::cout << "Use source: " << monitorsources[defaultsink] << std::endl; static const pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; pa_context_disconnect(pactx); int error; s = pa_simple_new(NULL,"GLCAP Record",PA_STREAM_RECORD,monitorsources[defaultsink].c_str(), "record", &ss, NULL,NULL , &error); if ( !s ) { printf("Cannot create pa_simple\n"); } run = true; ready = false; firstframe = true; this->width = width; this->height = height; pthread_mutex_init(&encode_mutex,NULL); pthread_mutex_init(&sound_buffer_lock,NULL); pthread_cond_init(&encode_cond,NULL); pthread_create(&encode_thread,NULL,(void*(*)(void*))&MediaRecorder::EncodingThread,this); av_log_set_level(AV_LOG_DEBUG); outCtx = avformat_alloc_context(); outCtx->oformat = av_guess_format(NULL, outfile, NULL); snprintf(outCtx->filename, sizeof(outCtx->filename), "%s", outfile); codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4); acodec = avcodec_find_encoder(AV_CODEC_ID_MP2); ctx = avcodec_alloc_context3(codec); actx = avcodec_alloc_context3(acodec); avcodec_get_context_defaults3(actx,acodec); avcodec_get_context_defaults3(ctx,codec); ctx->width = width; ctx->height = height; ctx->bit_rate = 6000*1000; std::cout << ctx->time_base.den << " " << ctx->time_base.num << std::endl; ctx->time_base.den = TIMEBASE; ctx->time_base.num = 1; ctx->thread_count = 4; ctx->qmin = 2; ctx->qmax = 31; ctx->b_sensitivity = 100; ctx->gop_size = 1; ctx->me_method = 1; ctx->global_quality = 100; ctx->lowres = 0; ctx->bit_rate_tolerance = 200000; actx->sample_fmt = AV_SAMPLE_FMT_S16; actx->sample_rate = 44100; actx->channels = 2; actx->time_base.den = 44100; actx->time_base.num = 1; actx->bit_rate = 128000; actx->frame_size = 8192; actx->channel_layout = 3; /* ctx->compression_level = 0; ctx->trellis = 0; ctx->gop_size = 1; /* emit one intra frame every ten frames */ /*ctx->me_pre_cmp = 0; ctx->me_cmp = 0; ctx->me_sub_cmp = 0; ctx->mb_cmp = 2; ctx->pre_dia_size = 0; ctx->dia_size = 1; ctx->quantizer_noise_shaping = 0; // qns=0 ctx->noise_reduction = 0; // nr=0 ctx->mb_decision = 0; // mbd=0 ("realtime" encoding) ctx->flags &= ~CODEC_FLAG_QPEL; ctx->flags &= ~CODEC_FLAG_4MV; ctx->trellis = 0; ctx->flags &= ~CODEC_FLAG_CBP_RD; ctx->flags &= ~CODEC_FLAG_QP_RD; ctx->flags &= ~CODEC_FLAG_MV0;*/ //ctx->s ctx->pix_fmt = PIX_FMT_YUV420P; if (avcodec_open2(ctx, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); } if (avcodec_open2(actx, acodec, NULL) < 0) { fprintf(stderr, "Could not open audio codec\n"); audiofailed = true; } printf("frame_size: %d\n",actx->frame_size); pthread_create(&record_sound_thread,NULL,(void*(*)(void*))&MediaRecorder::RecordingThread,this); AVStream* s = av_new_stream(outCtx,0); s->codec = ctx; s->r_frame_rate.den = TIMEBASE; s->r_frame_rate.num = 1; if (!audiofailed ) { AVStream* as = av_new_stream(outCtx,1); as->codec = actx; as->r_frame_rate.den = 44100; as->r_frame_rate.num = 1; } picture = alloc_picture(PIX_FMT_YUV420P, ctx->width, ctx->height); if (!picture) { fprintf(stderr, "Could not allocate picture\n"); exit(1); } tmp_picture = NULL; tmp_picture = alloc_picture(PIX_FMT_RGBA, ctx->width, ctx->height); if (!tmp_picture) { fprintf(stderr, "Could not allocate temporary picture\n"); exit(1); } img_convert_ctx = sws_getContext(ctx->width, ctx->height, PIX_FMT_RGBA, ctx->width, ctx->height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR , NULL, NULL, NULL); if (img_convert_ctx == NULL) { fprintf(stderr, "Cannot initialize the conversion context\n"); exit(1); } av_dump_format(outCtx, 0, outfile, 1); avio_open2(&outCtx->pb, outfile, AVIO_FLAG_WRITE,NULL,NULL); avformat_write_header(outCtx,NULL); } MediaRecorder::~MediaRecorder() { run = false; ready = false; pthread_cond_broadcast(&encode_cond); printf("Joining thread..\n"); pthread_join(encode_thread,NULL); printf("Joining recording thread..\n"); pthread_join(record_sound_thread,NULL); printf("Done\n"); av_write_trailer(outCtx); av_free(picture); avformat_free_context(outCtx); pa_simple_free(s); fclose(debug_samples_out); } int fcount = 0; void MediaRecorder::AppendFrame(float time, int width, int height, char* data) { if ( !ready ) return ; printf("AppendFrame\n"); this->time = getcurrenttime2(); if ( firstframe ) { starttime = getcurrenttime2(); firstframe = false; } this->height = height; this->width = width; m_data = data; ready = false; pthread_cond_broadcast(&encode_cond); /*int i = 0; unsigned int numpixels = width * height; unsigned int ui = numpixels; unsigned int vi = numpixels + numpixels / 4; for ( int j = 0; j < height; j++ ) { for ( int k = 0; k < width; k++ ) { int sR = data[i*4+0]; int sG = data[i*4+1]; int sB = data[i*4+2]; picture->data[0][i] = ( (66*sR + 129*sG + 25*sB + 128) >> 8) + 16; if (0 == j%2 && 0 == k%2) { picture->data[0][ui++] = ( (-38*sR - 74*sG + 112*sB + 128) >> 8) + 128; picture->data[0][vi++] = ( (112*sR - 94*sG - 18*sB + 128) >> 8) + 128; } i++; } }*/ // printf("End flip %f\n",(float)getcurrenttime2()); //memcpy(tmp_picture->data[0],data,width*height*4); } void MediaRecorder::EncodingThread() { while ( run ) { printf("Encode thread ready\n"); ready = true; pthread_cond_wait(&encode_cond,&encode_mutex); if (!run) { printf("Encoding finished\n"); break; } for ( int y = 0; y < height; y++ ) { /*for ( int x = 0; x < width; x++ ) {*/ char r,g,b; int oldindex = (y*width); int newindex = ((height-1-y)*width); memcpy(&tmp_picture->data[0][(newindex)*4],&m_data[oldindex*4],width*4); /* r = data[oldindex*4+0]; g = data[oldindex*4+1]; b = data[oldindex*4+2]; tmp_picture->data[0][(newindex)*4+0] = r; tmp_picture->data[0][(newindex)*4+1] = g; tmp_picture->data[0][(newindex)*4+2] = b; */ // } } sws_scale(img_convert_ctx,tmp_picture->data,tmp_picture->linesize,0,height,picture->data,picture->linesize); AVPacket p; av_init_packet(&p); p.data = NULL; p.size = 0; picture->pts = int64_t((time-starttime)*TIMEBASE); uint64_t vpts = picture->pts; // picture->pts = time*30.0; int got_frame; printf("%p %p\n",ctx, picture); if(avcodec_encode_video2(ctx, &p, picture, &got_frame) < 0) return; if(got_frame) { // outContainer is "mp4" p.pts = vpts; p.dts = AV_NOPTS_VALUE; av_write_frame(outCtx, &p); av_free_packet(&p); } //sleep(1); printf("End enc frame %f, pts %lld\n",(float)getcurrenttime2(),picture->pts); AVFrame * aframe = avcodec_alloc_frame(); bool unlocked = false; while ( sound_buffers.size() > 0 ) { uint64_t apts = audio_samples_written; /* if ( apts > vpts ) break;*/ pthread_mutex_lock(&sound_buffer_lock); short * buf = sound_buffers.front(); sound_buffers.pop_front(); pthread_mutex_unlock(&sound_buffer_lock); if (!audiofailed ) { unlocked = true; aframe->nb_samples = actx->frame_size; aframe->channel_layout = actx->channel_layout; aframe->format = AV_SAMPLE_FMT_S16; aframe->channels = actx->channels; avcodec_fill_audio_frame(aframe,actx->channels,AV_SAMPLE_FMT_S16,(char*)buf,actx->frame_size*2*2,0); // avcodec_fill_audio_frame(aframe,actx->channels,actx->sample_fmt,(char*)buf,actx->frame_size*2,0); printf("sound_buffers.size() = %d\n",sound_buffers.size()); av_init_packet(&p); p.data = NULL; p.size = 0; avcodec_encode_audio2(actx,&p,aframe,&got_frame); if ( got_frame ) { p.stream_index = 1; p.flags |= AV_PKT_FLAG_KEY; av_write_frame(outCtx,&p); av_free_packet(&p); } audio_samples_written += actx->frame_size;//samples/2 each channel } //printf("Consumed 1024 samples\n"); delete[] buf; } /* if ( !unlocked ) pthread_mutex_unlock(&sound_buffer_lock);*/ avcodec_free_frame(&aframe); } } bool MediaRecorder::isReady() { return ready; }
int AVFormatWriter::WriteAudioFrame(unsigned char *buf, int fnum, long long &timecode) { #if HAVE_BIGENDIAN bswap_16_buf((short int*) buf, m_audioFrameSize, m_audioChannels); #endif int got_packet = 0; int ret = 0; int samples_per_avframe = m_audioFrameSize * m_audioChannels; int sampleSizeIn = AudioOutputSettings::SampleSize(FORMAT_S16); AudioFormat format = AudioOutputSettings::AVSampleFormatToFormat(m_audioStream->codec->sample_fmt); int sampleSizeOut = AudioOutputSettings::SampleSize(format); AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; if (av_get_packed_sample_fmt(m_audioStream->codec->sample_fmt) == AV_SAMPLE_FMT_FLT) { AudioOutputUtil::toFloat(FORMAT_S16, (void *)m_audioInBuf, (void *)buf, samples_per_avframe * sampleSizeIn); buf = m_audioInBuf; } if (av_sample_fmt_is_planar(m_audioStream->codec->sample_fmt)) { AudioOutputUtil::DeinterleaveSamples(format, m_audioChannels, m_audioInPBuf, buf, samples_per_avframe * sampleSizeOut); // init AVFrame for planar data (input is interleaved) for (int j = 0, jj = 0; j < m_audioChannels; j++, jj += m_audioFrameSize) { m_audPicture->data[j] = (uint8_t*)(m_audioInPBuf + jj * sampleSizeOut); } } else { m_audPicture->data[0] = buf; } m_audPicture->linesize[0] = m_audioFrameSize; m_audPicture->nb_samples = m_audioFrameSize; m_audPicture->format = m_audioStream->codec->sample_fmt; m_audPicture->extended_data = m_audPicture->data; m_bufferedAudioFrameTimes.push_back(timecode); { QMutexLocker locker(avcodeclock); ret = avcodec_encode_audio2(m_audioStream->codec, &pkt, m_audPicture, &got_packet); } if (ret < 0) { LOG(VB_RECORD, LOG_ERR, "avcodec_encode_audio2() failed"); return ret; } if (!got_packet) { //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): Frame Buffered: cs: %1, mfw: %2, f->tc: %3, fn: %4").arg(m_audPkt->size).arg(m_framesWritten).arg(timecode).arg(fnum)); return ret; } long long tc = timecode; if (m_bufferedAudioFrameTimes.size()) tc = m_bufferedAudioFrameTimes.takeFirst(); if (m_startingTimecodeOffset == -1) m_startingTimecodeOffset = tc - 1; tc -= m_startingTimecodeOffset; if (m_avVideoCodec) pkt.pts = tc * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000; else pkt.pts = tc * m_audioStream->time_base.den / m_audioStream->time_base.num / 1000; pkt.dts = AV_NOPTS_VALUE; pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = m_audioStream->index; //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5, f->tc: %6").arg(m_audPkt->size).arg(m_framesWritten).arg(m_audPkt->pts).arg(tc).arg(fnum).arg(timecode)); ret = av_interleaved_write_frame(m_ctx, &pkt); if (ret != 0) LOG(VB_RECORD, LOG_ERR, LOC + "WriteAudioFrame(): " "av_interleaved_write_frame couldn't write Audio"); timecode = tc + m_startingTimecodeOffset; av_free_packet(&pkt); return 1; }
void Movie::EncodeAudio(bool last) { AVStream *astream = av->fmt_ctx->streams[av->audio_stream_idx]; AVCodecContext *acodec = astream->codec; av_fifo_generic_write(av->audio_fifo, &audiobuf[0], audiobuf.size(), NULL); // bps: bytes per sample int channels = acodec->channels; int read_bps = 2; int write_bps = av_get_bytes_per_sample(acodec->sample_fmt); int max_read = acodec->frame_size * read_bps * channels; int min_read = last ? read_bps * channels : max_read; while (av_fifo_size(av->audio_fifo) >= min_read) { int read_bytes = MIN(av_fifo_size(av->audio_fifo), max_read); av_fifo_generic_read(av->audio_fifo, av->audio_data, read_bytes, NULL); // convert int read_samples = read_bytes / (read_bps * channels); int write_samples = read_samples; if (read_samples < acodec->frame_size) { // shrink or pad audio frame if (acodec->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) acodec->frame_size = write_samples; else write_samples = acodec->frame_size; } convert_audio(read_samples, acodec->channels, -1, AV_SAMPLE_FMT_S16, av->audio_data, write_samples, acodec->channels, write_samples * write_bps, acodec->sample_fmt, av->audio_data_conv); #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) avcodec_get_frame_defaults(av->audio_frame); #else av_frame_unref(av->audio_frame); #endif av->audio_frame->nb_samples = write_samples; av->audio_frame->pts = av_rescale_q(av->audio_counter, (AVRational){1, acodec->sample_rate}, acodec->time_base); av->audio_counter += write_samples; int asize = avcodec_fill_audio_frame(av->audio_frame, acodec->channels, acodec->sample_fmt, av->audio_data_conv, write_samples * write_bps * channels, 1); if (asize >= 0) { AVPacket pkt; memset(&pkt, 0, sizeof(AVPacket)); av_init_packet(&pkt); int got_pkt = 0; if (0 == avcodec_encode_audio2(acodec, &pkt, av->audio_frame, &got_pkt) && got_pkt) { if (pkt.pts != AV_NOPTS_VALUE && pkt.pts < pkt.dts) pkt.pts = pkt.dts; if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(pkt.pts, acodec->time_base, astream->time_base); if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(pkt.dts, acodec->time_base, astream->time_base); pkt.duration = av_rescale_q(pkt.duration, acodec->time_base, astream->time_base); pkt.stream_index = astream->index; av_interleaved_write_frame(av->fmt_ctx, &pkt); av_free_packet(&pkt); } } } if (last) { bool done = false; while (!done) { AVPacket pkt; memset(&pkt, 0, sizeof(AVPacket)); av_init_packet(&pkt); int got_pkt = 0; if (0 == avcodec_encode_audio2(acodec, &pkt, NULL, &got_pkt) && got_pkt) { if (pkt.pts != AV_NOPTS_VALUE && pkt.pts < pkt.dts) pkt.pts = pkt.dts; if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(pkt.pts, acodec->time_base, astream->time_base); if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(pkt.dts, acodec->time_base, astream->time_base); pkt.duration = av_rescale_q(pkt.duration, acodec->time_base, astream->time_base); pkt.stream_index = astream->index; av_interleaved_write_frame(av->fmt_ctx, &pkt); av_free_packet(&pkt); } else { done = true; } } } }
static void write_audio_frame(AVFormatContext *oc, AVStream *st) { AVCodecContext *c; AVPacket pkt = { 0 }; // data and size must be 0; int got_packet, ret, dst_nb_samples; av_init_packet(&pkt); c = st->codec; get_audio_frame((int16_t *)src_samples_data[0], src_nb_samples, c->channels); /* convert samples from native format to destination codec format, using the resampler */ if (swr_ctx) { /* compute destination number of samples */ dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + src_nb_samples, c->sample_rate, c->sample_rate, AV_ROUND_UP); if (dst_nb_samples > max_dst_nb_samples) { av_free(dst_samples_data[0]); ret = av_samples_alloc(dst_samples_data, &dst_samples_linesize, c->channels, dst_nb_samples, c->sample_fmt, 0); if (ret < 0) exit(1); max_dst_nb_samples = dst_nb_samples; dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, dst_nb_samples, c->sample_fmt, 0); } /* convert to destination format */ ret = swr_convert(swr_ctx, dst_samples_data, dst_nb_samples, (const uint8_t **)src_samples_data, src_nb_samples); if (ret < 0) { fprintf(stderr, "Error while converting\n"); exit(1); } } else { dst_nb_samples = src_nb_samples; } audio_frame->nb_samples = dst_nb_samples; audio_frame->pts = av_rescale_q(samples_count, (AVRational){1, c->sample_rate}, c->time_base); avcodec_fill_audio_frame(audio_frame, c->channels, c->sample_fmt, dst_samples_data[0], dst_samples_size, 0); samples_count += dst_nb_samples; ret = avcodec_encode_audio2(c, &pkt, audio_frame, &got_packet); if (ret < 0) { fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); exit(1); } if (!got_packet) return; /* rescale output packet timestamp values from codec to stream timebase */ pkt.pts = av_rescale_q_rnd(pkt.pts, c->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.dts = av_rescale_q_rnd(pkt.dts, c->time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.duration = av_rescale_q(pkt.duration, c->time_base, st->time_base); pkt.stream_index = st->index; /* Write the compressed frame to the media file. */ ret = av_interleaved_write_frame(oc, &pkt); if (ret != 0) { fprintf(stderr, "Error while writing audio frame: %s\n", av_err2str(ret)); exit(1); } }
int udpsocket::ts_demux(void) { AVCodec *pVideoCodec[VIDEO_NUM]; AVCodec *pAudioCodec[AUDIO_NUM]; AVCodecContext *pVideoCodecCtx[VIDEO_NUM]; AVCodecContext *pAudioCodecCtx[AUDIO_NUM]; AVIOContext * pb; AVInputFormat *piFmt; AVFormatContext *pFmt; uint8_t *buffer; int videoindex[VIDEO_NUM]; int audioindex[AUDIO_NUM]; AVStream *pVst[VIDEO_NUM]; AVStream *pAst[AUDIO_NUM]; AVFrame *pVideoframe[VIDEO_NUM]; AVFrame *pAudioframe[AUDIO_NUM]; AVFrame *pOutAudioframe[AUDIO_NUM]; AVFrame *pOutAudioframelast[AUDIO_NUM]; AVPacket pkt; int got_picture; int video_num[VIDEO_NUM]; int audio_num[AUDIO_NUM]; int frame_size; //transcodepool transcodepool* pVideoTransPool[VIDEO_NUM]; transcodepool* pAudioTransPool[AUDIO_NUM]; for( int i=0; i<VIDEO_NUM; i++ ){ pVideoCodec[i] = NULL; pVideoCodecCtx[i] =NULL; videoindex[i] = -1; pVst[i] = NULL; video_num[i] = 0; pVideoframe[i] = NULL; pVideoframe[i] = av_frame_alloc(); pVideoTransPool[i] = NULL; } for( int i=0; i<AUDIO_NUM; i++ ){ pAudioCodec[i] = NULL; pAudioCodecCtx[i] = NULL; audioindex[i] = -1; pAst[i] = NULL; audio_num[i] = 0; pOutAudioframe[i] = NULL; pOutAudioframe[i] = av_frame_alloc(); pOutAudioframelast[i] = NULL; pOutAudioframelast[i] = av_frame_alloc(); pAudioframe[i] = NULL; pAudioframe[i] = av_frame_alloc(); pAudioTransPool[i] = NULL; } pb = NULL; piFmt = NULL; pFmt = NULL; buffer = (uint8_t*)av_mallocz(sizeof(uint8_t)*BUFFER_SIZE); got_picture = 0; frame_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2; //encoder AVFormatContext *ofmt_ctx = NULL; AVPacket enc_pkt; AVStream *out_stream; AVCodecContext *enc_ctx; AVCodec *encoder; AVFormatContext *outAudioFormatCtx[AUDIO_NUM]; AVPacket audio_pkt; AVStream *audio_stream[AUDIO_NUM]; AVCodecContext *AudioEncodeCtx[AUDIO_NUM]; AVCodec *AudioEncoder[AUDIO_NUM]; fp_v = fopen("OUT.h264","wb+"); //输出文件 fp_a = fopen("audio_out.aac","wb+"); //FFMPEG av_register_all(); pb = avio_alloc_context(buffer, 4096, 0, NULL, read_data, NULL, NULL); // printf("thread %d pid %lu tid %lu\n",index,(unsigned long)getpid(),(unsigned long)pthread_self()); if (!pb) { fprintf(stderr, "avio alloc failed!\n"); return -1; } int x = av_probe_input_buffer(pb, &piFmt, "", NULL, 0, 0); if (x < 0) { printf("probe error: %d",x); // fprintf(stderr, "probe failed!\n"); } else { fprintf(stdout, "probe success!\n"); fprintf(stdout, "format: %s[%s]\n", piFmt->name, piFmt->long_name); } pFmt = avformat_alloc_context(); pFmt->pb = pb; if (avformat_open_input(&pFmt, "", piFmt, NULL) < 0) { fprintf(stderr, "avformat open failed.\n"); return -1; } else { fprintf(stdout, "open stream success!\n"); } //pFmt->probesize = 4096 * 2000; //pFmt->max_analyze_duration = 5 * AV_TIME_BASE; //pFmt->probesize = 2048; // pFmt->max_analyze_duration = 1000; pFmt->probesize = 2048 * 1000 ; pFmt->max_analyze_duration = 2048 * 1000; if (avformat_find_stream_info(pFmt,0) < 0) { fprintf(stderr, "could not fine stream.\n"); return -1; } printf("dump format\n"); av_dump_format(pFmt, 0, "", 0); int videox = 0,audiox = 0; for (int i = 0; i < pFmt->nb_streams; i++) { if(videox == 7 && audiox == 7) break; if ( pFmt->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videox < 7 ) { videoindex[ videox++ ] = i; } if ( pFmt->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audiox < 7 ) { audioindex[ audiox++ ] = i; } } for(int i=0; i<VIDEO_NUM; i++) printf("videoindex %d = %d, audioindex %d = %d\n",i , videoindex[i], i ,audioindex[i]); if (videoindex[6] < 0 || audioindex[6] < 0) { fprintf(stderr, "videoindex=%d, audioindex=%d\n", videoindex[6], audioindex[6]); return -1; } for( int i=0; i<VIDEO_NUM; i++ ){ pVst[i] = pFmt->streams[videoindex[i]]; pVideoCodecCtx[i] = pVst[i]->codec; pVideoCodec[i] = avcodec_find_decoder(pVideoCodecCtx[i]->codec_id); if (!pVideoCodec[i]) { fprintf(stderr, "could not find video decoder!\n"); return -1; } if (avcodec_open2(pVideoCodecCtx[i], pVideoCodec[i], NULL) < 0) { fprintf(stderr, "could not open video codec!\n"); return -1; } } for( int i=0; i<AUDIO_NUM; i++ ){ pAst[i] = pFmt->streams[audioindex[i]]; pAudioCodecCtx[i] = pAst[i]->codec; pAudioCodec[i] = avcodec_find_decoder(pAudioCodecCtx[i]->codec_id); if (!pAudioCodec[i]) { fprintf(stderr, "could not find audio decoder!\n"); return -1; } if (avcodec_open2(pAudioCodecCtx[i], pAudioCodec[i], NULL) < 0) { fprintf(stderr, "could not open audio codec!\n"); return -1; } } //video encoder init avformat_alloc_output_context2(&ofmt_ctx, NULL, "h264", NULL); unsigned char* outbuffer = NULL; outbuffer = (unsigned char*)av_malloc(1024*1000); AVIOContext *avio_out = NULL; avio_out = avio_alloc_context(outbuffer, 1024*1000, 0, NULL, NULL, write_buffer,NULL); if(avio_out == NULL){ printf("avio_out error\n"); return -1; } ofmt_ctx->pb = avio_out; ofmt_ctx->flags = AVFMT_FLAG_CUSTOM_IO; out_stream = avformat_new_stream(ofmt_ctx, NULL); if(!out_stream){ av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n"); return -1; } enc_ctx = out_stream->codec; encoder = avcodec_find_encoder(AV_CODEC_ID_H264); enc_ctx->height = pVideoCodecCtx[0]->height; enc_ctx->width = pVideoCodecCtx[0]->width; enc_ctx->sample_aspect_ratio = pVideoCodecCtx[0]->sample_aspect_ratio; enc_ctx->pix_fmt = encoder->pix_fmts[0]; out_stream->time_base = pVst[0]->time_base; // out_stream->time_base.num = 1; // out_stream->time_base.den = 25; enc_ctx->me_range = 16; enc_ctx->max_qdiff = 4; enc_ctx->qmin = 25; enc_ctx->qmax = 40; enc_ctx->qcompress = 0.6; enc_ctx->refs = 3; enc_ctx->bit_rate = 1000000; int re = avcodec_open2(enc_ctx, encoder, NULL); if (re < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream \n"); return re; } if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; re = avformat_write_header(ofmt_ctx, NULL); if(re < 0){ av_log(NULL, AV_LOG_ERROR, "Error occured when opening output file\n"); return re; } //audio encoder for( int i=0; i<AUDIO_NUM; i++){ outAudioFormatCtx[i] = NULL; // audio_pkt = NULL; audio_stream[i] = NULL; AudioEncodeCtx[i] = NULL; AudioEncoder[i] = NULL; } const char* out_audio_file = "transcodeaudio.aac"; //Output URL //Method 1. outAudioFormatCtx[0] = avformat_alloc_context(); outAudioFormatCtx[0]->oformat = av_guess_format(NULL, out_audio_file, NULL); AVIOContext *avio_audio_out = NULL; avio_audio_out = avio_alloc_context(outbuffer, 1024*1000, 0, NULL, NULL, write_buffer,NULL); if(avio_audio_out == NULL){ printf("avio_out error\n"); return -1; } outAudioFormatCtx[0]->pb = avio_audio_out; //Method 2. //avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file); //fmt = pFormatCtx->oformat; //Open output URL if (avio_open(&outAudioFormatCtx[0]->pb,out_audio_file, AVIO_FLAG_READ_WRITE) < 0){ printf("Failed to open output file!\n"); return -1; } //Show some information av_dump_format(outAudioFormatCtx[0], 0, out_audio_file, 1); AudioEncoder[0] = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!AudioEncoder[0]){ printf("Can not find encoder!\n"); return -1; } audio_stream[0] = avformat_new_stream(outAudioFormatCtx[0], AudioEncoder[0]); if (audio_stream[0]==NULL){ return -1; } AudioEncodeCtx[0] = audio_stream[0]->codec; AudioEncodeCtx[0]->codec_id = outAudioFormatCtx[0]->oformat->audio_codec; AudioEncodeCtx[0]->codec_type = AVMEDIA_TYPE_AUDIO; AudioEncodeCtx[0]->sample_fmt = AV_SAMPLE_FMT_S16; AudioEncodeCtx[0]->sample_rate= 48000;//44100 AudioEncodeCtx[0]->channel_layout=AV_CH_LAYOUT_STEREO; AudioEncodeCtx[0]->channels = av_get_channel_layout_nb_channels(AudioEncodeCtx[0]->channel_layout); AudioEncodeCtx[0]->bit_rate = 64000;//64000 /** Allow the use of the experimental AAC encoder */ AudioEncodeCtx[0]->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /** Set the sample rate for the container. */ audio_stream[0]->time_base.den = pAudioCodecCtx[0]->sample_rate; audio_stream[0]->time_base.num = 1; if (avcodec_open2(AudioEncodeCtx[0], AudioEncoder[0],NULL) < 0){ printf("Failed to open encoder!\n"); return -1; } av_samples_get_buffer_size(NULL, AudioEncodeCtx[0]->channels,AudioEncodeCtx[0]->frame_size,AudioEncodeCtx[0]->sample_fmt, 1); //uint8_t samples[AVCODEC_MAX_AUDIO_FRAME_SIZE*3/2]; av_init_packet(&pkt); av_init_packet(&audio_pkt); av_init_packet(&enc_pkt); AVAudioFifo *af = NULL; SwrContext *resample_context = NULL; long long pts = 0; /** Initialize the resampler to be able to convert audio sample formats. */ // if (init_resampler(input_codec_context, output_codec_context, // &resample_context)) for(int i=0; i<1; i++){ printf("work \n"); printf(" samplerate input = %d , samplerate output = %d\n",pAudioCodecCtx[i]->sample_rate, AudioEncodeCtx[i]->sample_rate); resample_context = swr_alloc_set_opts(NULL, av_get_default_channel_layout(AudioEncodeCtx[i]->channels), AudioEncodeCtx[i]->sample_fmt, AudioEncodeCtx[i]->sample_rate, av_get_default_channel_layout(pAudioCodecCtx[i]->channels), pAudioCodecCtx[i]->sample_fmt, pAudioCodecCtx[i]->sample_rate, 0, NULL); swr_init(resample_context); } af = av_audio_fifo_alloc(AudioEncodeCtx[0]->sample_fmt, AudioEncodeCtx[0]->channels, 1); if(af == NULL) { printf("error af \n"); return -1; } while(1) { if (av_read_frame(pFmt, &pkt) >= 0) { for( int i=0; i<1; i++ ){ if (pkt.stream_index == videoindex[i]) { // av_frame_free(&pframe); avcodec_decode_video2(pVideoCodecCtx[i], pVideoframe[i], &got_picture, &pkt); if (got_picture) { if(videoindex[i] == 0){ // m_tsRecvPool->write_buffer(pkt.data, pkt.size); pVideoframe[i]->pts = av_frame_get_best_effort_timestamp(pVideoframe[i]); pVideoframe[i]->pict_type = AV_PICTURE_TYPE_NONE; // printf("videoframesize0 = %d, size1 = %d, size2 = %d, size3 = %d, size4 = %d,format = %d\n",pVideoframe[i]->linesize[0], // pVideoframe[i]->linesize[1],pVideoframe[i]->linesize[2],pVideoframe[i]->linesize[3],pVideoframe[i]->linesize[4],pVideoframe[i]->format); // pVideoTransPool[i]->PutFrame( pVideoframe[i] ,i); int enc_got_frame = 0; /* ffmpeg encoder */ enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); re = avcodec_encode_video2(ofmt_ctx->streams[videoindex[i]]->codec, &enc_pkt, pVideoframe[i], &enc_got_frame); // printf("enc_got_frame =%d, re = %d \n",enc_got_frame, re); printf("video Encode 1 Packet\tsize:%d\tpts:%lld\n",enc_pkt.size,enc_pkt.pts); /* prepare packet for muxing */ // fwrite(enc_pkt.data,enc_pkt.size, 1, fp_v); } // printf(" video %d decode %d num\n", i, video_num[i]++); break; } }else if (pkt.stream_index == audioindex[i]) { if (avcodec_decode_audio4(pAudioCodecCtx[i], pAudioframe[i], &frame_size, &pkt) >= 0) { if (i == 0){ // fwrite(pAudioframe[i]->data[0],pAudioframe[i]->linesize[0], 1, fp_a); // printf("index = %d audio %d decode %d num\n", index, i, audio_num[i]++); uint8_t *converted_input_samples = NULL; converted_input_samples = (uint8_t *)calloc(AudioEncodeCtx[i]->channels, sizeof(*converted_input_samples)); av_samples_alloc(&converted_input_samples, NULL, AudioEncodeCtx[i]->channels, pAudioframe[i]->nb_samples, AudioEncodeCtx[i]->sample_fmt, 0); int error = 0; if((error = swr_convert(resample_context, &converted_input_samples, pAudioframe[i]->nb_samples, (const uint8_t**)pAudioframe[i]->extended_data, pAudioframe[i]->nb_samples))<0){ printf("error : %d\n",error); } // av_audio_fifo_realloc(af, av_audio_fifo_size(af) + pAudioframe[i]->nb_samples); av_audio_fifo_write(af, (void **)&converted_input_samples, pAudioframe[i]->nb_samples); // fwrite(pkt.data,pkt.size, 1, fp_a); // pAudioframe[i]->data[0] = frame_buf; // init_converted_samples(&converted_input_samples, output_codec_context, pAudioframe[i]->nb_samples); /** Initialize temporary storage for one output frame. */ // printf("pkt.size = %d , pkt.pts = %d ,pkt.dts = %d\n",pkt.size, pkt.pts, pkt.dts); // printf("framesize = %d, audioframesize = %d\n", pAudioframe[i]->nb_samples, frame_size); // pOutAudioframe[i]->pict_type = AV_PICTURE_TYPE_NONE; int got_frame=0; //Encode // av_init_packet(&audio_pkt); // audio_pkt.data = NULL; // audio_pkt.size = 0; // avcodec_encode_audio2(AudioEncodeCtx[0], &audio_pkt, pOutAudioframe[i], &got_frame); // printf("Encode 1 Packet\tsize:%d\tpts:%lld\n", audio_pkt.size, audio_pkt.pts); while(av_audio_fifo_size(af) >= AudioEncodeCtx[i]->frame_size){ int frame_size = FFMIN(av_audio_fifo_size(af),AudioEncodeCtx[0]->frame_size); pOutAudioframe[i]->nb_samples = frame_size; pOutAudioframe[i]->channel_layout = AudioEncodeCtx[0]->channel_layout; pOutAudioframe[i]->sample_rate = AudioEncodeCtx[0]->sample_rate; pOutAudioframe[i]->format = AudioEncodeCtx[0]->sample_fmt; av_frame_get_buffer(pOutAudioframe[i], 0); av_audio_fifo_read(af, (void **)&pOutAudioframe[i]->data, frame_size); pOutAudioframe[i]->pts=pts; pts += pOutAudioframe[i]->nb_samples; audio_pkt.data = NULL; audio_pkt.size = 0; av_init_packet(&audio_pkt); avcodec_encode_audio2(AudioEncodeCtx[0], &audio_pkt, pOutAudioframe[i], &got_frame); printf("audio Encode 1 Packet\tsize:%d\tpts:%lld\n", audio_pkt.size, audio_pkt.pts); fwrite(audio_pkt.data,audio_pkt.size, 1, fp_a); } } // if(i == 0){ // fwrite(pkt.data,pkt.size, 1, fp_a); // } // printf("index = %d audio %d decode %d num\n", index, i, audio_num[i]++); break; } } } av_free_packet(&pkt); av_free_packet(&enc_pkt); } } av_free(buffer); for(int i=0; i<VIDEO_NUM; i++) av_free(pVideoframe[i]); for(int i=0; i<AUDIO_NUM; i++) av_free(pAudioframe[i]); return 0; }
void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right) { struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream; if (!encoder->context || !encoder->audioCodec) { return; } encoder->audioBuffer[encoder->currentAudioSample * 2] = left; encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right; ++encoder->currentAudioFrame; ++encoder->currentAudioSample; if ((encoder->currentAudioSample * 4) < encoder->audioBufferSize) { return; } encoder->currentAudioSample = 0; int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt); avresample_convert(encoder->resampleContext, 0, 0, 0, (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4); if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) { return; } #if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_make_writable(encoder->audioFrame); #endif avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize); AVRational timeBase = { 1, PREFERRED_SAMPLE_RATE }; encoder->audioFrame->pts = encoder->nextAudioPts; encoder->nextAudioPts = av_rescale_q(encoder->currentAudioFrame, timeBase, encoder->audioStream->time_base); AVPacket packet; av_init_packet(&packet); packet.data = 0; packet.size = 0; int gotData; #ifdef FFMPEG_USE_PACKETS avcodec_send_frame(encoder->audio, encoder->audioFrame); gotData = avcodec_receive_packet(encoder->audio, &packet) == 0; #else avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData); #endif if (gotData) { if (encoder->absf) { AVPacket tempPacket = packet; #ifdef FFMPEG_USE_NEW_BSF int success = av_bsf_send_packet(encoder->absf, &packet) && av_bsf_receive_packet(encoder->absf, &packet); #else int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0, &tempPacket.data, &tempPacket.size, packet.data, packet.size, 0); #endif if (success > 0) { #if LIBAVUTIL_VERSION_MAJOR >= 53 tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0); #endif #ifdef FFMPEG_USE_PACKET_UNREF av_packet_unref(&packet); #else av_free_packet(&packet); #endif } packet = tempPacket; } packet.stream_index = encoder->audioStream->index; av_interleaved_write_frame(encoder->context, &packet); } #ifdef FFMPEG_USE_PACKET_UNREF av_packet_unref(&packet); #else av_free_packet(&packet); #endif }
static int encode_audio(AVCodecContext *avctx, AVPacket *pkt, int16_t *audio_samples, int nb_samples) { int i, ch, buffer_size, ret, got_output = 0; void *samples = NULL; AVFrame *frame = NULL; if (audio_samples) { frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); frame->nb_samples = nb_samples; frame->format = avctx->sample_fmt; #if !defined(DISABLE_DYNAMIC_LOADING_FFMPEG) || (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 13, 0)) frame->channel_layout = avctx->channel_layout; #endif buffer_size = av_samples_get_buffer_size(NULL, avctx->channels, frame->nb_samples, avctx->sample_fmt, 0); if (buffer_size < 0) { wxMessageBox(wxString::Format(_("FFmpeg : ERROR - Could not get sample buffer size")), _("FFmpeg Error"), wxOK|wxCENTER|wxICON_EXCLAMATION); return buffer_size; } samples = av_malloc(buffer_size); if (!samples) { wxMessageBox(wxString::Format(_("FFmpeg : ERROR - Could not allocate bytes for samples buffer")), _("FFmpeg Error"), wxOK|wxCENTER|wxICON_EXCLAMATION); return AVERROR(ENOMEM); } /* setup the data pointers in the AVFrame */ ret = avcodec_fill_audio_frame(frame, avctx->channels, avctx->sample_fmt, (const uint8_t*)samples, buffer_size, 0); if (ret < 0) { wxMessageBox(wxString::Format(_("FFmpeg : ERROR - Could not setup audio frame")), _("FFmpeg Error"), wxOK|wxCENTER|wxICON_EXCLAMATION); return ret; } for (ch = 0; ch < avctx->channels; ch++) { for (i = 0; i < frame->nb_samples; i++) { switch(avctx->sample_fmt) { case AV_SAMPLE_FMT_U8: ((uint8_t*)(frame->data[0]))[ch + i*avctx->channels] = audio_samples[ch + i*avctx->channels]/258 + 128; break; case AV_SAMPLE_FMT_U8P: ((uint8_t*)(frame->data[ch]))[i] = audio_samples[ch + i*avctx->channels]/258 + 128; break; case AV_SAMPLE_FMT_S16: ((int16_t*)(frame->data[0]))[ch + i*avctx->channels] = audio_samples[ch + i*avctx->channels]; break; case AV_SAMPLE_FMT_S16P: ((int16_t*)(frame->data[ch]))[i] = audio_samples[ch + i*avctx->channels]; break; case AV_SAMPLE_FMT_S32: ((int32_t*)(frame->data[0]))[ch + i*avctx->channels] = audio_samples[ch + i*avctx->channels]<<16; break; case AV_SAMPLE_FMT_S32P: ((int32_t*)(frame->data[ch]))[i] = audio_samples[ch + i*avctx->channels]<<16; break; case AV_SAMPLE_FMT_FLT: ((float*)(frame->data[0]))[ch + i*avctx->channels] = audio_samples[ch + i*avctx->channels] / 32767.0; break; case AV_SAMPLE_FMT_FLTP: ((float*)(frame->data[ch]))[i] = audio_samples[ch + i*avctx->channels] / 32767.; break; case AV_SAMPLE_FMT_NONE: case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBLP: case AV_SAMPLE_FMT_NB: wxASSERT(false); break; } } } } av_init_packet(pkt); pkt->data = NULL; // packet data will be allocated by the encoder pkt->size = 0; ret = avcodec_encode_audio2(avctx, pkt, frame, &got_output); if (ret < 0) { wxMessageBox(wxString::Format(_("FFmpeg : ERROR - encoding frame failed")), _("FFmpeg Error"), wxOK|wxCENTER|wxICON_EXCLAMATION); return ret; } pkt->dts = pkt->pts = AV_NOPTS_VALUE; // we dont set frame.pts thus dont trust the AVPacket ts av_frame_free(&frame); av_freep(&samples); return got_output; }
static void encode_audio_and_write(struct ao *ao, AVFrame *frame) { // TODO: Can we unify this with the equivalent video code path? struct priv *ac = ao->priv; AVPacket packet = {0}; #if HAVE_AVCODEC_NEW_CODEC_API int status = avcodec_send_frame(ac->codec, frame); if (status < 0) { MP_ERR(ao, "error encoding at %d %d/%d\n", frame ? (int) frame->pts : -1, ac->codec->time_base.num, ac->codec->time_base.den); return; } for (;;) { av_init_packet(&packet); status = avcodec_receive_packet(ac->codec, &packet); if (status == AVERROR(EAGAIN)) { // No more packets for now. if (frame == NULL) { MP_ERR(ao, "sent flush frame, got EAGAIN"); } break; } if (status == AVERROR_EOF) { // No more packets, ever. if (frame != NULL) { MP_ERR(ao, "sent audio frame, got EOF"); } break; } if (status < 0) { MP_ERR(ao, "error encoding at %d %d/%d\n", frame ? (int) frame->pts : -1, ac->codec->time_base.num, ac->codec->time_base.den); break; } if (frame) { if (ac->savepts == AV_NOPTS_VALUE) ac->savepts = frame->pts; } encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec); write_packet(ao, &packet); av_packet_unref(&packet); } #else av_init_packet(&packet); int got_packet = 0; int status = avcodec_encode_audio2(ac->codec, &packet, frame, &got_packet); if (status < 0) { MP_ERR(ao, "error encoding at %d %d/%d\n", frame ? (int) frame->pts : -1, ac->codec->time_base.num, ac->codec->time_base.den); return; } if (!got_packet) { return; } if (frame) { if (ac->savepts == AV_NOPTS_VALUE) ac->savepts = frame->pts; } encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec); write_packet(ao, &packet); av_packet_unref(&packet); #endif }
int main(int argc, char* argv[]) { AVFormatContext *ifmt_ctx = NULL; AVFormatContext *ifmt_ctx_a = NULL; AVFormatContext *ofmt_ctx; AVInputFormat* ifmt; AVStream* video_st; AVStream* audio_st; AVCodecContext* pCodecCtx; AVCodecContext* pCodecCtx_a; AVCodec* pCodec; AVCodec* pCodec_a; AVPacket *dec_pkt, enc_pkt; AVPacket *dec_pkt_a, enc_pkt_a; AVFrame *pframe, *pFrameYUV; struct SwsContext *img_convert_ctx; struct SwrContext *aud_convert_ctx; char capture_name[80] = { 0 }; char device_name[80] = { 0 }; char device_name_a[80] = { 0 }; int framecnt = 0; int nb_samples = 0; int videoindex; int audioindex; int i; int ret; HANDLE hThread; const char* out_path = "rtmp://localhost/live/livestream"; int dec_got_frame, enc_got_frame; int dec_got_frame_a, enc_got_frame_a; int aud_next_pts = 0; int vid_next_pts = 0; int encode_video = 1, encode_audio = 1; AVRational time_base_q = { 1, AV_TIME_BASE }; av_register_all(); //Register Device avdevice_register_all(); avformat_network_init(); #if USEFILTER //Register Filter avfilter_register_all(); buffersrc = avfilter_get_by_name("buffer"); buffersink = avfilter_get_by_name("buffersink"); #endif //Show Dshow Device show_dshow_device(); printf("\nChoose video capture device: "); if (gets(capture_name) == 0) { printf("Error in gets()\n"); return -1; } sprintf(device_name, "video=%s", capture_name); printf("\nChoose audio capture device: "); if (gets(capture_name) == 0) { printf("Error in gets()\n"); return -1; } sprintf(device_name_a, "audio=%s", capture_name); //wchar_t *cam = L"video=Integrated Camera"; //wchar_t *cam = L"video=YY伴侣"; //char *device_name_utf8 = dup_wchar_to_utf8(cam); //wchar_t *cam_a = L"audio=麦克风阵列 (Realtek High Definition Audio)"; //char *device_name_utf8_a = dup_wchar_to_utf8(cam_a); ifmt = av_find_input_format("dshow"); // Set device params AVDictionary *device_param = 0; //if not setting rtbufsize, error messages will be shown in cmd, but you can still watch or record the stream correctly in most time //setting rtbufsize will erase those error messages, however, larger rtbufsize will bring latency //av_dict_set(&device_param, "rtbufsize", "10M", 0); //Set own video device's name if (avformat_open_input(&ifmt_ctx, device_name, ifmt, &device_param) != 0){ printf("Couldn't open input video stream.(无法打开输入流)\n"); return -1; } //Set own audio device's name if (avformat_open_input(&ifmt_ctx_a, device_name_a, ifmt, &device_param) != 0){ printf("Couldn't open input audio stream.(无法打开输入流)\n"); return -1; } //input video initialize if (avformat_find_stream_info(ifmt_ctx, NULL) < 0) { printf("Couldn't find video stream information.(无法获取流信息)\n"); return -1; } videoindex = -1; for (i = 0; i < ifmt_ctx->nb_streams; i++) if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoindex = i; break; } if (videoindex == -1) { printf("Couldn't find a video stream.(没有找到视频流)\n"); return -1; } if (avcodec_open2(ifmt_ctx->streams[videoindex]->codec, avcodec_find_decoder(ifmt_ctx->streams[videoindex]->codec->codec_id), NULL) < 0) { printf("Could not open video codec.(无法打开解码器)\n"); return -1; } //input audio initialize if (avformat_find_stream_info(ifmt_ctx_a, NULL) < 0) { printf("Couldn't find audio stream information.(无法获取流信息)\n"); return -1; } audioindex = -1; for (i = 0; i < ifmt_ctx_a->nb_streams; i++) if (ifmt_ctx_a->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioindex = i; break; } if (audioindex == -1) { printf("Couldn't find a audio stream.(没有找到视频流)\n"); return -1; } if (avcodec_open2(ifmt_ctx_a->streams[audioindex]->codec, avcodec_find_decoder(ifmt_ctx_a->streams[audioindex]->codec->codec_id), NULL) < 0) { printf("Could not open audio codec.(无法打开解码器)\n"); return -1; } //output initialize avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_path); //output video encoder initialize pCodec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!pCodec){ printf("Can not find output video encoder! (没有找到合适的编码器!)\n"); return -1; } pCodecCtx = avcodec_alloc_context3(pCodec); pCodecCtx->pix_fmt = PIX_FMT_YUV420P; pCodecCtx->width = ifmt_ctx->streams[videoindex]->codec->width; pCodecCtx->height = ifmt_ctx->streams[videoindex]->codec->height; pCodecCtx->time_base.num = 1; pCodecCtx->time_base.den = 25; pCodecCtx->bit_rate = 300000; pCodecCtx->gop_size = 250; /* Some formats want stream headers to be separate. */ if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; //H264 codec param //pCodecCtx->me_range = 16; //pCodecCtx->max_qdiff = 4; //pCodecCtx->qcompress = 0.6; pCodecCtx->qmin = 10; pCodecCtx->qmax = 51; //Optional Param pCodecCtx->max_b_frames = 0; // Set H264 preset and tune AVDictionary *param = 0; av_dict_set(¶m, "preset", "fast", 0); av_dict_set(¶m, "tune", "zerolatency", 0); if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0){ printf("Failed to open output video encoder! (编码器打开失败!)\n"); return -1; } //Add a new stream to output,should be called by the user before avformat_write_header() for muxing video_st = avformat_new_stream(ofmt_ctx, pCodec); if (video_st == NULL){ return -1; } video_st->time_base.num = 1; video_st->time_base.den = 25; video_st->codec = pCodecCtx; //output audio encoder initialize pCodec_a = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!pCodec_a){ printf("Can not find output audio encoder! (没有找到合适的编码器!)\n"); return -1; } pCodecCtx_a = avcodec_alloc_context3(pCodec_a); pCodecCtx_a->channels = 2; pCodecCtx_a->channel_layout = av_get_default_channel_layout(2); pCodecCtx_a->sample_rate = ifmt_ctx_a->streams[audioindex]->codec->sample_rate; pCodecCtx_a->sample_fmt = pCodec_a->sample_fmts[0]; pCodecCtx_a->bit_rate = 32000; pCodecCtx_a->time_base.num = 1; pCodecCtx_a->time_base.den = pCodecCtx_a->sample_rate; /** Allow the use of the experimental AAC encoder */ pCodecCtx_a->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; /* Some formats want stream headers to be separate. */ if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) pCodecCtx_a->flags |= CODEC_FLAG_GLOBAL_HEADER; if (avcodec_open2(pCodecCtx_a, pCodec_a, NULL) < 0){ printf("Failed to open ouput audio encoder! (编码器打开失败!)\n"); return -1; } //Add a new stream to output,should be called by the user before avformat_write_header() for muxing audio_st = avformat_new_stream(ofmt_ctx, pCodec_a); if (audio_st == NULL){ return -1; } audio_st->time_base.num = 1; audio_st->time_base.den = pCodecCtx_a->sample_rate; audio_st->codec = pCodecCtx_a; //Open output URL,set before avformat_write_header() for muxing if (avio_open(&ofmt_ctx->pb, out_path, AVIO_FLAG_READ_WRITE) < 0){ printf("Failed to open output file! (输出文件打开失败!)\n"); return -1; } //Show some Information av_dump_format(ofmt_ctx, 0, out_path, 1); //Write File Header avformat_write_header(ofmt_ctx, NULL); //prepare before decode and encode dec_pkt = (AVPacket *)av_malloc(sizeof(AVPacket)); #if USEFILTER #else //camera data may has a pix fmt of RGB or sth else,convert it to YUV420 img_convert_ctx = sws_getContext(ifmt_ctx->streams[videoindex]->codec->width, ifmt_ctx->streams[videoindex]->codec->height, ifmt_ctx->streams[videoindex]->codec->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); // Initialize the resampler to be able to convert audio sample formats aud_convert_ctx = swr_alloc_set_opts(NULL, av_get_default_channel_layout(pCodecCtx_a->channels), pCodecCtx_a->sample_fmt, pCodecCtx_a->sample_rate, av_get_default_channel_layout(ifmt_ctx_a->streams[audioindex]->codec->channels), ifmt_ctx_a->streams[audioindex]->codec->sample_fmt, ifmt_ctx_a->streams[audioindex]->codec->sample_rate, 0, NULL); /** * Perform a sanity check so that the number of converted samples is * not greater than the number of samples to be converted. * If the sample rates differ, this case has to be handled differently */ //av_assert0(pCodecCtx_a->sample_rate == ifmt_ctx_a->streams[audioindex]->codec->sample_rate); swr_init(aud_convert_ctx); #endif //Initialize the buffer to store YUV frames to be encoded. pFrameYUV = av_frame_alloc(); uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)); avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); //Initialize the FIFO buffer to store audio samples to be encoded. AVAudioFifo *fifo = NULL; fifo = av_audio_fifo_alloc(pCodecCtx_a->sample_fmt, pCodecCtx_a->channels, 1); //Initialize the buffer to store converted samples to be encoded. uint8_t **converted_input_samples = NULL; /** * Allocate as many pointers as there are audio channels. * Each pointer will later point to the audio samples of the corresponding * channels (although it may be NULL for interleaved formats). */ if (!(converted_input_samples = (uint8_t**)calloc(pCodecCtx_a->channels, sizeof(**converted_input_samples)))) { printf("Could not allocate converted input sample pointers\n"); return AVERROR(ENOMEM); } printf("\n --------call started----------\n"); #if USEFILTER printf("\n Press differnet number for different filters:"); printf("\n 1->Mirror"); printf("\n 2->Add Watermark"); printf("\n 3->Negate"); printf("\n 4->Draw Edge"); printf("\n 5->Split Into 4"); printf("\n 6->Vintage"); printf("\n Press 0 to remove filter\n"); #endif printf("\nPress enter to stop...\n"); hThread = CreateThread( NULL, // default security attributes 0, // use default stack size MyThreadFunction, // thread function name NULL, // argument to thread function 0, // use default creation flags NULL); // returns the thread identifier //start decode and encode int64_t start_time = av_gettime(); while (encode_video || encode_audio) { if (encode_video && (!encode_audio || av_compare_ts(vid_next_pts, time_base_q, aud_next_pts, time_base_q) <= 0)) { if ((ret=av_read_frame(ifmt_ctx, dec_pkt)) >= 0){ if (exit_thread) break; av_log(NULL, AV_LOG_DEBUG, "Going to reencode the frame\n"); pframe = av_frame_alloc(); if (!pframe) { ret = AVERROR(ENOMEM); return ret; } ret = avcodec_decode_video2(ifmt_ctx->streams[dec_pkt->stream_index]->codec, pframe, &dec_got_frame, dec_pkt); if (ret < 0) { av_frame_free(&pframe); av_log(NULL, AV_LOG_ERROR, "Decoding failed\n"); break; } if (dec_got_frame){ #if USEFILTER pframe->pts = av_frame_get_best_effort_timestamp(pframe); if (filter_change) apply_filters(ifmt_ctx); filter_change = 0; /* push the decoded frame into the filtergraph */ if (av_buffersrc_add_frame(buffersrc_ctx, pframe) < 0) { printf("Error while feeding the filtergraph\n"); break; } picref = av_frame_alloc(); /* pull filtered pictures from the filtergraph */ while (1) { ret = av_buffersink_get_frame_flags(buffersink_ctx, picref, 0); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) return ret; if (picref) { img_convert_ctx = sws_getContext(picref->width, picref->height, (AVPixelFormat)picref->format, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(img_convert_ctx, (const uint8_t* const*)picref->data, picref->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); sws_freeContext(img_convert_ctx); pFrameYUV->width = picref->width; pFrameYUV->height = picref->height; pFrameYUV->format = PIX_FMT_YUV420P; #else sws_scale(img_convert_ctx, (const uint8_t* const*)pframe->data, pframe->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); pFrameYUV->width = pframe->width; pFrameYUV->height = pframe->height; pFrameYUV->format = PIX_FMT_YUV420P; #endif enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); ret = avcodec_encode_video2(pCodecCtx, &enc_pkt, pFrameYUV, &enc_got_frame); av_frame_free(&pframe); if (enc_got_frame == 1){ //printf("Succeed to encode frame: %5d\tsize:%5d\n", framecnt, enc_pkt.size); framecnt++; enc_pkt.stream_index = video_st->index; //Write PTS AVRational time_base = ofmt_ctx->streams[0]->time_base;//{ 1, 1000 }; AVRational r_framerate1 = ifmt_ctx->streams[videoindex]->r_frame_rate;//{ 50, 2 }; //Duration between 2 frames (us) int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / av_q2d(r_framerate1)); //内部时间戳 //Parameters //enc_pkt.pts = (double)(framecnt*calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base)); enc_pkt.pts = av_rescale_q(framecnt*calc_duration, time_base_q, time_base); enc_pkt.dts = enc_pkt.pts; enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //(double)(calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base)); enc_pkt.pos = -1; //printf("video pts : %d\n", enc_pkt.pts); vid_next_pts=framecnt*calc_duration; //general timebase //Delay int64_t pts_time = av_rescale_q(enc_pkt.pts, time_base, time_base_q); int64_t now_time = av_gettime() - start_time; if ((pts_time > now_time) && ((vid_next_pts + pts_time - now_time)<aud_next_pts)) av_usleep(pts_time - now_time); ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); av_free_packet(&enc_pkt); } #if USEFILTER av_frame_unref(picref); } } #endif } else { av_frame_free(&pframe); } av_free_packet(dec_pkt); } else if (ret == AVERROR_EOF) encode_video = 0; else { printf("Could not read video frame\n"); return ret; } } else { //audio trancoding here const int output_frame_size = pCodecCtx_a->frame_size; if (exit_thread) break; /** * Make sure that there is one frame worth of samples in the FIFO * buffer so that the encoder can do its work. * Since the decoder's and the encoder's frame size may differ, we * need to FIFO buffer to store as many frames worth of input samples * that they make up at least one frame worth of output samples. */ while (av_audio_fifo_size(fifo) < output_frame_size) { /** * Decode one frame worth of audio samples, convert it to the * output sample format and put it into the FIFO buffer. */ AVFrame *input_frame = av_frame_alloc(); if (!input_frame) { ret = AVERROR(ENOMEM); return ret; } /** Decode one frame worth of audio samples. */ /** Packet used for temporary storage. */ AVPacket input_packet; av_init_packet(&input_packet); input_packet.data = NULL; input_packet.size = 0; /** Read one audio frame from the input file into a temporary packet. */ if ((ret = av_read_frame(ifmt_ctx_a, &input_packet)) < 0) { /** If we are at the end of the file, flush the decoder below. */ if (ret == AVERROR_EOF) { encode_audio = 0; } else { printf("Could not read audio frame\n"); return ret; } } /** * Decode the audio frame stored in the temporary packet. * The input audio stream decoder is used to do this. * If we are at the end of the file, pass an empty packet to the decoder * to flush it. */ if ((ret = avcodec_decode_audio4(ifmt_ctx_a->streams[audioindex]->codec, input_frame, &dec_got_frame_a, &input_packet)) < 0) { printf("Could not decode audio frame\n"); return ret; } av_packet_unref(&input_packet); /** If there is decoded data, convert and store it */ if (dec_got_frame_a) { /** * Allocate memory for the samples of all channels in one consecutive * block for convenience. */ if ((ret = av_samples_alloc(converted_input_samples, NULL, pCodecCtx_a->channels, input_frame->nb_samples, pCodecCtx_a->sample_fmt, 0)) < 0) { printf("Could not allocate converted input samples\n"); av_freep(&(*converted_input_samples)[0]); free(*converted_input_samples); return ret; } /** * Convert the input samples to the desired output sample format. * This requires a temporary storage provided by converted_input_samples. */ /** Convert the samples using the resampler. */ if ((ret = swr_convert(aud_convert_ctx, converted_input_samples, input_frame->nb_samples, (const uint8_t**)input_frame->extended_data, input_frame->nb_samples)) < 0) { printf("Could not convert input samples\n"); return ret; } /** Add the converted input samples to the FIFO buffer for later processing. */ /** * Make the FIFO as large as it needs to be to hold both, * the old and the new samples. */ if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + input_frame->nb_samples)) < 0) { printf("Could not reallocate FIFO\n"); return ret; } /** Store the new samples in the FIFO buffer. */ if (av_audio_fifo_write(fifo, (void **)converted_input_samples, input_frame->nb_samples) < input_frame->nb_samples) { printf("Could not write data to FIFO\n"); return AVERROR_EXIT; } } } /** * If we have enough samples for the encoder, we encode them. * At the end of the file, we pass the remaining samples to * the encoder. */ if (av_audio_fifo_size(fifo) >= output_frame_size) /** * Take one frame worth of audio samples from the FIFO buffer, * encode it and write it to the output file. */ { /** Temporary storage of the output samples of the frame written to the file. */ AVFrame *output_frame=av_frame_alloc(); if (!output_frame) { ret = AVERROR(ENOMEM); return ret; } /** * Use the maximum number of possible samples per frame. * If there is less than the maximum possible frame size in the FIFO * buffer use this number. Otherwise, use the maximum possible frame size */ const int frame_size = FFMIN(av_audio_fifo_size(fifo), pCodecCtx_a->frame_size); /** Initialize temporary storage for one output frame. */ /** * Set the frame's parameters, especially its size and format. * av_frame_get_buffer needs this to allocate memory for the * audio samples of the frame. * Default channel layouts based on the number of channels * are assumed for simplicity. */ output_frame->nb_samples = frame_size; output_frame->channel_layout = pCodecCtx_a->channel_layout; output_frame->format = pCodecCtx_a->sample_fmt; output_frame->sample_rate = pCodecCtx_a->sample_rate; /** * Allocate the samples of the created frame. This call will make * sure that the audio frame can hold as many samples as specified. */ if ((ret = av_frame_get_buffer(output_frame, 0)) < 0) { printf("Could not allocate output frame samples\n"); av_frame_free(&output_frame); return ret; } /** * Read as many samples from the FIFO buffer as required to fill the frame. * The samples are stored in the frame temporarily. */ if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) { printf("Could not read data from FIFO\n"); return AVERROR_EXIT; } /** Encode one frame worth of audio samples. */ /** Packet used for temporary storage. */ AVPacket output_packet; av_init_packet(&output_packet); output_packet.data = NULL; output_packet.size = 0; /** Set a timestamp based on the sample rate for the container. */ if (output_frame) { nb_samples += output_frame->nb_samples; } /** * Encode the audio frame and store it in the temporary packet. * The output audio stream encoder is used to do this. */ if ((ret = avcodec_encode_audio2(pCodecCtx_a, &output_packet, output_frame, &enc_got_frame_a)) < 0) { printf("Could not encode frame\n"); av_packet_unref(&output_packet); return ret; } /** Write one audio frame from the temporary packet to the output file. */ if (enc_got_frame_a) { output_packet.stream_index = 1; AVRational time_base = ofmt_ctx->streams[1]->time_base; AVRational r_framerate1 = { ifmt_ctx_a->streams[audioindex]->codec->sample_rate, 1 };// { 44100, 1}; int64_t calc_duration = (double)(AV_TIME_BASE)*(1 / av_q2d(r_framerate1)); //内部时间戳 output_packet.pts = av_rescale_q(nb_samples*calc_duration, time_base_q, time_base); output_packet.dts = output_packet.pts; output_packet.duration = output_frame->nb_samples; //printf("audio pts : %d\n", output_packet.pts); aud_next_pts = nb_samples*calc_duration; int64_t pts_time = av_rescale_q(output_packet.pts, time_base, time_base_q); int64_t now_time = av_gettime() - start_time; if ((pts_time > now_time) && ((aud_next_pts + pts_time - now_time)<vid_next_pts)) av_usleep(pts_time - now_time); if ((ret = av_interleaved_write_frame(ofmt_ctx, &output_packet)) < 0) { printf("Could not write frame\n"); av_packet_unref(&output_packet); return ret; } av_packet_unref(&output_packet); } av_frame_free(&output_frame); } } } //Flush Encoder ret = flush_encoder(ifmt_ctx, ofmt_ctx, 0, framecnt); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } ret = flush_encoder_a(ifmt_ctx_a, ofmt_ctx, 1, nb_samples); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } //Write file trailer av_write_trailer(ofmt_ctx); cleanup: //Clean #if USEFILTER if (filter_graph) avfilter_graph_free(&filter_graph); #endif if (video_st) avcodec_close(video_st->codec); if (audio_st) avcodec_close(audio_st->codec); av_free(out_buffer); if (converted_input_samples) { av_freep(&converted_input_samples[0]); //free(converted_input_samples); } if (fifo) av_audio_fifo_free(fifo); avio_close(ofmt_ctx->pb); avformat_free_context(ifmt_ctx); avformat_free_context(ifmt_ctx_a); avformat_free_context(ofmt_ctx); CloseHandle(hThread); return 0; }
static int write_audio_frame(FFMpegContext *context) { AVCodecContext *c = NULL; AVPacket pkt; AVFrame *frame = NULL; int got_output = 0; c = context->audio_stream->codec; av_init_packet(&pkt); pkt.size = 0; pkt.data = NULL; AUD_Device_read(context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples); context->audio_time += (double) context->audio_input_samples / (double) c->sample_rate; #ifdef FFMPEG_HAVE_ENCODE_AUDIO2 frame = avcodec_alloc_frame(); avcodec_get_frame_defaults(frame); frame->pts = context->audio_time / av_q2d(c->time_base); frame->nb_samples = context->audio_input_samples; frame->format = c->sample_fmt; #ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT frame->channel_layout = c->channel_layout; #endif if (context->audio_deinterleave) { int channel, i; uint8_t *temp; for (channel = 0; channel < c->channels; channel++) { for (i = 0; i < frame->nb_samples; i++) { memcpy(context->audio_deinterleave_buffer + (i + channel * frame->nb_samples) * context->audio_sample_size, context->audio_input_buffer + (c->channels * i + channel) * context->audio_sample_size, context->audio_sample_size); } } temp = context->audio_deinterleave_buffer; context->audio_deinterleave_buffer = context->audio_input_buffer; context->audio_input_buffer = temp; } avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, context->audio_input_buffer, context->audio_input_samples * c->channels * context->audio_sample_size, 1); if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) { // XXX error("Error writing audio packet"); return -1; } if (!got_output) { avcodec_free_frame(&frame); return 0; } #else pkt.size = avcodec_encode_audio(c, context->audio_output_buffer, context->audio_outbuf_size, (short *) context->audio_input_buffer); if (pkt.size < 0) { // XXX error("Error writing audio packet"); return -1; } pkt.data = context->audio_output_buffer; got_output = 1; #endif if (got_output) { if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(pkt.pts, c->time_base, context->audio_stream->time_base); if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(pkt.dts, c->time_base, context->audio_stream->time_base); if (pkt.duration > 0) pkt.duration = av_rescale_q(pkt.duration, c->time_base, context->audio_stream->time_base); pkt.stream_index = context->audio_stream->index; pkt.flags |= AV_PKT_FLAG_KEY; if (av_interleaved_write_frame(context->outfile, &pkt) != 0) { fprintf(stderr, "Error writing audio packet!\n"); if (frame) avcodec_free_frame(&frame); return -1; } av_free_packet(&pkt); } if (frame) avcodec_free_frame(&frame); return 0; }
static void *start_encoder( void *ptr ) { obe_aud_enc_params_t *enc_params = ptr; obe_t *h = enc_params->h; obe_encoder_t *encoder = enc_params->encoder; obe_output_stream_t *stream = enc_params->stream; obe_raw_frame_t *raw_frame; obe_coded_frame_t *coded_frame; void *audio_buf = NULL; int64_t cur_pts = -1, pts_increment; int i, frame_size, ret, got_pkt, num_frames = 0, total_size = 0, audio_buf_len; AVFifoBuffer *out_fifo = NULL; AVAudioResampleContext *avr = NULL; AVPacket pkt; AVCodecContext *codec = NULL; AVFrame *frame = NULL; AVDictionary *opts = NULL; char is_latm[2]; avcodec_register_all(); codec = avcodec_alloc_context3( NULL ); if( !codec ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } for( i = 0; lavc_encoders[i].obe_name != -1; i++ ) { if( lavc_encoders[i].obe_name == stream->stream_format ) break; } if( lavc_encoders[i].obe_name == -1 ) { fprintf( stderr, "[lavc] Could not find encoder1\n" ); goto finish; } AVCodec *enc = avcodec_find_encoder( lavc_encoders[i].lavc_name ); if( !enc ) { fprintf( stderr, "[lavc] Could not find encoder2\n" ); goto finish; } if( enc->sample_fmts[0] == -1 ) { fprintf( stderr, "[lavc] No valid sample formats\n" ); goto finish; } codec->sample_rate = enc_params->sample_rate; codec->bit_rate = stream->bitrate * 1000; codec->sample_fmt = enc->sample_fmts[0]; codec->channels = av_get_channel_layout_nb_channels( stream->channel_layout ); codec->channel_layout = stream->channel_layout; codec->time_base.num = 1; codec->time_base.den = OBE_CLOCK; codec->profile = stream->aac_opts.aac_profile == AAC_HE_V2 ? FF_PROFILE_AAC_HE_V2 : stream->aac_opts.aac_profile == AAC_HE_V1 ? FF_PROFILE_AAC_HE : FF_PROFILE_AAC_LOW; snprintf( is_latm, sizeof(is_latm), "%i", stream->aac_opts.latm_output ); av_dict_set( &opts, "latm", is_latm, 0 ); av_dict_set( &opts, "header_period", "2", 0 ); if( avcodec_open2( codec, enc, &opts ) < 0 ) { fprintf( stderr, "[lavc] Could not open encoder\n" ); goto finish; } avr = avresample_alloc_context(); if( !avr ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } av_opt_set_int( avr, "in_channel_layout", codec->channel_layout, 0 ); av_opt_set_int( avr, "in_sample_fmt", enc_params->input_sample_format, 0 ); av_opt_set_int( avr, "in_sample_rate", enc_params->sample_rate, 0 ); av_opt_set_int( avr, "out_channel_layout", codec->channel_layout, 0 ); av_opt_set_int( avr, "out_sample_fmt", codec->sample_fmt, 0 ); av_opt_set_int( avr, "dither_method", AV_RESAMPLE_DITHER_TRIANGULAR_NS, 0 ); if( avresample_open( avr ) < 0 ) { fprintf( stderr, "Could not open AVResample\n" ); goto finish; } /* The number of samples per E-AC3 frame is unknown until the encoder is ready */ if( stream->stream_format == AUDIO_E_AC_3 || stream->stream_format == AUDIO_AAC ) { pthread_mutex_lock( &encoder->queue.mutex ); encoder->is_ready = 1; encoder->num_samples = codec->frame_size; /* Broadcast because input and muxer can be stuck waiting for encoder */ pthread_cond_broadcast( &encoder->queue.in_cv ); pthread_mutex_unlock( &encoder->queue.mutex ); } frame_size = (double)codec->frame_size * 125 * stream->bitrate * enc_params->frames_per_pes / enc_params->sample_rate; /* NB: libfdk-aac already doubles the frame size appropriately */ pts_increment = (double)codec->frame_size * OBE_CLOCK * enc_params->frames_per_pes / enc_params->sample_rate; out_fifo = av_fifo_alloc( frame_size ); if( !out_fifo ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } audio_buf_len = codec->frame_size * av_get_bytes_per_sample( codec->sample_fmt ) * codec->channels; audio_buf = av_malloc( audio_buf_len ); if( !audio_buf ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } frame = avcodec_alloc_frame(); if( !frame ) { fprintf( stderr, "Could not allocate frame\n" ); goto finish; } while( 1 ) { /* TODO: detect bitrate or channel reconfig */ pthread_mutex_lock( &encoder->queue.mutex ); while( !encoder->queue.size && !encoder->cancel_thread ) pthread_cond_wait( &encoder->queue.in_cv, &encoder->queue.mutex ); if( encoder->cancel_thread ) { pthread_mutex_unlock( &encoder->queue.mutex ); goto finish; } raw_frame = encoder->queue.queue[0]; pthread_mutex_unlock( &encoder->queue.mutex ); if( cur_pts == -1 ) cur_pts = raw_frame->pts; if( avresample_convert( avr, NULL, 0, raw_frame->audio_frame.num_samples, raw_frame->audio_frame.audio_data, raw_frame->audio_frame.linesize, raw_frame->audio_frame.num_samples ) < 0 ) { syslog( LOG_ERR, "[lavc] Sample format conversion failed\n" ); break; } raw_frame->release_data( raw_frame ); raw_frame->release_frame( raw_frame ); remove_from_queue( &encoder->queue ); while( avresample_available( avr ) >= codec->frame_size ) { got_pkt = 0; avcodec_get_frame_defaults( frame ); frame->nb_samples = codec->frame_size; avresample_read( avr, &audio_buf, codec->frame_size ); if( avcodec_fill_audio_frame( frame, codec->channels, codec->sample_fmt, audio_buf, audio_buf_len, 0 ) < 0 ) { syslog( LOG_ERR, "[lavc] Could not fill audio frame\n" ); break; } av_init_packet( &pkt ); pkt.data = NULL; pkt.size = 0; ret = avcodec_encode_audio2( codec, &pkt, frame, &got_pkt ); if( ret < 0 ) { syslog( LOG_ERR, "[lavc] Audio encoding failed\n" ); goto finish; } if( !got_pkt ) continue; total_size += pkt.size; num_frames++; if( av_fifo_realloc2( out_fifo, av_fifo_size( out_fifo ) + pkt.size ) < 0 ) { syslog( LOG_ERR, "Malloc failed\n" ); break; } av_fifo_generic_write( out_fifo, pkt.data, pkt.size, NULL ); obe_free_packet( &pkt ); if( num_frames == enc_params->frames_per_pes ) { coded_frame = new_coded_frame( encoder->output_stream_id, total_size ); if( !coded_frame ) { syslog( LOG_ERR, "Malloc failed\n" ); goto finish; } av_fifo_generic_read( out_fifo, coded_frame->data, total_size, NULL ); coded_frame->pts = cur_pts; coded_frame->random_access = 1; /* Every frame output is a random access point */ add_to_queue( &h->mux_queue, coded_frame ); /* We need to generate PTS because frame sizes have changed */ cur_pts += pts_increment; total_size = num_frames = 0; } } } finish: if( frame ) avcodec_free_frame( &frame ); if( audio_buf ) av_free( audio_buf ); if( out_fifo ) av_fifo_free( out_fifo ); if( avr ) avresample_free( &avr ); if( codec ) { avcodec_close( codec ); av_free( codec ); } free( enc_params ); return NULL; }
static void * test_generator_thread(void *aux) { media_pipe_t *mp = aux; media_buf_t *mb = NULL; event_t *e; media_queue_t *mq = &mp->mp_audio; pcm_sound_t voices[8]; AVFrame *frame = av_frame_alloc(); AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AC3); AVCodecContext *ctx = avcodec_alloc_context3(codec); ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; ctx->sample_rate = 48000; ctx->channel_layout = AV_CH_LAYOUT_5POINT1; if(avcodec_open2(ctx, codec, NULL) < 0) { TRACE(TRACE_ERROR, "audio", "Unable to open encoder"); return NULL; } float *genbuf[8]; for(int i = 0; i < 8; i++) { genbuf[i] = av_malloc(ctx->frame_size * sizeof(float)); frame->data[i] = (void *)genbuf[i]; } frame->nb_samples = ctx->frame_size; media_codec_t *mc = media_codec_create(AV_CODEC_ID_AC3, 0, NULL, NULL, NULL, mp); mp_set_playstatus_by_hold(mp, 0, NULL); mp->mp_audio.mq_stream = 0; mp_configure(mp, 0, MP_BUFFER_NONE, 0, "testsignal"); mp_become_primary(mp); int sample = 0; unpack_speaker_positions(voices); while(1) { if(mb == NULL) { int got_packet; AVPacket pkt = {0}; generator_t *g; switch(signal_type) { case 0: for(int c = 0; c < 8; c++) { int z = ctx->frame_size; if(test_channels[c]) { int j = sample & 0xffff; int to_copy = MIN(ctx->frame_size, (voices[c].samples - j)); if(to_copy < 0) to_copy = 0; for(int i = 0; i < to_copy; i++) { genbuf[c][i] = voices[c].data[j+i] / 32767.0f; } z = ctx->frame_size - to_copy; } memset(genbuf[c] + ctx->frame_size - z, 0, sizeof(float) * z); } sample += ctx->frame_size; goto encode; default: g = &gen_pink_noise; break; case 2: g = &gen_sinewave; break; } for(int i = 0; i < ctx->frame_size; i++) { float x = g(sample); for(int c = 0; c < 8; c++) { genbuf[c][i] = test_channels[c] ? x : 0; } sample++; } encode: av_init_packet(&pkt); int r = avcodec_encode_audio2(ctx, &pkt, frame, &got_packet); if(!r && got_packet) { mb = media_buf_from_avpkt_unlocked(mp, &pkt); av_free_packet(&pkt); } else { sleep(1); } mb->mb_cw = media_codec_ref(mc); mb->mb_data_type = MB_AUDIO; mb->mb_pts = PTS_UNSET; } if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) { mb = NULL; /* Enqueue succeeded */ continue; } if(event_is_type(e, EVENT_EXIT)) { mp_flush(mp, 0); break; } event_release(e); } av_frame_free(&frame); for(int i = 0; i < 8; i++) av_freep(&genbuf[i]); for(int i = 0; i < 8; i++) free(voices[i].data); media_codec_deref(mc); return NULL; }
static hb_buffer_t* Encode(hb_work_object_t *w) { hb_work_private_t *pv = w->private_data; hb_audio_t *audio = w->audio; uint64_t pts, pos; if (hb_list_bytes(pv->list) < pv->input_samples * sizeof(float)) { return NULL; } hb_list_getbytes(pv->list, pv->input_buf, pv->input_samples * sizeof(float), &pts, &pos); // Prepare input frame int out_linesize; int out_size = av_samples_get_buffer_size(&out_linesize, pv->context->channels, pv->samples_per_frame, pv->context->sample_fmt, 1); AVFrame frame = { .nb_samples = pv->samples_per_frame, }; avcodec_fill_audio_frame(&frame, pv->context->channels, pv->context->sample_fmt, pv->output_buf, out_size, 1); if (pv->avresample != NULL) { int in_linesize; av_samples_get_buffer_size(&in_linesize, pv->context->channels, frame.nb_samples, AV_SAMPLE_FMT_FLT, 1); int out_samples = avresample_convert(pv->avresample, frame.extended_data, out_linesize, frame.nb_samples, &pv->input_buf, in_linesize, frame.nb_samples); if (out_samples != pv->samples_per_frame) { // we're not doing sample rate conversion, so this shouldn't happen hb_log("encavcodecaWork: avresample_convert() failed"); return NULL; } } // Libav requires that timebase of audio frames be in sample_rate units frame.pts = pts + (90000 * pos / (sizeof(float) * pv->out_discrete_channels * audio->config.out.samplerate)); frame.pts = av_rescale(frame.pts, pv->context->sample_rate, 90000); // Prepare output packet AVPacket pkt; int got_packet; hb_buffer_t *out = hb_buffer_init(pv->max_output_bytes); av_init_packet(&pkt); pkt.data = out->data; pkt.size = out->alloc; // Encode int ret = avcodec_encode_audio2(pv->context, &pkt, &frame, &got_packet); if (ret < 0) { hb_log("encavcodeca: avcodec_encode_audio failed"); hb_buffer_close(&out); return NULL; } if (got_packet && pkt.size) { out->size = pkt.size; // The output pts from libav is in context->time_base. Convert it back // to our timebase. out->s.start = av_rescale_q(pkt.pts, pv->context->time_base, (AVRational){1, 90000}); out->s.duration = (double)90000 * pv->samples_per_frame / audio->config.out.samplerate; out->s.stop = out->s.start + out->s.duration; out->s.type = AUDIO_BUF; out->s.frametype = HB_FRAME_AUDIO; } else { hb_buffer_close(&out); return Encode(w); } return out; } static hb_buffer_t * Flush( hb_work_object_t * w ) { hb_buffer_t *first, *buf, *last; first = last = buf = Encode( w ); while( buf ) { last = buf; buf->next = Encode( w ); buf = buf->next; } if( last ) { last->next = hb_buffer_init( 0 ); } else { first = hb_buffer_init( 0 ); } return first; }
static int filter_out(struct af_instance *af) { af_ac3enc_t *s = af->priv; if (!s->pending) return 0; AVFrame *frame = av_frame_alloc(); if (!frame) { MP_FATAL(af, "Could not allocate memory \n"); return -1; } int err = -1; AVPacket pkt = {0}; av_init_packet(&pkt); #if HAVE_AVCODEC_NEW_CODEC_API // Send input as long as it wants. while (1) { err = read_input_frame(af, frame); if (err < 0) goto done; if (err == 0) break; err = -1; int lavc_ret = avcodec_send_frame(s->lavc_actx, frame); // On EAGAIN, we're supposed to read remaining output. if (lavc_ret == AVERROR(EAGAIN)) break; if (lavc_ret < 0) { MP_FATAL(af, "Encode failed.\n"); goto done; } s->encoder_buffered += s->input->samples; s->input->samples = 0; } int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt); if (lavc_ret == AVERROR(EAGAIN)) { // Need to buffer more input. err = 0; goto done; } if (lavc_ret < 0) { MP_FATAL(af, "Encode failed.\n"); goto done; } #else err = read_input_frame(af, frame); if (err < 0) goto done; if (err == 0) goto done; err = -1; int ok; int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok); s->input->samples = 0; if (lavc_ret < 0 || !ok) { MP_FATAL(af, "Encode failed.\n"); goto done; } #endif MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", pkt.size, s->pending->samples + s->input->samples); s->encoder_buffered -= AC3_FRAME_SIZE; struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, s->out_samples); if (!out) goto done; mp_audio_copy_attributes(out, s->pending); int frame_size = pkt.size; int header_len = 0; char hdr[8]; if (s->cfg_add_iec61937_header && pkt.size > 5) { int bsmod = pkt.data[5] & 0x7; int len = frame_size; frame_size = AC3_FRAME_SIZE * 2 * 2; header_len = 8; AV_WL16(hdr, 0xF872); // iec 61937 syncword 1 AV_WL16(hdr + 2, 0x4E1F); // iec 61937 syncword 2 hdr[5] = bsmod; // bsmod hdr[4] = 0x01; // data-type ac3 AV_WL16(hdr + 6, len << 3); // number of bits in payload } if (frame_size > out->samples * out->sstride) abort(); char *buf = (char *)out->planes[0]; memcpy(buf, hdr, header_len); memcpy(buf + header_len, pkt.data, pkt.size); memset(buf + header_len + pkt.size, 0, frame_size - (header_len + pkt.size)); swap_16((uint16_t *)(buf + header_len), pkt.size / 2); out->samples = frame_size / out->sstride; af_add_output_frame(af, out); err = 0; done: av_packet_unref(&pkt); av_frame_free(&frame); update_delay(af); return err; }
int main(int argc, char* argv[]) { AVFormatContext* pFormatCtx; AVOutputFormat* fmt; AVStream* audio_st; AVCodecContext* pCodecCtx; AVCodec* pCodec; uint8_t* frame_buf; AVFrame* pFrame; AVPacket pkt; int got_frame=0; int ret=0; int size=0; FILE *in_file=NULL; //Raw PCM data int framenum=1000; //Audio frame number const char* out_file = "tdjm.aac"; //Output URL int i; in_file= fopen("tdjm.pcm", "rb"); av_register_all(); //Method 1. pFormatCtx = avformat_alloc_context(); fmt = av_guess_format(NULL, out_file, NULL); pFormatCtx->oformat = fmt; //Method 2. //avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file); //fmt = pFormatCtx->oformat; //Open output URL if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){ printf("Failed to open output file!\n"); return -1; } audio_st = avformat_new_stream(pFormatCtx, 0); if (audio_st==NULL){ return -1; } pCodecCtx = audio_st->codec; pCodecCtx->codec_id = fmt->audio_codec; pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO; pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; pCodecCtx->sample_rate= 44100; pCodecCtx->channel_layout=AV_CH_LAYOUT_STEREO; pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout); pCodecCtx->bit_rate = 64000; //Show some information av_dump_format(pFormatCtx, 0, out_file, 1); pCodec = avcodec_find_encoder(pCodecCtx->codec_id); if (!pCodec){ printf("Can not find encoder!\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){ printf("Failed to open encoder!\n"); return -1; } pFrame = av_frame_alloc(); pFrame->nb_samples= pCodecCtx->frame_size; pFrame->format= pCodecCtx->sample_fmt; size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1); frame_buf = (uint8_t *)av_malloc(size); avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1); //Write Header avformat_write_header(pFormatCtx,NULL); av_new_packet(&pkt,size); for (i=0; i<framenum; i++){ //Read PCM if (fread(frame_buf, 1, size, in_file) <= 0){ printf("Failed to read raw data! \n"); return -1; }else if(feof(in_file)){ break; } pFrame->data[0] = frame_buf; //PCM Data pFrame->pts=i*100; got_frame=0; //Encode ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame); if(ret < 0){ printf("Failed to encode!\n"); return -1; } if (got_frame==1){ printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size); pkt.stream_index = audio_st->index; ret = av_write_frame(pFormatCtx, &pkt); av_free_packet(&pkt); } } //Flush Encoder ret = flush_encoder(pFormatCtx,0); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } //Write Trailer av_write_trailer(pFormatCtx); //Clean if (audio_st){ avcodec_close(audio_st->codec); av_free(pFrame); av_free(frame_buf); } avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); fclose(in_file); return 0; }
/* * Audio encoding example */ static void audio_encode_example(const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; AVFrame *frame; AVPacket pkt; int i, j, k, ret, got_output; int buffer_size; FILE *f; uint16_t *samples; float t, tincr; printf("Audio encoding\n"); /* find the MP2 encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_MP2); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); /* put sample parameters */ c->bit_rate = 64000; /* check that the encoder supports s16 pcm input */ c->sample_fmt = AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "encoder does not support %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); c->channel_layout = select_channel_layout(codec); c->channels = av_get_channel_layout_nb_channels(c->channel_layout); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "could not open %s\n", filename); exit(1); } /* frame containing input raw audio */ frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; frame->channel_layout = c->channel_layout; /* the codec gives us the frame size, in samples, * we calculate the size of the samples buffer in bytes */ buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, c->sample_fmt, 0); samples = av_malloc(buffer_size); if (!samples) { fprintf(stderr, "could not allocate %d bytes for samples buffer\n", buffer_size); exit(1); } /* setup the data pointers in the AVFrame */ ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (const uint8_t*)samples, buffer_size, 0); if (ret < 0) { fprintf(stderr, "could not setup audio frame\n"); exit(1); } /* encode a single tone sound */ t = 0; tincr = 2 * M_PI * 440.0 / c->sample_rate; for(i=0;i<200;i++) { av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; for (j = 0; j < c->frame_size; j++) { samples[2*j] = (int)(sin(t) * 10000); for (k = 1; k < c->channels; k++) samples[2*j + k] = samples[2*j]; t += tincr; } /* encode the samples */ ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); if (ret < 0) { fprintf(stderr, "error encoding audio frame\n"); exit(1); } if (got_output) { fwrite(pkt.data, 1, pkt.size, f); av_packet_unref(&pkt); } } fclose(f); av_freep(&samples); av_frame_free(&frame); avcodec_close(c); av_free(c); }
/* * Audio encoding example */ static void audio_encode_example(const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; AVFrame *frame; AVPacket pkt; int i, j, k, ret, got_output; int buffer_size; FILE *f; uint16_t *samples; float t, tincr; printf("Encode audio file %s\n", filename); /* find the MP2 encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_MP2); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = 64000; /* check that the encoder supports s16 pcm input */ c->sample_fmt = AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); c->channel_layout = select_channel_layout(codec); c->channels = av_get_channel_layout_nb_channels(c->channel_layout); printf("Channels:%d %d %d\n",c->channels,c->sample_rate,c->channel_layout); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } /* frame containing input raw audio */ frame = avcodec_alloc_frame(); if (!frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; printf("FrameSize:%d\n",c->frame_size); frame->format = c->sample_fmt; frame->channel_layout = c->channel_layout; /* the codec gives us the frame size, in samples, * we calculate the size of the samples buffer in bytes */ buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, c->sample_fmt, 0); samples = (uint16_t *)av_malloc(buffer_size); if (!samples) { fprintf(stderr, "Could not allocate %d bytes for samples buffer\n", buffer_size); exit(1); } /* setup the data pointers in the AVFrame */ ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (const uint8_t*)samples, buffer_size, 0); if (ret < 0) { fprintf(stderr, "Could not setup audio frame\n"); exit(1); } int t1=0; /* encode a single tone sound */ t = 0; tincr = 2 * M_PI * 440.0 / c->sample_rate; for(i=0;i<200;i++) { av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; for (j = 0; j < c->frame_size; j++) { samples[2*j] = (int)(sin(t) * 10000); for (k = 1; k < c->channels; k++) samples[2*j + k] = samples[2*j]; t += tincr; } /* encode the samples */ if(t1==0) { FILE *f=fopen("C:/o11.dump","w"); fwrite(samples,buffer_size,1,f); fclose(f); } ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding audio frame\n"); exit(1); } if (got_output) { if(t1==1000000) { AVFrame *dframe=avcodec_alloc_frame(); avcodec_get_frame_defaults(dframe); AVCodec *decoder=avcodec_find_decoder(AV_CODEC_ID_MP2); AVCodecContext *decodecontext=avcodec_alloc_context3(decoder); avcodec_open2(decodecontext, decoder,NULL); int pic; int ret=avcodec_decode_audio4(decodecontext,dframe,&pic,&pkt); if(ret<0) { printf("Seem f**k\n"); } printf("LINE SIZE:%d<->%d\n",dframe->linesize[0],dframe->nb_samples); FILE *f=fopen("c:/o12.dump","w"); fwrite(dframe->data[0],dframe->linesize[0],1,f); fclose(f); } fwrite(pkt.data, 1, pkt.size, f); av_free_packet(&pkt); } t1++; } /* get the delayed frames */ fclose(f); av_freep(&samples); avcodec_free_frame(&frame); avcodec_close(c); av_free(c); printf("OK"); }
static void write_audio_frame(AVFormatContext *oc, AVStream *st, int flush) { AVCodecContext *c; AVPacket pkt = { 0 }; // data and size must be 0; int got_packet, ret, dst_nb_samples; av_init_packet(&pkt); c = st->codec; if (!flush) { get_audio_frame((int16_t *)src_samples_data[0], src_nb_samples, c->channels); /* convert samples from native format to destination codec format, using the resampler */ if (swr_ctx) { /* compute destination number of samples */ dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, c->sample_rate) + src_nb_samples, c->sample_rate, c->sample_rate, AV_ROUND_UP); if (dst_nb_samples > max_dst_nb_samples) { av_free(dst_samples_data[0]); ret = av_samples_alloc(dst_samples_data, &dst_samples_linesize, c->channels, dst_nb_samples, c->sample_fmt, 0); if (ret < 0) exit(1); max_dst_nb_samples = dst_nb_samples; dst_samples_size = av_samples_get_buffer_size(NULL, c->channels, dst_nb_samples, c->sample_fmt, 0); } /* convert to destination format */ ret = swr_convert(swr_ctx, dst_samples_data, dst_nb_samples, (const uint8_t **)src_samples_data, src_nb_samples); if (ret < 0) { fprintf(stderr, "Error while converting\n"); exit(1); } } else { dst_nb_samples = src_nb_samples; } audio_frame->nb_samples = dst_nb_samples; audio_frame->pts = av_rescale_q(samples_count, (AVRational){1, c->sample_rate}, c->time_base); avcodec_fill_audio_frame(audio_frame, c->channels, c->sample_fmt, dst_samples_data[0], dst_samples_size, 0); samples_count += dst_nb_samples; } ret = avcodec_encode_audio2(c, &pkt, flush ? NULL : audio_frame, &got_packet); if (ret < 0) { fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); exit(1); } if (!got_packet) { if (flush) audio_is_eof = 1; return; } ret = write_frame(oc, &c->time_base, st, &pkt); if (ret < 0) { fprintf(stderr, "Error while writing audio frame: %s\n", av_err2str(ret)); exit(1); } }
static bool encode_audio(ffemu_t *handle, AVPacket *pkt, bool dry) { av_init_packet(pkt); pkt->data = handle->audio.outbuf; pkt->size = handle->audio.outbuf_size; #ifdef HAVE_FFMPEG_AVCODEC_ENCODE_AUDIO2 AVFrame frame; avcodec_get_frame_defaults(&frame); frame.nb_samples = handle->audio.frames_in_buffer; frame.pts = handle->audio.frame_cnt; int samples_size = frame.nb_samples * handle->audio.codec->channels * sizeof(int16_t); avcodec_fill_audio_frame(&frame, handle->audio.codec->channels, handle->audio.codec->sample_fmt, (const uint8_t*)handle->audio.buffer, samples_size, 1); int got_packet = 0; if (avcodec_encode_audio2(handle->audio.codec, pkt, dry ? NULL : &frame, &got_packet) < 0) return false; if (!got_packet) { pkt->size = 0; pkt->pts = AV_NOPTS_VALUE; pkt->dts = AV_NOPTS_VALUE; return true; } if (pkt->pts != (int64_t)AV_NOPTS_VALUE) { pkt->pts = av_rescale_q(pkt->pts, handle->audio.codec->time_base, handle->muxer.astream->time_base); } if (pkt->dts != (int64_t)AV_NOPTS_VALUE) { pkt->dts = av_rescale_q(pkt->dts, handle->audio.codec->time_base, handle->muxer.astream->time_base); } #else if (dry) return false; memset(handle->audio.buffer + handle->audio.frames_in_buffer * handle->audio.codec->channels, 0, (handle->audio.codec->frame_size - handle->audio.frames_in_buffer) * handle->audio.codec->channels * sizeof(int16_t)); int out_size = avcodec_encode_audio(handle->audio.codec, handle->audio.outbuf, handle->audio.outbuf_size, handle->audio.buffer); if (out_size < 0) return false; if (out_size == 0) { pkt->size = 0; return true; } pkt->size = out_size; if (handle->audio.codec->coded_frame->pts != (int64_t)AV_NOPTS_VALUE) { pkt->pts = av_rescale_q(handle->audio.codec->coded_frame->pts, handle->audio.codec->time_base, handle->muxer.astream->time_base); } else pkt->pts = AV_NOPTS_VALUE; if (handle->audio.codec->coded_frame->key_frame) pkt->flags |= AV_PKT_FLAG_KEY; #endif pkt->stream_index = handle->muxer.astream->index; return true; }
/** * encodes raw audio to various encodings like mp3 * @param args it holds various parameters like desired output encoding * @see libav_encode_args */ void audio_encode(libav_encode_args* a) { libav_encode_args& args = *a; avcodec_register_all(); AVCodec *codec; AVCodecContext *c = NULL; AVFrame *frame; AVPacket pkt; int i, j, k, ret, got_output; int max_input_buffer_size = args.input_buffer.periodbuffer->size(); int input_buffer_size = args.initptr < args.termptr ? (args.termptr - args. initptr + 1) : (args.termptr + args.input_buffer.periodbuffer-> size() - args.initptr + 1); FILE *f; uint16_t *samples; float t, tincr; // printf("Encode audio file %s\n", filename); /* find the MP2 encoder */ codec = avcodec_find_encoder(args.codecID); if (!codec) { // fprintf(stderr, "Codec not found\n"); // exit(1); ErrnoExit("Codec not found"); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = args.bitrate; /* check that the encoder supports s16 pcm input */ c->sample_fmt = args.av_smpl_fmt; //AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); c->channel_layout = select_channel_layout(codec); c->channels = av_get_channel_layout_nb_channels(c->channel_layout); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } // f = fopen(filename, "wb"); // if (!f) { // fprintf(stderr, "Could not open %s\n", filename); // exit(1); // } /* frame containing input raw audio */ frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; frame->channel_layout = c->channel_layout; /* the codec gives us the frame size, in samples, * we calculate the size of the samples buffer in bytes */ int computed_buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, c->sample_fmt, 0); samples = (uint16_t*) av_malloc(computed_buffer_size); if (!samples) { fprintf(stderr, "Could not allocate %d bytes for samples buffer\n", computed_buffer_size); exit(1); } /* setup the data pointers in the AVFrame */ if (computed_buffer_size != (*args.input_buffer.periodbuffer)[(args.initptr) % max_input_buffer_size].length) { fp_err(FPOL_LAV, "buffer statement mismatch. Encoder exited"); return; } ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (const uint8_t*) samples, computed_buffer_size, 0); if (ret < 0) { fprintf(stderr, "Could not setup audio frame\n"); exit(1); } /* encode a single tone sound */ // t = 0; //tincr = 2 * M_PI * 440.0 / c->sample_rate; args.output_buffer = (char*) malloc(input_buffer_size * (*args.input_buffer.periodbuffer)[(args.initptr) % max_input_buffer_size].length); args.output_buffer_size = 0; int non_cycled_termptr = args.initptr + input_buffer_size; for (i = args.initptr; i < non_cycled_termptr; i++) { av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; // for (j = 0; j < c->frame_size; j++) { // samples[2 * j] = (int) (sin(t) * 10000); // for (k = 1; k < c->channels; k++) { // samples[2 * j + k] = samples[2 * j]; // } // t += tincr; // } /* setup the data pointers in the AVFrame */ int k = 0; int l = computed_buffer_size / 4; uint16_t* obuffer = (uint16_t*) ((*args.input_buffer.periodbuffer)[i % max_input_buffer_size].period); for (j = 0; j < computed_buffer_size / 2; j++) { samples[k++] = obuffer[j]; j++; samples[l++] = obuffer[j]; } /* encode the samples */ ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding audio frame\n"); exit(1); } if (got_output) { //fwrite(pkt.data, 1, pkt.size, f); //pkt.data[pkt.size] = 0; memcpy(args.output_buffer + args.output_buffer_size, pkt.data, pkt.size); args.output_buffer_size += pkt.size; av_packet_unref(&pkt); } } /* get the delayed frames */ for (got_output = 1; got_output; i++) { ret = avcodec_encode_audio2(c, &pkt, NULL, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); exit(1); } if (got_output) { //fwrite(pkt.data, 1, pkt.size, f); memcpy(args.output_buffer + args.output_buffer_size, pkt.data, pkt.size); args.output_buffer_size += pkt.size; av_packet_unref(&pkt); } } // fclose(f); av_freep(&samples); av_frame_free(&frame); avcodec_close(c); av_free(c); }
void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right) { struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream; if (!encoder->context || !encoder->audioCodec) { return; } if (encoder->absf && !left) { // XXX: AVBSF doesn't like silence. Figure out why. left = 1; } encoder->audioBuffer[encoder->currentAudioSample * 2] = left; encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right; ++encoder->currentAudioSample; if (encoder->currentAudioSample * 4 < encoder->audioBufferSize) { return; } int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt); encoder->currentAudioSample = 0; #ifdef USE_LIBAVRESAMPLE avresample_convert(encoder->resampleContext, 0, 0, 0, (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4); if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) { return; } #if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_make_writable(encoder->audioFrame); #endif int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize); #else #if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_make_writable(encoder->audioFrame); #endif if (swr_get_out_samples(encoder->resampleContext, encoder->audioBufferSize / 4) < encoder->audioFrame->nb_samples) { swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); return; } int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); #endif encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base); encoder->currentAudioFrame += samples; AVPacket packet; av_init_packet(&packet); packet.data = 0; packet.size = 0; packet.pts = encoder->audioFrame->pts; int gotData; #ifdef FFMPEG_USE_PACKETS avcodec_send_frame(encoder->audio, encoder->audioFrame); gotData = avcodec_receive_packet(encoder->audio, &packet); gotData = (gotData == 0) && packet.size; #else avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData); #endif if (gotData) { if (encoder->absf) { AVPacket tempPacket; #ifdef FFMPEG_USE_NEW_BSF int success = av_bsf_send_packet(encoder->absf, &packet); if (success >= 0) { success = av_bsf_receive_packet(encoder->absf, &tempPacket); } #else int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0, &tempPacket.data, &tempPacket.size, packet.data, packet.size, 0); #endif if (success >= 0) { #if LIBAVUTIL_VERSION_MAJOR >= 53 tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0); #endif #ifdef FFMPEG_USE_PACKET_UNREF av_packet_move_ref(&packet, &tempPacket); #else av_free_packet(&packet); packet = tempPacket; #endif packet.stream_index = encoder->audioStream->index; av_interleaved_write_frame(encoder->context, &packet); } } else { packet.stream_index = encoder->audioStream->index; av_interleaved_write_frame(encoder->context, &packet); } } #ifdef FFMPEG_USE_PACKET_UNREF av_packet_unref(&packet); #else av_free_packet(&packet); #endif }
int dc_audio_encoder_encode(AudioOutputFile *audio_output_file, AudioInputData *audio_input_data) { int got_pkt; AVCodecContext *audio_codec_ctx = audio_output_file->codec_ctx; while (av_fifo_size(audio_output_file->fifo) >= audio_output_file->frame_bytes) { #ifdef DC_AUDIO_RESAMPLER uint8_t **data; //mirror AVFrame::data int num_planes_out; #endif Bool resample; av_fifo_generic_read(audio_output_file->fifo, audio_output_file->adata_buf, audio_output_file->frame_bytes, NULL); audio_output_file->aframe->data[0] = audio_output_file->adata_buf; audio_output_file->aframe->linesize[0] = audio_output_file->frame_bytes; audio_output_file->aframe->linesize[1] = 0; av_init_packet(&audio_output_file->packet); audio_output_file->packet.data = NULL; audio_output_file->packet.size = 0; /* * Set PTS (method 1) */ //audio_output_file->aframe->pts = audio_input_data->next_pts; /* * Set PTS (method 2) */ //{ // int64_t now = av_gettime(); // AVRational avr; // avr.num = 1; // avr.den = AV_TIME_BASE; // audio_output_file->aframe->pts = av_rescale_q(now, avr, audio_codec_ctx->time_base); //} resample = (DC_AUDIO_SAMPLE_FORMAT != audio_codec_ctx->sample_fmt || DC_AUDIO_SAMPLE_RATE != audio_codec_ctx->sample_rate || DC_AUDIO_NUM_CHANNELS != audio_codec_ctx->channels || DC_AUDIO_CHANNEL_LAYOUT != audio_codec_ctx->channel_layout); /* Resample if needed */ if (resample) { #ifndef DC_AUDIO_RESAMPLER GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Audio resampling is needed at the encoding stage, but not supported by your version of DashCast. Aborting.\n")); exit(1); #else if (ensure_resampler(audio_output_file, audio_codec_ctx)) { return -1; } data = audio_output_file->aframe->extended_data; if (resample_audio(audio_output_file, audio_codec_ctx, &num_planes_out)) { return -1; } #endif } /* Encode audio */ if (avcodec_encode_audio2(audio_codec_ctx, &audio_output_file->packet, audio_output_file->aframe, &got_pkt) != 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Error while encoding audio.\n")); #ifdef DC_AUDIO_RESAMPLER if (resample) { int i; for (i=0; i<num_planes_out; ++i) { av_free(audio_output_file->aframe->extended_data[i]); } av_free(audio_output_file->aframe->extended_data); audio_output_file->aframe->extended_data = data; } #endif return -1; } #ifdef DC_AUDIO_RESAMPLER if (resample) { int i; for (i=0; i<num_planes_out; ++i) { av_free(audio_output_file->aframe->extended_data[i]); } av_free(audio_output_file->aframe->extended_data); audio_output_file->aframe->extended_data = data; } #endif if (got_pkt) { //audio_output_file->acc_samples += audio_output_file->aframe->nb_samples; return 0; } av_free_packet(&audio_output_file->packet); } return 1; }
static int filter_out(struct af_instance *af) { af_ac3enc_t *s = af->priv; if (!fill_buffer(af)) return 0; // need more input AVFrame *frame = av_frame_alloc(); if (!frame) { MP_FATAL(af, "Could not allocate memory \n"); return -1; } frame->nb_samples = s->in_samples; frame->format = s->lavc_actx->sample_fmt; frame->channel_layout = s->lavc_actx->channel_layout; assert(s->input->num_planes <= AV_NUM_DATA_POINTERS); frame->extended_data = frame->data; for (int n = 0; n < s->input->num_planes; n++) frame->data[n] = s->input->planes[n]; frame->linesize[0] = s->input->samples * s->input->sstride; int ok; int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &s->pkt, frame, &ok); av_frame_free(&frame); s->input->samples = 0; if (lavc_ret < 0 || !ok) { MP_FATAL(af, "Encode failed.\n"); return -1; } MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", s->pkt.size, s->pending->samples); struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, s->out_samples); if (!out) return -1; mp_audio_copy_attributes(out, s->pending); int frame_size = s->pkt.size; int header_len = 0; char hdr[8]; if (s->cfg_add_iec61937_header && s->pkt.size > 5) { int bsmod = s->pkt.data[5] & 0x7; int len = frame_size; frame_size = AC3_FRAME_SIZE * 2 * 2; header_len = 8; AV_WL16(hdr, 0xF872); // iec 61937 syncword 1 AV_WL16(hdr + 2, 0x4E1F); // iec 61937 syncword 2 hdr[5] = bsmod; // bsmod hdr[4] = 0x01; // data-type ac3 AV_WL16(hdr + 6, len << 3); // number of bits in payload } if (frame_size > out->samples * out->sstride) abort(); char *buf = (char *)out->planes[0]; memcpy(buf, hdr, header_len); memcpy(buf + header_len, s->pkt.data, s->pkt.size); memset(buf + header_len + s->pkt.size, 0, frame_size - (header_len + s->pkt.size)); swap_16((uint16_t *)(buf + header_len), s->pkt.size / 2); out->samples = frame_size / out->sstride; af_add_output_frame(af, out); update_delay(af); return 0; }
int AVFormatWriter::WriteAudioFrame(unsigned char *buf, int fnum, long long &timecode) { #if HAVE_BIGENDIAN bswap_16_buf((short int*) buf, m_audioFrameSize, m_audioChannels); #endif int got_packet = 0; int ret = 0; av_init_packet(m_audPkt); if (m_audioStream->codec->sample_fmt == AV_SAMPLE_FMT_FLT) { AudioOutputUtil::toFloat(FORMAT_S16, (void *)m_audioFltBuf, (void *)buf, m_audioFrameSize * 2 * m_audioChannels); m_audPicture->data[0] = (unsigned char *)m_audioFltBuf; } else { m_audPicture->data[0] = buf; } m_audPkt->data = m_audioOutBuf; m_audPkt->size = m_audioOutBufSize; m_audPicture->linesize[0] = m_audioFrameSize; m_audPicture->nb_samples = m_audioFrameSize; m_audPicture->format = m_audioStream->codec->sample_fmt; m_audPicture->extended_data = m_audPicture->data; m_bufferedAudioFrameTimes.push_back(timecode); { QMutexLocker locker(avcodeclock); ret = avcodec_encode_audio2(m_audioStream->codec, m_audPkt, m_audPicture, &got_packet); } if (ret < 0) { LOG(VB_RECORD, LOG_ERR, "avcodec_encode_audio2() failed"); return ret; } if (!got_packet) { //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): Frame Buffered: cs: %1, mfw: %2, f->tc: %3, fn: %4").arg(m_audPkt->size).arg(m_framesWritten).arg(timecode).arg(fnum)); return ret; } long long tc = timecode; if (m_bufferedAudioFrameTimes.size()) tc = m_bufferedAudioFrameTimes.takeFirst(); if (m_startingTimecodeOffset == -1) m_startingTimecodeOffset = tc - 1; tc -= m_startingTimecodeOffset; if (m_avVideoCodec) m_audPkt->pts = tc * m_videoStream->time_base.den / m_videoStream->time_base.num / 1000; else m_audPkt->pts = tc * m_audioStream->time_base.den / m_audioStream->time_base.num / 1000; m_audPkt->dts = AV_NOPTS_VALUE; m_audPkt->flags |= AV_PKT_FLAG_KEY; m_audPkt->stream_index = m_audioStream->index; //LOG(VB_RECORD, LOG_ERR, QString("WriteAudioFrame(): cs: %1, mfw: %2, pkt->pts: %3, tc: %4, fn: %5, f->tc: %6").arg(m_audPkt->size).arg(m_framesWritten).arg(m_audPkt->pts).arg(tc).arg(fnum).arg(timecode)); ret = av_interleaved_write_frame(m_ctx, m_audPkt); if (ret != 0) LOG(VB_RECORD, LOG_ERR, LOC + "WriteAudioFrame(): " "av_interleaved_write_frame couldn't write Audio"); timecode = tc + m_startingTimecodeOffset; return 1; }
void write_audio_frame (GeglProperties *o, AVFormatContext * oc, AVStream * st) { Priv *p = (Priv*)o->user_data; AVCodecContext *c = st->codec; int sample_count = 100000; static AVPacket pkt = { 0 }; if (pkt.size == 0) { av_init_packet (&pkt); } /* first we add incoming frames audio samples */ { int i; int sample_count = gegl_audio_fragment_get_sample_count (o->audio); GeglAudioFragment *af = gegl_audio_fragment_new (gegl_audio_fragment_get_sample_rate (o->audio), gegl_audio_fragment_get_channels (o->audio), gegl_audio_fragment_get_channel_layout (o->audio), sample_count); gegl_audio_fragment_set_sample_count (af, sample_count); for (i = 0; i < sample_count; i++) { af->data[0][i] = o->audio->data[0][i]; af->data[1][i] = o->audio->data[1][i]; } gegl_audio_fragment_set_pos (af, p->audio_pos); p->audio_pos += sample_count; p->audio_track = g_list_append (p->audio_track, af); } if (!(c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) sample_count = c->frame_size; /* then we encode as much as we can in a loop using the codec frame size */ while (p->audio_pos - p->audio_read_pos > sample_count) { long i; int ret; int got_packet = 0; AVFrame *frame = alloc_audio_frame (c->sample_fmt, c->channel_layout, c->sample_rate, sample_count); switch (c->sample_fmt) { case AV_SAMPLE_FMT_FLT: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((float*)frame->data[0])[c->channels*i+0] = left; ((float*)frame->data[0])[c->channels*i+1] = right; } break; case AV_SAMPLE_FMT_FLTP: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((float*)frame->data[0])[i] = left; ((float*)frame->data[1])[i] = right; } break; case AV_SAMPLE_FMT_S16: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int16_t*)frame->data[0])[c->channels*i+0] = left * (1<<15); ((int16_t*)frame->data[0])[c->channels*i+1] = right * (1<<15); } break; case AV_SAMPLE_FMT_S32: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int32_t*)frame->data[0])[c->channels*i+0] = left * (1<<31); ((int32_t*)frame->data[0])[c->channels*i+1] = right * (1<<31); } break; case AV_SAMPLE_FMT_S32P: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int32_t*)frame->data[0])[i] = left * (1<<31); ((int32_t*)frame->data[1])[i] = right * (1<<31); } break; case AV_SAMPLE_FMT_S16P: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int16_t*)frame->data[0])[i] = left * (1<<15); ((int16_t*)frame->data[1])[i] = right * (1<<15); } break; default: fprintf (stderr, "eeeek unhandled audio format\n"); break; } frame->pts = p->next_apts; p->next_apts += sample_count; av_frame_make_writable (frame); ret = avcodec_encode_audio2 (c, &pkt, frame, &got_packet); av_packet_rescale_ts (&pkt, st->codec->time_base, st->time_base); if (ret < 0) { fprintf (stderr, "Error encoding audio frame: %s\n", av_err2str (ret)); } if (got_packet) { pkt.stream_index = st->index; av_interleaved_write_frame (oc, &pkt); av_free_packet (&pkt); } av_frame_free (&frame); p->audio_read_pos += sample_count; } }
// must get exactly ac->aframesize amount of data static int encode(struct ao *ao, double apts, void **data) { AVPacket packet; struct priv *ac = ao->priv; struct encode_lavc_context *ectx = ao->encode_lavc_ctx; double realapts = ac->aframecount * (double) ac->aframesize / ao->samplerate; int status, gotpacket; ac->aframecount++; if (data) ectx->audio_pts_offset = realapts - apts; av_init_packet(&packet); packet.data = ac->buffer; packet.size = ac->buffer_size; if(data) { AVFrame *frame = av_frame_alloc(); frame->format = af_to_avformat(ao->format); frame->nb_samples = ac->aframesize; assert(ao->channels.num <= AV_NUM_DATA_POINTERS); for (int n = 0; n < ao->channels.num; n++) frame->extended_data[n] = data[n]; frame->linesize[0] = frame->nb_samples * ao->sstride; if (ectx->options->rawts || ectx->options->copyts) { // real audio pts frame->pts = floor(apts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5); } else { // audio playback time frame->pts = floor(realapts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5); } int64_t frame_pts = av_rescale_q(frame->pts, ac->stream->codec->time_base, ac->worst_time_base); if (ac->lastpts != MP_NOPTS_VALUE && frame_pts <= ac->lastpts) { // this indicates broken video // (video pts failing to increase fast enough to match audio) MP_WARN(ao, "audio frame pts went backwards (%d <- %d), autofixed\n", (int)frame->pts, (int)ac->lastpts); frame_pts = ac->lastpts + 1; frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->stream->codec->time_base); } ac->lastpts = frame_pts; frame->quality = ac->stream->codec->global_quality; status = avcodec_encode_audio2(ac->stream->codec, &packet, frame, &gotpacket); if (!status) { if (ac->savepts == MP_NOPTS_VALUE) ac->savepts = frame->pts; } av_frame_free(&frame); } else { status = avcodec_encode_audio2(ac->stream->codec, &packet, NULL, &gotpacket); } if(status) { MP_ERR(ao, "error encoding\n"); return -1; } if(!gotpacket) return 0; MP_DBG(ao, "got pts %f (playback time: %f); out size: %d\n", apts, realapts, packet.size); encode_lavc_write_stats(ao->encode_lavc_ctx, ac->stream); packet.stream_index = ac->stream->index; // Do we need this at all? Better be safe than sorry... if (packet.pts == AV_NOPTS_VALUE) { MP_WARN(ao, "encoder lost pts, why?\n"); if (ac->savepts != MP_NOPTS_VALUE) packet.pts = ac->savepts; } if (packet.pts != AV_NOPTS_VALUE) packet.pts = av_rescale_q(packet.pts, ac->stream->codec->time_base, ac->stream->time_base); if (packet.dts != AV_NOPTS_VALUE) packet.dts = av_rescale_q(packet.dts, ac->stream->codec->time_base, ac->stream->time_base); if(packet.duration > 0) packet.duration = av_rescale_q(packet.duration, ac->stream->codec->time_base, ac->stream->time_base); ac->savepts = MP_NOPTS_VALUE; if (encode_lavc_write_frame(ao->encode_lavc_ctx, &packet) < 0) { MP_ERR(ao, "error writing at %f %f/%f\n", realapts, (double) ac->stream->time_base.num, (double) ac->stream->time_base.den); return -1; } return packet.size; }