3#ifdef MOVIETEXTURE_FFMPEG
18#include "libavutil/imgutils.h"
25#include "libavformat/avformat.h"
27#include "libswscale/swscale.h"
34#include "libswresample/swresample.h"
39#include "../opengl/Textures.h"
42#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
43#define av_frame_alloc avcodec_alloc_frame
44#define av_frame_free avcodec_free_frame
50void SaveFrame(AVFrame *pFrame,
int width,
int height,
int nchan,
int iFrame) {
56 sprintf(szFilename,
"frame%d.ppm", iFrame);
57 pFile=fopen(szFilename,
"wb");
62 fprintf(pFile,
"P6\n%d %d\n255\n", width, height);
65 for(y=0; y<height; y++)
66 fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*nchan, pFile);
71float fwroundf(
float val){
75 singv = val < 0.0f ? -1.0f : 1.0f;
84struct fw_movietexture {
90 int width,height,nchan,nframes,fps;
91 unsigned char **frames;
93 unsigned char *audio_buf;
99int movie_load_from_file(
char *fname,
void **opaque){
101 struct fw_movietexture fw_movie;
102 AVFormatContext *pFormatCtx;
103 int i, videoStream, audioStream;
104 AVCodecContext *pCodecCtxOrig;
105 AVCodecContext *pCodecCtx;
106 AVCodecContext *aCodecCtxOrig;
107 AVCodecContext *aCodecCtx;
113 unsigned int audio_buf_size;
114 unsigned int audio_buf_index;
117 int audio_resample_target_fmt;
118 int do_audio_resample;
119 struct SwsContext *sws_ctx;
124 Stack *fw_framequeue;
140 if(avformat_open_input(&pFormatCtx, fname, NULL, NULL)!=0)
144 if(avformat_find_stream_info(pFormatCtx, NULL)<0)
148 av_dump_format(pFormatCtx, 0, fname, 0);
151 pCodecCtxOrig = NULL;
157 for(i=0; i<pFormatCtx->nb_streams; i++){
158 if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO && videoStream < 0) {
161 if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && audioStream < 0) {
165 if(videoStream==-1 && audioStream == -1)
171 memset(&fw_movie,0,
sizeof(
struct fw_movietexture));
172 fw_movie.frames = NULL;
173 fw_movie.nframes = 0;
174 fw_movie.audio_buf = NULL;
175 fw_movie.audio_buf_size = 0;
178 aCodecCtxOrig = NULL;
185 audio_buf_size = 1000000;
189 audio_resample_target_fmt = 0;
190 do_audio_resample = FALSE;
193 if(audioStream > -1){
195 aCodecCtxOrig=pFormatCtx->streams[audioStream]->codec;
196 aCodec = avcodec_find_decoder(aCodecCtxOrig->codec_id);
198 fprintf(stderr,
"Unsupported codec!\n");
207 #if LIBAVCODEC_VERSION_MAJOR == 56
209 aCodecCtx = aCodecCtxOrig;
210 #elif LIBAVCODEC_VERSION_MAJOR == 570
212 AVCodecParameters *aparams;
213 aCodecCtx = avcodec_alloc_context3(aCodec);
214 aparams = avcodec_parameters_alloc();
215 avcodec_parameters_from_context(aparams, aCodecCtxOrig);
216 avcodec_parameters_to_context(aCodecCtx,aparams);
217 avcodec_parameters_free(&aparams);
219 #elif LIBAVCODEC_VERSION_MAJOR >= 57
221 aCodecCtx = avcodec_alloc_context3(aCodecCtxOrig->codec);
222 avcodec_parameters_to_context(aCodecCtx, pFormatCtx->streams[audioStream]->codecpar);
223 av_opt_set_int(aCodecCtx,
"refcounted_frames", 1, 0);
227 fw_movie.channels = aCodecCtx->channels;
228 fw_movie.freq = aCodecCtx->sample_rate;
229 fw_movie.bits_per_channel = aCodecCtx->bits_per_raw_sample;
235 printf(
"bits per coded channel=%d\n",aCodecCtx->bits_per_coded_sample);
238 if(avcodec_open2(aCodecCtx, aCodec, NULL) < 0){
239 fprintf(stderr,
"Could not open codec\n");
244 audio_buf = malloc(audio_buf_size);
245 aFrame=av_frame_alloc();
246 aFrameB=av_frame_alloc();
249 audio_resample_target_fmt = aCodecCtx->sample_fmt;
250 if(aCodecCtx->sample_fmt != AV_SAMPLE_FMT_S16) {
251 fw_movie.channels = 2;
252 fw_movie.freq = 44100;
253 fw_movie.bits_per_channel = 16;
254 audio_resample_target_fmt = AV_SAMPLE_FMT_S16;
255 do_audio_resample = TRUE;
272 swr = swr_alloc_set_opts(NULL,
276 aCodecCtx->channel_layout,
277 aCodecCtx->sample_fmt,
278 aCodecCtx->sample_rate,
290 fw_framequeue = NULL;
294 if(videoStream > -1){
299 pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec;
303 pCodec=avcodec_find_decoder(pCodecCtxOrig->codec_id);
305 fprintf(stderr,
"Unsupported codec!\n");
309 #if LIBAVCODEC_VERSION_MAJOR == 56
311 pCodecCtx = pCodecCtxOrig;
312 #elif LIBAVCODEC_VERSION_MAJOR == 570
314 AVCodecParameters *vparams;
315 pCodecCtx = avcodec_alloc_context3(pCodec);
316 vparams = avcodec_parameters_alloc();
317 avcodec_parameters_from_context(vparams, pCodecCtxOrig);
318 avcodec_parameters_to_context(pCodecCtx, vparams);
319 avcodec_parameters_free(&vparams);
321 #elif LIBAVCODEC_VERSION_MAJOR >= 57
323 pCodecCtx = avcodec_alloc_context3(pCodecCtxOrig->codec);
324 avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar);
325 av_opt_set_int(pCodecCtx,
"refcounted_frames", 1, 0);
329 if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
335 pFrame=av_frame_alloc();
338 pFrameRGB=av_frame_alloc();
345 av_pix_fmt = AV_PIX_FMT_RGB24;
348 av_pix_fmt = AV_PIX_FMT_RGBA;
351 fw_movie.nchan = nchan;
352 fw_movie.width = pCodecCtx->width;
353 fw_movie.height = pCodecCtx->height;
357 numBytes = av_image_get_buffer_size(av_pix_fmt, pCodecCtx->width, pCodecCtx->height,1);
358 buffer=(uint8_t *)av_malloc(numBytes*
sizeof(uint8_t));
366 av_image_fill_arrays(pFrameRGB->data,pFrameRGB->linesize,buffer,av_pix_fmt,pCodecCtx->width, pCodecCtx->height,1);
369 sws_ctx = sws_getContext(pCodecCtx->width,
382 fw_framequeue = newStack(
unsigned char *);
387 while(av_read_frame(pFormatCtx, &packet)>=0) {
389 if(packet.stream_index==videoStream) {
391 #if LIBAVCODEC_VERSION_MAJOR < 57
393 avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
396 avcodec_send_packet(pCodecCtx,&packet);
397 frameFinished = avcodec_receive_frame(pCodecCtx,pFrame) == 0? TRUE : FALSE;
402 unsigned char * fw_frame;
404 sws_scale(sws_ctx, (uint8_t
const *
const *)pFrame->data,
405 pFrame->linesize, 0, pCodecCtx->height,
406 pFrameRGB->data, pFrameRGB->linesize);
412 SaveFrame(pFrameRGB, pCodecCtx->width,
413 pCodecCtx->height, nchan, i);
418 fw_frame = malloc(fw_movie.height * fw_movie.width * nchan);
420 for(k=0;k<pCodecCtx->height;k++){
423 kk = pCodecCtx->height - k - 1;
424 ks = k*pFrame->linesize[0]*nchan;
425 kd = kk * fw_movie.width * nchan;
426 src = ((
unsigned char *)pFrameRGB->data[0]) + ks;
427 memcpy(&fw_frame[kd],src,fw_movie.width * nchan);
429 stack_push(
unsigned char *,fw_framequeue,fw_frame);
432 }
else if(packet.stream_index==audioStream) {
442 #if LIBAVCODEC_VERSION_MAJOR < 57
445 len1 = avcodec_decode_audio4(aCodecCtx, aFrame, &got_frame, &packet);
447 avcodec_send_packet(aCodecCtx, &packet);
448 got_frame = avcodec_receive_frame(aCodecCtx, aFrame) == 0 ? TRUE : FALSE;
450 buf_size = audio_buf_size - audio_buf_index;
453 if(aFrame->nb_samples > 0){
454 data_size = av_samples_get_buffer_size(NULL,
462 if(data_size * 2 > buf_size){
463 audio_buf = realloc(audio_buf,audio_buf_size *2);
466 if (do_audio_resample)
473 int nb_samples = aFrame->nb_samples;
474 int channels = aFrame->channels;
475 int outputBufferLen = nb_samples * channels * 2;
476 short* outputBuffer = (
short*)&audio_buf[audio_buf_index];
478 for (i = 0; i < nb_samples; i++)
480 for (c = 0; c < channels; c++)
482 float* extended_data = (
float*)aFrame->extended_data[c];
483 float sample = extended_data[i];
484 if (sample < -1.0f) sample = -1.0f;
485 else if (sample > 1.0f) sample = 1.0f;
486 outputBuffer[i * channels + c] = (short)fwroundf(sample * 32767.0f);
489 audio_buf_index += outputBufferLen;
495 int in_samples = aFrame->nb_samples;
497 int out_samples = (int)av_rescale_rnd(swr_get_delay(swr, aCodecCtx->sample_rate) + in_samples, 44100, aCodecCtx->sample_rate, AV_ROUND_UP);
498 av_samples_alloc(&output, NULL, 2, out_samples, AV_SAMPLE_FMT_S16, 0);
499 out_samples = swr_convert(swr,&output,out_samples, aFrame->extended_data, aFrame->nb_samples);
500 memcpy(&audio_buf[audio_buf_index],output, out_samples * 2 * 2);
501 audio_buf_index += out_samples * 2 * 2;
509 memcpy(&audio_buf[audio_buf_index], aFrame->data[0], data_size);
510 audio_buf_index += data_size;
522 if(videoStream > -1){
523 fw_movie.frames = fw_framequeue->data;
524 fw_movie.nframes = fw_framequeue->n;
525 fw_movie.duration = (double)(fw_movie.nframes) / 30.0;
532 ttip->x = fw_movie.width;
533 ttip->y = fw_movie.height;
536 ttip->channels = nchan;
538 for(k=0;k<fw_movie.nframes;k++){
540 ttip->texdata = fw_movie.frames[k];
541 sprintf(namebuf,
"%s%d.web3dit",
"ffmpeg_frame_",k);
542 saveImage_web3dit(ttip, namebuf);
549 av_frame_free(&pFrameRGB);
552 av_frame_free(&pFrame);
555 avcodec_close(pCodecCtx);
556 avcodec_close(pCodecCtxOrig);
559 if(audioStream > -1){
560 fw_movie.audio_buf = audio_buf;
561 fw_movie.audio_buf_size = audio_buf_index;
562 fw_movie.duration = (double)(fw_movie.nframes) / 30.0;
564 avcodec_close(aCodecCtxOrig);
565 avcodec_close(aCodecCtx);
570 avformat_close_input(&pFormatCtx);
571 *opaque = malloc(
sizeof(
struct fw_movietexture));
572 memcpy(*opaque,&fw_movie,
sizeof(
struct fw_movietexture));
577double movie_get_duration(
void *opaque){
578 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
579 return fw_movie->duration;
582unsigned char *movie_get_frame_by_fraction(
void *opaque,
float fraction,
int *width,
int *height,
int *nchan){
584 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
585 if(!fw_movie)
return NULL;
587 iframe = (int)(fraction * ((
float)(fw_movie->nframes -1) + .5f));
588 iframe = max(0,iframe);
589 iframe = min(fw_movie->nframes -1,iframe);
590 *width = fw_movie->width;
591 *height = fw_movie->height;
592 *nchan = fw_movie->nchan;
593 return fw_movie->frames[iframe];
595unsigned char * movie_get_audio_PCM_buffer(
void *opaque,
int *freq,
int *channels,
int *size,
int *bits){
596 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
597 if(!fw_movie)
return NULL;
598 if(!fw_movie->audio_buf)
return NULL;
599 *freq = fw_movie->freq;
600 *channels = fw_movie->channels;
601 *size = fw_movie->audio_buf_size;
602 *bits = fw_movie->bits_per_channel;
603 return fw_movie->audio_buf;
605void movie_free(
void *opaque){
606 struct fw_movietexture *fw_movie = (
struct fw_movietexture *)opaque;
609 for(k=0;k<fw_movie->nframes;k++){
610 FREE_IF_NZ(fw_movie->frames[k]);