F2E Big Bang !!!

A Front-end Hack Diaries

ExoPlayer 筆記

- - posted in io2014,android,exoplayer,media, player

ExoPlayer – An application level media player for Android

exoplayer-url

Before ExoPlayer

之前 MediaPlayer 的用法

1
2
3
4
MediaPlayer player = MediaPlayer.create(ctx, uri, display);
player.start();
...
player.release();

mediaplayer-framework

MediaPlayer 隱藏很多的細節

方便使用卻難以客制化

例如自訂 buffer policy 或 cache

在 Jelly Bean 版本

Google 提供 MediaExtractor,MediaCodec and AudioTrack low-level API

exo-low-level

讓 media player 方便去做客制化

exo-high-level

What’s DASH

DASH

允許在播放的期間,依照網路速度調整影片的品質

ExoPlayer Benefit

  • Youtube use
  • 支援 Dynamic adaptive streaming over HTTP (DASH) and SmoothStreaming playback
  • DRM 保護
  • ExoPlayer gives a lot more control
  • ExoPlayer can easily update

exo vs mediaplayer

  • 減少啟動播放的延遲時間約 65%
  • 重新 buffer 的機率少了 40%
  • 平均播放高解析度影片的機率多了 11%

核心

MediaExtractorMediaCodec

exoplayer-framework exoplayer-model

提供

TrackRenderer

一個 abstract class

負責處理 video,audio 或 text 的播放

ExoPlayer library 提供這些 implements class:

  • MediaCodecVideoTrackRenderer as the default implementations rendering video
  • MediaCodecAudioTrackRenderer for audio
  • TextTrackRenderer for text

SampleSource

TrackRenderer 需要 SampleSource (interface)

它負責提供 格式資訊 和 media sample

ExoPlayer library 提供這些 implements class:

  • FrameworkSampleSource 使用 MediaExtractor 來 request,buffer 和解析 media sample! FrameworkSampleSource
1
2
3
4
5
6
7
8
  int numRenderer = 2;
  FrameworkSampleSource sampleSource = new FrameworkSampleSource(activity, uri, null, 2);
  MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource, null, true, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50);
  MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, null, true);
  ExoPlayer player = ExoPlayer.Factory.newInstance(numRenderer);
  player.prepare(videoRenderer, audioRenderer);
  player.setPlayWhenReady(true);
  

注意到,video 和 audio 的來源是同一個 URI,它也能來自不同的 URI,只需要分別給予兩個 FrameworkSampleSource object

  • ChunkSampleSource 提供 DASH or SmoothStreaming,未使用 MediaExtractor,而是自己實作 networking,buffering 和 media extraction

    它需要:

    • ChunkSource object,裡面包含 FormatEvaluatorDataSource
      • FormatEvaluator objects 會在每一塊 chunk 讀取前,去選擇有效的格式
      • DataSource objects 的任務就是去讀取資料
    • LoadControl object 可以控制 chunk 的 buffering 規則 ChunkSampleSource

Media presentation description parser

MediaPresentationDescriptionParser class to obtain Representation objects from media presentation description(MPD) files

支援格式

See Supported Media Formats for details

參考資料

ExoPlayer API Guide

Google I/O 2014 – Building great multi-media experiences on Android

ExoPlayer: Adaptive video streaming on Android

52 Weeks of UX: Finding Flow

- - posted in UX

FINDING FLOW

文章摘要

本篇文章是在描述 Optiaml Experience 狀態
是由 Mihaly Csikszentmihalyi 這位心理學教授
FLOW 這本書中所提出
什麼時候會進入此狀態呢?

“the mental state of operation
in which the person is fully immersed
in what he or she is doing by a feeling of energized focus,
full involvement,
and success in the process of the activity”

其實就是只當一個人非常非常專注在一件事情上
並且事情進行的十分順利且成功的時候
此狀態就會開啟

此研究有趣的因素有兩個
1. 之前的策略心理學大部分都是在研究有問題的人
因此他採取相反地方法
希望從成功的人身上找到可以複製的希望
2. 這研究適用於世界上所有的人,而不是只適用在愛因斯坦

又隨著軟體和硬體變得更容易使用
使得我們更可以專注在事情上面
而不用去煩惱設備的操作使用
例如 iPad 的發明
讓我們不用去煩惱視窗的操作
鍵盤的快捷鍵以及滑鼠使用等

因此,當一個設計達到一個程度上的簡約時
它和使用者的關係會發生改變
使用者有可能開始想要拿著它去作一些不一樣的事情
設計逐漸的消失在使用者的心中
可是卻大大的提升了使用經驗

最後
找尋心中的 FLOW 吧!

心得

FLOW 真是很玄的一個理論
有人稱他為 心流經驗 OR 流暢經驗 OR 神馳理論(囧)
台大心理系教授余德慧
在Csikszentmihalyi的Flow: The psychology of optimal experience中文版序中指出

心流出現時
會感受到行動與意識之間融合無間
整個意識的注意力集中在有限的視域
而行動的準確與立即的回饋有不斷互流的現象。

(這是不是EVA中的同步率啊XD)

生活上所有的事情
都有機會產生 FLOW
關鍵在於自己願不願意去投入的意志
當然
假如今天作的事情是自己有興趣且又是自己最拿手的
例如打籃球電慘對手
心流的產生想必更簡單
而設計在這邊扮演的角色
我想就是越簡單意用
意用到使用者根本就忘記了設計的存在
使他們可以完全沉浸在自己的創作世界裡面
那我想這就是一個最棒的設計了!

52 Weeks of UX: Changing Existing Situations

- - posted in UX

CHANGING EXISTING SITUATIONS

文章概要

本篇引述自人工智慧之父 Herbert Simon 的一段話

“Everyone designs who devise courses of action aimed at changing existing situations into prefer ones.
The intellectual activity that produces material artifacts is no different fundamentally
from the one that prescribes remedies for a sick patient or
the one that devises a new sales plan for a company
or a social welfare policy for a state.
Design, so construed, is the core of all professional training;
it is the principal mark that distinguishes the professions from the sciences.”

每個設法改變現狀,迎合己意的人都是在做設計。
每個生產材料人造物品的智慧活動沒有不一樣(?)
設計是專業訓練的核心
它是從科學去區分專業的重要標記

心得

又是一句很玄的話

不過大概可以理解為
當一個人對現狀不滿意或是無法滿足自己的需求
試圖去解決和改變現狀的行為
就是在做設計

52 Weeks of UX: Utility vs. Beauty

- - posted in ux

UTILITY VS. BEAUTY

文章概要

此篇文章大概在描述
一個好的設計
要兼具實用和美觀

在做設計的時候
常常看起來美觀卻不實用
或是實用卻不美觀

甚至是使用浮華和華麗手法(現在的流行趨勢)
去隱藏設計的問題
導致太容易專注在 “make it pretty”
卻沒有去考慮到這項設計的實用性

又或者
設計出一項非常實用的產品
可是看起來卻是枯燥又乏味

最優雅的設計是調和約束和精確度 並同時兼具實用和美觀

心得

在開發中
時常看到注重在實用性
例如提升產品穩定度
而忽略了美觀

不過很現實的
人是視覺動物
只要在產品中稍微加入了一點點美的元素
通常使用者都是會有反應的

所以一項好的設計
實用和美觀
都是不可或缺的

Android Concurrency: ReentrantLock

- - posted in android, concurrency

ReentrantLock

ReentrantLock uses the Ganga four bridge pattern

it provides mutual exclusion and implements the lock interface

  1. First, it inherits the bulk of its functionality from
    the AbstractQueuedSynchronizer class which
    provides a framework for implementing
    blocking locks and synchronizers that
    rely on First In, First Out or F.I.F.O.
    wait queues.

  2. Second, it implements several lock
    acquisition models via its common
    interface.

  3. The key methods in ReentrantLock are lock,
    lock interruptibly, and unlock.

Android Concurrency: CountDownLatch

- - posted in android, concurrency

CountDownLatch

Java CountDownLatch class that
implements barrier synchronization.

A barrier is a synchronization technique
that halts the
progress of one or more threads at a
particular point.

Barriers are commonly used in several ways.

One way is to defer the start of
current computations until after an object
has been initialized.

Another common use is to allow one thread
to wait until a group
of other concurrent threads are done with
their processing before it can continue.

52 Weeks of UX: The First Rule of UX

- - posted in UX

THE FIRST RULE OF UX

“You cannot not communicate. Every behaviour is a kind of communication. Because behaviour does not have a counterpart (there is no anti-behaviour), it is not possible not to communicate.” —Paul Watzlawick’s First Axiom of Communication

文章概要

溝通
是 UX 得第一個原則
一個好的設計師
會使用例如
copy-writing(?),文字的顏色,標題得對齊方式,全部大或小寫的導航連結等
去傳達想要表達的意思

所以我們可以時常問

“Does this element support or contradict what I am trying to communicate to the user?”

來幫助自己找到經常沒注意或忽略的事
從而去完善和改進他
最終提升了 User Experience


心得

可能是英文底子不夠好的關係
一直無法領悟文章的精髓

一開始以為
溝通
應該是建立在多方之間的行為
所以文章應該會描述如何和使用者作互動之類

不過看來看去
好像都沒有和使用者有關係

反而好像是在講述
該如何做好事前的溝通準備
例如使用
copy-writing,文字的顏色,標題得對齊方式,全部大或小寫的導航連結等
並反問自己這個元素是否可以讓使用者感受到我想表達的意思

JS Text Range Selector

- - posted in javascript

今天需要用到文字選取
情境是
當使用者需要更改檔案名稱時
直接將檔名反白選取
這樣也可以避免改到附檔名
如圖:
demo 程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

    /**
     * Text Range Selector
     *
     * @param   {Element}   element
     * @param   {Integer}   start
     * @param   {Integer}   end
     */
    function select (element, start, end) {
        element = element instanceof jQuery ? element.get(0) : element;
        end = end === -1 ? element.value.length : end;
        element.focus();
        try {
            if (element.createTextRange) {
                var range = element.createTextRange();

                if (win.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
                    start = element.value.substr(0, start).replace(/\r/g, '').length;
                    end = element.value.substr(0, end).replace(/\r/g, '').length;
                }

                range.collapse(true);
                range.moveStart('character', start);
                range.moveEnd('character', end - start);

                range.select();
            } else if (element.setSelectionRange) {
                element.setSelectionRange(start, end);
            }
        } catch (e) {
        }
    }