From Google's release of the various versions of the Android version of the source, android4.0 started to support the buffer playback of the interface and demo, after compiling the Android SDK in out will generate an executable file stream, This is a very good demo test program, support H264 TS playback, program source code location with android4.3 as an example, directory: Android4.3\frameworks\av\cmds\stagefright, The corresponding file for Stream.cpp, universal player with buffer to do a breach here oh, from here, interested can do so, first do a demo of their own, first play the local file, and then the streaming media protocol added in the set achievement OK, this file code is as follows:
/*
* Copyright (C) The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* You are not a use this file except in compliance with the License.
* Obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable or agreed to writing, software
* Distributed under the License is distributed on a "as is" BASIS,
* Without warranties or CONDITIONS of any KIND, either express or implied.
* See the License for the specific language governing permissions and
* Limitations under the License.
*/
#define LOG_NDEBUG 0
#define LOG_TAG "Stream"
#include "Utils/log.h"
#include <binder/ProcessState.h>
#include <cutils/properties.h>//For Property_get
#include <media/IStreamSource.h>
#include <media/mediaplayer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/Surface.h>
#include <fcntl.h>
#include <ui/DisplayInfo.h>
using namespace Android;
struct Mystreamsource:public Bnstreamsource {
Object assumes ownership of FD.
Mystreamsource (int fd);
virtual void Setlistener (const sp<istreamlistener> &listener);
virtual void setbuffers (const vector<sp<imemory> > &buffers);
virtual void onbufferavailable (size_t index);
Protected
Virtual ~mystreamsource ();
Private
int mFd;
off64_t mfilesize;
uint64_t mnumpacketssent;
Sp<istreamlistener> Mlistener;
vector<sp<imemory> > Mbuffers;
Disallow_evil_constructors (Mystreamsource);
};
Mystreamsource::mystreamsource (int fd)
: MFd (FD),
Mfilesize (0),
Mnumpacketssent (0) {
Check_ge (FD, 0);
Mfilesize = lseek64 (FD, 0, seek_end);
Lseek64 (FD, 0, Seek_set);
}
Mystreamsource::~mystreamsource () {
Close (mFd);
MFd =-1;
}
void Mystreamsource::setlistener (const sp<istreamlistener> &listener) {
Mlistener = listener;
}
void Mystreamsource::setbuffers (const vector<sp<imemory> > &buffers) {
Mbuffers = buffers;
}
void Mystreamsource::onbufferavailable (size_t index) {
CHECK_LT (Index, Mbuffers.size ());
#if 0
if (mnumpacketssent >= 20000) {
Alogi ("Signalling discontinuity Now");
off64_t offset = 0;
CHECK ((offset% 188) = = 0);
Lseek (mFd, offset, seek_set);
Sp<amessage> extra = new Amessage;
Extra->setint32 (istreamlistener::kkeyformatchange, 0);
Mlistener->issuecommand (
Istreamlistener::D iscontinuity, FALSE/* synchronous */, extra);
mnumpacketssent = 0;
}
#endif
Sp<imemory> mem = Mbuffers.itemat (index);
ssize_t n = Read (MFd, Mem->pointer (), mem->size ());
if (n <= 0) {
Mlistener->issuecommand (Istreamlistener::eos, FALSE/* synchronous */);
} else {
Mlistener->queuebuffer (index, n);
Mnumpacketssent + = n/188;
}
}
////////////////////////////////////////////////////////////////////////////////
struct Myconvertingstreamsource:public Bnstreamsource {
Myconvertingstreamsource (const char *filename);
virtual void Setlistener (const sp<istreamlistener> &listener);
virtual void setbuffers (const vector<sp<imemory> > &buffers);
virtual void onbufferavailable (size_t index);
Protected
Virtual ~myconvertingstreamsource ();
Private
Mutex MLock;
Condition mcondition;
Sp<istreamlistener> Mlistener;
vector<sp<imemory> > Mbuffers;
Sp<mpeg2tswriter> Mwriter;
ssize_t Mcurrentbufferindex;
size_t Mcurrentbufferoffset;
List<size_t> Mbufferqueue;
Static ssize_t writedatawrapper (void *me, const void *data, size_t size);
ssize_t writedata (const void *data, size_t size);
Disallow_evil_constructors (Myconvertingstreamsource);
};
////////////////////////////////////////////////////////////////////////////////
Myconvertingstreamsource::myconvertingstreamsource (const char *filename)
: Mcurrentbufferindex (-1),
Mcurrentbufferoffset (0) {
sp<datasource> DataSource = Datasource::createfromuri (filename);
CHECK (DataSource! = NULL);
sp<mediaextractor> extractor = mediaextractor::create (DataSource);
CHECK (Extractor! = NULL);
Mwriter = new Mpeg2tswriter (
this, &myconvertingstreamsource::writedatawrapper);
for (size_t i = 0; i < extractor->counttracks (); ++i) {
Const sp<metadata> &meta = Extractor->gettrackmetadata (i);
const char *mime;
CHECK (Meta->findcstring (Kkeymimetype, &mime));
if (strncasecmp ("video/", mime, 6) && strncasecmp ("audio/", mime, 6)) {
Continue
}
Check_eq (Mwriter->addsource (Extractor->gettrack (i)), (status_t) OK);
}
Check_eq (Mwriter->start (), (status_t) OK);
}
Myconvertingstreamsource::~myconvertingstreamsource () {
}
void Myconvertingstreamsource::setlistener (
Const sp<istreamlistener> &listener) {
Mlistener = listener;
}
void Myconvertingstreamsource::setbuffers (
Const vector<sp<imemory> > &buffers) {
Mbuffers = buffers;
}
ssize_t Myconvertingstreamsource::writedatawrapper (
void *me, const void *data, size_t size) {
return Static_cast<myconvertingstreamsource *> (Me)->writedata (data, size);
}
ssize_t myconvertingstreamsource::writedata (const void *data, size_t size) {
size_t totalwritten = 0;
while (Size > 0) {
Mutex::autolock Autolock (MLock);
if (Mcurrentbufferindex < 0) {
while (Mbufferqueue.empty ()) {
Mcondition.wait (MLock);
}
Mcurrentbufferindex = *mbufferqueue.begin ();
Mcurrentbufferoffset = 0;
Mbufferqueue.erase (Mbufferqueue.begin ());
}
Sp<imemory> mem = Mbuffers.itemat (Mcurrentbufferindex);
size_t copy = size;
if (copy + Mcurrentbufferoffset > mem->size ()) {
copy = Mem->size ()-mcurrentbufferoffset;
}
memcpy ((uint8_t *) mem->pointer () + mcurrentbufferoffset, data, copy);
Mcurrentbufferoffset + = copy;
if (Mcurrentbufferoffset = = Mem->size ()) {
Mlistener->queuebuffer (Mcurrentbufferindex, Mcurrentbufferoffset);
Mcurrentbufferindex =-1;
}
data = (const uint8_t *) data + copy;
Size-= copy;
Totalwritten + = copy;
}
Return (ssize_t) Totalwritten;
}
void Myconvertingstreamsource::onbufferavailable (size_t index) {
Mutex::autolock Autolock (MLock);
Mbufferqueue.push_back (index);
Mcondition.signal ();
if (Mwriter->reachedeos ()) {
if (mcurrentbufferindex >= 0) {
Mlistener->queuebuffer (Mcurrentbufferindex, Mcurrentbufferoffset);
Mcurrentbufferindex =-1;
}
Mlistener->issuecommand (Istreamlistener::eos, FALSE/* synchronous */);
}
}
////////////////////////////////////////////////////////////////////////////////
struct Myclient:public bnmediaplayerclient {
MyClient ()
: Meos (False) {
}
virtual void Notify (int msg, int ext1, int ext2, const Parcel *obj) {
Mutex::autolock Autolock (MLock);
if (msg = = Media_error | | msg = = media_playback_complete) {
Meos = true;
Mcondition.signal ();
}
}
void Waitforeos () {
Mutex::autolock Autolock (MLock);
while (!meos) {
Mcondition.wait (MLock);
}
}
Protected
Virtual ~myclient () {
}
Private
Mutex MLock;
Condition mcondition;
BOOL Meos;
Disallow_evil_constructors (myclient);
};
int main (int argc, char **argv) {
Android::P rocessstate::self ()->startthreadpool ();
Datasource::registerdefaultsniffers ();
if (argc! = 2) {
fprintf (stderr, "Usage:%s filename\n", argv[0]);
return 1;
}
sp<surfacecomposerclient> composerclient = new Surfacecomposerclient;
Check_eq (Composerclient->initcheck (), (status_t) OK);
sp<ibinder> Display (Surfacecomposerclient::getbuiltindisplay (
Isurfacecomposer::edisplayidmain));
DisplayInfo info;
Surfacecomposerclient::getdisplayinfo (display, &info);
ssize_t displaywidth = INFO.W;
ssize_t displayheight = info.h;
ALOGV ("Display is%d x%d\n", Displaywidth, Displayheight);
sp<surfacecontrol> control =
Composerclient->createsurface (
String8 ("A Surface"),
Displaywidth,
Displayheight,
pixel_format_rgb_565,
0);
CHECK (Control! = NULL);
CHECK (Control->isvalid ());
Surfacecomposerclient::openglobaltransaction ();
Check_eq (Control->setlayer (Int_max), (status_t) OK);
Check_eq (Control->show (), (status_t) OK);
Surfacecomposerclient::closeglobaltransaction ();
sp<surface> Surface = Control->getsurface ();
CHECK (surface! = NULL);
sp<iservicemanager> sm = Defaultservicemanager ();
sp<ibinder> Binder = Sm->getservice (String16 ("Media.player"));
sp<imediaplayerservice> service = interface_cast<imediaplayerservice> (binder);
CHECK (Service.get ()! = NULL);
sp<myclient> client = new MyClient;
Sp<istreamsource> source;
Char Prop[property_value_max];
BOOL Usemp4 = Property_get ("Media.stagefright.use-mp4source", prop, NULL) &&
(!STRCMP (prop, "1") | |!strcasecmp (prop, "true"));
size_t len = strlen (argv[1]);
if ((!usemp4 && len >= 3 &&!strcasecmp (". ts", &argv[1][len-3])) | |
(Usemp4 && len >= 4 &&
(!STRCASECMP (". mp4", &argv[1][len-4])
|| !STRCASECMP (". 3gp", &argv[1][len-4])
|| !STRCASECMP (". 3g2", &argv[1][len-4]))) {
int fd = open (argv[1], o_rdonly);
if (FD < 0) {
fprintf (stderr, "Failed to open file '%s '.", argv[1]);
return 1;
}
Source = new Mystreamsource (FD);
} else {
printf ("Converting file to transport stream for streaming...\n");
Source = new Myconvertingstreamsource (argv[1]);
}
Sp<imediaplayer> player =
Service->create (client, 0);
if (player! = NULL && player->setdatasource (source) = = No_error) {
Player->setvideosurfacetexture (Surface->getigraphicbufferproducer ());
Player->start ();
Client->waitforeos ();
Player->stop ();
} else {
fprintf (stderr, "failed to instantiate player.\n");
}
Composerclient->dispose ();
return 0;
}
"The first chapter-android platform buffer play Explore" Buffer play Demo