Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Mobile Development
  3. Android
  4. MediaExtractor.setDataSource works or doesn't based on Android OS version

MediaExtractor.setDataSource works or doesn't based on Android OS version

Scheduled Pinned Locked Moved Android
announcementandroiddata-structureshelp
2 Posts 1 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JudyL_MD
    wrote on last edited by
    #1

    It's been a while since I've participated on CP, and I'm back with a doozy I'm having a problem with MediaExtractor and using a MemoryFile as the data source. In the real world, this media viewer is part of a larger app that supplies a chunk of bytes that contains a complete MP4 video. To eliminate all the other stuff, I have created a little demo app that only contains the viewer and a test MemoryFile. Please note that not using a MemoryFile, i.e. saving the video data to storage and playing from there, is not an option. First, the code. I create the MemoryFile in the test app's MainActivity.onCreate

    // these lines are only in the test app
    InputStream inS = getResources ().getAssets ().open ("testmp4.mp4");

    int length = inS.available ();
    byte[] data = new byte[length];
    inS.read (data);
    inS.close ();

    // in the real world, the other stuff gives me a byte[] array and my code starts here
    m_memFile = new MemoryFile (null, length);
    m_memFile.writeBytes (data, 0, 0, length);

    Method getFD = MemoryFile.class.getMethod ("getFileDescriptor");
    m_memFileFD = (FileDescriptor) getFD.invoke (m_memFile);

    This is in the MainActivity's Play button click listener:

    if (m_player == null)
    {
    m_player = new MyPlayer (MainActivity.this.m_events, MainActivity.this.m_memFileFD, MainActivity.this.m_memFile.length (), (SurfaceView) findViewById (R.id.viewerMediaVideo));
    }
    m_player.play ();

    The video player is in the class MyPlayer that extends Runnable:

    protected MediaExtractor m_extractor = null;
    protected PlayerStates m_state = PlayerStates.STOPPED;
    private SurfaceHolder m_surface = null;
    protected FileDescriptor m_memFileFD = null;
    protected long m_memFileLen = 0;

    public MyPlayer (PlayerEvents ev, FileDescriptor fd, long len, SurfaceView s)
    {
    m_events = ev;
    m_memFileFD = fd;
    m_memFileLen = len;
    m_surface = s.getHolder ();
    }

    public void play ()
    {
    if (m_state == PlayerStates.STOPPED)
    {
    m_stop = false;
    new Thread (this).start ();
    }
    ...
    }

    public void run ()
    {
    android.os.Process.setThreadPriority (Process.THREAD_PRIORITY_URGENT_AUDIO);

    m\_extractor = new MediaExtractor ();
    try
    {
        m\_extractor.setDataSource (m\_memFileFD, 0, m\_memFileLen);
    }
    catch (final Exception excp)
    {
        m\_extractor.release ();
        m\_extractor = null;
    
        m\_handler.post (new Runnable (){public void run ()
                       {m\_events.onError ("
    
    J 1 Reply Last reply
    0
    • J JudyL_MD

      It's been a while since I've participated on CP, and I'm back with a doozy I'm having a problem with MediaExtractor and using a MemoryFile as the data source. In the real world, this media viewer is part of a larger app that supplies a chunk of bytes that contains a complete MP4 video. To eliminate all the other stuff, I have created a little demo app that only contains the viewer and a test MemoryFile. Please note that not using a MemoryFile, i.e. saving the video data to storage and playing from there, is not an option. First, the code. I create the MemoryFile in the test app's MainActivity.onCreate

      // these lines are only in the test app
      InputStream inS = getResources ().getAssets ().open ("testmp4.mp4");

      int length = inS.available ();
      byte[] data = new byte[length];
      inS.read (data);
      inS.close ();

      // in the real world, the other stuff gives me a byte[] array and my code starts here
      m_memFile = new MemoryFile (null, length);
      m_memFile.writeBytes (data, 0, 0, length);

      Method getFD = MemoryFile.class.getMethod ("getFileDescriptor");
      m_memFileFD = (FileDescriptor) getFD.invoke (m_memFile);

      This is in the MainActivity's Play button click listener:

      if (m_player == null)
      {
      m_player = new MyPlayer (MainActivity.this.m_events, MainActivity.this.m_memFileFD, MainActivity.this.m_memFile.length (), (SurfaceView) findViewById (R.id.viewerMediaVideo));
      }
      m_player.play ();

      The video player is in the class MyPlayer that extends Runnable:

      protected MediaExtractor m_extractor = null;
      protected PlayerStates m_state = PlayerStates.STOPPED;
      private SurfaceHolder m_surface = null;
      protected FileDescriptor m_memFileFD = null;
      protected long m_memFileLen = 0;

      public MyPlayer (PlayerEvents ev, FileDescriptor fd, long len, SurfaceView s)
      {
      m_events = ev;
      m_memFileFD = fd;
      m_memFileLen = len;
      m_surface = s.getHolder ();
      }

      public void play ()
      {
      if (m_state == PlayerStates.STOPPED)
      {
      m_stop = false;
      new Thread (this).start ();
      }
      ...
      }

      public void run ()
      {
      android.os.Process.setThreadPriority (Process.THREAD_PRIORITY_URGENT_AUDIO);

      m\_extractor = new MediaExtractor ();
      try
      {
          m\_extractor.setDataSource (m\_memFileFD, 0, m\_memFileLen);
      }
      catch (final Exception excp)
      {
          m\_extractor.release ();
          m\_extractor = null;
      
          m\_handler.post (new Runnable (){public void run ()
                         {m\_events.onError ("
      
      J Offline
      J Offline
      JudyL_MD
      wrote on last edited by
      #2

      Just a followup ... I never did get around to harassing Google about this. I simply worked around the problem by checking the build version and only using the "old" way with a MemoryFile for KitKat and Lollipop and using the "new with API 23" MediaDataSource with the data behind the MemoryFile for Marshmallow and up.

      Be wary of strong drink. It can make you shoot at tax collectors - and miss. Lazarus Long, "Time Enough For Love" by Robert A. Heinlein

      1 Reply Last reply
      0
      Reply
      • Reply as topic
      Log in to reply
      • Oldest to Newest
      • Newest to Oldest
      • Most Votes


      • Login

      • Don't have an account? Register

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • World
      • Users
      • Groups