From c42d40b8f609c35c687efc180a7143cf30601cf0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 21 Nov 2013 09:55:57 -0500 Subject: [PATCH] Remove an extra frame copy that wasn't needed. Only update the stored frame if the previous frame had been displayed. Don't render the same frame again if there's no new frame to update. --- jni/nv_avc_dec/nv_avc_dec.c | 59 ++++++++++-------------------- libs/armeabi-v7a/libnv_avc_dec.so | Bin 17700 -> 17700 bytes libs/x86/libnv_avc_dec.so | Bin 9580 -> 9576 bytes 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/jni/nv_avc_dec/nv_avc_dec.c b/jni/nv_avc_dec/nv_avc_dec.c index 8758318e..525f3567 100644 --- a/jni/nv_avc_dec/nv_avc_dec.c +++ b/jni/nv_avc_dec/nv_avc_dec.c @@ -12,12 +12,10 @@ AVCodec* decoder; AVCodecContext* decoder_ctx; AVFrame* yuv_frame; AVFrame* rgb_frame; -AVFrame* rnd_frame; AVFrame* dec_frame; pthread_mutex_t mutex; char* rgb_frame_buf; struct SwsContext* scaler_ctx; -int picture_new; #define RENDER_PIX_FMT AV_PIX_FMT_RGBA #define BYTES_PER_PIXEL 4 @@ -161,43 +159,31 @@ void nv_avc_destroy(void) { av_free(rgb_frame_buf); rgb_frame_buf = NULL; } - if (rnd_frame) { - av_frame_free(&rnd_frame); - rnd_frame = NULL; - } pthread_mutex_destroy(&mutex); } void nv_avc_redraw(JNIEnv *env, jobject surface) { ANativeWindow* window; ANativeWindow_Buffer buffer; + AVFrame *our_yuv_frame; int err; - // Free the old decoded frame - if (rnd_frame) { - av_frame_free(&rnd_frame); - } - pthread_mutex_lock(&mutex); // Check if there's a new frame - if (picture_new) { - // Clone the decoder's last frame - rnd_frame = av_frame_clone(yuv_frame); + if (yuv_frame) { + // We now own the decoder's frame and are + // responsible for freeing it when we're done + our_yuv_frame = yuv_frame; + yuv_frame = NULL; // The remaining processing can be done without the mutex pthread_mutex_unlock(&mutex); - if (rnd_frame == NULL) { - __android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC", - "Cloning failed"); - return; - } - // Convert the YUV image to RGB err = sws_scale(scaler_ctx, - rnd_frame->data, - rnd_frame->linesize, + our_yuv_frame->data, + our_yuv_frame->linesize, 0, decoder_ctx->height, rgb_frame->data, @@ -205,14 +191,14 @@ void nv_avc_redraw(JNIEnv *env, jobject surface) { if (err != decoder_ctx->height) { __android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC", "Scaling failed"); - return; + goto free_frame_and_return; } window = ANativeWindow_fromSurface(env, surface); if (window == NULL) { __android_log_write(ANDROID_LOG_ERROR, "NVAVCDEC", "Failed to get window from surface"); - return; + goto free_frame_and_return; } // Lock down a render buffer @@ -236,10 +222,12 @@ void nv_avc_redraw(JNIEnv *env, jobject surface) { } ANativeWindow_release(window); + + free_frame_and_return: + av_frame_free(&our_yuv_frame); } else { pthread_mutex_unlock(&mutex); - rnd_frame = NULL; } } @@ -272,24 +260,17 @@ int nv_avc_decode(unsigned char* indata, int inlen) { } if (got_pic) { - // Update the frame if it's not being read - if (pthread_mutex_trylock(&mutex) == 0) { - // Free the old frame - if (yuv_frame) { - av_frame_free(&yuv_frame); - } + pthread_mutex_lock(&mutex); + // Only clone this frame if the last frame was taken. + // This saves on extra copies for frames that don't get + // rendered. + if (yuv_frame == NULL) { // Clone a new frame yuv_frame = av_frame_clone(dec_frame); - if (yuv_frame) { - picture_new = 1; - } - else { - picture_new = 0; - } - - pthread_mutex_unlock(&mutex); } + + pthread_mutex_unlock(&mutex); } pkt.size -= err; diff --git a/libs/armeabi-v7a/libnv_avc_dec.so b/libs/armeabi-v7a/libnv_avc_dec.so index 2d1c289d1afab7eaef53641c405239895c88efa5..ad485f7c990cde52cc2cf7229c9447db6b13c568 100644 GIT binary patch delta 4429 zcmb_gdu&tJ9X{7_5<3lfhdAWr*hv#e=p4es&_W&#ZW0GVA%H3ENY+qU6_9p9DC-c{ z9keh+A#fO@O;^GMTDrn;=57KlP^(32hF}UCLNqWikA%RmV}$C4-#yCb z@Av)Ax#ym9e&=yd4s90>Z5O)Q=N_BJ7$KG+r7$LdJad5sVbrM@YX{=we32tkRBTnGe!P&eBT)suf);WZyM#Py&|p;l)hIn2r5~#J#h83CJBG1uQB8te%|hs# z&@|Lk?FZ1ep($3RPeS{k&9Z&~9Z3cliFoiec|;8;Z-j19=sD0CQ^HT6K9MbjL;cLb z)ZAq^K}Qmen-_YtfU!E*lpla@(MPnHAWzfqBk;3~ z(6oJ~i=hK$jO|5Fse(CC`HP^}6fxE$=eI)VDjL`cov6?|q01v$M1{xT=!`g^zkwc9 z=xfl&OP)5ZXu$N*dgi7%>b46R83R94T-_ z3OJ!n&>s1LUqdU0_;cu6XdpTrYQX6zeHmJV5sT#Ci_#CF%ftC%sDiBcr;d=WfL^4i zpgu~!4!vHH|4x+N487$?*capm?t?xJT`udR&;e*OvxR$b4vtdOvmw3(ZBpom&}!@k zlv3DzNreqVsgt0K+$-YqRNSd8GNCGDFzRG5PFZCsE zO3USo()3&}sQD*piFugXp$!}qif|qoa?kA6eKM>BAd+UmK+IV) zK(S5)C}EB~O~tUL0+>9ZWWn!3;B^2KlD!DL%x9$6P+&tVEIjIT2-4`sFctq*`dU7i zuHlIp>s6iw{Ns#yLOuUBqeN`Qo2ko9;7s(powyoP9Xt{7>m(K!+eoa&A}7XXu!R_7 zzl|6(bq6tKWEZg(I~Or}x}W$t#y%lN?|O(a7Y-38F_HC>foXJv7(H+iBRF3WBVfmg z5yXCC1kppR$J!#s^c^5J;1DOqL>nZ=B)mY3p}RzkKwlw7*u2EpXl@Zt5wTH|fpNS? zjMW+-#z;IM#{3^A#$10yjJ2ZnP90Wz4-6-HcX>5|Q^PKb?q7G^h&i+4hU>fj;fUR< zuzM8teudp7D#SL0?Nr#E3j1w^?NHdQ3fr!*7b)y|gQ%@+vYeDeOUoJ)p2X3j4Uib}8&$h1~;NqdzdrQhIKx z^t-%!BT|MBy>OyMrSt;-W` z@Yrl)=0!g%jkm@R6*oLD*D3|S;B&K$f`_+d=ZOEnUUFKJqygY87Sca~v#|dRz67)Y zUBDoG^T0cS3$RPUoxmm78t~h|C>G>f;4AR`0k##k`A-E+1-6ZK!}d~#sZRhm4TGe}`pw(Ytt7yD7KHwd(_t;y;ld3Bn>W?mrGp}%8uev(E(JOF$rHYqX z&%wvg(`kOA<8sITTJ>Ng0$Q)xT7x%~`|;NN6NU!E)4=@QSLluXYzi`q5H{UqBY!0) zOPmBdZYZ-MPM;YnDFy%NGows~pMG_Ib*~h>>Qi~C+4p=Yu9KsI_t=-~W`qM9=`Z!4 z#$h`4?NJ~fxDMQy$k;bv8iswYc&n;+0_ypXue1r1xHQfhFAkO9)g|()*ZZoxn*Fn_ z)W{KEh1bw%upPDwzrSgp?9e$>pG(0TK6>oAp*%d5CqMP7FBd_Pf}i?wyh8WpKAo*) zJjPj#I(GUdVl}+z$T>mt;*8JSO5W{0ZFhH$mTS7ZvzKVNwwslmxuWWgyF0Q$3ZC+r ztP|y4F2=#_Ko8o`1Bx#7a2oV{Xqwj4`xI-om3=G)&!3cneWy}U{S$sIw?KH8OSx^r zF?UAstvCJ2xCVT^NV2oty}RPD;GSREk>K`JCJPPg(dPX^`=Vpo1al+DP!&bO)2($j=@D2A<*r<@D!%tj;A7c8fA}*Hw zGi7d&d5O$zGOv?)gUp-2^a1o1fU`I)bd9DjDfk)o0ye-8&nqb$M2jDxk$chN$6$Kp z6R-;!;p&LN7h5IQSEYz_L8ePFU4-e1OKArVS-Nr4WtgsSbY+W9z4##f0buz7Dsexl z`mG@7`N5h3EyaVdmH!QjqCv>u_n~M|2&Z{=Z9yCj&E9lAuhtMpqvA^EZ`K;L6m5c& z@2)M-(p(_u_z9>;caQVywFL>Sm@I@*9Z#_2$JJxJ>P`FwiyL4IE`(LVzY_hdsm!l7me}u`(5tF)1Ca6GxP2D z`+n!1*Y7;;*}MBSY4>YVM}5%;`HT@pFr;|KB+$Vk;IUy;>lkYV3|c-+){FdJkR74_qoTfR zPHitHivKGr&MQZ_XGG`)&?hYn6%JRs7W#8&nl@_Y1L$+mH1DLZKz{{YsA-uV)KVt6 z5V~5MkxUljWmRyLKX9-{XyfGJ5>(+j=%Gmu^bTmVkbeZ)D(EkuI|Y3Ux*z3}Q3cg! zP*-rcKFq;LIQnG9%CrY8(B&BqbgobUkFnwiy%4%Tm$7XaIW^E2k>3VgI{_<6%ijbY zAMT(R1$I+`umk!-Xj#zbpqm8!AL!$Pjz#SETOTa)vCs#hcWVQh0qvfMjiTvl=oaWE zXfO4+9u7Yovi87wXoip>a_We-LF=Kz`TL=>p?kIbze0;4{v7%YI+(5H4@T(dXvXdh z=X=!#%nux@&ViN@(r^X#2>lFnnULQSp*KQ%g#0%n^a1Er8>W)>AVuI99EadQ8C8D) z-47jJ#dn}BIK0B=NIZ;eLFYj0t5Fy!p50WYMCjSjxk5gxsae)qSJSxMR}^j1MXg?0 z&*z)0adj`$G_I~&(NMFjsd;4sZ!~qpu3EmVWzFh_nw1Sd=eJF>N3Uw}tZt~QuUWCC zrJ=Q^W%Y|q&C8zi6~(L{VQN6*bAZQrf|S&NQ;sbK@_;O$1gHYsKsY_E891lEOV7g6 zdaC-0@oNSi1?quxAe>^Ur4%t3GW*A6fhH*4lDpD(aK*8$N-K=RtMAoINzBS zptNk5)ZY~R765TTE-y*=6|YV(@)HRbE=ziTIYG`Cj~rT^;Y8aJbF8LE@H>u6i79z> z=7f_3V}>T|;JHAlrirHT6^SX%*|6}IWs86x10w-SKN=?WHwV91n{1lqbAT5DwLk_i z52)ZL6HC&mO_~usFg!2x;+E7I!YuKeq!kk5Jn7}J^cts8%UB}B*&17`cw+KAsgf^D z&heJRIT~@PCB_(5fybc!7Gkv3N{qJJh;c}@6Ju^(A;u2cK#VADA~rGBK^%jVlQ)jecjVeco#5$(Tg2E!L&U{6 z-H1yNcz@o2-v9PMoPUeoICx|roA${^TfUC^WYgE#cX|fGwnea$1$(4m>%D@wH}s(J zEy2Dn*!_atC)lS2`-EU07wjIvKB(DV>h*phW4B=M66|e)y-BcN5$ra>ZV~Jz!LAqV zr9(a5@51%CkWnevWr96dunPn`SFp1M+alP>f;|$pQGR=X#XH}*pp&=ww-tJgZ`D*79*G5NM8Os>$@Vk}Jm>bQ5(M$=MZzv(l4U4RV#`6Oy zqtnLTc+7RtZL2Nsu5?ybyjZrj%pg|{Dl?T(BL6bQ>AV%(QyT5ipPlZUq2?C&mC#_Y zz;(fGu9dsISsi$DcQ6jXo7*)@Voc z*$K{vwYHSdANgK$mh>S%X-@Ob#t3>8Md<}{v9QO>%L6$YScD!rA3%6Ny zlOxSF;GXQs>aseNP^J;{QnQS~IiGhE9eRmTZWJg$0TTz>cA%Z0_#VC`Ri zffob~kUIIX;#HJ0Fla@eb-w4HL(Kp0p*Fw7<$N7yStp?xsu>fU>^axGy;Of{qI05Jg~^}cC`83^ zLA|4}Tb$DUfgC@}9I;mk88G4IbCW%$-|T2U*UYv?eWSa%kx5%E88*~;KftVpv#Cyl zoT}F7RYI=^WK=n%{@xAf{nYb+1U|y35;_lG9$e3k9>Yl&j*K7Cp@{8D!F2)m1Bx7l zl0y0veB}(`U1Bw0RpxrplU%hYN~j{>^c%O& za!kTQ#{zTwITbms_ubOI3+{;?vq$%PC3J*(?}$B{iBg$bDO(@|vx|ilnBbRoe%3XP zwuIvl>ewIH-kkV*0H0j@s4gEgEtyRMLU8;$$P3wjtLlKI1q&nCR zCG_rLCA98H0y=YsUrS4uR`OU&o%Czp3d^gKE_s^ozvB`msh^wDmq?%Ty7ZT%Bfj(L zqjXXc4`eKpa`?i`-|4=+=ewJ^Skl=h`4(lrp_g9rU9sAu$L_nMTr(EuUD*R}eYDrX zdfy%xHMq%tdVo7@^HSfrsCYa7U}#@@S@G^QcC{O?kdAM!^u1|&Uy8HiqPcwKPvyqC zGB`m)I|TiM?EvTwNcW(-iqaep zrkhzZ%Hi!!Uk%jH2lcoL;H}Smc#v);W@O+I_7(uvvH84YUdodTkxlMrHD05!SL4kZ z@6h-?jrW1+;`TED2bcPVf-Zn?GaN*$hj-1($tXlm@1c`=bpBf~wR9gWLu2Baqj2rZ z=ehIaz4X0-zA?~u1^Qw@UkT`sH>Gym!RVs~ePf`1we&|eGTE>$egLX|Na61(>$^Yy zJxQwO@0O&SXeJ0g{&y&v2ZGFRLQ#MSpYYVubOVJ+pUmf#W*R6$ax!l$%{0->6FT_T z(sUE83xdqMp~6Ex&c7;6kGX|~Lnu$>G4}C>xro`^seFn((=hx^h%dIIIz*E&jjyw( zo768$xKkPVRC^Ndv5y?lgG*`;KWWbzp?+23x9wRb8H-cKzXU(eD65jJ{P{B9{{TD= B$HM>s diff --git a/libs/x86/libnv_avc_dec.so b/libs/x86/libnv_avc_dec.so index 44b86be8267e1210f70e6e84684a64013820d746..8c52cb7f5e84caa28580ba396c6dd800611fcce4 100644 GIT binary patch literal 9576 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