공개 URL에서 사용할 수있는 MP3 파일을 재생하는 애플리케이션이 있습니다. 불행하게도 서버는 스트리밍을 지원하지 않지만 안드로이드는 사용자 경험을 상당히 받아들입니다.Android JellyBean 네트워크 미디어 문제
JellyBean을 제외한 모든 플랫폼에서 모두 정상적으로 작동합니다. MP3를 요청할 때 JB는 Range-Header를 10 번 요청합니다. 10 번째 시도 후에 만 이전 행동으로 되돌아가는 것처럼 보입니다. Looks like this already reported issue.
SO thread 해결책을 권장하는 곳에서 Tranfer-Encoding : chunked 헤더를 사용하는 것이 좋습니다. 그러나 바로 아래에는 이것이 작동하지 않는다는 의견이 있습니다.
지금까지는 응답 헤더를 제공 할 수있는 권한이 전혀 없었지만이를 수행 할 수있을 때까지 클라이언트 측에서 대안을 찾아야한다고 생각했습니다. (그렇다고해도 0에서 Content-Length - 1까지의 인덱스를 포함하는 Content-Range 만 반환 할 수 있습니다. 예 : Content-Range : 0-3123456/3123457 바이트). 내가 할 노력은 무엇
이구현하는 것입니다 의사 스트리밍 클라이언트 측에서 :
- 를 열고 MP3에 입력 스트림.
- JLayer를 사용하여 들어오는 바이트를 디코딩합니다. 디코딩을 this link에서 찾았습니다.
- 이미 재생할 수있는 stream_mode AudioTrack에 디코딩 된 배열 바이트를 보냅니다. 나는 시간의 덩어리에서 디코딩 된 바이트를 요청하고
public byte[] decode(InputStream inputStream, int startMs, int maxMs) throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024); float totalMs = 0; boolean seeking = true; try { Bitstream bitstream = new Bitstream(inputStream); Decoder decoder = new Decoder(); boolean done = false; while (!done) { Header frameHeader = bitstream.readFrame(); if (frameHeader == null) { done = true; } else { totalMs += frameHeader.ms_per_frame(); if (totalMs >= startMs) { seeking = false; } if (!seeking) { // logger.debug("Handling header: " + frameHeader.layer_string()); SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream); if (output.getSampleFrequency() != 44100 || output.getChannelCount() != 2) { throw new IllegalArgumentException("mono or non-44100 MP3 not supported"); } short[] pcm = output.getBuffer(); for (short s : pcm) { outStream.write(s & 0xff); outStream.write((s >> 8) & 0xff); } } if (totalMs >= (startMs + maxMs)) { done = true; } } bitstream.closeFrame(); } return outStream.toByteArray(); } catch (BitstreamException e) { throw new IOException("Bitstream error: " + e); } catch (DecoderException e) { throw new IOException("Decoder error: " + e); } }
:로 시작하는이 InputStream를받을 수 있도록
디코딩을 수행하는 코드의 조각이 발견 될 수있다, 나는 단지 그것을 수정 한 (5000, 1000), (6000, 1000), (7000, 1000) 등의 순서로 다음 바이트 배열을 요청할 것입니다.
디코딩 속도가 빠르며 다른 스레드에서 처리되고 디코딩 된 바이트 배열을 사용할 수있게되면 블로킹 큐를 사용하여 다른 thread로 재생 중의 AudioTrack에 기입 해주세요.
문제는 트랙에서 청크가 연속적이지 않으므로 매끄럽지 않습니다 (각 청크는 연속이지만 AudioTrack에 추가하면 부 자연스러운 재생이 발생 함).
마무리하려면 :
- 이 젤리 빈 문제로 충돌 한 경우, 어떻게 그것을 해결 했습니까?
- 내 접근 방식을 시도한 사람이 있으면 위 코드에서 무엇을 잘못하고 있습니까? 이 솔루션을 사용했다면 나머지 코드를 게시 할 수 있습니다.
고마워요!
응답 해 주셔서 감사합니다 ... 필자는 필요한 프로젝트에 대해이 접근법을 따르고 싶지 않지만 언젠가는 여가 시간을 갖기 위해 교육적인 목적으로이 방법을 시도 할 것입니다. 열린 질문은 여전히 유효합니다 (JellyBean을 제외한 모든 플랫폼에서 정상적으로 작동합니다.) MP3를 요청할 때 JB는 Range-Header를 10 번 요청합니다. 10 번째 시도 후에 만 이전 동작으로 되돌아갑니다.) 당신이 이것에 부딪쳤다면, 어떻게 이것을 고치셨습니까? 그것은 서버 측에서나 클라이언트 쪽에서였습니까? – gunar
이 줄에 코드를 포함 할 수 있습니까? "MP3를 요청할 때 JB는 Range-Header를 10 회 요청합니다. 10 번째 시도 후에 만 이전 동작으로 되돌아갑니다." – Matt
JB가 Range-Header를 요청하는 코드를 추가하지 않았습니다. [Android 관련 문제] (https://code.google.com/p/android/issues/detail?id=35790)를 참조하십시오. 그것은 그것과 관련이 있습니다. – gunar