2012-05-23 35 views
6

Tôi đang cố gắng gửi video h264/AAC từ MediaRecorder của Android thông qua một Ổ cắm cục bộ. Mục đích là để gửi video đến một máy chủ WOWZA qua RTMP hoặc RTSP, nhưng nó mang lại cho tôi rất nhiều rắc rối và bây giờ tôi chỉ đang cố gắng ghi dữ liệu vào một tệp từ LocalServerSocket.Streaming video từ MediaRecorder qua LocalSocket

Dưới đây là một số mã. Xin lỗi nó không thực sự sạch sẽ, nhưng tôi đã dành nhiều giờ thử nghiệm nhiều thứ và dự án của tôi là một mớ hỗn độn ngay bây giờ.

Trong hoạt động Camera, thiết lập tập tin đầu ra:

LocalSocket outSocket = new LocalSocket(); 

try { 
    outSocket.connect(new LocalSocketAddress(LOCAL_SOCKET)); 
} catch (Exception e) { 
    Log.i(LOG_TAG, "Error connecting socket: "+e); 
} 
mMediaRecorder.setOutputFile(outSocket.getFileDescriptor()); 

Việc thực hiện LocalServerSocket:

try { 
    mLocalServerSocket = new LocalServerSocket(mName); 
} catch (Exception e) { 
    Log.e(LOG_TAG, "Error creating server socket: "+e); 
    return; 
} 

while (true) { 

    File out = null; 
    FileOutputStream fop = null; 
    try { 
     mLocalClientSocket = mLocalServerSocket.accept(); 

     InputStream in = mLocalClientSocket.getInputStream(); 

     out = new File(mContext.getExternalFilesDir(null), "testfile.mp4"); 
     fop = new FileOutputStream(out); 

     int len = 0; 
     byte[] buffer = new byte[1024]; 
     while ((len = in.read(buffer)) >= 0) { 

      Log.i(LOG_TAG, "Writing "+len+" bytes"); 
      fop.write(buffer, 0, len); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    finally{ 
     try { 
      fop.close(); 
      mLocalClientSocket.close(); 
     } catch (Exception e2) {} 
    } 
} 

Vấn đề là file kết quả từ này là không thể đọc được bởi bất kỳ media player. Bạn có nghĩ điều này là do sự cố mã hóa không? Mã này sẽ tạo ra một tệp nhị phân nếu tôi hiểu rõ ?!

Xin cảm ơn trước, chúc mừng.

+0

nếu bạn không gặp lỗi, có thể do vấn đề về mã hóa/tên tệp. [OutputFormat] (http://developer.android.com/reference/android/media/MediaRecorder.OutputFormat.html) bạn đã đặt? Có thể đổi tên nó thành '.3gp' hoặc như vậy sẽ giúp - xem [ở đây] (http://stackoverflow.com/questions/9110711/android-mediarecorder-getting-3gp-instead-of-mpeg4) – zapl

+0

Định dạng đầu ra là MPEG_4, vì vậy tôi đoán nó nên bằng ok với một phần mở rộng .mp4. Bên cạnh đó, nếu tôi viết trực tiếp vào một tập tin .mp4 trong mMediaRecorder.setOutputFile() nó hoạt động hoàn hảo. – Simon

+0

bạn có kiểm tra xem một cái gì đó như [mediainfo] (http://mediainfo.sourceforge.net/en) có thể đọc các thuộc tính của video được tạo không? Bạn cũng có thể thử một khác biệt nhị phân (ít nhất là tiêu đề) của tệp được tạo trực tiếp và tệp gửi qua ổ cắm cục bộ của bạn để kiểm tra xem tệp được tạo có đúng không. – zapl

Trả lời

2

Ok, tôi đã tìm thấy lý do các tệp không thể phát. Trong các tập tin MP4 và 3GPP, có một tiêu đề chứa các byte:

ftyp3gp4 3gp43gp6 rộng mdat

trong HEX

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

4 byte trước Thẻ 'mdat' đại diện cho vị trí của một thẻ 'moov' khác nằm ở kết thúc của tập tin. Vị trí thường được đặt khi quá trình ghi kết thúc, nhưng vì MediaRecorder không thể tìm kiếm các ổ cắm, nó không thể đặt các byte này thành giá trị chính xác trong trường hợp của chúng tôi.

Vấn đề của tôi bây giờ là tìm cách tạo một tệp như vậy có thể phát trực tuyến, vì nó liên quan đến nó để phát trước khi quá trình ghi kết thúc.

+3

Bạn đã tìm ra một giải pháp để làm cho nó có thể phát trực tuyến? – Houf

+0

Xin chào Simon, Bạn đã tìm thấy một số giải pháp..xin vui lòng chia sẻ nó, tôi đang mắc kẹt trong cùng một vấn đề –

+0

Hi Ankita. Xin lỗi nhưng chúng tôi đã bỏ dự án này ngay bây giờ nên tôi đã ngừng làm việc về vấn đề này. Chúc may mắn với điều này, chúc mừng. – Simon

1

Bạn có thể thử sử dụng mp4box để cấu trúc lại tệp của mình. Hộp moov cung cấp các chỉ mục cho từng mẫu âm thanh và video. Nếu đó là ở cuối của tập tin, nó làm cho nó khó khăn để dòng.

này có thể giúp: http://boliston.wordpress.com/tag/moov-box/

Hoặc này: mp4box -inter 0,5 some_file.mp4

(Tôi không có cơ hội để hiện thử)

Nếu bạn cần điều này để làm việc với ứng dụng của bạn, tôi không biết bất kỳ hoạt động nào để chuyển mp4box sang Android.

+0

BTW mp4box là một phần của dự án GPAC hiện nay. Có một gói cho rằng trong Ubuntu, ít nhất. http://gpac.wp.mines-telecom.fr/ –

0

Tôi đã thử hôm nay để làm tương tự, nhưng mp4 không phải là rất dễ dàng để dòng (như đã nói trước khi một số phần được viết ở cuối). Tôi không nói điều đó là không thể nhưng có vẻ ít nhất là khá khó.

Vì vậy, giải pháp cho các API Android mới hơn (4.3) có thể là cái này:

  • Đặt preview camera để một SurfaceTexture: camera.setPreviewTexture
  • Ghi kết cấu này sử dụng OpenGL và MediaCodex + muxer

Hạn chế của giải pháp này là kích thước xem trước của máy ảnh có thể nhỏ hơn kích thước video. Điều này có nghĩa là tùy thuộc vào thiết bị bạn không thể ghi ở độ phân giải cao nhất. Gợi ý: một số máy ảnh cho biết họ không hỗ trợ kích thước xem trước cao hơn nhưng chúng cũng có thể cố gắng định cấu hình máy ảnh để đặt kích thước xem trước cho kích thước video. Nếu bạn làm như vậy bắt được RuntimeException của camera.setParameters và nếu nó không chỉ sử dụng các kích thước xem trước được hỗ trợ.

Một số liên kết như thế nào để ghi lại từ một SurfaceTexture:

Bigflage: great examples for MediaCodec stuff.

The VideoRecorder class from Lablet.

Cũng có thể có ích: spydroid-ipcamera suối dữ liệu từ các ổ cắm MediaRecorder như suối RTP nhưng tôi đã không tìm thấy cách để cấp dữ liệu đó cho MediaCodec. (Tôi đã gặp khó khăn khi đọc đúng kích thước đơn vị NAL như họ ...)

Các vấn đề liên quan