Android background video recording -


i developing recording service custom android platform. when application starts start recording video in background. unfortunately application runs on hardware prevents me using video recording. solution problem take images , hold them in circular buffer, when event happens stop feeding images buffer , place them in video.

the problem encountering when save images video noisy green screen.

i based code on example: using mediacodec save series of images video

note: cannot use mediamux either, developing api level <18.

i guide through steps take. on creation of service open camera, set preview on surfacetexture , add images buffer when previewcallback called.

private camera mcamera; private string mtimestamp; surfacetexture msurfacetexture;  private circularbuffer<bytearrayoutputstream> mcircularbuffer; private static final int max_buffer_size = 200; private int mwidth = 720; private int mheight = 480;  @override public void oncreate() {     try {         mcircularbuffer = new circularbuffer(max_buffer_size);         mtimestamp = new simpledateformat("yyyymmdd_hhmmss").format(new date());         msurfacetexture = new surfacetexture(10);          mcamera = getcamerainstance();         parameters parameters = mcamera.getparameters();         parameters.setjpegquality(20);         parameters.setpicturesize(mwidth, mheight);         mcamera.setparameters(parameters);         mcamera.setpreviewtexture(msurfacetexture);         mcamera.startpreview();         mcamera.setpreviewcallback(mpreviewcallback);     } catch (ioexception e) {         log.d(tag, "ioexception: " + e.getmessage());     } catch (exception e) {         log.d(tag, "exception: " + e.getmessage());     } }  private previewcallback mpreviewcallback = new previewcallback() {      @override     public void onpreviewframe(byte[] data, camera camera) {         bytearrayoutputstream out = new bytearrayoutputstream();         yuvimage yuvimage = new yuvimage(data, imageformat.nv21, mwidth, mheight, null);         rect rectangle = new rect(0, 0, mwidth, mheight);         yuvimage.compresstojpeg(rectangle, 20, out);         mcircularbuffer.add(out);     } }; 

all of works, when convert byte arrays jpg @ point correct image files.

now when event happens, service destroyed , last 200 images need placed behind each other , converted mp4. first saving h264, based on code provided in link above. , converting file mp4 using mp4parser.

@override public void ondestroy() {     super.ondestroy();     mcamera.stoppreview();     savefiletoh264("video/avc");     converth264tomp4(); }  private void savefiletoh264(string mimetype) {     mediacodec codec = mediacodec.createencoderbytype(mimetype);     mediaformat mediaformat = null;      int height = mcamera.getparameters().getpicturesize().height;     int width = mcamera.getparameters().getpicturesize().width;      log.d(tag, height + ", " + width);      mediaformat = mediaformat.createvideoformat(mimetype, width, height);      mediaformat.setinteger(mediaformat.key_bit_rate, 1000000);     mediaformat.setinteger(mediaformat.key_frame_rate, 15);     mediaformat.setinteger(mediaformat.key_color_format,             mediacodecinfo.codeccapabilities.color_formatyuv420semiplanar);     mediaformat.setinteger(mediaformat.key_i_frame_interval, 10);     codec.configure(mediaformat, null, null, mediacodec.configure_flag_encode);     codec.start();      bytebuffer[] inputbuffers = codec.getinputbuffers();     bytebuffer[] outputbuffers = codec.getoutputbuffers();     boolean sawinputeos = false;     int inputbufferindex = -1, outputbufferindex = -1;     bufferinfo info = null;      try {         file file = new file("/sdcard/output.h264");         fileoutputstream fstream2 = new fileoutputstream(file);         dataoutputstream dos = new dataoutputstream(fstream2);          // loop through buffer , image output streams         (int = 0; < max_buffer_size; i++) {             bytearrayoutputstream out = mcircularbuffer.getdata(i);             byte[] dat = out.tobytearray();              long waittime = 50;              inputbufferindex = codec.dequeueinputbuffer(waittime);             int bytesread = max_buffer_size - 1 - i;              int presentationtime = 0;              if (bytesread <= 0)                 sawinputeos = true;              if (inputbufferindex >= 0) {                 if (!sawinputeos) {                     int samplesiz = dat.length;                     inputbuffers[inputbufferindex].put(dat);                     codec.queueinputbuffer(inputbufferindex, 0, samplesiz, presentationtime, 0);                     presentationtime += 100;                      info = new bufferinfo();                     outputbufferindex = codec.dequeueoutputbuffer(info, waittime);                     log.i("bata", "outputbufferindex=" + outputbufferindex);                     if (outputbufferindex >= 0) {                         byte[] array = new byte[info.size];                         outputbuffers[outputbufferindex].get(array);                          if (array != null) {                             try {                                 dos.write(array);                             } catch (ioexception e) {                                 e.printstacktrace();                             }                         }                          codec.releaseoutputbuffer(outputbufferindex, false);                         inputbuffers[inputbufferindex].clear();                         outputbuffers[outputbufferindex].clear();                          if (sawinputeos)                             break;                     }                 } else {                     codec.queueinputbuffer(inputbufferindex, 0, 0, presentationtime,                             mediacodec.buffer_flag_end_of_stream);                      info = new bufferinfo();                     outputbufferindex = codec.dequeueoutputbuffer(info, waittime);                      if (outputbufferindex >= 0) {                         byte[] array = new byte[info.size];                         outputbuffers[outputbufferindex].get(array);                          if (array != null) {                             try {                                 dos.write(array);                             } catch (ioexception e) {                                 e.printstacktrace();                             }                         }                          codec.releaseoutputbuffer(outputbufferindex, false);                         inputbuffers[inputbufferindex].clear();                         outputbuffers[outputbufferindex].clear();                         break;                     }                 }             }         }         codec.flush();          try {             fstream2.close();             dos.flush();             dos.close();         } catch (ioexception e) {             e.printstacktrace();         }         codec.stop();         codec.release();         codec = null;     } catch (filenotfoundexception e) {         log.d(tag, "file not found: " + e.getmessage());     } catch (exception e) {         log.d(tag, "exception: " + e.getmessage());     } }  private void converth264tomp4() {     try {         datasource videofile = new filedatasourceimpl("/sdcard/output.h264");          h264trackimpl h264track = new h264trackimpl(videofile, "eng", 5, 1);         // 5fps. can play timescale , timetick non integer fps, 23.967         // 24000/1001          movie movie = new movie();          movie.addtrack(h264track);          container out = new defaultmp4builder().build(movie);          fileoutputstream fos = new fileoutputstream(new file("/sdcard/output.mp4"));         out.writecontainer(fos.getchannel());         fos.flush();         fos.close();         log.d(tag, "video saved sdcard");     } catch (exception e) {         log.d(tag, "no file saved");     } } 

i'm pretty sure problem in savefiletoh264 code. i've read post, on link provided above, stride and/or alignment issue(?). have no experience encoding/decoding i'm not sure how solve issue. if appreciated!

note: know code not optimal , still need add more checks , whatnot, first want working video out of this.


Comments