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

로컬 스트리밍과 관련한 소켓 outputStream 질문입니다.

0 추천

현재 소켓 서버로 로컬 서버를 구현했습니다.  플레이할 동영상은 제가 짠 로직으로 바이트 배열을 바꿔서 암호화 되어있습니다.  4096 바이트씩 묶어서 암호화 했구요. 하지만 seek을 하게 되면 재생이 되질 않습니다.

아래는 로컬 서버에서 Url로 들어온 요청된 http 헤더에서 range 키 값이 존재하면 실행되는 구문입니다. 

 

protected void execute() {
            ExternalResourceDataSource dataSource = new ExternalResourceDataSource(targetFile, context);
            long fileSize = dataSource.getContentLength();

            String headers = "";
            if (cbSkip > 0) {// It is a seek or skip request if there's a Range
                // header
                headers += "HTTP/1.1 206 Partial Content\r\n";
                headers += "Content-Type: " + dataSource.getContentType() + "\r\n";
                headers += "Accept-Ranges: bytes\r\n";
                headers += "Content-Length: " + (fileSize - cbSkip) + "\r\n";
                headers += "Content-Range: bytes " + cbSkip + "-" + (fileSize - 1) + "/" + fileSize + "\r\n";
                headers += "Connection: Keep-Alive\r\n";
                headers += "\r\n";
            } else {
                headers += "HTTP/1.1 200 OK\r\n";
                headers += "Content-Type: " + dataSource.getContentType() + "\r\n";
                headers += "Accept-Ranges: bytes\r\n";
                headers += "Content-Length: " + fileSize + "\r\n";
                headers += "Connection: Keep-Alive\r\n";
                headers += "\r\n";
            }

            Log.i(TAG, "headers: " + headers);

            OutputStream output = null;
            int difference = (int) (cbSkip - editSkipBytes(cbSkip));
            byte[] buff = new byte[4096];

            try {
                output = new BufferedOutputStream(client.getOutputStream(), 30 * 1024);
                output.write(headers.getBytes());
                FileInputStream data = (FileInputStream) dataSource.getInputStream();
                int cbRead;

                if (cbSkip > 0) {

                    data.skip(editSkipBytes(cbSkip));
                    data.read(buff, 0, buff.length);
                    enDecryptVideo.combineByteArray(buff);
                    output.write(buff, difference, buff.length);

                    while (!client.isClosed() && (cbRead = data.read(buff, 0, buff.length)) != -1) {
                        enDecryptVideo.combineByteArray(buff);
                        output.write(buff, 0, cbRead);
                    }

                } else if (cbSkip == 0) {
                    dataSource.skipFully(data, cbSkip);//try to skip as much as possible

                    // Loop as long as there's stuff to send and client has not closed
                    while (!client.isClosed() && (cbRead = data.read(buff, 0, buff.length)) != -1) {
                        enDecryptVideo.combineByteArray(buff);
                        output.write(buff, 0, cbRead);
                    }
                }

            } catch (SocketException socketException) {
                Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
            } catch (Exception e) {
                Log.e(TAG, "Exception thrown from streaming task:");
                Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
            }

            // Cleanup
            try {
                if (output != null) {
                    output.close();
                }
                client.close();
            } catch (IOException e) {
                Log.e(TAG, "IOException while cleaning up streaming task:");
                Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
                e.printStackTrace();
            }
        }

        private long editSkipBytes(long cbSkip) {
            return cbSkip / 4096 * 4096;
        }

enDecryptVideo.combineByteArray(buff); 는 매개변수로 들어온 바이트 배열을 로직에 의해서 바이트 배열을 바꿔주는 역할을 합니다. 

skip된 바이트 가 4096의 배수가 아니기 때문에 이를 처리해서 스트림해줘야 하고 그 뒤부터는 4096씩 가져와서 복호화해 스트림해줍니다. 제가 짠 로직에 어떤 오류가 있어서 재생이 되지 않을까요... 부탁드립니다.

익명사용자 님이 2018년 9월 7일 질문

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...