1 /******************************************************************************
2 * FOBS Java JMF Native PlugIn
3 * This file contain the native implementation of the stand-alone codec that
4 * allows to use all the JMF internals along with ffmpeg. This file is included
5 * as of version 0.3 to provide support for custom DataSources. Some issues has
6 * been detected using this classes. See documentation for further details.
8 * Copyright (c) 2004 Omnividea Multimedia S.L
9 * Coded by JosĀ San Pedro Wandelmer
11 * This file is part of FOBS.
13 * FOBS is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as
15 * published by the Free Software Foundation; either version 2.1
16 * of the License, or (at your option) any later version.
18 * FOBS is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with FOBS; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ******************************************************************************/
33 //#include <libavformat/avformat.h>
35 //#include <libavcodec/avcodec.h>
37 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
47 #include "com_omnividea_media_codec_video_JavaDecoder.h"
48 #include "com_omnividea_media_codec_audio_JavaDecoder.h"
50 (JNIEnv *env, jobject obj, jint peer,
51 jobject jinBuffer, jlong inBytes, jint inOffset,
52 jobject joutBuffer, jlong outBytes, jlong size, jdouble dts);
55 * Wrapper structure that holds relevant data per codec instance.
59 //AVCodecParserContext *parser_context;
60 AVCodecContext *codec_context;
72 /* temporary buffer used for encoding h263/rtp ONLY (i.e. not
73 * for encoding plain old h263). NULL during decode */
83 CodecID getCodecId(char *t)
85 CodecID id = CODEC_ID_NONE;
86 int iTag = MKTAG(t[0], t[1], t[2], t[3]);
88 id = codec_get_id(codec_bmp_tags, iTag);
89 if(id != CODEC_ID_NONE) return id;
90 id = codec_get_id(mov_video_tags, iTag);
91 if(id != CODEC_ID_NONE) return id;
92 id = codec_get_id(nsv_codec_video_tags, iTag);
93 if(id != CODEC_ID_NONE) return id;
95 id = codec_get_id(codec_wav_tags, iTag);
96 if(id != CODEC_ID_NONE) return id;
97 id = codec_get_id(mov_audio_tags, iTag);
98 if(id != CODEC_ID_NONE) return id;
99 id = codec_get_id(nsv_codec_audio_tags, iTag);
100 if(id != CODEC_ID_NONE) return id;
105 CodecID _getCodecId(char *tag)
107 if(!strcasecmp(tag, "iv31") ||
108 !strcasecmp(tag, "iv32"))
110 return CODEC_ID_INDEO3;
113 else if(!strcasecmp(tag, "msvc") ||
114 !strcasecmp(tag, "cram") ||
115 !strcasecmp(tag, "wham"))
117 return CODEC_ID_MSVIDEO1;
119 else if(!strcasecmp(tag, "wmv1"))
121 return CODEC_ID_WMV1;
123 else if(!strcasecmp(tag, "wmv2"))
125 return CODEC_ID_WMV2;
127 else if(!strcasecmp(tag, "mpeg") ||
128 !strcasecmp(tag, "mpg1") ||
129 !strcasecmp(tag, "pim1") ||
130 !strcasecmp(tag, "vcr2") ||
131 !strcasecmp(tag, "mpg2"))
133 return CODEC_ID_MPEG1VIDEO;
135 else if(!strcasecmp(tag, "mjpa") ||
136 !strcasecmp(tag, "mjpb") ||
137 !strcasecmp(tag, "mjpg") ||
138 !strcasecmp(tag, "ljpg") ||
139 !strcasecmp(tag, "avdj") ||
140 !strcasecmp(tag, "jpgl"))
142 return CODEC_ID_MJPEG;
144 else if(!strcasecmp(tag, "svq1") ||
145 !strcasecmp(tag, "svqi"))
147 return CODEC_ID_SVQ1;
149 else if(!strcasecmp(tag, "sv31"))
151 return CODEC_ID_SVQ3;
153 else if(!strcasecmp(tag, "mp4v") ||
154 !strcasecmp(tag, "divx") ||
155 !strcasecmp(tag, "dx50") ||
156 !strcasecmp(tag, "xvid") ||
157 !strcasecmp(tag, "mp4s") ||
158 !strcasecmp(tag, "div1") ||
159 !strcasecmp(tag, "blz0") ||
160 !strcasecmp(tag, "ump4") ||
161 !strcasecmp(tag, "m4s2"))
163 return CODEC_ID_MPEG4;
165 else if(!strcasecmp(tag, "h264"))
167 return CODEC_ID_H264;
169 else if(!strcasecmp(tag, "h263"))
171 return CODEC_ID_H263;
173 else if(!strcasecmp(tag, "u263") ||
174 !strcasecmp(tag, "viv1"))
176 return CODEC_ID_H263P;
178 /* else if(!strcasecmp(tag, "i263"))
180 return CODEC_ID_I263;
182 else if(!strcasecmp(tag, "dvc") ||
183 !strcasecmp(tag, "dvcp") ||
184 !strcasecmp(tag, "dvsd") ||
185 !strcasecmp(tag, "dvhs") ||
186 !strcasecmp(tag, "dvs1") ||
187 !strcasecmp(tag, "dv25"))
189 return CODEC_ID_DVVIDEO;
191 else if(!strcasecmp(tag, "vp31"))
195 /*else if(!strcasecmp(tag, "rpza"))
197 return CODEC_ID_RPZA;
199 else if(!strcasecmp(tag, "cvid"))
201 return CODEC_ID_CINEPAK;
203 else if(!strcasecmp(tag, "smc"))
207 else if(!strcasecmp(tag, "mp42")||
208 !strcasecmp(tag, "div2"))
210 return CODEC_ID_MSMPEG4V2;
212 else if(!strcasecmp(tag, "mpg4"))
214 return CODEC_ID_MSMPEG4V1;
216 else if(!strcasecmp(tag, "div3") ||
217 !strcasecmp(tag, "mp43") ||
218 !strcasecmp(tag, "mpg3") ||
219 !strcasecmp(tag, "div5") ||
220 !strcasecmp(tag, "div6") ||
221 !strcasecmp(tag, "div4") ||
222 !strcasecmp(tag, "ap41") ||
223 !strcasecmp(tag, "col1") ||
224 !strcasecmp(tag, "col0"))
226 return CODEC_ID_MSMPEG4V3;
228 return CODEC_ID_NONE;
233 int tmp = 0x12345678;
234 char *buf = (char*)(&tmp);
235 //printf("%x %x %x %x\n", (int)buf[0], (int)buf[1], (int)buf[2], (int)buf[3]);
236 if(buf[0]==0x78) return (jboolean)0;
237 else return (jboolean)1;
242 * Class: com_omnividea_media_codec_video_JavaDecoder
243 * Method: isBigEndian
246 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_video_JavaDecoder_isBigEndian
247 (JNIEnv *env, jclass cl)
249 return (jboolean)isBigEndianSA();
254 static void setOutputDone(JNIEnv *env, jobject obj, int done) {
255 jclass clazz = env->GetObjectClass(obj);
256 jfieldID fid = env->GetFieldID(clazz, "outputDone", "Z");
257 env->SetIntField(obj, fid, (jboolean)done);
262 * Class: com_omnividea_media_codec_video_JavaDecoder
266 JNIEXPORT void JNICALL Java_com_omnividea_media_codec_video_JavaDecoder_init
267 (JNIEnv *env, jobject obj)
269 FFMPEGWrapper *wrapper;
273 avcodec_register_all();
278 jclass clazz = env->GetObjectClass(obj);
279 jfieldID fidPeer = env->GetFieldID(clazz, "peer", "I");
280 jint peerVal = env->GetIntField(obj, fidPeer);
285 wrapper = (FFMPEGWrapper *) av_malloc( sizeof(FFMPEGWrapper) );
289 memset(wrapper,0,sizeof(FFMPEGWrapper));
291 env->SetIntField(obj, fidPeer, (jint)wrapper);
293 av_log(NULL, AV_LOG_INFO, "obj initialized.\n");
300 * Class: com_omnividea_media_codec_video_JavaDecoder
302 * Signature: (ILjava/lang/String;)Z
304 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_video_JavaDecoder_open_1codec
305 (JNIEnv *env, jobject obj, jint peer, jstring codec_name)
307 FFMPEGWrapper *wrapper;
308 enum CodecID codec_required;
313 wrapper = (FFMPEGWrapper *) peer;
315 // Find matching ffmpeg codec using the codec_name passed in
316 const char *str = env->GetStringUTFChars(codec_name, 0);
318 av_log(NULL, AV_LOG_INFO, "open_codec called for %s\n", str);
320 av_log(NULL, AV_LOG_INFO, "Encoding: %s\n", str);
322 //codec_required = getCodecId((char*)str);
323 codec_required = getCodecId((char*)str);
324 env->ReleaseStringUTFChars(codec_name, str);
325 if (codec_required == CODEC_ID_NONE)
327 av_log(NULL, AV_LOG_INFO, "Codec NOT Found!\n");
330 av_log(NULL, AV_LOG_INFO, "Codec Found: %d\n", codec_required);
333 /* find the video decoder */
334 wrapper->codec = avcodec_find_decoder(codec_required);
335 if (!wrapper->codec ) {
336 //fprintf(stderr, "codec not found\n");
340 // Allocate and zero the codec context and frame. Remember
341 // them in the wrapper structure.
342 AVCodecContext *context = avcodec_alloc_context();
343 wrapper->codec_context = context;
345 //try to alloc some extradata space, just in case
346 context->extradata = (uint8_t*) av_malloc(200); //solve some issues with SVQ3 codec (and maybe others)
347 context->time_base.num = 1;
348 context->time_base.num = 30000;
349 context->sample_aspect_ratio.num = 1;
350 context->sample_aspect_ratio.den = 1;
351 //wrapper->codec_context->bit_rate = 0;
352 //wrapper->codec_context->codec_tag = (str[3] << 24)|(str[2] << 16)|(str[1] << 8)|str[0];
353 //wrapper->codec_context->frame_rate_base = 1001;
354 //wrapper->codec_context->frame_rate *= 1001;
355 //wrapper->picture = avcodec_alloc_frame();
356 //context->flags |= CODEC_FLAG_EMU_EDGE;
357 //context->flags |= CODEC_FLAG_TRUNCATED;
359 /* for some codecs, such as msmpeg4 and mpeg4, width and height
360 MUST be initialized there because these info are not available
362 if(wrapper->codec_context->width ==0)
363 wrapper->codec_context->width = wrapper->width;
364 if(wrapper->codec_context->height == 0)
365 wrapper->codec_context->height = wrapper->height;
368 wrapper->codec_context->codec_id = codec_required;
369 if (avcodec_open(wrapper->codec_context, wrapper->codec) < 0) {
370 //fprintf(stderr, "could not open codec\n");
373 //wrapper->parser_context = av_parser_init(codec_required);
375 av_log(NULL, AV_LOG_INFO, "Codec opened...W=%d H=%d\n", wrapper->codec_context->width, wrapper->codec_context->height);
377 av_log(NULL, AV_LOG_INFO, "open_codec successful!\n");
386 unsigned char* getRGB(AVPicture *decodedPicture, FFMPEGWrapper *wrapper, int *outBuf)//, int sizeOutBuf)
391 AVPicture *tmpPicture;
392 enum PixelFormat pix_fmt=PIX_FMT_RGB24;
393 AVCodecContext *dec = wrapper->codec_context;
395 /* convert pixel format if needed */
396 if(pix_fmt == dec->pix_fmt)
398 av_log(NULL, AV_LOG_INFO, "Same PIXFMT!\n");
399 tmpPicture = decodedPicture;
403 /* create temporary picture */
404 if(wrapper->rgbBuf == NULL)
406 int size = avpicture_get_size(pix_fmt, dec->width, dec->height);
407 wrapper->rgbBuf = (uint8_t *)av_malloc(size);
408 if (!wrapper->rgbBuf)
412 avpicture_fill(&(wrapper->rgbPicture), wrapper->rgbBuf, pix_fmt, dec->width, dec->height);
415 int size = avpicture_get_size(pix_fmt, dec->width, dec->height);
416 if(size > sizeOutBuf)
418 printf("FFMPEG PLUGIN: Not enough buffer(%d, %d)!!!!\n", size, sizeOutBuf);
421 avpicture_fill(&(wrapper->rgbPicture), outBuf, pix_fmt, dec->width, dec->height);*/
422 ret = img_convert(&(wrapper->rgbPicture), pix_fmt,
423 decodedPicture, dec->pix_fmt,
424 dec->width, dec->height);
430 tmpPicture = &(wrapper->rgbPicture);
432 return (unsigned char *)tmpPicture->data[0];
438 * Class: com_omnividea_media_codec_video_JavaDecoder
439 * Method: init_decoding
442 JNIEXPORT void JNICALL Java_com_omnividea_media_codec_video_JavaDecoder_init_1decoding
443 (JNIEnv *env, jobject obj, jint peer, jint width, jint height)
445 FFMPEGWrapper *wrapper;
446 int got_picture, len, inBuf_size;
450 av_log(NULL, AV_LOG_INFO, "Setting size - %dx%d\n", width, height);
451 wrapper = (FFMPEGWrapper *) peer;
452 wrapper->width = width;
453 wrapper->height = height;
455 //if(wrapper->frameBuf != NULL) free(wrapper->frameBuf);
456 //wrapper->frameBuf = NULL;// (unsigned char*)malloc(width * height * 3);
461 * Class: com_omnividea_media_codec_video_JavaDecoder
463 * Signature: (ILjava/lang/Object;JILjava/lang/Object;JJD)Z
465 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_video_JavaDecoder_convert
466 (JNIEnv *env, jobject obj, jint peer,
467 jobject jinBuffer, jlong inBytes, jint inOffset,
468 jobject joutBuffer, jlong outBytes, jlong size, jdouble dts)
470 static int counter = 0;
471 unsigned char *inBuf = (unsigned char *) inBytes;
472 int *outBuf = (int *) outBytes;
473 unsigned char *inBuf_ptr = NULL;
474 int outputDone = 0; // false by default
475 FFMPEGWrapper *wrapper;
476 int got_picture, len, inBuf_size;
478 // int64_t ffDts = dts * 1000000;
479 jlong outBufferSize = outBytes;
484 wrapper = (FFMPEGWrapper *) peer;
485 c = wrapper->codec_context;
487 //if(c->codec_type == CODEC_TYPE_AUDIO) return convertAudio(env, obj, peer, jinBuffer, inBytes, inOffset, joutBuffer, outBytes, size, dts);
489 //printf("OutputBuffer Size: %ld\n", (long)outBytes);
490 if(c->width == 0 && c->height == 0)
492 //printf("Setting W%H in codec context:%dx%d\n",wrapper->width, wrapper->height);
493 c->width = wrapper->width;
494 c->height = wrapper-> height;
498 inBuf = (unsigned char *) env->GetByteArrayElements((jbyteArray) jinBuffer, NULL);
500 if (dts > 0 && outBytes == 0)
502 outBuf = (int *) env->GetIntArrayElements((jintArray) joutBuffer, NULL);
503 //outBufferSize = env->GetArrayLength((jbyteArray)joutBuffer);
505 outBuf = (int *) env->GetDirectBufferAddress(joutBuffer);
511 //printf("DTS: %lf %ld\n", dts, ffDts);
513 inBuf_ptr += inOffset;
515 while (inBuf_size > 0) {
516 // unsigned long pts, dts;
517 // printf("Trace 0: %p %p %p %p\n", wrapper->parser_context, wrapper->parser_context->parser, wrapper->codec, wrapper->frameBuf);
518 //len = av_parser_parse(wrapper->parser_context, wrapper->codec_context, &(wrapper->frameBuf), &(wrapper->frameBufSize), inBuf_ptr, inBuf_size, ffDts, ffDts*1000);
521 //printf("avdecode: len=%d bSize=%d frameBufSize=%d\n", len, inBuf_size, wrapper->frameBufSize);
522 //if(wrapper->frameBufSize <= 0) continue;
524 //len = avcodec_decode_video(c, wrapper->picture, &got_picture, wrapper->frameBuf, wrapper->frameBufSize);
525 len = avcodec_decode_video(c, &big_picture, &got_picture, inBuf_ptr, inBuf_size);
526 /*if(len != inBuf_size)
531 inBuf_size = 0; //FIX 0.4.1
532 //printf("avdecode: len=%d bSize=%d frameBufSize=%d\n", len, inBuf_size, wrapper->frameBufSize);
535 //fprintf(stderr, "Error while decoding frame \n");
538 if (len >= 0 && got_picture) {
539 wrapper->picture = *(AVPicture*)&big_picture;
540 //printf("Hey...there's a frame!!");
541 unsigned int rgbSize = wrapper->codec_context->width * wrapper->codec_context->height;
544 //Code for wrapper->getRGBA((char*)outBuf);
546 enum PixelFormat pix_fmt=PIX_FMT_RGBA32;
547 AVPicture tmpPicture;
548 avpicture_fill(&tmpPicture, (uint8_t *)outBuf, pix_fmt, c->width, c->height);
549 ret = img_convert(&tmpPicture, pix_fmt,
550 &(wrapper->picture), c->pix_fmt,
551 c->width, c->height);
554 av_log(NULL, AV_LOG_INFO, "Error Converting into RGBA\n");
561 unsigned char *buffer = getRGB(&(wrapper->picture), wrapper, outBuf);//, outBufferSize);
564 av_log(NULL, AV_LOG_INFO, "Error converting into RGB\n");
567 //JpegLib::rgb2jpeg(buffer, wrapper->codec_context->width, wrapper->codec_context->height, (String("frame_")+String::intToStr(counter++)+String(".jpg")).c_str());
568 unsigned int i = 0, offset = 0, offsetRGB = 0, w = 0, h = 0;
572 int* dst = outBuf;//(int*)(((char *)outBuf)+1);
573 unsigned char* src = (unsigned char*)buffer;
574 bool flag = isBigEndianSA();
577 for(; i < rgbSize; i++)
579 memcpy(((char*)dst)+1, src, 3);
583 //*dst = (*src)<<16 | (*(++src))<<8 | (*(++src));
590 for(; i < rgbSize; i++)
593 //memcpy(((char*)dst)+1, src, 3);
597 *dst = (*src)<<16 | (*(src+1))<<8 | (*(src+2));
607 // export the outputDone variable to tell JMF when the output buffer has
608 // been filled with data.
609 setOutputDone(env, obj, outputDone);
612 if(dts > 0)env->ReleaseIntArrayElements((jintArray) joutBuffer, (jint *) outBuf, 0);
614 env->ReleaseByteArrayElements((jbyteArray) jinBuffer, (jbyte *) inBuf, JNI_ABORT);
616 jboolean retCode = len >=0;
620 jboolean convertAudio
621 (JNIEnv *env, jobject obj, jint peer,
622 jobject jinBuffer, jlong inBytes, jint inOffset,
623 jobject joutBuffer, jlong outBytes, jlong size, jdouble dts)
625 static int counter = 0;
626 unsigned char *inBuf = (unsigned char *) inBytes;
627 int *outBuf = (int *) outBytes;
628 unsigned char *inBuf_ptr = NULL;
629 int outputDone = 0; // false by default
630 FFMPEGWrapper *wrapper;
631 int got_picture, len, inBuf_size;
633 int64_t ffDts = (int64_t) (dts * 1000000);
634 jlong outBufferSize = outBytes;
639 wrapper = (FFMPEGWrapper *) peer;
640 c = wrapper->codec_context;
643 inBuf = (unsigned char *) env->GetByteArrayElements((jbyteArray) jinBuffer, NULL);
647 outBuf = (int *) env->GetIntArrayElements((jintArray) joutBuffer, NULL);
648 //outBufferSize = env->GetArrayLength((jbyteArray)joutBuffer);
654 //printf("DTS: %lf %ld\n", dts, ffDts);
656 inBuf_ptr += inOffset;
658 while (inBuf_size > 0) {
659 //short decodedSamples[AVCODEC_MAX_AUDIO_FRAME_SIZE];
662 len = avcodec_decode_audio(c, (int16_t*)outBuf, &data_size, inBuf_ptr, inBuf_size);
663 wrapper->lastAudioSize = data_size;
667 //printf("avdecode: len=%d bSize=%d frameBufSize=%d\n", len, inBuf_size, wrapper->frameBufSize);
670 //fprintf(stderr, "Error while decoding frame \n");
678 // export the outputDone variable to tell JMF when the output buffer has
679 // been filled with data.
680 setOutputDone(env, obj, outputDone);
683 env->ReleaseIntArrayElements((jintArray) joutBuffer, (jint *) outBuf, 0);
685 env->ReleaseByteArrayElements((jbyteArray) jinBuffer, (jbyte *) inBuf, JNI_ABORT);
691 * Class: com_omnividea_media_codec_video_JavaDecoder
692 * Method: close_codec
695 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_video_JavaDecoder_close_1codec
696 (JNIEnv *env, jobject obj, jint peer)
698 FFMPEGWrapper *wrapper;
703 wrapper = (FFMPEGWrapper *) peer;
705 //av_parser_close(wrapper->parser_context);
706 if(wrapper->codec_context)
708 av_free(wrapper->codec_context->extradata); //solve some issues with SVQ3 codec (and maybe others)
709 avcodec_close(wrapper->codec_context);
710 av_free(wrapper->codec_context);
713 if(wrapper->parser_context)
715 free(wrapper->parser_context);
718 //free(wrapper->picture);
719 if(wrapper->rgbBuf) av_free(wrapper->rgbBuf);
720 //if(wrapper->frameBuf)free(wrapper->frameBuf);
721 if(wrapper) av_free(wrapper);
724 // Make sure the "peer" variable is zeroed in java class
725 jclass clazz = env->GetObjectClass(obj);
726 jfieldID fidPeer = env->GetFieldID(clazz, "peer", "I");
727 env->SetIntField(obj, fidPeer, (jint)0);
730 av_log(NULL, AV_LOG_INFO, "close_codec finished\n");
740 /* Inaccessible static: bigEndian */
742 * Class: com_omnividea_media_codec_audio_JavaDecoder
743 * Method: isBigEndian
746 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_isBigEndian
747 (JNIEnv *env , jclass cl)
749 return Java_com_omnividea_media_codec_video_JavaDecoder_isBigEndian(env , cl);
753 * Class: com_omnividea_media_codec_audio_JavaDecoder
757 JNIEXPORT void JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_init
758 (JNIEnv *env, jobject obj)
760 return Java_com_omnividea_media_codec_video_JavaDecoder_init(env, obj);
764 * Class: com_omnividea_media_codec_audio_JavaDecoder
766 * Signature: (ILjava/lang/String;)Z
768 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_open_1codec
769 (JNIEnv *env, jobject obj, jint peer, jstring codec_name)
771 return Java_com_omnividea_media_codec_video_JavaDecoder_open_1codec(env, obj, peer, codec_name);
775 * Class: com_omnividea_media_codec_audio_JavaDecoder
776 * Method: close_codec
779 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_close_1codec
780 (JNIEnv *env, jobject obj, jint peer)
782 return Java_com_omnividea_media_codec_video_JavaDecoder_close_1codec(env, obj, peer);
786 * Class: com_omnividea_media_codec_audio_JavaDecoder
787 * Method: init_decoding
790 JNIEXPORT void JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_init_1decoding
791 (JNIEnv *env, jobject obj, jint peer, jint width, jint height)
793 return Java_com_omnividea_media_codec_video_JavaDecoder_init_1decoding(env, obj, peer, width, height);
797 * Class: com_omnividea_media_codec_audio_JavaDecoder
799 * Signature: (ILjava/lang/Object;JILjava/lang/Object;JJD)Z
801 JNIEXPORT jboolean JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_convert
802 (JNIEnv *env, jobject obj, jint peer,
803 jobject jinBuffer, jlong inBytes, jint inOffset,
804 jobject joutBuffer, jlong outBytes, jlong size, jdouble dts)
806 return convertAudio(env, obj, peer, jinBuffer, inBytes, inOffset,
807 joutBuffer, outBytes, size, dts);
812 * Class: com_omnividea_media_codec_audio_JavaDecoder
813 * Method: lastAudioSize
816 JNIEXPORT jint JNICALL Java_com_omnividea_media_codec_audio_JavaDecoder_lastAudioSize
817 (JNIEnv *env, jobject obj, jint peer)
819 FFMPEGWrapper *wrapper;
822 wrapper = (FFMPEGWrapper *) peer;
823 return wrapper->lastAudioSize;