int dc_audio_encoder_open(AudioOutputFile *audio_output_file, AudioDataConf *audio_data_conf) { AVDictionary *opts = NULL; audio_output_file->fifo = av_fifo_alloc(2 * MAX_AUDIO_PACKET_SIZE); audio_output_file->aframe = FF_ALLOC_FRAME(); audio_output_file->adata_buf = (uint8_t*) av_malloc(2 * MAX_AUDIO_PACKET_SIZE); #ifndef GPAC_USE_LIBAV audio_output_file->aframe->channels = -1; #endif #ifndef LIBAV_FRAME_OLD audio_output_file->aframe->channel_layout = 0; audio_output_file->aframe->sample_rate = -1; #endif audio_output_file->aframe->format = -1; audio_output_file->codec = avcodec_find_encoder_by_name(audio_data_conf->codec); if (audio_output_file->codec == NULL) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Output audio codec not found\n")); return -1; } audio_output_file->codec_ctx = avcodec_alloc_context3(audio_output_file->codec); audio_output_file->codec_ctx->codec_id = audio_output_file->codec->id; audio_output_file->codec_ctx->codec_type = AVMEDIA_TYPE_AUDIO; audio_output_file->codec_ctx->bit_rate = audio_data_conf->bitrate; audio_output_file->codec_ctx->sample_rate = DC_AUDIO_SAMPLE_RATE /*audio_data_conf->samplerate*/; { AVRational time_base; time_base.num = 1; time_base.den = audio_output_file->codec_ctx->sample_rate; audio_output_file->codec_ctx->time_base = time_base; } audio_output_file->codec_ctx->channels = audio_data_conf->channels; audio_output_file->codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO; /*FIXME: depends on channels -> http://ffmpeg.org/doxygen/trunk/channel__layout_8c_source.html#l00074*/ audio_output_file->codec_ctx->sample_fmt = audio_output_file->codec->sample_fmts[0]; #ifdef DC_AUDIO_RESAMPLER audio_output_file->aresampler = NULL; #endif if (audio_data_conf->custom) { build_dict(audio_output_file->codec_ctx->priv_data, audio_data_conf->custom); } audio_output_file->astream_idx = 0; /* open the audio codec */ av_dict_set(&opts, "strict", "experimental", 0); if (avcodec_open2(audio_output_file->codec_ctx, audio_output_file->codec, &opts) < 0) { /*FIXME: if we enter here (set "mp2" as a codec and "200000" as a bitrate -> deadlock*/ GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot open output audio codec\n")); av_dict_free(&opts); return -1; } av_dict_free(&opts); audio_output_file->frame_bytes = audio_output_file->codec_ctx->frame_size * av_get_bytes_per_sample(DC_AUDIO_SAMPLE_FORMAT) * DC_AUDIO_NUM_CHANNELS; #ifndef FF_API_AVFRAME_LAVC avcodec_get_frame_defaults(audio_output_file->aframe); #else av_frame_unref(audio_output_file->aframe); #endif audio_output_file->aframe->nb_samples = audio_output_file->codec_ctx->frame_size; if (avcodec_fill_audio_frame(audio_output_file->aframe, audio_output_file->codec_ctx->channels, audio_output_file->codec_ctx->sample_fmt, audio_output_file->adata_buf, audio_output_file->codec_ctx->frame_size * av_get_bytes_per_sample(audio_output_file->codec_ctx->sample_fmt) * audio_output_file->codec_ctx->channels, 1) < 0) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Fill audio frame failed\n")); return -1; } //audio_output_file->acc_samples = 0; return 0; }
int CVideoDecoder2::Init(void) { int ret = -1; while (!bInit){ pQueueMutex = (uv_mutex_t*)malloc(sizeof(uv_mutex_t)); if(!pQueueMutex){ ret = -1; break; } ret = uv_mutex_init(pQueueMutex); if (ret < 0){ free(pQueueMutex); pQueueMutex = NULL; break; } pQueueNotEmpty = (uv_cond_t*)malloc(sizeof(uv_cond_t)); if(!pQueueNotEmpty){ ret = -1; break; } ret = uv_cond_init(pQueueNotEmpty); if (ret < 0){ free(pQueueNotEmpty); pQueueNotEmpty = NULL; break; } // Register all codecs avcodec_register_all(); pCodec = avcodec_find_decoder(codecId); if (!pCodec){ ret = -1; break; } pCodecCtx = avcodec_alloc_context3(pCodec); if (!pCodecCtx){ ret = -1; break; } if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){ ret = -1; break; } pCodecParserCtx = av_parser_init(codecId); if (!pCodecParserCtx){ ret = -1; break; } decodeWorkerReq.data = this; ret = uv_queue_work(pLoop, &decodeWorkerReq, DecodeWorker, AfterDecode); if(ret < 0){ bStop = true; break; } bInit = true; } if (!bInit){ Finit(); return -1; } else { return 0; } }
/** * Loads image data from a file in pnm format. * * @param f file to load * @param image structure to hold loaded image * @param type returns the type of the loaded image */ void loadImage(const char *filename, AVFrame **image) { int ret, got_frame = 0; AVFormatContext *s = NULL; AVCodecContext *avctx = avcodec_alloc_context3(NULL); AVCodec *codec; AVPacket pkt; AVFrame *frame = av_frame_alloc(); char errbuff[1024]; if (!avctx) errOutput("cannot allocate a new context"); ret = avformat_open_input(&s, filename, NULL, NULL); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("unable to open file %s: %s", filename, errbuff); } avformat_find_stream_info(s, NULL); if (verbose >= VERBOSE_MORE) av_dump_format(s, 0, filename, 0); if (s->nb_streams < 1) errOutput("unable to open file %s: missing streams", filename); if (s->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO) errOutput("unable to open file %s: wrong stream", filename); ret = avcodec_copy_context(avctx, s->streams[0]->codec); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("cannot set the new context for %s: %s", filename, errbuff); } codec = avcodec_find_decoder(avctx->codec_id); if (!codec) errOutput("unable to open file %s: unsupported format", filename); ret = avcodec_open2(avctx, codec, NULL); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("unable to open file %s: %s", filename, errbuff); } ret = av_read_frame(s, &pkt); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("unable to open file %s: %s", filename, errbuff); } if (pkt.stream_index != 0) errOutput("unable to open file %s: invalid stream.", filename); ret = avcodec_decode_video2(avctx, frame, &got_frame, &pkt); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("unable to open file %s: %s", filename, errbuff); } switch(frame->format) { case AV_PIX_FMT_Y400A: // 8-bit grayscale PNG case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_RGB24: case AV_PIX_FMT_MONOBLACK: case AV_PIX_FMT_MONOWHITE: *image = av_frame_clone(frame); break; case AV_PIX_FMT_PAL8: initImage(image, frame->width, frame->height, AV_PIX_FMT_RGB24, -1); const uint32_t *palette = (const uint32_t *)frame->data[1]; for (int y = 0; y < frame->height; y++) { for (int x = 0; x < frame->width; x++) { const uint8_t palette_index = frame->data[0][frame->linesize[0]*y + x]; setPixel(palette[palette_index], x, y, *image); } } break; default: errOutput("unable to open file %s: unsupported pixel format", filename); } avcodec_close(avctx); av_free(avctx); avformat_close_input(&s); }
/* * Audio decoding. */ static void audio_decode_example(const char *outfilename, const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int len; FILE *f, *outfile; uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; AVPacket avpkt; AVFrame *decoded_frame = NULL; av_init_packet(&avpkt); printf("Decode audio file %s to %s\n", filename, outfilename); /* find the mpeg audio decoder */ codec = avcodec_find_decoder(AV_CODEC_ID_AAC); 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); } /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } outfile = fopen(outfilename, "wb"); if (!outfile) { av_free(c); exit(1); } /* decode until eof */ avpkt.data = inbuf; avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); while (avpkt.size > 0) { int got_frame = 0; if (!decoded_frame) { if (!(decoded_frame = avcodec_alloc_frame())) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } } else avcodec_get_frame_defaults(decoded_frame); len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); if (len < 0) { fprintf(stderr, "Error while decoding\n"); exit(1); } if (got_frame) { /* if a frame has been decoded, output it */ int data_size = av_samples_get_buffer_size(NULL, c->channels, decoded_frame->nb_samples, c->sample_fmt, 1); fwrite(decoded_frame->data[0], 1, data_size, outfile); } avpkt.size -= len; avpkt.data += len; avpkt.dts = avpkt.pts = AV_NOPTS_VALUE; if (avpkt.size < AUDIO_REFILL_THRESH) { /* Refill the input buffer, to avoid trying to decode * incomplete frames. Instead of this, one could also use * a parser, or use a proper container format through * libavformat. */ memmove(inbuf, avpkt.data, avpkt.size); avpkt.data = inbuf; len = fread(avpkt.data + avpkt.size, 1, AUDIO_INBUF_SIZE - avpkt.size, f); if (len > 0) avpkt.size += len; } } fclose(outfile); fclose(f); avcodec_close(c); av_free(c); avcodec_free_frame(&decoded_frame); }
bool ffmpeg_save_flv::init_flv(std::string session_name, int width, int height) { // find the flv video encoder (for output) set_outer_stream_state(VSTR_OST_STATE_PENDING, ""); #if (LIBAVCODEC_VERSION_MAJOR < 54) flv_codec = avcodec_find_encoder(CODEC_ID_FLV1); #else flv_codec = avcodec_find_encoder(AV_CODEC_ID_FLV1); #endif if (!flv_codec) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "FLV1 Codec not found!", VSTR_OST_ERR_CODEC_NOT_FOUND); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } // allocate flv codec context (for output) flv_codec_context = avcodec_alloc_context3(flv_codec); if (!flv_codec_context) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "Could not allocate video FLV1 codec context!", VSTR_OST_ERR_OPEN_CODEC); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } flv_format_context = avformat_alloc_context(); flv_fmt = av_guess_format("flv", output_filename.c_str(), NULL); flv_format_context->oformat = flv_fmt; flv_stream = avformat_new_stream(flv_format_context, flv_codec); flv_stream->codec = flv_codec_context; flv_codec_context->pix_fmt = pEncodedFormat; flv_codec_context->width = width; flv_codec_context->height = height; flv_codec_context->qmin=2; flv_codec_context->qmax=32; //flv_codec_context->time_base.den = 30; //flv_codec_context->time_base.num = 1; flv_stream->time_base.den = 1000; flv_stream->time_base.num = 1; // add headers and flags for saving flv_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER; av_dump_format(flv_format_context, 0, output_filename.c_str(), 1); int ret = avio_open(&flv_format_context->pb, output_filename.c_str(), AVIO_FLAG_WRITE); if (ret < 0) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "Could not open output.", VSTR_OST_ERR_SEND_DATA); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } ret = avformat_write_header(flv_format_context, NULL); if (ret < 0) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "Could not open output header.", VSTR_OST_ERR_SEND_DATA); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } return true; }
int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *pkt) { uint8_t *dummy_data; int dummy_size; int ret; if (!q->avctx_internal) { q->avctx_internal = avcodec_alloc_context3(NULL); if (!q->avctx_internal) return AVERROR(ENOMEM); if (avctx->extradata) { q->avctx_internal->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!q->avctx_internal->extradata) return AVERROR(ENOMEM); memcpy(q->avctx_internal->extradata, avctx->extradata, avctx->extradata_size); q->avctx_internal->extradata_size = avctx->extradata_size; } q->parser = av_parser_init(avctx->codec_id); if (!q->parser) return AVERROR(ENOMEM); q->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; q->orig_pix_fmt = AV_PIX_FMT_NONE; } if (!pkt->size) return qsv_decode(avctx, q, frame, got_frame, pkt); /* we assume the packets are already split properly and want * just the codec parameters here */ av_parser_parse2(q->parser, q->avctx_internal, &dummy_data, &dummy_size, pkt->data, pkt->size, pkt->pts, pkt->dts, pkt->pos); /* TODO: flush delayed frames on reinit */ if (q->parser->format != q->orig_pix_fmt || q->parser->coded_width != avctx->coded_width || q->parser->coded_height != avctx->coded_height) { enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV, AV_PIX_FMT_NONE, AV_PIX_FMT_NONE }; enum AVPixelFormat qsv_format; qsv_format = ff_qsv_map_pixfmt(q->parser->format); if (qsv_format < 0) { av_log(avctx, AV_LOG_ERROR, "Only 8-bit YUV420 streams are supported.\n"); ret = AVERROR(ENOSYS); goto reinit_fail; } q->orig_pix_fmt = q->parser->format; avctx->pix_fmt = pix_fmts[1] = qsv_format; avctx->width = q->parser->width; avctx->height = q->parser->height; avctx->coded_width = q->parser->coded_width; avctx->coded_height = q->parser->coded_height; avctx->level = q->avctx_internal->level; avctx->profile = q->avctx_internal->profile; ret = ff_get_format(avctx, pix_fmts); if (ret < 0) goto reinit_fail; avctx->pix_fmt = ret; ret = qsv_decode_init(avctx, q); if (ret < 0) goto reinit_fail; } return qsv_decode(avctx, q, frame, got_frame, pkt); reinit_fail: q->orig_pix_fmt = q->parser->format = avctx->pix_fmt = AV_PIX_FMT_NONE; return ret; }
static void jpg_process(MSFilter *f){ JpegWriter *s=(JpegWriter*)f->data; ms_filter_lock(f); if (s->file!=NULL && s->codec!=NULL){ MSPicture yuvbuf, yuvjpeg; mblk_t *m=ms_queue_peek_last(f->inputs[0]); if (ms_yuv_buf_init_from_mblk(&yuvbuf,m)==0){ int error,got_pict; int comp_buf_sz=msgdsize(m); uint8_t *comp_buf=(uint8_t*)ms_malloc0(comp_buf_sz); mblk_t *jpegm; struct SwsContext *sws_ctx; struct AVPacket packet; AVCodecContext *avctx=avcodec_alloc_context3(s->codec); memset(&packet, 0, sizeof(packet)); avctx->width=yuvbuf.w; avctx->height=yuvbuf.h; avctx->time_base.num = 1; avctx->time_base.den =1; avctx->pix_fmt=AV_PIX_FMT_YUVJ420P; error=avcodec_open2(avctx,s->codec,NULL); if (error!=0) { ms_error("avcodec_open() failed: %i",error); cleanup(s,NULL, FALSE); av_free(avctx); goto end; } sws_ctx=sws_getContext(avctx->width,avctx->height,AV_PIX_FMT_YUV420P, avctx->width,avctx->height,avctx->pix_fmt,SWS_FAST_BILINEAR,NULL, NULL, NULL); if (sws_ctx==NULL) { ms_error(" sws_getContext() failed."); cleanup(s,avctx, FALSE); goto end; } jpegm=ms_yuv_buf_alloc (&yuvjpeg,avctx->width, avctx->height); #if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0,9,0) if (sws_scale(sws_ctx,(const uint8_t *const*)yuvbuf.planes,yuvbuf.strides,0,avctx->height,yuvjpeg.planes,yuvjpeg.strides)<0){ #else if (sws_scale(sws_ctx,(uint8_t **)yuvbuf.planes,yuvbuf.strides,0,avctx->height,yuvjpeg.planes,yuvjpeg.strides)<0){ #endif ms_error("sws_scale() failed."); sws_freeContext(sws_ctx); cleanup(s,avctx, FALSE); freemsg(jpegm); goto end; } sws_freeContext(sws_ctx); av_frame_unref(s->pict); avpicture_fill((AVPicture*)s->pict,(uint8_t*)jpegm->b_rptr,avctx->pix_fmt,avctx->width,avctx->height); packet.data=comp_buf; packet.size=comp_buf_sz; error=avcodec_encode_video2(avctx, &packet, s->pict, &got_pict); if (error<0){ ms_error("Could not encode jpeg picture."); }else{ if (fwrite(comp_buf,packet.size,1,s->file)>0){ ms_message("Snapshot done"); }else{ ms_error("Error writing snapshot."); } } ms_free(comp_buf); cleanup(s,avctx, TRUE); freemsg(jpegm); } goto end; } end: ms_filter_unlock(f); ms_queue_flush(f->inputs[0]); } static MSFilterMethod jpg_methods[]={ { MS_JPEG_WRITER_TAKE_SNAPSHOT, take_snapshot }, { 0,NULL} }; #ifndef _MSC_VER MSFilterDesc ms_jpeg_writer_desc={ .id=MS_JPEG_WRITER_ID, .name="MSJpegWriter", .text="Take a video snapshot as jpg file", .category=MS_FILTER_OTHER, .ninputs=1, .noutputs=0, .init=jpg_init, .process=jpg_process, .uninit=jpg_uninit, .methods=jpg_methods }; #else MSFilterDesc ms_jpeg_writer_desc={ MS_JPEG_WRITER_ID, "MSJpegWriter", "Take a video snapshot as jpg file", MS_FILTER_OTHER, NULL, 1, 0, jpg_init, NULL, jpg_process, NULL, jpg_uninit, jpg_methods }; #endif MS_FILTER_DESC_EXPORT(ms_jpeg_writer_desc)
/* * Audio encoding example */ static void audio_encode_example(const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int frame_size, i, j, out_size, outbuf_size; FILE *f; short *samples; float t, tincr; uint8_t *outbuf; printf("Audio encoding\n"); /* find the MP2 encoder */ codec = avcodec_find_encoder(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; c->sample_rate = 44100; c->channels = 2; c->sample_fmt = AV_SAMPLE_FMT_S16; /* open it */ if (avcodec_open(c, codec) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } /* the codec gives us the frame size, in samples */ frame_size = c->frame_size; samples = malloc(frame_size * 2 * c->channels); outbuf_size = 10000; outbuf = malloc(outbuf_size); f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "could not open %s\n", filename); exit(1); } /* encode a single tone sound */ t = 0; tincr = 2 * M_PI * 440.0 / c->sample_rate; for(i=0;i<200;i++) { for(j=0;j<frame_size;j++) { samples[2*j] = (int)(sin(t) * 10000); samples[2*j+1] = samples[2*j]; t += tincr; } /* encode the samples */ out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples); fwrite(outbuf, 1, out_size, f); } fclose(f); free(outbuf); free(samples); avcodec_close(c); av_free(c); }
/* * Video encoding example */ static void video_encode_example(const char *filename, int codec_id) { AVCodec *codec; AVCodecContext *c= NULL; int i, ret, x, y, got_output; FILE *f; AVFrame *frame; AVPacket pkt; uint8_t endcode[] = { 0, 0, 1, 0xb7 }; printf("Encode video file %s\n", filename); /* find the mpeg1 video encoder */ codec = avcodec_find_encoder(codec_id); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate video codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = 400000; /* resolution must be a multiple of two */ c->width = 352; c->height = 288; /* frames per second */ c->time_base= (AVRational){1,25}; c->gop_size = 10; /* emit one intra frame every ten frames */ c->max_b_frames=1; c->pix_fmt = AV_PIX_FMT_YUV420P; if(codec_id == AV_CODEC_ID_H264) av_opt_set(c->priv_data, "preset", "slow", 0); /* 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 = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate video frame\n"); exit(1); } frame->format = c->pix_fmt; frame->width = c->width; frame->height = c->height; /* the image can be allocated by any means and av_image_alloc() is * just the most convenient way if av_malloc() is to be used */ ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32); if (ret < 0) { fprintf(stderr, "Could not allocate raw picture buffer\n"); exit(1); } /* encode 1 second of video */ for(i=0;i<25;i++) { av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; fflush(stdout); /* prepare a dummy image */ /* Y */ for(y=0;y<c->height;y++) { for(x=0;x<c->width;x++) { frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; } } /* Cb and Cr */ for(y=0;y<c->height/2;y++) { for(x=0;x<c->width/2;x++) { frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; } } frame->pts = i; /* encode the image */ ret = avcodec_encode_video2(c, &pkt, frame, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); exit(1); } if (got_output) { printf("Write frame %3d (size=%5d)\n", i, pkt.size); fwrite(pkt.data, 1, pkt.size, f); av_free_packet(&pkt); } } /* get the delayed frames */ for (got_output = 1; got_output; i++) { fflush(stdout); ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); exit(1); } if (got_output) { printf("Write frame %3d (size=%5d)\n", i, pkt.size); fwrite(pkt.data, 1, pkt.size, f); av_free_packet(&pkt); } } /* add sequence end code to have a real mpeg file */ fwrite(endcode, 1, sizeof(endcode), f); fclose(f); avcodec_close(c); av_free(c); av_freep(&frame->data[0]); avcodec_free_frame(&frame); printf("\n"); }
/* * Video encoding example */ static void video_encode_example(const char *filename, int codec_id) { AVCodec *codec; AVCodecContext *c= NULL; int i, out_size, size, x, y, outbuf_size; FILE *f; AVFrame *picture; uint8_t *outbuf; printf("Video encoding\n"); /* find the mpeg1 video encoder */ codec = avcodec_find_encoder(codec_id); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); picture= avcodec_alloc_frame(); /* put sample parameters */ c->bit_rate = 400000; /* resolution must be a multiple of two */ c->width = 352; c->height = 288; /* frames per second */ c->time_base= (AVRational){1,25}; c->gop_size = 10; /* emit one intra frame every ten frames */ c->max_b_frames=1; c->pix_fmt = PIX_FMT_YUV420P; if(codec_id == CODEC_ID_H264) av_opt_set(c->priv_data, "preset", "slow", 0); /* open it */ if (avcodec_open(c, codec) < 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); } /* alloc image and output buffer */ outbuf_size = 100000; outbuf = malloc(outbuf_size); /* the image can be allocated by any means and av_image_alloc() is * just the most convenient way if av_malloc() is to be used */ av_image_alloc(picture->data, picture->linesize, c->width, c->height, c->pix_fmt, 1); /* encode 1 second of video */ for(i=0;i<25;i++) { fflush(stdout); /* prepare a dummy image */ /* Y */ for(y=0;y<c->height;y++) { for(x=0;x<c->width;x++) { picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; } } /* Cb and Cr */ for(y=0;y<c->height/2;y++) { for(x=0;x<c->width/2;x++) { picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2; picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5; } } /* encode the image */ out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); printf("encoding frame %3d (size=%5d)\n", i, out_size); fwrite(outbuf, 1, out_size, f); } /* get the delayed frames */ for(; out_size; i++) { fflush(stdout); out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); printf("write frame %3d (size=%5d)\n", i, out_size); fwrite(outbuf, 1, out_size, f); } /* add sequence end code to have a real mpeg file */ outbuf[0] = 0x00; outbuf[1] = 0x00; outbuf[2] = 0x01; outbuf[3] = 0xb7; fwrite(outbuf, 1, 4, f); fclose(f); free(outbuf); avcodec_close(c); av_free(c); av_free(picture->data[0]); av_free(picture); printf("\n"); }
static void video_decode_example(const char *outfilename, const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int frame, got_picture, len; FILE *f; AVFrame *picture; uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; char buf[1024]; AVPacket avpkt; av_init_packet(&avpkt); /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); printf("Video decoding\n"); /* find the mpeg1 video decoder */ codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); picture= avcodec_alloc_frame(); if(codec->capabilities&CODEC_CAP_TRUNCATED) c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ /* For some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because this information is not available in the bitstream. */ /* open it */ if (avcodec_open(c, codec) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } /* the codec gives us the frame size, in samples */ f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "could not open %s\n", filename); exit(1); } frame = 0; for(;;) { avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); if (avpkt.size == 0) break; /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) and this is the only method to use them because you cannot know the compressed data size before analysing it. BUT some other codecs (msmpeg4, mpeg4) are inherently frame based, so you must call them with all the data for one frame exactly. You must also initialize 'width' and 'height' before initializing them. */ /* NOTE2: some codecs allow the raw parameters (frame size, sample rate) to be changed at any frame. We handle this, so you should also take care of it */ /* here, we use a stream based decoder (mpeg1video), so we feed decoder and see if it could decode a frame */ avpkt.data = inbuf; while (avpkt.size > 0) { len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); if (len < 0) { fprintf(stderr, "Error while decoding frame %d\n", frame); exit(1); } if (got_picture) { printf("saving frame %3d\n", frame); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), outfilename, frame); pgm_save(picture->data[0], picture->linesize[0], c->width, c->height, buf); frame++; } avpkt.size -= len; avpkt.data += len; } } /* some codecs, such as MPEG, transmit the I and P frame with a latency of one frame. You must do the following to have a chance to get the last frame of the video */ avpkt.data = NULL; avpkt.size = 0; len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); if (got_picture) { printf("saving last frame %3d\n", frame); fflush(stdout); /* the picture is allocated by the decoder. no need to free it */ snprintf(buf, sizeof(buf), outfilename, frame); pgm_save(picture->data[0], picture->linesize[0], c->width, c->height, buf); frame++; } fclose(f); avcodec_close(c); av_free(c); av_free(picture); printf("\n"); }
// initialization taken from plugin h263-1998 in opal-2.8.0 bool VideoEncoderFfmpeg::InitEncoder(int bitrate, int fps, int width, int height, int fragsize, int *fragcount, const char *enc_params) { if (!VideoEncoder::InitEncoder(bitrate, fps, width, height, fragsize, fragcount, enc_params)) goto InitEncoder_ErrInitParent; avcodec_init(); avcodec_register_all(); // codec codec_ = avcodec_find_encoder(GetCodecId()); if (NULL == codec_) goto InitEncoder_ErrFindEncoder; // frame input_buffer_size_ = width * height * 3 / 2; input_buffer_ = static_cast<unsigned char *>( _aligned_malloc(input_buffer_size_, kMemAlign)); frame_ = avcodec_alloc_frame(); if (NULL == frame_) goto InitEncoder_ErrAllocFrame; frame_->data[0] = input_buffer_; frame_->data[1] = frame_->data[0] + width * height; frame_->data[2] = frame_->data[1] + width * height / 4; frame_->linesize[0] = width; frame_->linesize[1] = frame_->linesize[2] = width / 2; // context context_ = avcodec_alloc_context3(codec_); if (NULL == context_) goto InitEncoder_ErrAllocContext; context_->pix_fmt = PIX_FMT_YUV420P; context_->width = width; context_->height = height; context_->time_base.num = 1; context_->time_base.den = fps; context_->gop_size = param_video()->GetGopSize(); context_->flags = CODEC_FLAG_INPUT_PRESERVED | CODEC_FLAG_EMU_EDGE | CODEC_FLAG_PASS1 | GetFlags(); context_->mb_decision = FF_MB_DECISION_SIMPLE; context_->me_method = ME_EPZS; context_->max_b_frames = 0; // target bitrate context_->bit_rate = bitrate * 3 / 4; context_->bit_rate_tolerance = bitrate / 2; context_->rc_min_rate = 0; context_->rc_max_rate = bitrate; context_->rc_buffer_size = bitrate / 1000; /* ratecontrol qmin qmax limiting method 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax. */ context_->rc_qsquish = 0; // limit q by clipping context_->rc_eq = (char*) "1"; // rate control equation context_->rc_buffer_size = bitrate * 64; // temporal spatial trade off context_->max_qdiff = 10; // was 3 // max q difference between frames context_->qcompress = 0.5; // qscale factor between easy & hard scenes (0.0-1.0) context_->i_quant_factor = (float)-0.6; // qscale factor between p and i frames context_->i_quant_offset = (float)0.0; // qscale offset between p and i frames context_->me_subpel_quality = 8; context_->qmin = MIN_QUANT; context_->qmax = static_cast<int>(round ( (31.0 - MIN_QUANT) / 31.0 * GetTsto() + MIN_QUANT)); context_->qmax = min(context_->qmax, 31); // TODO: vedere come mapparli in ffmpeg 0.10.3 //context_->mb_qmin = context_->qmin; //context_->mb_qmax = context_->qmax; // Lagrange multipliers - this is how the context defaults do it: context_->lmin = context_->qmin * FF_QP2LAMBDA; context_->lmax = context_->qmax * FF_QP2LAMBDA; context_->debug = FF_DEBUG_RC | FF_DEBUG_PICT_INFO | FF_DEBUG_MV; // frammentazione if (fragsize > 0) { context_->opaque = GetOpaque(); context_->rtp_payload_size = 1; // if I leave 0, ffmpeg doesn't split at gobs, if I use a large value // ffmpeg aggregates gobs without inserting gob headers } if (0 != avcodec_open2(context_, codec_, &opts_)) { goto InitEncoder_ErrOpenCodec; } return true; InitEncoder_ErrOpenCodec: avcodec_close(context_); av_free(context_); context_ = NULL; InitEncoder_ErrAllocContext: av_free(frame_); frame_ = NULL; InitEncoder_ErrAllocFrame: codec_ = NULL; _aligned_free(input_buffer_); input_buffer_ = NULL; input_buffer_size_ = 0; InitEncoder_ErrFindEncoder: VideoEncoder::DestroyEncoder(); InitEncoder_ErrInitParent: return false; }
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; }
bool CDVDDemuxClient::ParsePacket(DemuxPacket* pkt) { bool change = false; CDemuxStream* st = GetStream(pkt->iStreamId); if (st == nullptr) return change; if (st->ExtraSize || !CodecHasExtraData(st->codec)) return change; CDemuxStreamClientInternal* stream = dynamic_cast<CDemuxStreamClientInternal*>(st); if (stream == nullptr || stream->m_parser == nullptr) return change; if (stream->m_context == nullptr) { AVCodec *codec = avcodec_find_decoder(st->codec); if (codec == nullptr) { CLog::Log(LOGERROR, "%s - can't find decoder", __FUNCTION__); stream->DisposeParser(); return change; } stream->m_context = avcodec_alloc_context3(codec); if (stream->m_context == nullptr) { CLog::Log(LOGERROR, "%s - can't allocate context", __FUNCTION__); stream->DisposeParser(); return change; } stream->m_context->time_base.num = 1; stream->m_context->time_base.den = DVD_TIME_BASE; } if (stream->m_parser_split && stream->m_parser->parser->split) { int len = stream->m_parser->parser->split(stream->m_context, pkt->pData, pkt->iSize); if (len > 0 && len < FF_MAX_EXTRADATA_SIZE) { if (st->ExtraData) delete[] st->ExtraData; st->changes++; st->disabled = false; st->ExtraSize = len; st->ExtraData = new uint8_t[len+AV_INPUT_BUFFER_PADDING_SIZE]; memcpy(st->ExtraData, pkt->pData, len); memset(st->ExtraData + len, 0 , AV_INPUT_BUFFER_PADDING_SIZE); stream->m_parser_split = false; change = true; CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - split extradata"); } } uint8_t *outbuf = nullptr; int outbuf_size = 0; int len = av_parser_parse2(stream->m_parser, stream->m_context, &outbuf, &outbuf_size, pkt->pData, pkt->iSize, (int64_t)(pkt->pts * DVD_TIME_BASE), (int64_t)(pkt->dts * DVD_TIME_BASE), 0); // our parse is setup to parse complete frames, so we don't care about outbufs if (len >= 0) { if (stream->m_context->profile != st->profile && stream->m_context->profile != FF_PROFILE_UNKNOWN) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - ({}) profile changed from {} to {}", st->uniqueId, st->profile, stream->m_context->profile); st->profile = stream->m_context->profile; st->changes++; st->disabled = false; } if (stream->m_context->level != st->level && stream->m_context->level != FF_LEVEL_UNKNOWN) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - ({}) level changed from {} to {}", st->uniqueId, st->level, stream->m_context->level); st->level = stream->m_context->level; st->changes++; st->disabled = false; } switch (st->type) { case STREAM_AUDIO: { CDemuxStreamClientInternalTpl<CDemuxStreamAudio>* sta = static_cast<CDemuxStreamClientInternalTpl<CDemuxStreamAudio>*>(st); if (stream->m_context->channels != sta->iChannels && stream->m_context->channels != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - ({}) channels changed from {} to {}", st->uniqueId, sta->iChannels, stream->m_context->channels); sta->iChannels = stream->m_context->channels; sta->changes++; sta->disabled = false; } if (stream->m_context->sample_rate != sta->iSampleRate && stream->m_context->sample_rate != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - ({}) samplerate changed from {} to {}", st->uniqueId, sta->iSampleRate, stream->m_context->sample_rate); sta->iSampleRate = stream->m_context->sample_rate; sta->changes++; sta->disabled = false; } break; } case STREAM_VIDEO: { CDemuxStreamClientInternalTpl<CDemuxStreamVideo>* stv = static_cast<CDemuxStreamClientInternalTpl<CDemuxStreamVideo>*>(st); if (stream->m_context->width != stv->iWidth && stream->m_context->width != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - ({}) width changed from {} to {}", st->uniqueId, stv->iWidth, stream->m_context->width); stv->iWidth = stream->m_context->width; stv->changes++; stv->disabled = false; } if (stream->m_context->height != stv->iHeight && stream->m_context->height != 0) { CLog::Log(LOGDEBUG, "CDVDDemuxClient::ParsePacket - ({}) height changed from {} to {}", st->uniqueId, stv->iHeight, stream->m_context->height); stv->iHeight = stream->m_context->height; stv->changes++; stv->disabled = false; } break; } default: break; } } else CLog::Log(LOGDEBUG, "%s - parser returned error %d", __FUNCTION__, len); return change; }
bool FFMpegLoader::open(qint64 &position) { if (!AbstractFFMpegLoader::open(position)) { return false; } int res = 0; char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; auto codecParams = fmtContext->streams[streamId]->codecpar; codecContext = avcodec_alloc_context3(nullptr); if (!codecContext) { LOG(("Audio Error: Unable to avcodec_alloc_context3 for file '%1', data size '%2'").arg(_file.name()).arg(_data.size())); return false; } if ((res = avcodec_parameters_to_context(codecContext, codecParams)) < 0) { LOG(("Audio Error: Unable to avcodec_parameters_to_context for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return false; } av_codec_set_pkt_timebase(codecContext, fmtContext->streams[streamId]->time_base); av_opt_set_int(codecContext, "refcounted_frames", 1, 0); if ((res = avcodec_open2(codecContext, codec, 0)) < 0) { LOG(("Audio Error: Unable to avcodec_open2 for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return false; } auto layout = codecParams->channel_layout; if (!layout) { auto channelsCount = codecParams->channels; switch (channelsCount) { case 1: layout = AV_CH_LAYOUT_MONO; break; case 2: layout = AV_CH_LAYOUT_STEREO; break; default: LOG(("Audio Error: Unknown channel layout for %1 channels.").arg(channelsCount)); break; } } inputFormat = codecContext->sample_fmt; switch (layout) { case AV_CH_LAYOUT_MONO: switch (inputFormat) { case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8P: fmt = AL_FORMAT_MONO8; sampleSize = 1; break; case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16P: fmt = AL_FORMAT_MONO16; sampleSize = sizeof(uint16); break; default: sampleSize = -1; // convert needed break; } break; case AV_CH_LAYOUT_STEREO: switch (inputFormat) { case AV_SAMPLE_FMT_U8: fmt = AL_FORMAT_STEREO8; sampleSize = 2; break; case AV_SAMPLE_FMT_S16: fmt = AL_FORMAT_STEREO16; sampleSize = 2 * sizeof(uint16); break; default: sampleSize = -1; // convert needed break; } break; default: sampleSize = -1; // convert needed break; } if (_samplesFrequency != 44100 && _samplesFrequency != 48000) { sampleSize = -1; // convert needed } if (sampleSize < 0) { swrContext = swr_alloc(); if (!swrContext) { LOG(("Audio Error: Unable to swr_alloc for file '%1', data size '%2'").arg(_file.name()).arg(_data.size())); return false; } int64_t src_ch_layout = layout, dst_ch_layout = AudioToChannelLayout; srcRate = _samplesFrequency; AVSampleFormat src_sample_fmt = inputFormat, dst_sample_fmt = AudioToFormat; dstRate = (_samplesFrequency != 44100 && _samplesFrequency != 48000) ? Media::Player::kDefaultFrequency : _samplesFrequency; av_opt_set_int(swrContext, "in_channel_layout", src_ch_layout, 0); av_opt_set_int(swrContext, "in_sample_rate", srcRate, 0); av_opt_set_sample_fmt(swrContext, "in_sample_fmt", src_sample_fmt, 0); av_opt_set_int(swrContext, "out_channel_layout", dst_ch_layout, 0); av_opt_set_int(swrContext, "out_sample_rate", dstRate, 0); av_opt_set_sample_fmt(swrContext, "out_sample_fmt", dst_sample_fmt, 0); if ((res = swr_init(swrContext)) < 0) { LOG(("Audio Error: Unable to swr_init for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return false; } sampleSize = AudioToChannels * sizeof(short); _samplesFrequency = dstRate; _samplesCount = av_rescale_rnd(_samplesCount, dstRate, srcRate, AV_ROUND_UP); position = av_rescale_rnd(position, dstRate, srcRate, AV_ROUND_DOWN); fmt = AL_FORMAT_STEREO16; maxResampleSamples = av_rescale_rnd(AVBlockSize / sampleSize, dstRate, srcRate, AV_ROUND_UP); if ((res = av_samples_alloc_array_and_samples(&dstSamplesData, 0, AudioToChannels, maxResampleSamples, AudioToFormat, 0)) < 0) { LOG(("Audio Error: Unable to av_samples_alloc for file '%1', data size '%2', error %3, %4").arg(_file.name()).arg(_data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return false; } } if (position) { int64 ts = (position * fmtContext->streams[streamId]->time_base.den) / (_samplesFrequency * fmtContext->streams[streamId]->time_base.num); if (av_seek_frame(fmtContext, streamId, ts, AVSEEK_FLAG_ANY) < 0) { if (av_seek_frame(fmtContext, streamId, ts, 0) < 0) { } } } return true; }
static void video_decode_example(const char *outfilename, const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; int frame_count; FILE *f; AVFrame *frame; uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; AVPacket avpkt; av_init_packet(&avpkt); /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); printf("Decode video file %s to %s\n", filename, outfilename); /* find the mpeg1 video decoder */ codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate video codec context\n"); exit(1); } if(codec->capabilities&CODEC_CAP_TRUNCATED) c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ /* For some codecs, such as msmpeg4 and mpeg4, width and height MUST be initialized there because this information is not available in the bitstream. */ /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate video frame\n"); exit(1); } frame_count = 0; for(;;) { avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); if (avpkt.size == 0) break; /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) and this is the only method to use them because you cannot know the compressed data size before analysing it. BUT some other codecs (msmpeg4, mpeg4) are inherently frame based, so you must call them with all the data for one frame exactly. You must also initialize 'width' and 'height' before initializing them. */ /* NOTE2: some codecs allow the raw parameters (frame size, sample rate) to be changed at any frame. We handle this, so you should also take care of it */ /* here, we use a stream based decoder (mpeg1video), so we feed decoder and see if it could decode a frame */ avpkt.data = inbuf; while (avpkt.size > 0) if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0) exit(1); } /* some codecs, such as MPEG, transmit the I and P frame with a latency of one frame. You must do the following to have a chance to get the last frame of the video */ avpkt.data = NULL; avpkt.size = 0; decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1); fclose(f); avcodec_close(c); av_free(c); avcodec_free_frame(&frame); printf("\n"); }
// Convert an MPEG I-frame into a bitmap. This is used as the way of // sending still pictures. We convert the image to a QImage even // though that actually means converting it from YUV and eventually // converting it back again but we do this very infrequently so the // cost is outweighed by the simplification. void MHIBitmap::CreateFromMPEG(const unsigned char *data, int length) { AVCodecContext *c = NULL; AVFrame *picture = NULL; AVPacket pkt; uint8_t *buff = NULL; int gotPicture = 0, len; m_image = QImage(); // Find the mpeg2 video decoder. AVCodec *codec = avcodec_find_decoder(CODEC_ID_MPEG2VIDEO); if (!codec) return; c = avcodec_alloc_context3(NULL); picture = avcodec_alloc_frame(); if (avcodec_open2(c, codec, NULL) < 0) goto Close; // Copy the data into AVPacket if (av_new_packet(&pkt, length) < 0) goto Close; memcpy(pkt.data, data, length); buff = pkt.data; while (pkt.size > 0 && ! gotPicture) { len = avcodec_decode_video2(c, picture, &gotPicture, &pkt); if (len < 0) // Error goto Close; pkt.data += len; pkt.size -= len; } if (!gotPicture) { pkt.data = NULL; pkt.size = 0; // Process any buffered data if (avcodec_decode_video2(c, picture, &gotPicture, &pkt) < 0) goto Close; } if (gotPicture) { int nContentWidth = c->width; int nContentHeight = c->height; m_image = QImage(nContentWidth, nContentHeight, QImage::Format_ARGB32); m_opaque = true; // MPEG images are always opaque. AVPicture retbuf; memset(&retbuf, 0, sizeof(AVPicture)); int bufflen = nContentWidth * nContentHeight * 3; unsigned char *outputbuf = new unsigned char[bufflen]; avpicture_fill(&retbuf, outputbuf, PIX_FMT_RGB24, nContentWidth, nContentHeight); myth_sws_img_convert( &retbuf, PIX_FMT_RGB24, (AVPicture*)picture, c->pix_fmt, nContentWidth, nContentHeight); uint8_t * buf = outputbuf; // Copy the data a pixel at a time. // This should handle endianness correctly. for (int i = 0; i < nContentHeight; i++) { for (int j = 0; j < nContentWidth; j++) { int red = *buf++; int green = *buf++; int blue = *buf++; m_image.setPixel(j, i, qRgb(red, green, blue)); } } delete [] outputbuf; } Close: pkt.data = buff; av_free_packet(&pkt); avcodec_close(c); av_free(c); av_free(picture); }
static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job) { AVCodec *codec; AVCodecContext *context; hb_audio_t *audio = w->audio; hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t)); w->private_data = pv; pv->job = job; pv->list = hb_list_init(); // channel count, layout and matrix encoding int matrix_encoding; uint64_t channel_layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, &matrix_encoding); pv->out_discrete_channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown); // default settings and options AVDictionary *av_opts = NULL; const char *codec_name = NULL; enum AVCodecID codec_id = AV_CODEC_ID_NONE; enum AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLTP; int bits_per_raw_sample = 0; int profile = FF_PROFILE_UNKNOWN; // override with encoder-specific values switch (audio->config.out.codec) { case HB_ACODEC_AC3: codec_id = AV_CODEC_ID_AC3; if (matrix_encoding != AV_MATRIX_ENCODING_NONE) av_dict_set(&av_opts, "dsur_mode", "on", 0); break; case HB_ACODEC_FDK_AAC: case HB_ACODEC_FDK_HAAC: codec_name = "libfdk_aac"; sample_fmt = AV_SAMPLE_FMT_S16; bits_per_raw_sample = 16; switch (audio->config.out.codec) { case HB_ACODEC_FDK_HAAC: profile = FF_PROFILE_AAC_HE; break; default: profile = FF_PROFILE_AAC_LOW; break; } // Libav's libfdk-aac wrapper expects back channels for 5.1 // audio, and will error out unless we translate the layout if (channel_layout == AV_CH_LAYOUT_5POINT1) channel_layout = AV_CH_LAYOUT_5POINT1_BACK; break; case HB_ACODEC_FFAAC: codec_name = "aac"; av_dict_set(&av_opts, "stereo_mode", "ms_off", 0); break; case HB_ACODEC_FFFLAC: case HB_ACODEC_FFFLAC24: codec_id = AV_CODEC_ID_FLAC; switch (audio->config.out.codec) { case HB_ACODEC_FFFLAC24: sample_fmt = AV_SAMPLE_FMT_S32; bits_per_raw_sample = 24; break; default: sample_fmt = AV_SAMPLE_FMT_S16; bits_per_raw_sample = 16; break; } break; default: hb_error("encavcodecaInit: unsupported codec (0x%x)", audio->config.out.codec); return 1; } if (codec_name != NULL) { codec = avcodec_find_encoder_by_name(codec_name); if (codec == NULL) { hb_error("encavcodecaInit: avcodec_find_encoder_by_name(%s) failed", codec_name); return 1; } } else { codec = avcodec_find_encoder(codec_id); if (codec == NULL) { hb_error("encavcodecaInit: avcodec_find_encoder(%d) failed", codec_id); return 1; } } // allocate the context and apply the settings context = avcodec_alloc_context3(codec); hb_ff_set_sample_fmt(context, codec, sample_fmt); context->bits_per_raw_sample = bits_per_raw_sample; context->profile = profile; context->channel_layout = channel_layout; context->channels = pv->out_discrete_channels; context->sample_rate = audio->config.out.samplerate; if (audio->config.out.bitrate > 0) { context->bit_rate = audio->config.out.bitrate * 1000; } else if (audio->config.out.quality >= 0) { context->global_quality = audio->config.out.quality * FF_QP2LAMBDA; context->flags |= CODEC_FLAG_QSCALE; } if (audio->config.out.compression_level >= 0) { context->compression_level = audio->config.out.compression_level; } // For some codecs, libav requires the following flag to be set // so that it fills extradata with global header information. // If this flag is not set, it inserts the data into each // packet instead. context->flags |= CODEC_FLAG_GLOBAL_HEADER; if (hb_avcodec_open(context, codec, &av_opts, 0)) { hb_error("encavcodecaInit: hb_avcodec_open() failed"); return 1; } // avcodec_open populates the opts dictionary with the // things it didn't recognize. AVDictionaryEntry *t = NULL; while ((t = av_dict_get(av_opts, "", t, AV_DICT_IGNORE_SUFFIX))) { hb_log("encavcodecaInit: Unknown avcodec option %s", t->key); } av_dict_free(&av_opts); pv->context = context; audio->config.out.samples_per_frame = pv->samples_per_frame = context->frame_size; pv->input_samples = context->frame_size * context->channels; pv->input_buf = malloc(pv->input_samples * sizeof(float)); // Some encoders in libav (e.g. fdk-aac) fail if the output buffer // size is not some minumum value. 8K seems to be enough :( pv->max_output_bytes = MAX(FF_MIN_BUFFER_SIZE, (pv->input_samples * av_get_bytes_per_sample(context->sample_fmt))); // sample_fmt conversion if (context->sample_fmt != AV_SAMPLE_FMT_FLT) { pv->output_buf = malloc(pv->max_output_bytes); pv->avresample = avresample_alloc_context(); if (pv->avresample == NULL) { hb_error("encavcodecaInit: avresample_alloc_context() failed"); return 1; } av_opt_set_int(pv->avresample, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0); av_opt_set_int(pv->avresample, "out_sample_fmt", context->sample_fmt, 0); av_opt_set_int(pv->avresample, "in_channel_layout", context->channel_layout, 0); av_opt_set_int(pv->avresample, "out_channel_layout", context->channel_layout, 0); if (hb_audio_dither_is_supported(audio->config.out.codec)) { // dithering needs the sample rate av_opt_set_int(pv->avresample, "in_sample_rate", context->sample_rate, 0); av_opt_set_int(pv->avresample, "out_sample_rate", context->sample_rate, 0); av_opt_set_int(pv->avresample, "dither_method", audio->config.out.dither_method, 0); } if (avresample_open(pv->avresample)) { hb_error("encavcodecaInit: avresample_open() failed"); avresample_free(&pv->avresample); return 1; } } else { pv->avresample = NULL; pv->output_buf = pv->input_buf; } if (context->extradata != NULL) { memcpy(w->config->extradata.bytes, context->extradata, context->extradata_size); w->config->extradata.length = context->extradata_size; } audio->config.out.delay = av_rescale_q(context->delay, context->time_base, (AVRational){1, 90000}); return 0; }
int main(int argc, char *argv[]) { // Initalizing these to NULL prevents segfaults! AVFormatContext *pFormatCtx = nullptr; int i, videoStream,audioStream; AVCodecContext *pCodecCtxOrig = nullptr; AVCodecContext *pCodecCtx = nullptr; AVCodec *pCodec = nullptr; AVFrame *pFrame = nullptr; AVFrame *pFrameYUV = nullptr; AVPacket packet; int frameFinished; int numBytes; uint8_t *buffer = nullptr; struct SwsContext *sws_ctx = nullptr; HANDLE hAudioPlay = nullptr; const char *inputFile = "rtmp://live.hkstv.hk.lxdns.com/live/hks"; //SDL--------------------------- int screen_w = 0, screen_h = 0; SDL_Window *screen; SDL_Renderer* sdlRenderer; SDL_Texture* sdlTexture; SDL_Rect sdlRect; // Register all formats and codecs av_register_all(); avformat_network_init(); // Open video file if (avformat_open_input(&pFormatCtx, inputFile, NULL, NULL) != 0) return -1; // Couldn't open file // Retrieve stream information if (avformat_find_stream_info(pFormatCtx, NULL) < 0) return -1; // Couldn't find stream information // Dump information about file onto standard error av_dump_format(pFormatCtx, 0, inputFile, 0); // Find the first video stream videoStream = -1; audioStream = -1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) videoStream = i; else if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) audioStream = i; } if (videoStream == -1) return -1; // Didn't find a video stream if (audioStream == -1) return -1; // Didn't find a audio stream // Get a pointer to the codec context for the video stream pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id); if (pCodec == NULL) { fprintf(stderr, "Unsupported codec!\n"); return -1; // Codec not found } // Copy context pCodecCtx = avcodec_alloc_context3(pCodec); if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) { fprintf(stderr, "Couldn't copy codec context"); return -1; // Error copying codec context } // Open codec if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) return -1; // Could not open codec // Allocate video frame pFrame = av_frame_alloc(); // Allocate an AVFrame structure pFrameYUV = av_frame_alloc(); if (pFrameYUV == NULL) return -1; // Determine required buffer size and allocate buffer numBytes = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1); buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); // Assign appropriate parts of buffer to image planes in pFrameYUV // Note that pFrameYUV is an AVFrame, but AVFrame is a superset // of AVPicture int linesize = 0; av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1); // initialize SWS context for software scaling sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL ); //SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { printf("Could not initialize SDL - %s\n", SDL_GetError()); return -1; } screen_w = pCodecCtx->width; screen_h = pCodecCtx->height; //SDL 2.0 Support for multiple windows screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, SDL_WINDOW_OPENGL); if (!screen) { printf("SDL: could not create window - exiting:%s\n", SDL_GetError()); return -1; } sdlRenderer = SDL_CreateRenderer(screen, -1, 0); sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height); sdlRect.x = 0; sdlRect.y = 0; sdlRect.w = screen_w; sdlRect.h = screen_h; // Read frames and save first five frames to disk i = 0; while (av_read_frame(pFormatCtx, &packet) >= 0) { // Is this a packet from the video stream? if (packet.stream_index == videoStream) { // Decode video frame int iret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); // Did we get a video frame? if (frameFinished) { // Convert the image from its native format to YUV sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); // SDL SDL_UpdateTexture(sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0]); SDL_RenderClear(sdlRenderer); SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect); SDL_RenderPresent(sdlRenderer); //SDL End----------------------- double time = (double)packet.duration * 1000 / (((*(pFormatCtx->streams))->time_base.den) / ((*(pFormatCtx->streams))->time_base.num)); SDL_Delay(time); } } // Free the packet that was allocated by av_read_frame av_packet_unref(&packet); } SDL_Quit(); // Free the YUV image //av_free(buffer); av_frame_free(&pFrameYUV); // Free the YUV frame av_frame_free(&pFrame); // Close the codecs avcodec_close(pCodecCtx); avcodec_close(pCodecCtxOrig); // Close the video file avformat_close_input(&pFormatCtx); return 0; }
bool CDVDOverlayCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { // decoding of this kind of subs does not work reliable if (hints.codec == AV_CODEC_ID_EIA_608) return false; AVCodec* pCodec = avcodec_find_decoder(hints.codec); if (!pCodec) { CLog::Log(LOGDEBUG,"%s - Unable to find codec %d", __FUNCTION__, hints.codec); return false; } m_pCodecContext = avcodec_alloc_context3(pCodec); if (!m_pCodecContext) return false; m_pCodecContext->debug_mv = 0; m_pCodecContext->debug = 0; m_pCodecContext->workaround_bugs = FF_BUG_AUTODETECT; m_pCodecContext->codec_tag = hints.codec_tag; m_pCodecContext->time_base.num = 1; m_pCodecContext->time_base.den = DVD_TIME_BASE; m_pCodecContext->pkt_timebase.num = 1; m_pCodecContext->pkt_timebase.den = DVD_TIME_BASE; if( hints.extradata && hints.extrasize > 0 ) { m_pCodecContext->extradata_size = hints.extrasize; m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); // start parsing of extra data - create a copy to be safe and make it zero-terminating to avoid access violations! unsigned int parse_extrasize = hints.extrasize; char* parse_extra = new char[parse_extrasize + 1]; memcpy(parse_extra, hints.extradata, parse_extrasize); parse_extra[parse_extrasize] = '\0'; // assume that the extra data is formatted as a concatenation of lines ('\n' terminated) char *ptr = parse_extra; do // read line by line { if (!strncmp(ptr, "size:", 5)) { int width = 0, height = 0; sscanf(ptr, "size: %dx%d", &width, &height); if (width > 0 && height > 0) { m_pCodecContext->width = width; m_pCodecContext->height = height; CLog::Log(LOGDEBUG,"%s - parsed extradata: size: %d x %d", __FUNCTION__, width, height); } } /* // leaving commented code: these items don't work yet... but they may be meaningful if (!strncmp(ptr, "palette:", 8)) if (sscanf(ptr, "palette: %x, %x, %x, %x, %x, %x, %x, %x," " %x, %x, %x, %x, %x, %x, %x, %x", ... if (!strncasecmp(ptr, "forced subs: on", 15)) forced_subs_only = 1; */ // if tried all possibilities, then read newline char and move to next line ptr = strchr(ptr, '\n'); if (ptr != NULL) ptr++; } while (ptr != NULL && ptr <= parse_extra + parse_extrasize); delete[] parse_extra; } if (avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) { CLog::Log(LOGDEBUG,"CDVDVideoCodecFFmpeg::Open() Unable to open codec"); avcodec_free_context(&m_pCodecContext); return false; } return true; }
/* * 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 audio_process_audio(audio_decoder_t *ad, media_buf_t *mb) { const audio_class_t *ac = ad->ad_ac; AVFrame *frame = ad->ad_frame; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; int r; int got_frame; if(mb->mb_skip || mb->mb_stream != mq->mq_stream) return; while(mb->mb_size) { if(mb->mb_cw == NULL) { frame->sample_rate = mb->mb_rate; frame->format = AV_SAMPLE_FMT_S16; switch(mb->mb_channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; frame->nb_samples = mb->mb_size / 2; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = mb->mb_size / 4; break; default: abort(); } frame->data[0] = mb->mb_data; frame->linesize[0] = 0; r = mb->mb_size; got_frame = 1; } else { media_codec_t *mc = mb->mb_cw; AVCodecContext *ctx = mc->ctx; if(mc->codec_id != ad->ad_in_codec_id) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); TRACE(TRACE_DEBUG, "audio", "Codec changed to %s (0x%x)", codec ? codec->name : "???", mc->codec_id); ad->ad_in_codec_id = mc->codec_id; ad->ad_in_sample_rate = 0; audio_cleanup_spdif_muxer(ad); ad->ad_mode = ac->ac_get_mode != NULL ? ac->ac_get_mode(ad, mc->codec_id, ctx ? ctx->extradata : NULL, ctx ? ctx->extradata_size : 0) : AUDIO_MODE_PCM; if(ad->ad_mode == AUDIO_MODE_SPDIF) { audio_setup_spdif_muxer(ad, codec, mq); } else if(ad->ad_mode == AUDIO_MODE_CODED) { hts_mutex_lock(&mp->mp_mutex); ac->ac_deliver_coded_locked(ad, mb->mb_data, mb->mb_size, mb->mb_pts, mb->mb_epoch); hts_mutex_unlock(&mp->mp_mutex); return; } } if(ad->ad_spdif_muxer != NULL) { mb->mb_pkt.stream_index = 0; ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; mb->mb_pts = AV_NOPTS_VALUE; mb->mb_dts = AV_NOPTS_VALUE; av_write_frame(ad->ad_spdif_muxer, &mb->mb_pkt); avio_flush(ad->ad_spdif_muxer->pb); return; } if(ad->ad_mode == AUDIO_MODE_CODED) { ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; } if(ctx == NULL) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); assert(codec != NULL); // Checked in libav.c ctx = mc->ctx = avcodec_alloc_context3(codec); if(ad->ad_stereo_downmix) ctx->request_channel_layout = AV_CH_LAYOUT_STEREO; if(avcodec_open2(mc->ctx, codec, NULL) < 0) { av_freep(&mc->ctx); return; } } r = avcodec_decode_audio4(ctx, frame, &got_frame, &mb->mb_pkt); if(r < 0) return; if(frame->sample_rate == 0) { frame->sample_rate = ctx->sample_rate; if(frame->sample_rate == 0 && mb->mb_cw->fmt_ctx) frame->sample_rate = mb->mb_cw->fmt_ctx->sample_rate; if(frame->sample_rate == 0) { if(!ad->ad_sample_rate_fail) { ad->ad_sample_rate_fail = 1; TRACE(TRACE_ERROR, "Audio", "Unable to determine sample rate"); } return; } } if(frame->channel_layout == 0) { frame->channel_layout = av_get_default_channel_layout(ctx->channels); if(frame->channel_layout == 0) { if(!ad->ad_channel_layout_fail) { ad->ad_channel_layout_fail = 1; TRACE(TRACE_ERROR, "Audio", "Unable to map %d channels to channel layout"); } return; } } if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); } if(mb->mb_pts != PTS_UNSET) { int od = 0, id = 0; if(ad->ad_avr != NULL) { od = avresample_available(ad->ad_avr) * 1000000LL / ad->ad_out_sample_rate; id = avresample_get_delay(ad->ad_avr) * 1000000LL / frame->sample_rate; } ad->ad_pts = mb->mb_pts - od - id; ad->ad_epoch = mb->mb_epoch; if(mb->mb_drive_clock) mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, mb->mb_epoch, mb->mb_delta); mb->mb_pts = PTS_UNSET; // No longer valid } mb->mb_data += r; mb->mb_size -= r; if(got_frame) { if(frame->sample_rate != ad->ad_in_sample_rate || frame->format != ad->ad_in_sample_format || frame->channel_layout != ad->ad_in_channel_layout || ad->ad_want_reconfig) { ad->ad_want_reconfig = 0; ad->ad_in_sample_rate = frame->sample_rate; ad->ad_in_sample_format = frame->format; ad->ad_in_channel_layout = frame->channel_layout; ac->ac_reconfig(ad); if(ad->ad_avr == NULL) ad->ad_avr = avresample_alloc_context(); else avresample_close(ad->ad_avr); av_opt_set_int(ad->ad_avr, "in_sample_fmt", ad->ad_in_sample_format, 0); av_opt_set_int(ad->ad_avr, "in_sample_rate", ad->ad_in_sample_rate, 0); av_opt_set_int(ad->ad_avr, "in_channel_layout", ad->ad_in_channel_layout, 0); av_opt_set_int(ad->ad_avr, "out_sample_fmt", ad->ad_out_sample_format, 0); av_opt_set_int(ad->ad_avr, "out_sample_rate", ad->ad_out_sample_rate, 0); av_opt_set_int(ad->ad_avr, "out_channel_layout", ad->ad_out_channel_layout, 0); char buf1[128]; char buf2[128]; av_get_channel_layout_string(buf1, sizeof(buf1), -1, ad->ad_in_channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, ad->ad_out_channel_layout); TRACE(TRACE_DEBUG, "Audio", "Converting from [%s %dHz %s] to [%s %dHz %s]", buf1, ad->ad_in_sample_rate, av_get_sample_fmt_name(ad->ad_in_sample_format), buf2, ad->ad_out_sample_rate, av_get_sample_fmt_name(ad->ad_out_sample_format)); if(avresample_open(ad->ad_avr)) { TRACE(TRACE_ERROR, "Audio", "Unable to open resampler"); avresample_free(&ad->ad_avr); } if(ac->ac_set_volume != NULL) { prop_set(mp->mp_prop_ctrl, "canAdjustVolume", PROP_SET_INT, 1); ac->ac_set_volume(ad, ad->ad_vol_scale); } } if(ad->ad_avr != NULL) { avresample_convert(ad->ad_avr, NULL, 0, 0, frame->data, frame->linesize[0], frame->nb_samples); } else { int delay = 1000000LL * frame->nb_samples / frame->sample_rate; usleep(delay); } } } }
int audio_thr(LPVOID lpParam) { int iRet = -1; //音频测试,播放文件显示波形 AVFormatContext * pFmtCtx = NULL; AVFormatContext * pFOutmtCtx = NULL; AVInputFormat * pAudioInputFmt = NULL; AVOutputFormat * pAudioOutputFmt = NULL; AVCodecContext * pOutputCodecCtx = NULL; AVPacket * pAudioPacket = NULL; int iAudioIndex = -1; int data_size = 0; int resampled_data_size = 0; uint8_t * out_buffer = 0; int64_t dec_channel_layout = 0; double pts; CLS_DlgStreamPusher* pThis = (CLS_DlgStreamPusher*)lpParam; if (pThis == NULL || pThis->m_pStreamInfo == NULL){ TRACE("audio_thr--pThis == NULL || pThis->m_pStreamInfo == NULL\n"); return iRet; } struct_stream_info* strct_stream_info = pThis->m_pStreamInfo; pAudioInputFmt = av_find_input_format("dshow"); if (pAudioInputFmt == NULL){ TRACE("pAudioInputFmt == NULL\n"); return iRet; } char* psDevName = pThis->GetDeviceName(n_Audio); if (psDevName == NULL){ TRACE("audio_thr--psDevName == NULL"); return iRet; } if (avformat_open_input(&pFmtCtx, psDevName, pAudioInputFmt, NULL) != 0){ TRACE("avformat_open_input err!\n"); goto END; } if (avformat_find_stream_info(pFmtCtx, NULL) < 0){ TRACE("avformat_find_stream_info(pFmtCtx, NULL) < 0\n"); goto END; } for (int i = 0; i < pFmtCtx->nb_streams; i++){ if (pFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){ iAudioIndex = i; AVCodec *tmpCodec = avcodec_find_decoder(pFmtCtx->streams[i]->codec->codec_id); if (0 > avcodec_open2(pFmtCtx->streams[i]->codec, tmpCodec, NULL)){ TRACE("can not find or open decoder!\n"); } break; } } //找到音频流信息 strct_stream_info->m_pAudioStream = pFmtCtx->streams[iAudioIndex]; if (strct_stream_info->m_pAudioStream == NULL){ TRACE("strct_stream_info->m_pAudioStream == NULL\n"); goto END; } AVCodecContext *pAudioDec = strct_stream_info->m_pAudioStream->codec; if (NULL == pAudioDec){ TRACE("NULL == pAudioDec\n"); goto END; } AVCodec* audio_encoder = avcodec_find_encoder(AV_CODEC_ID_AAC); if (audio_encoder == NULL){ TRACE("audio_encoder == NULL\r\n"); goto END; } pOutputCodecCtx = avcodec_alloc_context3(audio_encoder); if (pOutputCodecCtx == NULL){ TRACE("pOutputCodecCtx == NULL"); goto END; } pOutputCodecCtx->sample_rate = pFmtCtx->streams[0]->codec->sample_rate; pOutputCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout); pOutputCodecCtx->sample_fmt = audio_encoder->sample_fmts[0]; pOutputCodecCtx->codec = audio_encoder; pOutputCodecCtx->codec_tag = 0; if (avcodec_open2(pOutputCodecCtx, pOutputCodecCtx->codec, 0) < 0){ //编码器打开失败,退出程序 TRACE("音频编码器打开失败!\n"); goto END; } //SDL_AudioSpec int out_nb_samples = AUDIO_BUF_SIZE; AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16; int out_buffer_size = av_samples_get_buffer_size(NULL, pOutputCodecCtx->channels, out_nb_samples, out_sample_fmt, 1); SDL_AudioSpec wanted_spec, spec; wanted_spec.freq = pOutputCodecCtx->sample_rate; wanted_spec.format = AUDIO_S16SYS; wanted_spec.channels = pOutputCodecCtx->channels; wanted_spec.silence = 0; wanted_spec.samples = out_nb_samples; wanted_spec.callback = fill_audio;//&CLS_DlgStreamPusher:: wanted_spec.userdata = strct_stream_info; strct_stream_info->m_content_out_channels = pOutputCodecCtx->channels; if (SDL_OpenAudio(&wanted_spec, &spec)<0){ TRACE("can't open audio.\n"); goto END; } int audio_hw_buf_size = spec.size; if (audio_hw_buf_size < 0){ TRACE("audio_hw_buf_size < 0\n"); return -1; } strct_stream_info->m_audio_src.fmt = AV_SAMPLE_FMT_S16; strct_stream_info->m_audio_src.freq = spec.freq; strct_stream_info->m_audio_src.channel_layout = pOutputCodecCtx->channel_layout; strct_stream_info->m_audio_src.channels = spec.channels; strct_stream_info->m_audio_hw_buf_size = audio_hw_buf_size; strct_stream_info->m_audio_tgt = strct_stream_info->m_audio_src; AVPacket pkt; out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2); strct_stream_info->m_audio_refresh_tid = SDL_CreateThread(audio_refresh_thread, NULL, strct_stream_info); while (av_read_frame(pFmtCtx, &pkt) == 0 && _kbhit() == 0){ if (!pThis->m_blAudioShow){ break; } if (pkt.stream_index != iAudioIndex){ continue; } if (!strct_stream_info->m_pAudioFrame) { if (!(strct_stream_info->m_pAudioFrame = avcodec_alloc_frame())){ TRACE("!(strct_stream_info->m_pAudioFrame = avcodec_alloc_frame())\n"); goto END; } } else{ avcodec_get_frame_defaults(strct_stream_info->m_pAudioFrame); } int gotframe = -1; strct_stream_info->m_pAudioFrame = av_frame_alloc(); if (avcodec_decode_audio4(pAudioDec, strct_stream_info->m_pAudioFrame, &gotframe, &pkt) < 0){ av_frame_free(&strct_stream_info->m_pAudioFrame); TRACE("can not decoder a frame\n"); break; } av_free_packet(&pkt); if (!gotframe){ //没有获取到数据,继续下一次 continue; } strct_stream_info->m_pAudioFrame->nb_samples = 1024;//这里暂时写死值 data_size = av_samples_get_buffer_size(NULL, pOutputCodecCtx->channels, strct_stream_info->m_pAudioFrame->nb_samples, pOutputCodecCtx->sample_fmt, 1); dec_channel_layout = (pOutputCodecCtx->channel_layout && pOutputCodecCtx->channels == av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout)) ? pOutputCodecCtx->channel_layout : av_get_default_channel_layout(pOutputCodecCtx->channels); //wanted_nb_samples = SynAudio(strct_stream_info, strct_stream_info->m_pAudioFrame->nb_samples); /*if (pOutputCodecCtx->sample_fmt != strct_stream_info->m_audio_src.fmt || dec_channel_layout != strct_stream_info->m_audio_src.channel_layout || pOutputCodecCtx->sample_rate != strct_stream_info->m_audio_src.freq){*/ swr_free(&strct_stream_info->m_audio_swr_ctx); strct_stream_info->m_audio_swr_ctx = swr_alloc_set_opts(NULL, strct_stream_info->m_audio_tgt.channel_layout, strct_stream_info->m_audio_tgt.fmt, strct_stream_info->m_audio_tgt.freq, dec_channel_layout, pOutputCodecCtx->sample_fmt, pOutputCodecCtx->sample_rate, 0, NULL); if (!strct_stream_info->m_audio_swr_ctx || swr_init(strct_stream_info->m_audio_swr_ctx) < 0){ TRACE("!pThis->m_pStreamInfstrct_stream_infoo->m_audio_swr_ctx || swr_init(strct_stream_info->m_audio_swr_ctx) < 0"); break; } strct_stream_info->m_audio_src.channel_layout = dec_channel_layout; strct_stream_info->m_audio_src.channels = pOutputCodecCtx->channels; strct_stream_info->m_audio_src.freq = pOutputCodecCtx->sample_rate; strct_stream_info->m_audio_src.fmt = pOutputCodecCtx->sample_fmt; //} if (NULL != strct_stream_info->m_audio_swr_ctx){ const uint8_t **in = (const uint8_t **)strct_stream_info->m_pAudioFrame->extended_data; uint8_t *out[] = { strct_stream_info->m_audio_buf2 }; int out_count = sizeof(strct_stream_info->m_audio_buf2) / strct_stream_info->m_audio_tgt.channels / av_get_bytes_per_sample(strct_stream_info->m_audio_tgt.fmt); int iRet = swr_convert(strct_stream_info->m_audio_swr_ctx, out, out_count, in, strct_stream_info->m_pAudioFrame->nb_samples); if (iRet < 0){ TRACE("swr_convert < 0\n"); break; } if (iRet == out_count) { TRACE("warning: audio buffer is probably too small\n"); swr_init(strct_stream_info->m_audio_swr_ctx); } strct_stream_info->m_audio_buf = strct_stream_info->m_audio_buf2; resampled_data_size = iRet * strct_stream_info->m_audio_tgt.channels * av_get_bytes_per_sample(strct_stream_info->m_audio_tgt.fmt); } else{ strct_stream_info->m_audio_buf = strct_stream_info->m_pAudioFrame->data[0]; resampled_data_size = data_size; } /* if no pts, then compute it */ pts = strct_stream_info->m_audio_clock; //*pts_ptr = pts; strct_stream_info->m_audio_clock += (double)data_size / (pAudioDec->channels * pAudioDec->sample_rate * av_get_bytes_per_sample(pAudioDec->sample_fmt)); #ifdef DEBUG { static double last_clock; /*printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n", is->audio_clock - last_clock, is->audio_clock, pts);*/ last_clock = strct_stream_info->m_audio_clock; } #endif //FIX:FLAC,MP3,AAC Different number of samples /*if (wanted_spec.samples != strct_stream_info->m_pAudioFrame->nb_samples){ SDL_CloseAudio(); out_nb_samples = strct_stream_info->m_pAudioFrame->nb_samples; out_buffer_size = av_samples_get_buffer_size(NULL, pOutputCodecCtx->channels, out_nb_samples, out_sample_fmt, 1); wanted_spec.samples = out_nb_samples; SDL_OpenAudio(&wanted_spec, NULL); }*/ //设置PCM数据 TRACE("----out_buffer_size---is [%ld]\n",out_buffer_size); audio_chunk = (Uint8 *)out_buffer; audio_len = out_buffer_size; audio_pos = audio_chunk; strct_stream_info->m_aduio_pkt_size = resampled_data_size;//audio_len;// av_free_packet(&pkt); //写PCM进行test if (1){ FILE *p = NULL; fopen_s(&p, "test.pcm", "a+b"); if (p == NULL){ continue; } int tempLenght = 2 * strct_stream_info->m_pAudioFrame->nb_samples;//由于实验中知道这是16位深,所以才这么写 uint8_t *tmpPtr = strct_stream_info->m_pAudioFrame->data[0]; if (NULL != p) { while (tempLenght > 0) { size_t temp = fwrite(tmpPtr, 1, tempLenght, p); tmpPtr += temp; tempLenght = tempLenght - temp; } fclose(p); } } SDL_PauseAudio(0); //while (audio_len > 0){ // //Wait until finish // SDL_Delay(1); //} //if (pFmtCtx->streams[iAudioIndex]->codec->sample_fmt != pOutputCodecCtx->sample_fmt // || pFmtCtx->streams[iAudioIndex]->codec->channels != pOutputCodecCtx->channels // || pFmtCtx->streams[iAudioIndex]->codec->sample_rate != pOutputCodecCtx->sample_rate){ // //TODO如果输入和输出的音频格式不一样 需要重采样,这里是一样的就没做 //} //av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame->nb_samples); //av_audio_fifo_write(fifo, (void **)frame->data, frame->nb_samples); ////循环读取数据,直到buf里数据采样数不够 //while (av_audio_fifo_size(fifo) >= (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : AUDIO_BUF_SIZE)) //{ // av_frame_free(&frame); // frame = av_frame_alloc(); // frame->nb_samples = pOutputCodecCtx->frame_size>0 ? pOutputCodecCtx->frame_size : AUDIO_BUF_SIZE; // frame->channel_layout = pOutputCodecCtx->channel_layout; // frame->format = pOutputCodecCtx->sample_fmt; // frame->sample_rate = pOutputCodecCtx->sample_rate; // av_frame_get_buffer(frame, 0); // av_audio_fifo_read(fifo, (void **)frame->data, (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : AUDIO_BUF_SIZE)); // av_init_packet(&pkt_out); // //frame->pts = pFrame->pts; // int got_picture = -1; // pkt_out.data = NULL; // pkt_out.size = 0; // if (avcodec_encode_audio2(pOutputCodecCtx, &pkt_out, frame, &got_picture) < 0){ // printf("can not decoder a frame"); // } // av_frame_free(&frame); // if (got_picture) // { // pkt_out.pts = frameIndex * pOutputCodecCtx->frame_size; // pkt_out.dts = frameIndex * pOutputCodecCtx->frame_size; // pkt_out.duration = pOutputCodecCtx->frame_size; // //TODO将编码结果后续做合成处理[pkt_out] // if (pFile != NULL){ // /*fwrite((uint8_t *)pDlg->m_streamstate->audio_buf + pDlg->m_streamstate->audio_buf_index, 1, len1, pFile);*/ // } // frameIndex++; // } //} } iRet = 1; END: //swr_free(&au_convert_ctx); SDL_CloseAudio(); SDL_Quit(); av_free(out_buffer); avcodec_close(pOutputCodecCtx); return iRet; }
jint perfetch_start(JNIEnv *pEnv, jobject pObj, jobject pMainAct, jstring pFileName, jint video_fps) { AVFormatContext *pFormatCtx = NULL; int i, videoStream; AVCodecContext *pCodecCtx = NULL; AVCodec *pCodec = NULL; AVFrame *pFrame = NULL; AVFrame *pFrameRGBA = NULL; AVPacket packet; int frameFinished; jobject bitmap; void* buffer; AVDictionary *optionsDict = NULL; struct SwsContext *sws_ctx = NULL; char *videoFileName; // Register all formats and codecs av_register_all(); //get C string from JNI jstring videoFileName = (char *)(*pEnv)->GetStringUTFChars(pEnv, pFileName, NULL); // Open video file if(avformat_open_input(&pFormatCtx, videoFileName, NULL, NULL)!=0) return -1; // Couldn't open file // Retrieve stream information if(avformat_find_stream_info(pFormatCtx, NULL)<0) return -1; // Couldn't find stream information // Dump information about file onto standard error av_dump_format(pFormatCtx, 0, videoFileName, 0); // Find the first video stream videoStream=-1; for(i=0; i<pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) { videoStream=i; break; } } if(videoStream==-1) return -1; // Didn't find a video stream // Get a pointer to the codec context for the video stream pCodecCtx=pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) { fprintf(stderr, "Unsupported codec!\n"); return -1; // Codec not found } // Open codec if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0) return -1; // Could not open codec // Allocate video frame pFrame=avcodec_alloc_frame(); // Allocate an AVFrame structure pFrameRGBA=avcodec_alloc_frame(); if(pFrameRGBA==NULL) return -1; //create a bitmap as the buffer for pFrameRGBA bitmap = createBitmap(pEnv, pCodecCtx->width, pCodecCtx->height); if (AndroidBitmap_lockPixels(pEnv, bitmap, &buffer) < 0) return -1; //get the scaling context sws_ctx = sws_getContext ( pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL ); // Assign appropriate parts of bitmap to image planes in pFrameRGBA // Note that pFrameRGBA is an AVFrame, but AVFrame is a superset // of AVPicture avpicture_fill((AVPicture *)pFrameRGBA, buffer, AV_PIX_FMT_RGBA, pCodecCtx->width, pCodecCtx->height); // Read frames and save first five frames to disk i=0; int ret; int fps = 0; int previous_pts = 0; int current_pts = 0; int prefetch_frame_index = 100; finish = 0; while(finish == 0) { // LOGI("av_read_frame start"); ret = av_read_frame(pFormatCtx, &packet); // LOGI("av_read_frame end"); if (ret <0){ av_free_packet(&packet); break; } // Is this a packet from the video stream? if(packet.stream_index==videoStream) { // Decode video frame LOGI("avcodec_decode_video2 start"); avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); LOGI("avcodec_decode_video2 end"); // Did we get a video frame? if(frameFinished) { if (fps == 0){ if (i == 0){ previous_pts = av_frame_get_best_effort_timestamp ( pFrame ); }else if (i == 8){ current_pts = av_frame_get_best_effort_timestamp ( pFrame ); //fps = 800000/(current_pts - previous_pts); fps = video_fps; LOGI("video fps %d", fps); prefetch_frame_index = fps*16/60; LOGI("prefetch_frame_index %d", prefetch_frame_index); } } if (i++%prefetch_frame_index == 0 && i < 1500){ // Convert the image from its native format to RGBA sws_scale ( sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGBA->data, pFrameRGBA->linesize ); // return the frame to java layer int64_t pts = av_frame_get_best_effort_timestamp ( pFrame ); pts = av_rescale_q ( pts, pFormatCtx->streams[videoStream]->time_base, AV_TIME_BASE_Q ); LOGI("save frame %d, pts: %d", i, (int)pts); SaveFrame(pEnv, pMainAct, bitmap, pCodecCtx->width, pCodecCtx->height, i, pts); int got_packet_ptr; AVCodecContext *c= NULL; c = avcodec_alloc_context3(avcodec_find_encoder(pCodecCtx->codec_id)); if (!c) { LOGI("Could not allocate video codec context\n"); return 0; } av_free_packet(&packet); } } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); } LOGI("final frame %d", i); //unlock the bitmap AndroidBitmap_unlockPixels(pEnv, bitmap); // Free the RGB image av_free(pFrameRGBA); // Free the YUV frame av_free(pFrame); // Close the codec avcodec_close(pCodecCtx); // Close the video file avformat_close_input(&pFormatCtx); return 0; }
JNIEXPORT void JNICALL Java_com_parizene_streamer_Streamer_init(JNIEnv *env, jobject obj, jstring filename, jint width, jint height, jint frameRate) { LOGD("init()"); av_register_all(); AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!codec) { LOGE("codec not found"); exit(1); } codecContext = avcodec_alloc_context3(codec); if (!codec) { LOGE("couldn't allocate codec context"); exit(1); } /* put sample parameters */ codecContext->bit_rate = 400000; /* resolution must be a multiple of two */ codecContext->width = width; codecContext->height = height; /* frames per second */ codecContext->time_base = (AVRational ) {1, frameRate}; codecContext->gop_size = frameRate; /* emit one intra frame every ten frames */ codecContext->max_b_frames = 1; codecContext->pix_fmt = AV_PIX_FMT_YUV420P; av_opt_set(codecContext->priv_data, "profile", "baseline", 0); av_opt_set(codecContext->priv_data, "preset", "ultrafast", 0); if (avcodec_open2(codecContext, codec, NULL) < 0) { LOGE("couldn't open codec"); exit(1); } inputFilename = env->GetStringUTFChars(filename, NULL); file = fopen(inputFilename, "wb"); if (!file) { LOGE("couldn't open %s", inputFilename); exit(1); } frame = avcodec_alloc_frame(); if (!frame) { LOGE("couldn't allocate frame"); exit(1); } frame->format = codecContext->pix_fmt; frame->width = codecContext->width; frame->height = codecContext->height; if (av_image_alloc(frame->data, frame->linesize, codecContext->width, codecContext->height, codecContext->pix_fmt, 32) < 0) { LOGE("couldn't allocate raw picture buffer"); exit(1); } tmpFrame = avcodec_alloc_frame(); if (!tmpFrame) { LOGE("couldn't allocate frame"); exit(1); } if (av_image_alloc(tmpFrame->data, tmpFrame->linesize, codecContext->width, codecContext->height, AV_PIX_FMT_NV21, 32) < 0) { LOGE("couldn't allocate raw picture buffer"); exit(1); } count = 0; }
bool COMXAudioCodecOMX::Open(COMXStreamInfo &hints, enum PCMLayout layout) { AVCodec* pCodec; m_bOpenedCodec = false; avcodec_register_all(); pCodec = avcodec_find_decoder(hints.codec); if (!pCodec) { LOG_TRACE_2 << "COMXAudioCodecOMX::Open() Unable to find codec " << hints.codec; return false; } m_bFirstFrame = true; m_pCodecContext = avcodec_alloc_context3(pCodec); m_pCodecContext->debug_mv = 0; m_pCodecContext->debug = 0; m_pCodecContext->workaround_bugs = 1; if (pCodec->capabilities & CODEC_CAP_TRUNCATED) m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED; m_channels = 0; m_pCodecContext->channels = hints.channels; m_pCodecContext->sample_rate = hints.samplerate; m_pCodecContext->block_align = hints.blockalign; m_pCodecContext->bit_rate = hints.bitrate; m_pCodecContext->bits_per_coded_sample = hints.bitspersample; if (hints.codec == AV_CODEC_ID_TRUEHD) { if (layout == PCM_LAYOUT_2_0) { m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_STEREO; m_pCodecContext->channels = 2; m_pCodecContext->channel_layout = av_get_default_channel_layout(m_pCodecContext->channels); } else if (layout <= PCM_LAYOUT_5_1) { m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_5POINT1; m_pCodecContext->channels = 6; m_pCodecContext->channel_layout = av_get_default_channel_layout(m_pCodecContext->channels); } } if (m_pCodecContext->request_channel_layout) LOG_TRACE_2 << "COMXAudioCodecOMX::Open() Requesting channel layout of " << (unsigned)m_pCodecContext->request_channel_layout; if(m_pCodecContext->bits_per_coded_sample == 0) m_pCodecContext->bits_per_coded_sample = 16; if( hints.extradata && hints.extrasize > 0 ) { m_pCodecContext->extradata_size = hints.extrasize; m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); } if (avcodec_open2(m_pCodecContext, pCodec, NULL) < 0) { LOG_TRACE_2 << "COMXAudioCodecOMX::Open() Unable to open codec"; Dispose(); return false; } m_pFrame1 = av_frame_alloc(); m_bOpenedCodec = true; m_iSampleFormat = AV_SAMPLE_FMT_NONE; m_desiredSampleFormat = m_pCodecContext->sample_fmt == AV_SAMPLE_FMT_S16 ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLTP; return true; }
int CVideoDecoder::open(void) { int ret = 0; bOpen = true; pFormatCtx = avformat_alloc_context(); const int BUF_LEN = (1024 * 200); iobuffer = (unsigned char *)av_malloc(BUF_LEN); avio = avio_alloc_context(iobuffer, BUF_LEN, 0, this, fill_iobuffer, NULL, NULL); pFormatCtx->pb = avio; if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0){ bOpen = false; return -1; // Couldn't open file } // Retrieve stream information if (avformat_find_stream_info(pFormatCtx, NULL)<0){ bOpen = false; return -1; // Couldn't find stream information } // Find the first video stream videoStream = -1; unsigned int i; for (i = 0; i<pFormatCtx->nb_streams; i++) if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; break; } if (videoStream == -1){ bOpen = false; return -1; // Didn't find a video stream } /*AV_SAMPLE_FMT_S16;*/ // Get a pointer to the codec context for the video stream pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec; if (!pCodecCtxOrig){ fprintf(stderr, "Unsupported codec!\n"); bOpen = false; return -1; // Codec not found } // Find the decoder for the video stream pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id); if (pCodec == NULL) { fprintf(stderr, "Unsupported codec!\n"); bOpen = false; return -1; // Codec not found } // Copy context pCodecCtx = avcodec_alloc_context3(pCodec); if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) { fprintf(stderr, "Couldn't copy codec context"); bOpen = false; return -1; // Error copying codec context } // Open codec if (avcodec_open2(pCodecCtx, pCodec, NULL)<0){ bOpen = false; return -1; // Could not open codec } // Allocate video frame pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); // Make a screen to put our video if (hWin){ screen = SDL_CreateWindowFrom(hWin); RECT rc; GetClientRect(hWin, &rc); SDL_SetWindowSize(screen, rc.right - rc.left, rc.bottom - rc.top); rect_dst.x = rect_dst.y = 0; rect_dst.w = rc.right - rc.left; rect_dst.h = rc.bottom - rc.top; } else screen = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, pCodecCtx->width, pCodecCtx->height, 0); renderer = SDL_CreateRenderer(screen, -1, 0); if (!screen) { fprintf(stderr, "SDL: could not set video mode - exiting\n"); bOpen = false; return -1;; } // Allocate a place to put our YUV image on that screen texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV /*SDL_PIXELFORMAT_YV12*/, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height); // initialize SWS context for software scaling sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL ); int numBytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); uint8_t* buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); bOpen = true; //bStop = false; //start(); return ret; }
struct enc_handle *encode_open(struct enc_param param) { struct enc_handle *handle = malloc(sizeof(struct enc_handle)); if (!handle) { printf("--- malloc enc handle failed\n"); return NULL; } CLEAR(*handle); handle->codec = NULL; handle->ctx = NULL; handle->frame = NULL; handle->inbuffer = NULL; handle->inbufsize = 0; handle->frame_counter = 0; handle->params.src_picwidth = param.src_picwidth; handle->params.src_picheight = param.src_picheight; handle->params.enc_picwidth = param.enc_picwidth; handle->params.enc_picheight = param.enc_picheight; handle->params.fps = param.fps; handle->params.bitrate = param.bitrate; handle->params.gop = param.gop; handle->params.chroma_interleave = param.chroma_interleave; avcodec_register_all(); handle->codec = avcodec_find_encoder(AV_CODEC_ID_H264); if (!handle->codec) { printf("--- H264 codec not found\n"); goto err0; } handle->ctx = avcodec_alloc_context3(handle->codec); if (!handle->ctx) { printf("--- Could not allocate video codec context\n"); goto err0; } handle->ctx->bit_rate = handle->params.bitrate * 1000; // to kbps handle->ctx->width = handle->params.src_picwidth; handle->ctx->height = handle->params.src_picheight; handle->ctx->time_base = (AVRational ) { 1, handle->params.fps }; // frames per second handle->ctx->gop_size = handle->params.gop; handle->ctx->max_b_frames = 1; handle->ctx->pix_fmt = AV_PIX_FMT_YUV420P; // handle->ctx->thread_count = 1; // eliminate frame delay! av_opt_set(handle->ctx->priv_data, "preset", "ultrafast", 0); av_opt_set(handle->ctx->priv_data, "tune", "zerolatency", 0); av_opt_set(handle->ctx->priv_data, "x264opts", "no-mbtree:sliced-threads:sync-lookahead=0", 0); if (avcodec_open2(handle->ctx, handle->codec, NULL) < 0) { printf("--- Could not open codec\n"); goto err1; } handle->frame = av_frame_alloc(); if (!handle->frame) { printf("--- Could not allocate video frame\n"); goto err2; } handle->frame->format = handle->ctx->pix_fmt; handle->frame->width = handle->ctx->width; handle->frame->height = handle->ctx->height; handle->inbufsize = avpicture_get_size(AV_PIX_FMT_YUV420P, handle->params.src_picwidth, handle->params.src_picheight); handle->inbuffer = av_malloc(handle->inbufsize); if (!handle->inbuffer) { printf("--- Could not allocate inbuffer\n"); goto err3; } avpicture_fill((AVPicture *) handle->frame, handle->inbuffer, AV_PIX_FMT_YUV420P, handle->params.src_picwidth, handle->params.src_picheight); av_init_packet(&handle->packet); handle->packet.data = NULL; handle->packet.size = 0; printf("+++ Encode Opened\n"); return handle; err3: av_frame_free(&handle->frame); err2: avcodec_close(handle->ctx); err1: av_free(handle->ctx); err0: free(handle); return NULL; }
int CAudioDecoder::open(void) { int ret = 0; bOpen = true; pFormatCtx = avformat_alloc_context(); const int BUF_LEN = (1024 * 200); iobuffer = (unsigned char *)av_malloc(BUF_LEN); avio = avio_alloc_context(iobuffer, BUF_LEN, 0, this, fill_iobuffer, NULL, NULL); pFormatCtx->pb = avio; pFormatCtx->flags = AVFMT_FLAG_CUSTOM_IO; if (avformat_open_input(&pFormatCtx, NULL, NULL, NULL) != 0){ bOpen = false; return -1; // Couldn't open file } // Retrieve stream information if (avformat_find_stream_info(pFormatCtx, NULL)<0){ bOpen = false; return -1; // Couldn't find stream information } // Find the first video stream audioStream = -1; unsigned int i; for (i = 0; i<pFormatCtx->nb_streams; i++) if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioStream = i; break; } if (audioStream == -1){ bOpen = false; return -1; // Didn't find a video stream } /*AV_SAMPLE_FMT_S16;*/ // Get a pointer to the codec context for the video stream pCodecCtxOrig = pFormatCtx->streams[audioStream]->codec; if (!pCodecCtxOrig){ fprintf(stderr, "Unsupported codec!\n"); bOpen = false; return -1; // Codec not found } // Find the decoder for the video stream pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id); if (pCodec == NULL) { fprintf(stderr, "Unsupported codec!\n"); bOpen = false; return -1; // Codec not found } // Copy context pCodecCtx = avcodec_alloc_context3(pCodec); if (avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) { fprintf(stderr, "Couldn't copy codec context"); bOpen = false; return -1; // Error copying codec context } // Open codec if (avcodec_open2(pCodecCtx, pCodec, NULL)<0){ bOpen = false; return -1; // Could not open codec } // Allocate audio frame pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); av_init_packet(&packet); out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2); //Out Audio Param out_channel_layout = AV_CH_LAYOUT_STEREO; out_nb_samples = 1024; out_sample_fmt = AV_SAMPLE_FMT_S16; out_sample_rate = 44100; out_channels = av_get_channel_layout_nb_channels(out_channel_layout); //Out Buffer Size out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1); //SDL_AudioSpec wanted_spec.freq = out_sample_rate; wanted_spec.format = AUDIO_S16SYS; wanted_spec.channels = out_channels; wanted_spec.silence = 0; wanted_spec.samples = 1024/*out_nb_samples*/; wanted_spec.callback = fill_audio; wanted_spec.userdata = pCodecCtx; if (SDL_OpenAudio(&wanted_spec, NULL)<0){ printf("can't open audio.\n"); return -1; } int64_t in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels); au_convert_ctx = swr_alloc(); au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate, in_channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL); swr_init(au_convert_ctx); bOpen = true; //bStop = false; //start(); return ret; }
static bool ffmpeg_init_video(ffmpeg_t *handle) { size_t size; struct ff_config_param *params = &handle->config; struct ff_video_info *video = &handle->video; struct ffemu_params *param = &handle->params; AVCodec *codec = NULL; if (*params->vcodec) codec = avcodec_find_encoder_by_name(params->vcodec); else { /* By default, lossless video. */ av_dict_set(¶ms->video_opts, "qp", "0", 0); codec = avcodec_find_encoder_by_name("libx264rgb"); } if (!codec) { RARCH_ERR("[FFmpeg]: Cannot find vcodec %s.\n", *params->vcodec ? params->vcodec : "libx264rgb"); return false; } video->encoder = codec; /* Don't use swscaler unless format is not something "in-house" scaler * supports. * * libswscale doesn't scale RGB -> RGB correctly (goes via YUV first), * and it's non-trivial to fix upstream as it's heavily geared towards YUV. * If we're dealing with strange formats or YUV, just use libswscale. */ if (params->out_pix_fmt != PIX_FMT_NONE) { video->pix_fmt = params->out_pix_fmt; if (video->pix_fmt != PIX_FMT_BGR24 && video->pix_fmt != PIX_FMT_RGB32) video->use_sws = true; switch (video->pix_fmt) { case PIX_FMT_BGR24: video->scaler.out_fmt = SCALER_FMT_BGR24; break; case PIX_FMT_RGB32: video->scaler.out_fmt = SCALER_FMT_ARGB8888; break; default: break; } } else /* Use BGR24 as default out format. */ { video->pix_fmt = PIX_FMT_BGR24; video->scaler.out_fmt = SCALER_FMT_BGR24; } switch (param->pix_fmt) { case FFEMU_PIX_RGB565: video->scaler.in_fmt = SCALER_FMT_RGB565; video->in_pix_fmt = PIX_FMT_RGB565; video->pix_size = 2; break; case FFEMU_PIX_BGR24: video->scaler.in_fmt = SCALER_FMT_BGR24; video->in_pix_fmt = PIX_FMT_BGR24; video->pix_size = 3; break; case FFEMU_PIX_ARGB8888: video->scaler.in_fmt = SCALER_FMT_ARGB8888; video->in_pix_fmt = PIX_FMT_RGB32; video->pix_size = 4; break; default: return false; } video->codec = avcodec_alloc_context3(codec); /* Useful to set scale_factor to 2 for chroma subsampled formats to * maintain full chroma resolution. (Or just use 4:4:4 or RGB ...) */ param->out_width *= params->scale_factor; param->out_height *= params->scale_factor; video->codec->codec_type = AVMEDIA_TYPE_VIDEO; video->codec->width = param->out_width; video->codec->height = param->out_height; video->codec->time_base = av_d2q((double) params->frame_drop_ratio /param->fps, 1000000); /* Arbitrary big number. */ video->codec->sample_aspect_ratio = av_d2q( param->aspect_ratio * param->out_height / param->out_width, 255); video->codec->pix_fmt = video->pix_fmt; video->codec->thread_count = params->threads; if (params->video_qscale) { video->codec->flags |= CODEC_FLAG_QSCALE; video->codec->global_quality = params->video_global_quality; } else if (params->video_bit_rate) video->codec->bit_rate = params->video_bit_rate; if (handle->muxer.ctx->oformat->flags & AVFMT_GLOBALHEADER) video->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; if (avcodec_open2(video->codec, codec, params->video_opts ? ¶ms->video_opts : NULL) != 0) return false; /* Allocate a big buffer. ffmpeg API doesn't seem to give us some * clues how big this buffer should be. */ video->outbuf_size = 1 << 23; video->outbuf = (uint8_t*)av_malloc(video->outbuf_size); video->frame_drop_ratio = params->frame_drop_ratio; size = avpicture_get_size(video->pix_fmt, param->out_width, param->out_height); video->conv_frame_buf = (uint8_t*)av_malloc(size); video->conv_frame = av_frame_alloc(); avpicture_fill((AVPicture*)video->conv_frame, video->conv_frame_buf, video->pix_fmt, param->out_width, param->out_height); video->conv_frame->width = param->out_width; video->conv_frame->height = param->out_height; video->conv_frame->format = video->pix_fmt; return true; }