3#ifdef MOVIETEXTURE_FFMPEG
18#include "libavutil/imgutils.h"
25#include "libavformat/avformat.h"
27#include "libswscale/swscale.h"
31#include "libavcodec/avcodec.h"
35#include "libswresample/swresample.h"
40#include "../opengl/Textures.h"
43#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
44#define av_frame_alloc avcodec_alloc_frame
45#define av_frame_free avcodec_free_frame
51void SaveFrame(AVFrame *pFrame,
int width,
int height,
int nchan,
int iFrame) {
57 sprintf(szFilename,
"frame%d.ppm", iFrame);
58 pFile=fopen(szFilename,
"wb");
63 fprintf(pFile,
"P6\n%d %d\n255\n", width, height);
66 for(y=0; y<height; y++)
67 fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*nchan, pFile);
72float fwroundf(
float val){
76 singv = val < 0.0f ? -1.0f : 1.0f;
85struct fw_movietexture {
91 int width,height,nchan,nframes,fps;
92 unsigned char **frames;
94 unsigned char *audio_buf;
100int movie_load_from_file(
char *fname,
void **opaque){
102 struct fw_movietexture fw_movie;
103 AVFormatContext *pFormatCtx;
104 int i, videoStream, audioStream;
105 AVCodecContext *pCodecCtxOrig;
106 AVCodecContext *pCodecCtx;
107 AVCodecContext *aCodecCtxOrig;
108 AVCodecContext *aCodecCtx;
114 unsigned int audio_buf_size;
115 unsigned int audio_buf_index;
118 int audio_resample_target_fmt;
119 int do_audio_resample;
120 struct SwsContext *sws_ctx;
125 Stack *fw_framequeue;
141 if(avformat_open_input(&pFormatCtx, fname, NULL, NULL)!=0)
145 if(avformat_find_stream_info(pFormatCtx, NULL)<0)
149 av_dump_format(pFormatCtx, 0, fname, 0);
152 pCodecCtxOrig = NULL;
158 for(i=0; i<pFormatCtx->nb_streams; i++){
159 if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO && videoStream < 0) {
162 if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_AUDIO && audioStream < 0) {
166 if(videoStream==-1 && audioStream == -1)
172 memset(&fw_movie,0,
sizeof(
struct fw_movietexture));
173 fw_movie.frames = NULL;
174 fw_movie.nframes = 0;
175 fw_movie.audio_buf = NULL;
176 fw_movie.audio_buf_size = 0;
179 aCodecCtxOrig = NULL;
186 audio_buf_size = 1000000;
190 audio_resample_target_fmt = 0;
191 do_audio_resample = FALSE;
194 if(audioStream > -1){
196 aCodecCtxOrig=pFormatCtx->streams[audioStream]->codecpar;
197 aCodec = avcodec_find_decoder(aCodecCtxOrig->codec_id);
199 fprintf(stderr,
"Unsupported codec!\n");
208 #if LIBAVCODEC_VERSION_MAJOR == 56
210 aCodecCtx = aCodecCtxOrig;
211 #elif LIBAVCODEC_VERSION_MAJOR == 570
213 AVCodecParameters *aparams;
214 aCodecCtx = avcodec_alloc_context3(aCodec);
215 aparams = avcodec_parameters_alloc();
216 avcodec_parameters_from_context(aparams, aCodecCtxOrig);
217 avcodec_parameters_to_context(aCodecCtx,aparams);
218 avcodec_parameters_free(&aparams);
220 #elif LIBAVCODEC_VERSION_MAJOR >= 57
222 aCodecCtx = avcodec_alloc_context3(aCodecCtxOrig->codec);
223 avcodec_parameters_to_context(aCodecCtx, pFormatCtx->streams[audioStream]->codecpar);
224 av_opt_set_int(aCodecCtx,
"refcounted_frames", 1, 0);
228 fw_movie.channels = aCodecCtx->channels;
229 fw_movie.freq = aCodecCtx->sample_rate;
230 fw_movie.bits_per_channel = aCodecCtx->bits_per_raw_sample;
236 printf(
"bits per coded channel=%d\n",aCodecCtx->bits_per_coded_sample);
239 if(avcodec_open2(aCodecCtx, aCodec, NULL) < 0){
240 fprintf(stderr,
"Could not open codec\n");
245 audio_buf = malloc(audio_buf_size);
246 aFrame=av_frame_alloc();
247 aFrameB=av_frame_alloc();
250 audio_resample_target_fmt = aCodecCtx->sample_fmt;
251 if(aCodecCtx->sample_fmt != AV_SAMPLE_FMT_S16) {
252 fw_movie.channels = 2;
253 fw_movie.freq = 44100;
254 fw_movie.bits_per_channel = 16;
255 audio_resample_target_fmt = AV_SAMPLE_FMT_S16;
256 do_audio_resample = TRUE;
273 swr = swr_alloc_set_opts(NULL,
277 aCodecCtx->channel_layout,
278 aCodecCtx->sample_fmt,
279 aCodecCtx->sample_rate,
291 fw_framequeue = NULL;
295 if(videoStream > -1){
300 pCodecCtxOrig = pFormatCtx->streams[videoStream]->codecpar;
304 pCodec=avcodec_find_decoder(pCodecCtxOrig->codec_id);
306 fprintf(stderr,
"Unsupported codec!\n");
310 #if LIBAVCODEC_VERSION_MAJOR == 56
312 pCodecCtx = pCodecCtxOrig;
313 #elif LIBAVCODEC_VERSION_MAJOR == 570
315 AVCodecParameters *vparams;
316 pCodecCtx = avcodec_alloc_context3(pCodec);
317 vparams = avcodec_parameters_alloc();
318 avcodec_parameters_from_context(vparams, pCodecCtxOrig);
319 avcodec_parameters_to_context(pCodecCtx, vparams);
320 avcodec_parameters_free(&vparams);
322 #elif LIBAVCODEC_VERSION_MAJOR >= 57
324 pCodecCtx = avcodec_alloc_context3(pCodecCtxOrig->codec);
325 avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar);
326 av_opt_set_int(pCodecCtx,
"refcounted_frames", 1, 0);
330 if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
336 pFrame=av_frame_alloc();
339 pFrameRGB=av_frame_alloc();
346 av_pix_fmt = AV_PIX_FMT_RGB24;
349 av_pix_fmt = AV_PIX_FMT_RGBA;
352 fw_movie.nchan = nchan;
353 fw_movie.width = pCodecCtx->width;
354 fw_movie.height = pCodecCtx->height;
358 numBytes = av_image_get_buffer_size(av_pix_fmt, pCodecCtx->width, pCodecCtx->height,1);
359 buffer=(uint8_t *)av_malloc(numBytes*
sizeof(uint8_t));
367 av_image_fill_arrays(pFrameRGB->data,pFrameRGB->linesize,buffer,av_pix_fmt,pCodecCtx->width, pCodecCtx->height,1);
370 sws_ctx = sws_getContext(pCodecCtx->width,
383 fw_framequeue = newStack(
unsigned char *);
388 while(av_read_frame(pFormatCtx, &packet)>=0) {
390 if(packet.stream_index==videoStream) {
392 #if LIBAVCODEC_VERSION_MAJOR < 57
394 avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
397 avcodec_send_packet(pCodecCtx,&packet);
398 frameFinished = avcodec_receive_frame(pCodecCtx,pFrame) == 0? TRUE : FALSE;
403 unsigned char * fw_frame;
405 sws_scale(sws_ctx, (uint8_t
const *
const *)pFrame->data,
406 pFrame->linesize, 0, pCodecCtx->height,
407 pFrameRGB->data, pFrameRGB->linesize);
413 SaveFrame(pFrameRGB, pCodecCtx->width,
414 pCodecCtx->height, nchan, i);
419 fw_frame = malloc(fw_movie.height * fw_movie.width * nchan);
421 for(k=0;k<pCodecCtx->height;k++){
424 kk = pCodecCtx->height - k - 1;
425 ks = k*pFrame->linesize[0]*nchan;
426 kd = kk * fw_movie.width * nchan;
427 src = ((
unsigned char *)pFrameRGB->data[0]) + ks;
428 memcpy(&fw_frame[kd],src,fw_movie.width * nchan);
430 stack_push(
unsigned char *,fw_framequeue,fw_frame);
433 }
else if(packet.stream_index==audioStream) {
443 #if LIBAVCODEC_VERSION_MAJOR < 57
446 len1 = avcodec_decode_audio4(aCodecCtx, aFrame, &got_frame, &packet);
448 avcodec_send_packet(aCodecCtx, &packet);
449 got_frame = avcodec_receive_frame(aCodecCtx, aFrame) == 0 ? TRUE : FALSE;
451 buf_size = audio_buf_size - audio_buf_index;
454 if(aFrame->nb_samples > 0){
455 data_size = av_samples_get_buffer_size(NULL,
463 if(data_size * 2 > buf_size){
464 audio_buf = realloc(audio_buf,audio_buf_size *2);
467 if (do_audio_resample)
474 int nb_samples = aFrame->nb_samples;
475 int channels = aFrame->channels;
476 int outputBufferLen = nb_samples * channels * 2;
477 short* outputBuffer = (
short*)&audio_buf[audio_buf_index];
479 for (i = 0; i < nb_samples; i++)
481 for (c = 0; c < channels; c++)
483 float* extended_data = (
float*)aFrame->extended_data[c];
484 float sample = extended_data[i];
485 if (sample < -1.0f) sample = -1.0f;
486 else if (sample > 1.0f) sample = 1.0f;
487 outputBuffer[i * channels + c] = (short)fwroundf(sample * 32767.0f);
490 audio_buf_index += outputBufferLen;
496 int in_samples = aFrame->nb_samples;
498 int out_samples = (int)av_rescale_rnd(swr_get_delay(swr, aCodecCtx->sample_rate) + in_samples, 44100, aCodecCtx->sample_rate, AV_ROUND_UP);
499 av_samples_alloc(&output, NULL, 2, out_samples, AV_SAMPLE_FMT_S16, 0);
500 out_samples = swr_convert(swr,&output,out_samples, aFrame->extended_data, aFrame->nb_samples);
501 memcpy(&audio_buf[audio_buf_index],output, out_samples * 2 * 2);
502 audio_buf_index += out_samples * 2 * 2;
510 memcpy(&audio_buf[audio_buf_index], aFrame->data[0], data_size);
511 audio_buf_index += data_size;
523 if(videoStream > -1){
524 fw_movie.frames = fw_framequeue->data;
525 fw_movie.nframes = fw_framequeue->n;
526 fw_movie.duration = (double)(fw_movie.nframes) / 30.0;
533 ttip->x = fw_movie.width;
534 ttip->y = fw_movie.height;
537 ttip->channels = nchan;
539 for(k=0;k<fw_movie.nframes;k++){
541 ttip->texdata = fw_movie.frames[k];
542 sprintf(namebuf,
"%s%d.web3dit",
"ffmpeg_frame_",k);
543 saveImage_web3dit(ttip, namebuf);
550 av_frame_free(&pFrameRGB);
553 av_frame_free(&pFrame);
556 avcodec_close(pCodecCtx);
557 avcodec_close(pCodecCtxOrig);
560 if(audioStream > -1){
561 fw_movie.audio_buf = audio_buf;
562 fw_movie.audio_buf_size = audio_buf_index;
563 fw_movie.duration = (double)(fw_movie.nframes) / 30.0;
565 avcodec_close(aCodecCtxOrig);
566 avcodec_close(aCodecCtx);
571 avformat_close_input(&pFormatCtx);
572 *opaque = malloc(
sizeof(
struct fw_movietexture));
573 memcpy(*opaque,&fw_movie,
sizeof(
struct fw_movietexture));
578double movie_get_duration(
void *opaque){
579 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
580 return fw_movie->duration;
583unsigned char *movie_get_frame_by_fraction(
void *opaque,
float fraction,
int *width,
int *height,
int *nchan){
585 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
586 if(!fw_movie)
return NULL;
588 iframe = (int)(fraction * ((
float)(fw_movie->nframes -1) + .5f));
589 iframe = max(0,iframe);
590 iframe = min(fw_movie->nframes -1,iframe);
591 *width = fw_movie->width;
592 *height = fw_movie->height;
593 *nchan = fw_movie->nchan;
594 return fw_movie->frames[iframe];
596unsigned char * movie_get_audio_PCM_buffer(
void *opaque,
int *freq,
int *channels,
int *size,
int *bits){
597 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
598 if(!fw_movie)
return NULL;
599 if(!fw_movie->audio_buf)
return NULL;
600 *freq = fw_movie->freq;
601 *channels = fw_movie->channels;
602 *size = fw_movie->audio_buf_size;
603 *bits = fw_movie->bits_per_channel;
604 return fw_movie->audio_buf;
606void movie_free(
void *opaque){
607 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
610 for(k=0;k<fw_movie->nframes;k++){
611 FREE_IF_NZ(fw_movie->frames[k]);