2016-03-01 14 views
6

Tôi gặp phải sự cố lạ khi cố gắng triển khai phát lại âm thanh phát chậm trễ trên Nexus 6 chạy Android 6.0.1 sử dụng OpenSL ES.Android với Nexus 6 - cách tránh ưu tiên của luồng âm thanh OpenSL giảm liên quan đến trọng tâm ứng dụng?

Nỗ lực ban đầu của tôi dường như đang bị các vấn đề về đói, vì vậy tôi đã thêm một số điểm chuẩn thời gian cơ bản trong hàm gọi lại hoàn thành bộ đệm. Những gì tôi đã tìm thấy là âm thanh phát lại tốt nếu tôi liên tục nhấn vào màn hình trong khi ứng dụng của tôi đang mở, nhưng nếu tôi để nó một mình trong vài giây, cuộc gọi lại sẽ mất nhiều thời gian hơn. Tôi có thể tái tạo hành vi này một cách nhất quán. Một vài điều cần lưu ý:

  • "một vài giây" ~ = 3-5 giây, không đủ thời gian để kích hoạt một sự thay đổi màn hình
  • hoạt động ứng dụng của tôi đặt FLAG_KEEP_SCREEN_ON, vì vậy không có thay đổi màn hình nên xảy ra nào
  • Tôi đã không thực hiện hành động nào để cố tăng ưu tiên của chuỗi gọi lại âm thanh, vì tôi đã có ấn tượng rằng Android đặt ưu tiên cao cho các chủ đề này đã
  • Hành vi xảy ra trên Nexus 6 của tôi (Android 6.0.1), nhưng không phải trên Galaxy S6 tôi cũng có sẵn (Android 5.1.1).

Các triệu chứng mà tôi thấy thực sự có vẻ như hệ điều hành khởi động ưu tiên luồng âm thanh sau một vài giây không tương tác với điện thoại. Thê nay đung không? Có cách nào để tránh hành vi này không?

+0

Cũng không xảy ra trên Nexus 5 chạy Android 4.4.2. –

+0

Ghi nhật ký ưu tiên luồng trong khi phát lại dường như cho thấy mức độ ưu tiên của luồng không thực sự thay đổi khi chạm vào màn hình. Có lẽ sự kiện cảm ứng đang kích hoạt một gián đoạn gây rối với những gì mà trình lên lịch có khả năng quay trở lại? –

+0

Tôi gặp sự cố tương tự trong ứng dụng của mình. Miễn là tôi tương tác với màn hình, tất cả chạy trơn tru như nó phải. Ngay sau khi tôi ngừng chạm vào màn hình, nó bắt đầu với sự sụt giảm lớn sau một vài (khoảng 3-5 giây). Khi tôi bắt đầu tương tác lại với màn hình, nó trở lại hoạt động trơn tru. Nó không quan trọng nếu tương tác màn hình làm bất cứ điều gì thực sự, cũng không phải nếu ngón tay được kích hoạt với một điều khiển/nút cụ thể. Ngay khi ngón tay di chuyển trên màn hình, tất cả âm thanh đều chạy mượt mà. Nó không xảy ra trên Android 5.x, nó chỉ bắt đầu với 6.0, và nó cũng là trường hợp trên Android N. – gal

Trả lời

3

Trong khi xem bản trình bày âm thanh Google I/O 2016 mới nhất, cuối cùng tôi đã tìm ra nguyên nhân và giải pháp (xấu xí) cho vấn đề này.

Chỉ cần xem xung quanh một phút này, bạn kẹp ống (bắt đầu từ 8m56s): https://youtu.be/F2ZDp-eNrh4?t=8m56s

Nó giải thích tại sao điều này đang xảy ra và làm thế nào bạn có thể thoát khỏi nó.

Trên thực tế, Android sẽ làm chậm CPU sau vài giây không hoạt động để giảm mức sử dụng pin. Anh chàng trong video hứa hẹn một giải pháp thích hợp cho việc này sớm, nhưng bây giờ cách duy nhất để loại bỏ nó là gửi những chạm giả (đó là đề nghị chính thức).

Instrumentation instr = new Instrumentation(); 
instr.sendKeyDownUpSync(KeyEvent.KEYCODE_BACKSLASH); // or whatever event you prefer 

Lặp lại điều này với bộ hẹn giờ sau 1,5 giây và sự cố sẽ biến mất.

Tôi biết, đây là một hack xấu xí, và nó có thể có tác dụng phụ xấu xí phải được xử lý. Nhưng bây giờ, nó chỉ đơn giản là giải pháp duy nhất.

Cập nhật: Về nhận xét mới nhất của bạn ... đây là giải pháp của tôi. Tôi đang sử dụng MotionEvent.ACTION_DOWN thông thường tại một vị trí bên ngoài giới hạn màn hình. Mọi thứ khác can thiệp một cách không mong muốn với giao diện người dùng. Để tránh SecurityException, khởi tạo bộ đếm thời gian trong trình xử lý onStart() của hoạt động chính và chấm dứt nó trong trình xử lý onStop(). Vẫn có những tình huống khi ứng dụng chuyển sang nền (tùy thuộc vào tải CPU) mà bạn có thể chạy vào SecurityException, do đó bạn phải bao quanh cuộc gọi chạm giả với khối thử try.

Xin lưu ý rằng tôi đang sử dụng khung thời gian của riêng mình, vì vậy bạn phải chuyển đổi mã để sử dụng bất kỳ bộ hẹn giờ nào bạn muốn sử dụng.

Ngoài ra, tôi không thể đảm bảo rằng mã này là 100% chống đạn. Ứng dụng của tôi có ứng dụng hack, nhưng hiện đang ở trạng thái beta, do đó tôi không thể đảm bảo cho bạn nếu tính năng này hoạt động chính xác trên tất cả các thiết bị và phiên bản Android.

Timer fakeTouchTimer = null; 
Instrumentation instr; 
void initFakeTouchTimer() 
{ 
    if (this.fakeTouchTimer != null) 
    { 
     if (this.instr == null) 
     { 
      this.instr = new Instrumentation(); 
     } 
     this.fakeTouchTimer.restart(); 
    } 
    else 
    { 
     if (this.instr == null) 
     { 
      this.instr = new Instrumentation(); 
     } 
     this.fakeTouchTimer = new Timer(1500, Thread.MIN_PRIORITY, new TimerTask() 
     { 
      @Override 
      public void execute() 
      { 
       if (instr != null && fakeTouchTimer != null && hasWindowFocus()) 
       { 
        try 
        { 
         long downTime = SystemClock.uptimeMillis(); 

         MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, -100, -100, 0); 
         instr.sendPointerSync(event); 
         event.recycle(); 
        } 
        catch (Exception e) 
        { 
        } 
       } 
      } 
     }, true/*isInfinite*/); 
    } 
} 
void killFakeTouchTimer() 
{ 
    if (this.fakeTouchTimer != null) 
    { 
     this.fakeTouchTimer.interupt(); 
     this.fakeTouchTimer = null; 
     this.instr = null; 
    } 
} 

@Override 
protected void onStop() 
{ 
    killFakeTouchTimer(); 
    super.onStop(); 

    ..... 
} 

@Override 
protected void onStart() 
{ 
    initFakeTouchTimer(); 
    super.onStart(); 

    ..... 
} 
+0

Cảm ơn câu trả lời; điều này chắc chắn có vẻ như vấn đề tôi đã cố gắng để có được trái tim của. Tôi đã cập nhật ứng dụng của mình với công việc được đề xuất của họ, nhưng có vẻ như nó không may hơn nhiều so với dự đoán. Đặc biệt, nó có thể sụp đổ với một ngoại lệ bảo mật nếu cảnh báo khối lượng xuất hiện trong sự kiện cảm ứng mô phỏng (không có sự kiện liên lạc chương trình ứng dụng chéo). Bạn đã có cơ hội để thực hiện một phiên bản mạnh mẽ hơn của chính mình? –

+1

Đó là những gì tôi muốn nói với các tác dụng phụ xấu xí. SecurityException chỉ là một trong số chúng. Tôi đã cập nhật câu trả lời của mình với giải pháp cuối cùng. – gal

+1

Tôi chỉ nhận thấy rằng tôi đã không chăm sóc các tình huống như cảnh báo khối lượng (hoặc các tình huống khác có cùng tính chất) cho đến nay. Tôi cập nhật các giải pháp để có tất cả những tình huống được bảo hiểm. – gal

1

Được biết, the audio pipeline in Android 6 has been completely rewritten. Mặc dù các vấn đề liên quan đến độ trễ được cải thiện này trong hầu hết các trường hợp, nó không phải là không thể tạo ra một số tác dụng phụ không mong muốn, như thường là trường hợp với những thay đổi quy mô lớn như vậy.

Trong khi vấn đề của bạn dường như không phải là một trong những phổ biến, có một vài điều bạn có thể thử:

  • Tăng thread âm thanh ưu tiên. Ưu tiên mặc định cho chuỗi âm thanh trong Android là -16, với mức tối đa là -20, thường chỉ có sẵn cho các dịch vụ hệ thống. Mặc dù bạn không thể chỉ định giá trị này cho chuỗi âm thanh, nhưng bạn có thể chỉ định điều tốt nhất tiếp theo: -19 bằng cách sử dụng cờ ANDROID_PRIORITY_URGENT_AUDIO khi đặt mức độ ưu tiên của chuỗi.

  • Tăng số lượng bộ đệm để ngăn chặn bất kỳ loại jitter hoặc độ trễ nào (thậm chí bạn có thể lên tới 16). Tuy nhiên trên một số thiết bị the callback to fill a new buffer isn’t always called when it should.

  • This SO post có một số đề xuất để cải thiện độ trễ âm thanh trên Anrdoid. Quan tâm đặc biệt là các điểm 3, 4 và 5 trong câu trả lời được chấp nhận.

  • Kiểm tra xem hệ thống Android hiện tại có bật độ trễ thấp bằng cách truy vấn xem hasSystemFeature(FEATURE_AUDIO_LOW_LATENCY) hoặc hasSystemFeature(FEATURE_AUDIO_PRO).


Bên cạnh đó, this academic paper thảo luận về các chiến lược để cải thiện các vấn đề độ trễ liên quan đến âm thanh trong Android/OpenSL, bao gồm cách tiếp cận khoảng liên quan đến buffer- và gọi lại.

+0

Cảm ơn câu trả lời. Thật không may, tôi đã đọc tất cả các tài nguyên (rất hữu ích) này và áp dụng các kỹ thuật được đề xuất trong đó. Tôi đang chạy ở tốc độ mẫu thiết bị gốc và ở kích thước bộ đệm gốc của thiết bị trên thiết bị yêu cầu hỗ trợ âm thanh có độ trễ thấp (trên thực tế, tôi tin rằng đồng hồ Nexus 6 ở bộ đệm gốc nhỏ nhất ở 192 khung - 4 ms ở 48kHz). Việc tăng số bộ đệm đã không giúp ích cho lý do được mô tả trong bài viết heatvst.com mà bạn đã liên kết. Câu hỏi của tôi là cụ thể về lý do tại sao giao diện người dùng dường như ảnh hưởng đến phát lại âm thanh. –

+0

Bạn có cài đặt bất kỳ ứng dụng của bên thứ ba nào có thể lấy nét trong nền sau một vài giây không tương tác không? – Pickle

+1

Làm cách nào để tạo chủ đề âm thanh 'ANDROID_PRIORITY_URGENT_AUDIO' ưu tiên? –

-1

Force resampling đến tỷ lệ mẫu thiết bị gốc trên Android 6.

Sử dụng tỷ lệ mẫu có nguồn gốc của thiết bị của 48000. Ví dụ:

SLDataFormat_PCM dataFormat;

dataFormat.samplesPerSec = 48000;

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