포토로그 마이가든 방명록



NuPlayer for HTTP live streaming Android


NuPlayer for HTTP live streaming


HTTP Live Streaming is separated from Stagefright on the recent release, which is basically another light-weighted playback engine, except it only supports the fixed container and codecs format currently.
It seems that the author really prefers rewriting than refactoring:)

Unlike Awesomeplayer, NuPlayer is built upon Stagefright's foundation classes, and leverages the Looper/Handlers mechanism to handle requests asynchronously by queuing them in a message loop, so there are less mutex/lock in place.


  • NuPlayer::Source is the parser module. Actually its interface looks like a combination of MediaExtractor and MediaSource, and it also makes seekTo as an explicit API now.
  • NuPlayer::Decoder connects to ACodec for AVC decoding, and to DecoderWrapper for AAC decoding, which in turn wrapps AAC software decoder in the OpenMAX style. ACodec is functionally similar as OMXCodec in Stagefright, besides the application of State pattern and passing MediaBuffers around with messages.
  • NuPlayer::Render is responsible for rendering audio and also controls when to post video buffers back to NativeWindow for A/V sync.

Eclipse 단축키 모음 Android

Eclipse 단축키 모음


ctrl + s: 저장 및 컴파일
ctrl + i: 소스 깔끔 정리(인덴트 중심의 자동구문정리)
ctrl + space : 어휘의 자동완성(Content Assistance)

ctrl + E : 열린파일 옮겨다니기

ctrl + shift + E : 열린파일 띄우기

ctrl + M : 에디터화면 넓게
ctrl + 1 : Quick Fix(Rename에 주로 사용)
ctrl + shift + M : 캐럿이 위치한 대상에 필요한 특정클래스 import
ctrl + shift + O : 소스에 필요한 패키지의 자동 임포트
ctrl + /: 한줄 또는 선택영역 주석처리/제거
ctrl + Q : 마지막 편집위치로 가기
ctrl + L : 특정줄번호로 가기
ctrl + D : 한줄삭제
ctrl + H : Find 및 Replace
ctrl + K : 다음찾기(또는, 찾고자 하는 문자열을 블럭으로 설정한 후 키를 누른다.)
ctrl + shift + K : 이전찾기(또는, 찾고자 하는 문자열을 블럭으로 설정한 후 역으로 찾고자 하는 문자열을 찾아감.)
alt + shift + j : 설정해 둔 기본주석 달기
Ctrl + 객체클릭(혹은 F3) : 클래스나 메소드 혹은 멤버를 정의한 곳으로 이동(Open Declaration)


ctrl + shift + f : 소스 깔끔 정리
ctrl + 2 + R : Rename(리팩토링)
ctrl + shift + / : 선택영역 block comment 설정
ctrl + shift + \ : 선택영역 block comment 제거
alt + shift + up: Enclosing Element 선택(괄호의 열고 닫기 쌍 확인에 유용함)
ctrl + O : Outline창열기

ctrl + T : 상속구조 보기, 한번더 누르면 수퍼타입/서브타입 구조가 토글된다

Alt + ->, Alt + <-: 이후, 이전
해당프로젝트에서 alt + enter : Project 속성
sysout > Ctrl + Space: System.out.println();
try > Ctrl + Space : 기본 try-catch문 완성
for > Ctrl + Space : 기본 for문 완성
템플릿을 수정,추가: Preferences > java > editor > Templates

블럭 씌운상태에서 alt + shift + z : try/catch, do/while, if, for, runnable.... 등 블럭씌우기


ctrl + N : 새로운 파일 및 프로젝트 생성
ctrl + shift + s : 열려진 모든파일 저장 및 컴파일
alt + / : Word Completion
alt + shift + R : Rename
ctrl + shift + G : 특정 메써드나 필드를 참조하고 있는 곳을 찾는다.
ctrl + shift + B : 현재커서위치에 Break point설정/해제
ctrl + alt + R
ctrl + f11 : 실행
f11 : 디버깅 시작

f4 : 상속구조 클래스 보기(메소드, 멤버)
f5 : step into
f6 : step over
f8 : 디버깅 계속
ctrl + . : 다음오류부분으로 가기
ctrl + , : 이전오류부분으로 가기
f12 : 에디터로 커서이동
ALT + UP,DOWN : 현재 줄 위치 이동
Ctrl + j : 검색할 단어를 입력하면서 실시간으로 검색
Ctrl + Shift + j : 검색할 단어를 입력하면서 실시간으로 거꾸로 검색
F4 : 클래스명을 선택하고 누르면 해당 클래스의 Hierarchy 를 볼 수 있다.
ctrl + alt + up/down : 한줄 duplicate
alt + shift + 방향 : 선택
ctrl + shift + g : 객체(변수)가 참조 되는 곳을 찾아 준다

alt + shift + m : 코드 중복 해결(중복부분을 블록선택한 다음 단축키를 누르면 이부분을 별도의 메서드로 뽑아내줌)

ctrl + alt + h : 메서드 호출구조 보기



[ndk addr2line] 디버깅 - stack trace Android

navtive 단에서 에러가 나면 증말 골치가 아프죠...


제가 격은 에러입니다.


*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

01-18 16:33:21.830: I/DEBUG(20605): Build fingerprint: '~~~~~~~~~~/user/release-keys'

 I/DEBUG(20605): pid: 20611, tid: 20611  >>> [packageName] <<<

 I/DEBUG(20605): signal 4 (SIGILL), code 1 (ILL_ILLOPC), fault addr 818798e8

 I/DEBUG(20605):  r0 00000000  r1 8192004c  r2 00000000  r3 00000160

 I/DEBUG(20605):  r4 001c7ea0  r5 001c82a0  r6 81914b48  r7 8192004c

 I/DEBUG(20605):  r8 00000000  r9 81913c38  10 00000001  fp 00000002

 I/DEBUG(20605):  ip 00000160  sp becaf070  lr aff10cb4  pc 818798e8  cpsr 60000010

 I/DEBUG(20605):  d0  bfc62e4300000000  d1  bebbb7eb81720340

 I/DEBUG(20605):  d2  3f1153165ec18a01  d3  4000000000000000

 I/DEBUG(20605):  d4  bf8d0c1646588a4b  d5  3ff0000000000000

 I/DEBUG(20605):  d6  3ff0000000000000  d7  437ae89f5bd744fd

 I/DEBUG(20605):  d8  3ff0000000000000  d9  0000000000000000

 I/DEBUG(20605):  d10 0000000000000000  d11 0000000000000000

 I/DEBUG(20605):  d12 0000000000000000  d13 0000000000000000

 I/DEBUG(20605):  d14 0000000000000000  d15 0000000000000000

 I/DEBUG(20605):  scr 60000012

 

 I/DEBUG(20605):          #00  pc 000798e8  /data/data/[packageName]/lib/libbasicplayer.so

 I/DEBUG(20605):          #01  lr aff10cb4  /system/lib/libc.so

 I/DEBUG(20605): libc base address: aff00000

 I/DEBUG(20605): code around pc:

 I/DEBUG(20605): 818798c8 e58de00c e58de010 e58da000 e58da004 

 I/DEBUG(20605): 818798d8 e58d8014 e58d8018 e58d801c eb001b72 

 I/DEBUG(20605): 818798e8 eddf0b3a e2850c15 e3a0100b e1a0200a 

 I/DEBUG(20605): 818798f8 e2800020 ee680b20 edcd0b00 eb01304b 

 I/DEBUG(20605): 81879908 eddf0b34 e2850d55 e1a0200a e3a01008 

 I/DEBUG(20605): code around lr:

 I/DEBUG(20605): aff10c94 08bd87f0 e5964000 e5967000 e2144903 

 I/DEBUG(20605): aff10ca4 1a00000f f57ff05f e5965000 ebffed97 

 I/DEBUG(20605): aff10cb4 e2055a02 e3853001 e1500003 0a000006 

 I/DEBUG(20605): aff10cc4 e5865000 e1a00006 e1a01005 e3a02001 

 I/DEBUG(20605): aff10cd4 ebfffede e1a00004 e8bd87f0 e3a00000 

 I/DEBUG(20605): stack:

 I/DEBUG(20605):     becaf030  8192004c  

 I/DEBUG(20605):     becaf034  0000031c  

 I/DEBUG(20605):     becaf038  00000004  

 I/DEBUG(20605):     becaf03c  81903104  /data/data/ [packageName] /lib/libbasicplayer.so

 I/DEBUG(20605):     becaf040  81902f20  /data/data/ [packageName] /lib/libbasicplayer.so

 I/DEBUG(20605):     becaf044  00000000  

 I/DEBUG(20605):     becaf048  8192004c  

 I/DEBUG(20605):     becaf04c  001c7ea0  

 I/DEBUG(20605):     becaf050  001c82a0  

 I/DEBUG(20605):     becaf054  81914b48  

 I/DEBUG(20605):     becaf058  8192004c  

 I/DEBUG(20605):     becaf05c  00000000  

 I/DEBUG(20605):     becaf060  81913c38  

 I/DEBUG(20605):     becaf064  00000001  

 I/DEBUG(20605):     becaf068  df002777  

 I/DEBUG(20605):     becaf06c  e3a070ad  

 I/DEBUG(20605): #00 becaf070  00000001  

 I/DEBUG(20605):     becaf074  00000001  

 I/DEBUG(20605):     becaf078  81902f20  /data/data/ [packageName] r/lib/libbasicplayer.so

 I/DEBUG(20605):     becaf07c  00000004  

 I/DEBUG(20605):     becaf080  00000004  

 I/DEBUG(20605):     becaf084  00000000  

 I/DEBUG(20605):     becaf088  00000000  

 I/DEBUG(20605):     becaf08c  00000000  

 I/DEBUG(20605):     becaf090  00000004  

 I/DEBUG(20605):     becaf094  aff1446f  /system/lib/libc.so

 I/DEBUG(20605):     becaf098  becaf0e4  

 I/DEBUG(20605):     becaf09c  8190325c  /data/data/ [packageName] /lib/libbasicplayer.so

 I/DEBUG(20605):     becaf0a0  8192c01c  

 I/DEBUG(20605):     becaf0a4  8192a024  

 I/DEBUG(20605):     becaf0a8  81903180  /data/data/ [packageName] /lib/libbasicplayer.so

 I/DEBUG(20605):     becaf0ac  81913c64  

 I/DEBUG(20605):     becaf0b0  81915100  

 I/DEBUG(20605):     becaf0b4  43660000  


스택의 메모리 값을 추적하여 native 소스 코드의 어느 부분에서 에러가 나는지 출력해주는 addr2line을 이용하면 쉽게 에러 부분을 찾을 수가 있습니다. native 소스 코드가 컴파일 오류가 나지않고 실행오류가 날 때 이용하면 참 유용하죠!!!


(저는 ndk-r7 버전을 사용합니다.)


먼저 cygwin에서 다음과 같은 명령으로 add2line을 찾습니다.

/cydrive 

find . -name *addr2line 


~~ 어쩌고저쩌고

/cygdrive/c/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-addr2line.exe


에러를 가지고 있는 libName.so 파일로 이동합니다.


$ cd [ndk폴더]/[projectName ]/obj/local/armeabi-v7a


이동하였으면 다음과 같은 명령을 입력합니다.

/cygdrive/c/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-addr2line.exe -f -e  libName.so address

위의 address 부분은 에로 로그에 빨간으로 표기된 16진수 숫자를 입력하면 됩니다.
#00  pc 000798e8 <- error가 일어난 부분입니다. 
(addr2line은 환경변수 해서 하면 되는데 cygwin에서 환경변수 설정하는걸 몰라서 절대경로
로 addr2line 실행한 겁니다 ^^;)
저는 경로를 저도 모르게 틀리게 잡아서 여러번 삽질했습니다. 저같은 실수 안하시기를~


참고 문헌 

http://stackoverflow.com/questions/5314036/how-to-use-addr2line-in-android


CPU, Memory 사용량 표시 Android


1. CPU 사용량


adb shell top -m 10
- 10개의 process에 대한 항목만 반복하여 표시

1
$ adb shell top -n 1

을 입력하면 CPU 사용량을 출력합니다.

top 에 대한 자세한 설명은 아래 명령을 입력합니다.

1
$ adb shell top --help

shell 명령을 Android App 에서 수행하려면 다음과 같이 합니다. ( shell 명령 수행시 App 의 권한은 항상 User 이기 때문에 su 권한을 필요로 하는 명령은 수행할 수 없음에 유의하셔야 합니다. )


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Runtime runtime = Runtime.getRuntime();
Process process;
String res = "-0-";
try {
        String cmd = "top -n 1";
        process = runtime.exec(cmd);
        InputStream is = process.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line ;
        while ((line = br.readLine()) != null) {
                String segs[] = line.trim().split("[ ]+");
                if (segs[0].equalsIgnoreCase([Your Process ID])) {
                        res = segs[1];
                        break;
                }
        }
} catch (Exception e) {
        e.fillInStackTrace();
        Log.e("Process Manager", "Unable to execute top command");
}

2. 메모리 사용량

$ adb shell procrank

procrank 명령이 가장 정확한 메모리 사용 정보를 보여준다고 합니다. (by Dianne Hackborn)

특히, 
uss 칼럼은 app 고유의 메모리 사용량을 나타내고,
pss 는 또한 프로세스간에 공유되는 메모리 량을 포함하고 있습니다.

하지만 이 명령은 production device 에는 지원하지 않을수 있습니다. 그때는 다음의 명령을 사용합니다.

1
2
$ adb shell dumpsys meminfo
$ adb shell dumpsys meminfo [processname]

위의 명령을 들을 이용하여 CPU 와 Memory 의 사용량을 차트 등으로 한눈에 보여줄 수 있습니다.

참고:

아래 링크 추가


SurfaceView, 예제 Android


프로그램은 크게 두가지 파일로 구성되어 있다.
ImgMove.java, GraphicsVies.java

ImgMove.java는 메인 엑티비티로, GraphicsView를 자신의 ContentView로 설정하게 된다.
그 소스코드는 다음과 같다.
===========================================
ImgMove.java
===========================================
package org.com;

import android.app.Activity;
import android.os.Bundle;

public class ImgMove extends Activity {
    --* Called when the activity is first created. --
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new GraphicsView(this));
    }
}
===========================================
여기서는 큰 무리가 없을거라고 생각한다.
그럼 이제 GraphicsView.java로 넘어가보자.

이 클래스는 SurfaceView 클래스를 extends 한 것이다.
보통 쓰레드를 내부클래스로 하나 만들어놓고 사용하는 경우가 많은데,
필자는 GraphicsView를 Runnable을 implements하여서 사용하였다.
(간단히 애니메이션 효과만 내고 싶은거라면 이게 더 편해보인다.)
그럼 이제 메인 코드로 넘어가보자.
=====================================================================
public class GraphicsView extends SurfaceView implements SurfaceHolder.Callback, Runnable{
-- 여기서 주목할 점은 바로 SurfaceView를 extends했고, SurfaceHolder.Callback을 implements했다는 점!!
 * SurfaceHolder.Callback 은 surface의 변화에 대한 정보를 얻어오기 위해서 반드시 implements해야 하는 인터페이스이다.
 * SurfaceView 와 SurfaceHolder.Callback가 함께 사용될 경우, 잡혀있는 Surface는 created되는 사이사이마다만 사용 가능하다.
 * 그렇기 때문에 exclusive한 성질을 띄게 되고, synchronized(동기화)될 수 있는 것이다. 이 점에서 SurfaceView가 View에 비해
 * 사용이 편리하다는 것인 듯 싶다.
 --
    private Display display;
    private int width;
    private int height;
    private Bitmap img;
    private Bitmap src;
    private Paint paint;
    private SurfaceHolder holder; // surface의 동기화를 위해 화면을 잡아주고 있을 홀더
    private Thread thread;  // surface에 그려주는 작업을 해줄 thread

    int x = 0;
    int y = 0;
   
    public GraphicsView(Context context){
        super(context);
        display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        width = display.getWidth();
        height = display.getHeight();
        paint = new Paint();
        src = BitmapFactory.decodeResource(this.getResources(), R.drawable.van);
       
        holder = getHolder(); // 홀더를 만들고,
        holder.addCallback(this); // 홀더에 이 SurfaceView에 대한 콜백 인터페이스를 제공해준다.
--
 *  여기서 잠시, SurfaceHolder가 뭐하는 놈인지는 알고 넘어가는 편이 속시원할 것 같다.
 *  SurfaceHolder란, 화면의 디스플레이에 대한 권한을 가지고 있는 객체에 대한 인터페이스이다.
 *  그렇기 때문에, SurfaceHolder는 프로그래머로 하여금 surface size, format를 제어할 수 있게 해주고,
 *  surface의 픽셀을 수정하고, 변화를 모니터할 수 있게 해준다.
 --
        setFocusable(true);
    }

-- 
 *  SurfaceHolder.Callback을 implements했다면 반드시 surfaceCreated, surfaceChanged, surfaceDestroyed를 구현해주어야 한다.
 *  안그러면 에러가 날테니까??
 --

public void surfaceCreated(SurfaceHolder holder){
// surface가 첫번째로 생성되자마자 바로 호출되는 메소드
        thread = new Thread(this); // 나중에 밑에서 구현될 스레드를 시작하는 지점.
        thread.start();
    }
   
    public void surfaceChanged(SurfaceHolder holder, int a, int b, int c){
// surface에 포멧이나 사이즈 등 어떠한 변화가 생기면 바로 호출되는 메소드
       
    }
   
    public void surfaceDestroyed(SurfaceHolder holder){
// surface가 종료되기 직전 바로 호출되는 메소드
       
    }

--
 *  run()와 doDraw()는 이제 그리기 작업에 필요한 작업들만 해주면 된다.
 --
public void run(){
        int flag = 0;
        int flagCnt = 0;
       
        while(true){
            Canvas c = null; // 그림을 그릴 캔버스
           
            try{
                c = holder.lockCanvas(null); // 해당 캔버스에 이제 그림그리기를 시작하기 위해 lock을 얻어왔다.
                synchronized(holder){
// 동기화를 위해 반드시 필요한 synchronized. holder가 잡고 있는 surface에 대해서 비동기식이 아닌 동기식으로 업데이트가 진행되도록 해준다.
                    if(flag == 0 && y >= 0 && y < src.getHeight() - height){
                        doDraw(c); // 캔버스에 그림을 그립시다아~~
                        x++;
                        y++;
                        flagCnt++;
                       
                        if(flagCnt == src.getHeight() - height){
                            flag = 1;
                        }
                    }else{
                        doDraw(c);
                        x--;
                        y--;
                        flagCnt--;
                       
                        if(flagCnt == 0){
                            flag = 0;
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                if(c != null){
                    holder.unlockCanvasAndPost(c);
                    // surface의 픽셀들에 대한 수정작업을 마무리 한다. unlockCanvasAndPost가 호출되고 난 뒤에 수정된 픽셀들이 스크린에 반영이 된다.
                }
            }
        }
    }

    public void doDraw(Canvas c){
        img = Bitmap.createBitmap(src, x, y, width, height);
        c.drawBitmap(img, 0, 0, paint);
    }   

이 소스코드가 도움이 되었으면 한다.
다음은 외부 블로그에서 SurfaceView를 사용하기 위해 필요한 과정들에 대해 정리해져 있는 내용을 펌해온 것이다.
소스를 보고 공부를 했으면, 그를 바탕으로 마무리로 정리해본다는 마음으로 읽어보면 도움이 될 것이다.

출처: http://samse.tistory.com/entry/Android-Graphics-1

On a SurfaceView

SurfaceView View구 조내에서 surface 그리는 목적으로 고안된 특별한 subclass이 다. 목 적은 애 플리케이션의 두 번째 스 레드에서 별 도로 그 려서 시 스템의 View구 조에서 그 리기 타 임까지 기 다리지 않 도록 하 게 하 기 위 해 고 안되었다. 두 번째 thread에 서 참 조하는 SurfaceView 자신만의 Canvas 그리기를 수행한다.

1.     SurfaceView extend 새로운 클래스를 선언한다.

2.     SurfaceHolder.callback implement한 다. 콜백 subclass 하부의 Surface 대한 정보와 함께 통지하는데 생성, 변 경 또 는 제 거되었을 통지하게 된다. 이벤트를 통해서 언제 그리기를 시작해야 하는지 알수 있고, 새 로운 surface속 성에 맞 게 조 정하고, 언 제 그 리기를 종 료하고 테 스트를 죽 일지등을 알 수 있 다. SurfaceView에 서 두 번째 Thread 정의하여 모든 drawing procedure 수행하는 것이 좋다.

3.     SurfaceHolder 생성한다. Surface 객 체를 직 접 처 리하지 않 고 SurfaceHolder 통해서 하는 것이 좋다. SurfaceView 초기화되면 getHolder() SurfaceHolder 얻는다.

4.     addCallback() 호출하여 SurfaceHolder.Callback으 로부터 이 벤트를 수 신하도록 한 다. SurfaceHolder.Callback SurfaceView클 래스내에서 override하 여 addCallback()한 다.

5.     두번째 thread에 서 Surface Canvas draw하 려면 반 드시 SurfaceHandler 전달해야 하며 lockCanvas() canvas 얻어야 한다. 이 렇게 해 야 SurfaceHolder 제공해준 Canvas 얻게 된다.

6.     Canvas drawing 한번 수행하면 canvas object 인자로 unlockCanvasAndPost() 호출해야 한다. lockCanvad() unlockCanvasAndPost() draw 반드시 쌍으로 호출되어야 한다.

 

Note: 한 번 canvas 얻어져서 사용되면 canvas 이전상태를 유지한다. 따 라서 적 절하게 animate 하려면 surface전 체를 re-paint해 야 한 다. 경우 drawColor() drawBitmap()등 으로 background 갱신하면 된다. 그 렇게 하 지 않 으면 이 전 이 미지가 표 시될 것 이다.



1 2 3 4 5 6 7 8 9 10 다음



메모장