마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

동영상 파일 다운로드 중 OutOfMemoryError 가 발생합니다.

0 추천

mp4 파일을 받고 있구요 5GB짜리를 받고 있습니다. 100mb 크기의 파일을 받는데는 문제가 없었는데 크기가 커지니 오류가 뜨네요. 

Manifest에서 large hear = true, hardwareAccelerated=false 도 해보았습니다. 

오류는 다음과 같습니다. 

07-06 11:46:24.953 1898-1944/com.example.junburg.testencoding E/AndroidRuntime: FATAL EXCEPTION: Thread-5
    Process: com.example.junburg.testencoding, PID: 1898
    java.lang.OutOfMemoryError: Failed to allocate a 536870924 byte allocation with 16773232 free bytes and 249MB until OOM
        at java.util.Arrays.copyOf(Arrays.java:3256)
        at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
        at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
        at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
        at com.example.junburg.testencoding.MainActivity$1.run(MainActivity.java:82)
        at java.lang.Thread.run(Thread.java:762)

 

그리고 코드는 다음과 같습니다.

 

@Override
        public void run() {
            OutputStream outputStream = null;
            InputStream isVideo = null;
            ByteArrayOutputStream tempOut = new ByteArrayOutputStream();
            RandomAccessFile existVideo = null;

            try {

                File videoLocation = new File(getExternalFilesDir(Environment.DIRECTORY_MOVIES).getAbsolutePath() + File.separator + "Fuck" + ".mp4");
                if (!videoLocation.exists()) {
                    videoLocation.createNewFile();
                }

                long gottenSize = 0;
                existVideo = new RandomAccessFile(videoLocation.getAbsolutePath(), "rw");
                gottenSize = videoLocation.length();
                existVideo.seek(gottenSize);

                URL url = new URL("video url");
                HttpURLConnection c = (HttpURLConnection) url.openConnection();
                c.setRequestProperty("Range", "bytes=" + gottenSize + "-");
                c.connect();

                isVideo = c.getInputStream();

                byte[] buffer = new byte[4096];

                if (fileSize == 0) {
                    fileSize = Double.parseDouble(c.getHeaderField("Content-Length"));
                }

                int len = 0;
                int value = 0;

                byte[] tempByte = new byte[4096];

                long startTime = System.currentTimeMillis();
                while (true) {
                    int read = isVideo.read(tempByte);
                    if (read == -1) break;
                    tempOut.write(tempByte, 0, read);
                }
                Log.d(TAG, "run: " + (System.currentTimeMillis() - startTime));
                existVideo.write(encodingMp4(tempOut));
existVideo.close();
isVideo.close();
} catch (IOException e) {
            e.getStackTrace();
        } finally {
            fileSize = 0;
            Log.d(TAG, "run: " + "done");
        }
    }
};

 

 

혹시 아시는 분은 혜안을 부탁드립니당

준버기 (1,160 포인트) 님이 2018년 7월 6일 질문
준버기님이 2018년 11월 7일 수정

1개의 답변

+2 추천
 
채택된 답변

ByteArrayOutputStream write하면, 파일로 적어지는게 아니라. 메모리에 쌓이게 됩니다. 

100mb 넘어가면, 메모리가 부족할 수 밖에 없죠.. 

 

 existVideo.write(encodingMp4(tempOut)); 코드가 어떻게 되어 있는지 모르겠으나,

아래 굵은 표시한 부분 같이 서버에서 받은 buffer만큼 계속 업데이트 방식으로 변경 하셔야 할 듯 합니다.

(만약 전체 파일 정보가 필요하다면, FileOutPutStream을 통해 임시 파일로 저장 한 후, 넘겨주는 것도 방법입니다.)

    while (true) {
                    int read = isVideo.read(tempByte);
                    if (read == -1) break;
                    existVideo.write(encodingMp4(tempByte, 0, read));
                }
 

 

익명사용자 님이 2018년 7월 6일 답변
준버기님이 2018년 7월 6일 채택됨
...