From 4fe8f07c82d531fbdc88e60a7c319fc462522cd2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 21 Apr 2012 21:16:00 +0200 Subject: FFMPEGMediaPlayer: Fix NPE; Add remarks about binary incompatibility in upcoming version (master branch) We need native structure access methods to deal with API changes in the libav headers, which break binary compatibility! Currently we are binary compatible w/ [0.6 ?, ] 0.7 and 0.8 but not w/ trunk. Tested: Linux, Windows and OSX (self compiled binary) --- .../jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c | 353 ++++++++++++--------- 1 file changed, 198 insertions(+), 155 deletions(-) (limited to 'src/jogl/native') diff --git a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c index 9acce34f1..647de15ef 100644 --- a/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c +++ b/src/jogl/native/libav/jogamp_opengl_util_av_impl_FFMPEGMediaPlayer.c @@ -90,6 +90,8 @@ static AV_GET_BITS_PER_PIXEL sp_av_get_bits_per_pixel; // count: 18 // libavformat +typedef AVFormatContext *(APIENTRYP AVFORMAT_ALLOC_CONTEXT)(void); +typedef void (APIENTRYP AVFORMAT_FREE_CONTEXT)(AVFormatContext *s); // 52.96.0 typedef void (APIENTRYP AVFORMAT_CLOSE_INPUT)(AVFormatContext **s); // 53.17.0 typedef void (APIENTRYP AV_CLOSE_INPUT_FILE)(AVFormatContext *s); typedef void (APIENTRYP AV_REGISTER_ALL)(void); @@ -101,6 +103,9 @@ typedef int (APIENTRYP AVFORMAT_NETWORK_INIT)(void); typedef int (APIENTRYP AVFORMAT_NETWORK_DEINIT)(void); // 53.13.0 typedef int (APIENTRYP AVFORMAT_FIND_STREAM_INFO)(AVFormatContext *ic, AVDictionary **options); // 53.3.0 typedef int (APIENTRYP AV_FIND_STREAM_INFO)(AVFormatContext *ic); + +static AVFORMAT_ALLOC_CONTEXT sp_avformat_alloc_context; +static AVFORMAT_FREE_CONTEXT sp_avformat_free_context; // 52.96.0 static AVFORMAT_CLOSE_INPUT sp_avformat_close_input; // 53.17.0 static AV_CLOSE_INPUT_FILE sp_av_close_input_file; static AV_REGISTER_ALL sp_av_register_all; @@ -112,9 +117,9 @@ static AVFORMAT_NETWORK_INIT sp_avformat_network_init; // 53.13.0 static AVFORMAT_NETWORK_DEINIT sp_avformat_network_deinit; // 53.13.0 static AVFORMAT_FIND_STREAM_INFO sp_avformat_find_stream_info; // 53.3.0 static AV_FIND_STREAM_INFO sp_av_find_stream_info; -// count: 29 +// count: 31 -#define SYMBOL_COUNT 29 +#define SYMBOL_COUNT 31 JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGDynamicLibraryBundleInfo_initSymbols0 (JNIEnv *env, jclass clazz, jobject jSymbols, jint count) @@ -156,6 +161,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGDynamicLibraryB sp_av_get_bits_per_pixel = (AV_GET_BITS_PER_PIXEL) (intptr_t) symbols[i++]; // count: 18 + sp_avformat_alloc_context = (AVFORMAT_ALLOC_CONTEXT) (intptr_t) symbols[i++];; + sp_avformat_free_context = (AVFORMAT_FREE_CONTEXT) (intptr_t) symbols[i++]; sp_avformat_close_input = (AVFORMAT_CLOSE_INPUT) (intptr_t) symbols[i++]; sp_av_close_input_file = (AV_CLOSE_INPUT_FILE) (intptr_t) symbols[i++]; sp_av_register_all = (AV_REGISTER_ALL) (intptr_t) symbols[i++]; @@ -167,7 +174,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGDynamicLibraryB sp_avformat_network_deinit = (AVFORMAT_NETWORK_DEINIT) (intptr_t) symbols[i++]; sp_avformat_find_stream_info = (AVFORMAT_FIND_STREAM_INFO) (intptr_t) symbols[i++]; sp_av_find_stream_info = (AV_FIND_STREAM_INFO) (intptr_t) symbols[i++]; - // count: 29 + // count: 31 (*env)->ReleasePrimitiveArrayCritical(env, jSymbols, symbols, 0); @@ -186,8 +193,16 @@ static void _updateJavaAttributes(JNIEnv *env, jobject instance, FFMPEGToolBasic // int shallBeDetached = 0; // JNIEnv * env = JoglCommon_GetJNIEnv (&shallBeDetached); if(NULL!=env) { + int32_t w, h; + if( NULL != pAV->pVCodecCtx ) { + // FIXME: Libav Binary compatibility! JAU01 + w = pAV->pVCodecCtx->width; h = pAV->pVCodecCtx->height; + } else { + w = 0; h = 0; + } + (*env)->CallVoidMethod(env, instance, jni_mid_updateAttributes1, - pAV->pVCodecCtx->width, pAV->pVCodecCtx->height, + w, h, pAV->bps_stream, pAV->bps_video, pAV->bps_audio, pAV->fps, (int32_t)((pAV->duration/1000)*pAV->fps), pAV->duration, (*env)->NewStringUTF(env, pAV->vcodec), @@ -204,16 +219,6 @@ static void _updateJavaAttributes(JNIEnv *env, jobject instance, FFMPEGToolBasic static void freeInstance(FFMPEGToolBasicAV_t* pAV) { int i; if(NULL != pAV) { - // Close the video file - if(NULL != pAV->pFormatCtx) { - if(HAS_FUNC(sp_avformat_close_input)) { - sp_avformat_close_input(&pAV->pFormatCtx); - } else { - sp_av_close_input_file(pAV->pFormatCtx); - } - pAV->pFormatCtx = NULL; - } - // Close the V codec if(NULL != pAV->pVCodecCtx) { sp_avcodec_close(pAV->pVCodecCtx); @@ -228,6 +233,7 @@ static void freeInstance(FFMPEGToolBasicAV_t* pAV) { } pAV->pACodec=NULL; + // Close the frames if(NULL != pAV->pVFrame) { sp_av_free(pAV->pVFrame); pAV->pVFrame = NULL; @@ -237,6 +243,18 @@ static void freeInstance(FFMPEGToolBasicAV_t* pAV) { pAV->pAFrame = NULL; } + // Close the video file + if(NULL != pAV->pFormatCtx) { + if(HAS_FUNC(sp_avformat_close_input)) { + sp_avformat_close_input(&pAV->pFormatCtx); + } else { + sp_av_close_input_file(pAV->pFormatCtx); + if(HAS_FUNC(sp_avformat_free_context)) { + sp_avformat_free_context(pAV->pFormatCtx); + } + } + pAV->pFormatCtx = NULL; + } free(pAV); } } @@ -362,171 +380,192 @@ JNIEXPORT void JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_setStre jboolean iscopy; FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)(intptr_t)ptr; - if (pAV != NULL) { - // Open video file - const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy); - res = sp_avformat_open_input(&pAV->pFormatCtx, urlPath, NULL, NULL); - if(res != 0) { + if (pAV == NULL) { + JoglCommon_throwNewRuntimeException(env, "NULL AV ptr"); + return; + } + + pAV->pFormatCtx = sp_avformat_alloc_context(); + + // Open video file + const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy); + res = sp_avformat_open_input(&pAV->pFormatCtx, urlPath, NULL, NULL); + if(res != 0) { + (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); + JoglCommon_throwNewRuntimeException(env, "Couldn't open URL"); + return; + } + + // Retrieve detailed stream information + if(HAS_FUNC(sp_avformat_find_stream_info)) { + if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) { + (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); + JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information"); + return; + } + } else { + if(sp_av_find_stream_info(pAV->pFormatCtx)<0) { (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); - JoglCommon_throwNewRuntimeException(env, "Couldn't open URL"); + JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information"); return; } + } - // Retrieve detailed stream information - if(HAS_FUNC(sp_avformat_find_stream_info)) { - if(sp_avformat_find_stream_info(pAV->pFormatCtx, NULL)<0) { - (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); - JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information"); - return; + if(pAV->verbose) { + // Dump information about file onto standard error + sp_av_dump_format(pAV->pFormatCtx, 0, urlPath, JNI_FALSE); + } + (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); + // FIXME: Libav Binary compatibility! JAU01 + if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) { + pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC; + } + if (pAV->pFormatCtx->start_time != AV_NOPTS_VALUE) { + pAV->start_time = pAV->pFormatCtx->start_time / AV_TIME_BASE_MSEC; + } + if (pAV->pFormatCtx->bit_rate) { + pAV->bps_stream = pAV->pFormatCtx->bit_rate; + } + + fprintf(stderr, "Streams: %d\n", pAV->pFormatCtx->nb_streams); // JAU + + // Find the first audio and video stream, or the one matching vid + // FIXME: Libav Binary compatibility! JAU01 + for(i=0; ( -1==pAV->aid || -1==pAV->vid ) && ipFormatCtx->nb_streams; i++) { + AVStream *st = pAV->pFormatCtx->streams[i]; + fprintf(stderr, "Stream: %d: is-video %d, is-audio %d\n", i, (AVMEDIA_TYPE_VIDEO == st->codec->codec_type), AVMEDIA_TYPE_AUDIO == st->codec->codec_type); // JAU + if(AVMEDIA_TYPE_VIDEO == st->codec->codec_type) { + if(-1==pAV->vid && (-1==vid || vid == i) ) { + pAV->pVStream = st; + pAV->vid=i; } - } else { - if(sp_av_find_stream_info(pAV->pFormatCtx)<0) { - (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); - JoglCommon_throwNewRuntimeException(env, "Couldn't find stream information"); - return; + } else if(AVMEDIA_TYPE_AUDIO == st->codec->codec_type) { + if(-1==pAV->aid && (-1==aid || aid == i) ) { + pAV->pAStream = st; + pAV->aid=i; } } + } + + fprintf(stderr, "Found vid %d, aid %d\n", pAV->vid, pAV->aid); // JAU + + if(0<=pAV->aid) { + // Get a pointer to the codec context for the audio stream + // FIXME: Libav Binary compatibility! JAU01 + pAV->pACodecCtx=pAV->pAStream->codec; - if(pAV->verbose) { - // Dump information about file onto standard error - sp_av_dump_format(pAV->pFormatCtx, 0, urlPath, JNI_FALSE); + // FIXME: Libav Binary compatibility! JAU01 + if (pAV->pACodecCtx->bit_rate) { + pAV->bps_audio = pAV->pACodecCtx->bit_rate; } - (*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath); - if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) { - pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC; + sp_avcodec_string(pAV->acodec, sizeof(pAV->acodec), pAV->pACodecCtx, 0); + + // Find the decoder for the audio stream + pAV->pACodec=sp_avcodec_find_decoder(pAV->pACodecCtx->codec_id); + if(pAV->pACodec==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't find audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec); + return; } - if (pAV->pFormatCtx->start_time != AV_NOPTS_VALUE) { - pAV->start_time = pAV->pFormatCtx->start_time / AV_TIME_BASE_MSEC; + + // Open codec + if(HAS_FUNC(sp_avcodec_open2)) { + res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL); + } else { + res = sp_avcodec_open(pAV->pACodecCtx, pAV->pACodec); } - if (pAV->pFormatCtx->bit_rate) { - pAV->bps_stream = pAV->pFormatCtx->bit_rate; + if(res<0) { + JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec); + return; } - // Find the first audio and video stream, or the one matching vid - for(i=0; ( -1==pAV->aid || -1==pAV->vid ) && ipFormatCtx->nb_streams; i++) { - AVStream *st = pAV->pFormatCtx->streams[i]; - if(AVMEDIA_TYPE_VIDEO == st->codec->codec_type) { - if(-1==pAV->vid && (-1==vid || vid == i) ) { - pAV->pVStream = st; - pAV->vid=i; - } - } else if(AVMEDIA_TYPE_AUDIO == st->codec->codec_type) { - if(-1==pAV->aid && (-1==aid || aid == i) ) { - pAV->pAStream = st; - pAV->aid=i; - } - } + // Allocate audio frames + // FIXME: Libav Binary compatibility! JAU01 + pAV->aSampleRate = pAV->pACodecCtx->sample_rate; + pAV->aChannels = pAV->pACodecCtx->channels; + pAV->aFrameSize = pAV->pACodecCtx->frame_size; + pAV->aSampleFmt = pAV->pACodecCtx->sample_fmt; + pAV->pAFrame=sp_avcodec_alloc_frame(); + if(pAV->pAFrame==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't alloc audio frame"); + return; } + } - if(0<=pAV->aid) { - // Get a pointer to the codec context for the audio stream - pAV->pACodecCtx=pAV->pAStream->codec; - - if (pAV->pACodecCtx->bit_rate) { - pAV->bps_audio = pAV->pACodecCtx->bit_rate; - } - sp_avcodec_string(pAV->acodec, sizeof(pAV->acodec), pAV->pACodecCtx, 0); - - // Find the decoder for the audio stream - pAV->pACodec=sp_avcodec_find_decoder(pAV->pACodecCtx->codec_id); - if(pAV->pACodec==NULL) { - JoglCommon_throwNewRuntimeException(env, "Couldn't find audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec); - return; - } - - // Open codec - if(HAS_FUNC(sp_avcodec_open2)) { - res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL); - } else { - res = sp_avcodec_open(pAV->pACodecCtx, pAV->pACodec); - } - if(res<0) { - JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec); - return; - } - - // Allocate audio frames - pAV->aSampleRate = pAV->pACodecCtx->sample_rate; - pAV->aChannels = pAV->pACodecCtx->channels; - pAV->aFrameSize = pAV->pACodecCtx->frame_size; - pAV->aSampleFmt = pAV->pACodecCtx->sample_fmt; - pAV->pAFrame=sp_avcodec_alloc_frame(); - if(pAV->pAFrame==NULL) { - JoglCommon_throwNewRuntimeException(env, "Couldn't alloc audio frame"); - return; - } + if(0<=pAV->vid) { + // Get a pointer to the codec context for the video stream + // FIXME: Libav Binary compatibility! JAU01 + pAV->pVCodecCtx=pAV->pVStream->codec; + #if 0 + pAV->pVCodecCtx->get_format = my_get_format; + #endif + + if (pAV->pVCodecCtx->bit_rate) { + // FIXME: Libav Binary compatibility! JAU01 + pAV->bps_video = pAV->pVCodecCtx->bit_rate; } + sp_avcodec_string(pAV->vcodec, sizeof(pAV->vcodec), pAV->pVCodecCtx, 0); - if(0<=pAV->vid) { - // Get a pointer to the codec context for the video stream - pAV->pVCodecCtx=pAV->pVStream->codec; - #if 0 - pAV->pVCodecCtx->get_format = my_get_format; - #endif - - if (pAV->pVCodecCtx->bit_rate) { - pAV->bps_video = pAV->pVCodecCtx->bit_rate; - } - sp_avcodec_string(pAV->vcodec, sizeof(pAV->vcodec), pAV->pVCodecCtx, 0); + // Find the decoder for the video stream + pAV->pVCodec=sp_avcodec_find_decoder(pAV->pVCodecCtx->codec_id); + if(pAV->pVCodec==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't find video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec); + return; + } - // Find the decoder for the video stream - pAV->pVCodec=sp_avcodec_find_decoder(pAV->pVCodecCtx->codec_id); - if(pAV->pVCodec==NULL) { - JoglCommon_throwNewRuntimeException(env, "Couldn't find video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec); - return; - } + // Open codec + if(HAS_FUNC(sp_avcodec_open2)) { + res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL); + } else { + res = sp_avcodec_open(pAV->pVCodecCtx, pAV->pVCodec); + } + if(res<0) { + JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec); + return; + } - // Open codec - if(HAS_FUNC(sp_avcodec_open2)) { - res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL); + // Hack to correct wrong frame rates that seem to be generated by some codecs + // FIXME: Libav Binary compatibility! JAU01 + if(pAV->pVCodecCtx->time_base.num>1000 && pAV->pVCodecCtx->time_base.den==1) { + pAV->pVCodecCtx->time_base.den=1000; + } + // FIXME: Libav Binary compatibility! JAU01 + pAV->fps = my_av_q2f(pAV->pVStream->avg_frame_rate); + + // Allocate video frames + // FIXME: Libav Binary compatibility! JAU01 + pAV->vPixFmt = pAV->pVCodecCtx->pix_fmt; + { + AVPixFmtDescriptor pixDesc = sp_av_pix_fmt_descriptors[pAV->vPixFmt]; + pAV->vBitsPerPixel = sp_av_get_bits_per_pixel(&pixDesc); + pAV->vBufferPlanes = my_getPlaneCount(&pixDesc); + } + pAV->pVFrame=sp_avcodec_alloc_frame(); + if( pAV->pVFrame == NULL ) { + JoglCommon_throwNewRuntimeException(env, "Couldn't alloc video frame"); + return; + } + res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame); + if(0==res) { + const int32_t bytesPerPixel = ( pAV->vBitsPerPixel + 7 ) / 8 ; + if(1 == pAV->vBufferPlanes) { + pAV->vBytesPerPixelPerPlane = bytesPerPixel; } else { - res = sp_avcodec_open(pAV->pVCodecCtx, pAV->pVCodec); + pAV->vBytesPerPixelPerPlane = 1; } - if(res<0) { - JoglCommon_throwNewRuntimeException(env, "Couldn't open video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec); - return; - } - - // Hack to correct wrong frame rates that seem to be generated by some codecs - if(pAV->pVCodecCtx->time_base.num>1000 && pAV->pVCodecCtx->time_base.den==1) { - pAV->pVCodecCtx->time_base.den=1000; - } - pAV->fps = my_av_q2f(pAV->pVStream->avg_frame_rate); - - // Allocate video frames - pAV->vPixFmt = pAV->pVCodecCtx->pix_fmt; - { - AVPixFmtDescriptor pixDesc = sp_av_pix_fmt_descriptors[pAV->vPixFmt]; - pAV->vBitsPerPixel = sp_av_get_bits_per_pixel(&pixDesc); - pAV->vBufferPlanes = my_getPlaneCount(&pixDesc); - } - pAV->pVFrame=sp_avcodec_alloc_frame(); - if( pAV->pVFrame == NULL ) { - JoglCommon_throwNewRuntimeException(env, "Couldn't alloc video frame"); - return; - } - res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame); - if(0==res) { - const int32_t bytesPerPixel = ( pAV->vBitsPerPixel + 7 ) / 8 ; - if(1 == pAV->vBufferPlanes) { - pAV->vBytesPerPixelPerPlane = bytesPerPixel; - } else { - pAV->vBytesPerPixelPerPlane = 1; - } - for(i=0; i<3; i++) { - pAV->vLinesize[i] = pAV->pVFrame->linesize[i]; - pAV->vTexWidth[i] = pAV->vLinesize[i] / pAV->vBytesPerPixelPerPlane ; - } - sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame); - } else { - JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension"); - return; + for(i=0; i<3; i++) { + // FIXME: Libav Binary compatibility! JAU01 + pAV->vLinesize[i] = pAV->pVFrame->linesize[i]; + pAV->vTexWidth[i] = pAV->vLinesize[i] / pAV->vBytesPerPixelPerPlane ; } + sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame); + } else { + JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension"); + return; } - pAV->vPTS=0; - pAV->aPTS=0; - _updateJavaAttributes(env, instance, pAV); } + pAV->vPTS=0; + pAV->aPTS=0; + _updateJavaAttributes(env, instance, pAV); } JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNextPacket0 @@ -595,6 +634,7 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex if(frameFinished) { res = 2; + // FIXME: Libav Binary compatibility! JAU01 const AVRational time_base = pAV->pVStream->time_base; const int64_t pts = pAV->pVFrame->pkt_pts; if(AV_NOPTS_VALUE != pts) { // discard invalid PTS .. @@ -614,6 +654,7 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex #endif // 1st plane or complete packed frame + // FIXME: Libav Binary compatibility! JAU01 procAddrGLTexSubImage2D(texTarget, 0, 0, 0, pAV->vTexWidth[0], pAV->pVCodecCtx->height, @@ -621,11 +662,13 @@ JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGMediaPlayer_readNex if(pAV->vPixFmt == PIX_FMT_YUV420P) { // U plane + // FIXME: Libav Binary compatibility! JAU01 procAddrGLTexSubImage2D(texTarget, 0, pAV->pVCodecCtx->width, 0, pAV->vTexWidth[1], pAV->pVCodecCtx->height/2, texFmt, texType, pAV->pVFrame->data[1]); // V plane + // FIXME: Libav Binary compatibility! JAU01 procAddrGLTexSubImage2D(texTarget, 0, pAV->pVCodecCtx->width, pAV->pVCodecCtx->height/2, pAV->vTexWidth[2], pAV->pVCodecCtx->height/2, -- cgit v1.2.3