Android MediaExtractor und mp3-stream
Ich versuche zu spielen, einem mp3-stream mit MediaExtractor/MediaCodec. MediaPlayer ist aus der Frage wegen Latenz und lange Puffer-Größe.
Nur Beispiel-code, den ich gefunden habe, ist diese: http://dpsm.wordpress.com/category/android/
Die code-Beispiele sind nur partielle (?) und verwenden Sie eine Datei statt einem stream.
Ich habe versucht, anpassen, in diesem Beispiel spielen Sie eine Audio-Stream aber ich kann nicht meinen Kopf herum, wie dies funktionieren soll. Die Android-Dokumentation wie üblich ist nicht mehr zu helfen.
Verstehe ich, dass wir zuerst erhalten Sie Informationen über den stream, vermutlich setup der Hörgeschichte mit diesen Informationen ( code-Beispiel enthält Hörgeschichte Initialisierung ?) und dann öffnen Sie eine Eingabe-Puffer-und Ausgabe-Puffer.
Habe ich neu erstellt-code, mit dem, was ich denke, wäre die fehlenden Teile, aber kein Ton kommt aus diesem.
Kann mir jemand zeigen in die richtige Richtung zu verstehen, wie dies funktionieren soll?
public final String LOG_TAG = "mediadecoderexample";
private static int TIMEOUT_US = -1;
MediaCodec codec;
MediaExtractor extractor;
MediaFormat format;
ByteBuffer[] codecInputBuffers;
ByteBuffer[] codecOutputBuffers;
Boolean sawInputEOS = false;
Boolean sawOutputEOS = false;
AudioTrack mAudioTrack;
BufferInfo info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "http://82.201.100.9:8000/RADIO538_WEB_MP3";
extractor = new MediaExtractor();
try {
extractor.setDataSource(url);
} catch (IOException e) {
}
format = extractor.getTrackFormat(0);
String mime = format.getString(MediaFormat.KEY_MIME);
int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
Log.i(LOG_TAG, "===========================");
Log.i(LOG_TAG, "url "+url);
Log.i(LOG_TAG, "mime type : "+mime);
Log.i(LOG_TAG, "sample rate : "+sampleRate);
Log.i(LOG_TAG, "===========================");
codec = MediaCodec.createDecoderByType(mime);
codec.configure(format, null , null , 0);
codec.start();
codecInputBuffers = codec.getInputBuffers();
codecOutputBuffers = codec.getOutputBuffers();
extractor.selectTrack(0);
mAudioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
sampleRate,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
AudioTrack.getMinBufferSize (
sampleRate,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT
),
AudioTrack.MODE_STREAM
);
info = new BufferInfo();
input();
output();
}
private void output()
{
final int res = codec.dequeueOutputBuffer(info, TIMEOUT_US);
if (res >= 0) {
int outputBufIndex = res;
ByteBuffer buf = codecOutputBuffers[outputBufIndex];
final byte[] chunk = new byte[info.size];
buf.get(chunk); //Read the buffer all at once
buf.clear(); //** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN
if (chunk.length > 0) {
mAudioTrack.write(chunk, 0, chunk.length);
}
codec.releaseOutputBuffer(outputBufIndex, false /* render */);
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
sawOutputEOS = true;
}
} else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
codecOutputBuffers = codec.getOutputBuffers();
} else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
final MediaFormat oformat = codec.getOutputFormat();
Log.d(LOG_TAG, "Output format has changed to " + oformat);
mAudioTrack.setPlaybackRate(oformat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
}
}
private void input()
{
Log.i(LOG_TAG, "inputLoop()");
int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_US);
Log.i(LOG_TAG, "inputBufIndex : "+inputBufIndex);
if (inputBufIndex >= 0) {
ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
int sampleSize = extractor.readSampleData(dstBuf, 0);
Log.i(LOG_TAG, "sampleSize : "+sampleSize);
long presentationTimeUs = 0;
if (sampleSize < 0) {
Log.i(LOG_TAG, "Saw input end of stream!");
sawInputEOS = true;
sampleSize = 0;
} else {
presentationTimeUs = extractor.getSampleTime();
Log.i(LOG_TAG, "presentationTimeUs "+presentationTimeUs);
}
codec.queueInputBuffer(inputBufIndex,
0, //offset
sampleSize,
presentationTimeUs,
sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
if (!sawInputEOS) {
Log.i(LOG_TAG, "extractor.advance()");
extractor.advance();
}
}
}
}
Bearbeiten: hinzufügen logcat Ausgang für zusätzliche Ideen.
03-10 16:47:54.115: I/mediadecoderexample(24643): ===========================
03-10 16:47:54.115: I/mediadecoderexample(24643): url ....
03-10 16:47:54.115: I/mediadecoderexample(24643): mime type : audio/mpeg
03-10 16:47:54.115: I/mediadecoderexample(24643): sample rate : 32000
03-10 16:47:54.115: I/mediadecoderexample(24643): ===========================
03-10 16:47:54.120: I/OMXClient(24643): Using client-side OMX mux.
03-10 16:47:54.150: I/Reverb(24643): getpid() 24643, IPCThreadState::self()->getCallingPid() 24643
03-10 16:47:54.150: I/mediadecoderexample(24643): inputLoop()
03-10 16:47:54.155: I/mediadecoderexample(24643): inputBufIndex : 0
03-10 16:47:54.155: I/mediadecoderexample(24643): sampleSize : 432
03-10 16:47:54.155: I/mediadecoderexample(24643): presentationTimeUs 0
03-10 16:47:54.155: I/mediadecoderexample(24643): extractor.advance()
03-10 16:47:59.085: D/HTTPBase(24643): [2] Network BandWidth = 187 Kbps
03-10 16:47:59.085: D/NuCachedSource2(24643): Remaining (64K), HighWaterThreshold (20480K)
03-10 16:48:04.635: D/HTTPBase(24643): [3] Network BandWidth = 141 Kbps
03-10 16:48:04.635: D/NuCachedSource2(24643): Remaining (128K), HighWaterThreshold (20480K)
03-10 16:48:09.930: D/HTTPBase(24643): [4] Network BandWidth = 127 Kbps
03-10 16:48:09.930: D/NuCachedSource2(24643): Remaining (192K), HighWaterThreshold (20480K)
03-10 16:48:15.255: D/HTTPBase(24643): [5] Network BandWidth = 120 Kbps
03-10 16:48:15.255: D/NuCachedSource2(24643): Remaining (256K), HighWaterThreshold (20480K)
03-10 16:48:20.775: D/HTTPBase(24643): [6] Network BandWidth = 115 Kbps
03-10 16:48:20.775: D/NuCachedSource2(24643): Remaining (320K), HighWaterThreshold (20480K)
03-10 16:48:26.510: D/HTTPBase(24643): [7] Network BandWidth = 111 Kbps
03-10 16:48:26.510: D/NuCachedSource2(24643): Remaining (384K), HighWaterThreshold (20480K)
03-10 16:48:31.740: D/HTTPBase(24643): [8] Network BandWidth = 109 Kbps
03-10 16:48:31.740: D/NuCachedSource2(24643): Remaining (448K), HighWaterThreshold (20480K)
03-10 16:48:37.260: D/HTTPBase(24643): [9] Network BandWidth = 107 Kbps
03-10 16:48:37.260: D/NuCachedSource2(24643): Remaining (512K), HighWaterThreshold (20480K)
03-10 16:48:42.620: D/HTTPBase(24643): [10] Network BandWidth = 106 Kbps
03-10 16:48:42.620: D/NuCachedSource2(24643): Remaining (576K), HighWaterThreshold (20480K)
03-10 16:48:48.295: D/HTTPBase(24643): [11] Network BandWidth = 105 Kbps
03-10 16:48:48.295: D/NuCachedSource2(24643): Remaining (640K), HighWaterThreshold (20480K)
03-10 16:48:53.735: D/HTTPBase(24643): [12] Network BandWidth = 104 Kbps
03-10 16:48:53.735: D/NuCachedSource2(24643): Remaining (704K), HighWaterThreshold (20480K)
03-10 16:48:59.115: D/HTTPBase(24643): [13] Network BandWidth = 103 Kbps
03-10 16:48:59.115: D/NuCachedSource2(24643): Remaining (768K), HighWaterThreshold (20480K)
03-10 16:49:04.480: D/HTTPBase(24643): [14] Network BandWidth = 103 Kbps
03-10 16:49:04.480: D/NuCachedSource2(24643): Remaining (832K), HighWaterThreshold (20480K)
03-10 16:49:09.955: D/HTTPBase(24643): [15] Network BandWidth = 102 Kbps
DecoderTest
ist für audio. Sehen Sie etwas "interessant" im logcat?Ich habe auch gesehen, dass diejenigen Beispiele, aber ich denke, das Thema ist zu kompliziert für mich, um herauszufinden, wie "port Sie" zu meinem speziellen Szenario. Der logcat (ill fügen Sie es zu der Frage) nicht, alles zu interessant, und das Telefon scheint zu 'hängen', kann ich nicht Falle drehen Sie volume nach oben oder unten mit den Tasten an der Seite. Die app stürzt nicht ab, obwohl
es ist die openmxplayer für audio -, opensource-Lizenz veröffentlicht.
Ich bin auch interessiert, hast du eine Lösung finden?
Ja, verwenden Sie exoplayer statt
InformationsquelleAutor Juan Carlos Ospina Gonzalez | 2014-03-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den code in
onCreate()
schlägt vor, Sie haben eine falsche Vorstellung darüber, wieMediaCodec
funktioniert. Dein code ist aktuell:MediaCodec
betreibt on-access-Einheiten. Für video-Aufruf-Eingang/- Ausgang erhalten Sie einen einzelnen frame des Videos. Ich habe nicht gearbeitet mit audio, aber mein Verständnis ist, verhält es sich ähnlich. Sie erhalten nicht die gesamte Datei geladen, die in einem Eingabepuffer, und es spielt nicht den stream für Sie; Sie nehmen ein kleines Stück von der Datei, die hand an die decoder und die Hände wieder dekodierten Daten (z.B. ein YUV-video-Puffer-oder PCM-audio-Daten). Sie dann tun, was notwendig ist, um zu spielen, die Daten.Also dein Beispiel würde, am besten, Dekodiere einen Bruchteil einer Sekunde audio. Brauchen Sie zu tun submit-input-get-output in einer Schleife mit der richtigen Handhabung von end-of-stream. Sie können sehen, dass dies getan für video in den verschiedenen bigflake Beispiele. Es sieht aus wie dein code hat die notwendigen Teile.
Bist du mit einem timeout von -1 (unendlich), so dass Sie gehen, um die Versorgung eines Puffer-Eingangs-und ewig warten, bis ein Puffer, der die Ausgabe. Im video würde das nicht funktionieren-die Decoder die ich getestet habe scheinen zu wollen, über vier Puffer eingeben, bevor Sie produzieren keine Ausgabe-aber auch hier habe ich noch nicht gearbeitet, mit audio, so bin ich nicht sicher, ob dies erwartet wird, um zu arbeiten. Da Ihr code ist hängen ich vermute, es ist nicht. Es kann sinnvoll sein, ändern Sie den timeout-Wert auf (sagen wir) 10000 und sehen, ob der hang geht Weg.
Ich nehme an, dies ist ein experiment und du bist nicht wirklich gehen, um all dies zu tun in
onCreate()
. 🙂Ich habe versucht, ändern der OPs-code für die Verwendung einer do/while:
do { input(); output(); } while (!sawInputEOS);
aber ich verstehe immer noch nicht klingen...InformationsquelleAutor fadden
Für jemand, der noch auf der Suche nach einer Antwort auf das problem der Wiedergabe von streamin audio-zuverlässig, möchten Sie vielleicht einen Blick auf dieses Projekt (basierend auf den MediaCodec API)
https://code.google.com/p/android-openmxplayer/
InformationsquelleAutor Juan Carlos Ospina Gonzalez
Gibt es zwei Probleme mit dem oben genannten code. Erstens haben die Staaten akzeptierten Antworten, nur Lesen wird aus dem Eingabe-stream. Aber, zweitens, einen Anruf zu
.play()
erforderlich ist, auf dieAudioTrack
.Diese änderung behebt OPs-code:
InformationsquelleAutor IcedDante