JCodecを使って任意のフレームを取得してみます。勘ですぐに気づくと思いますが、nextFrame()をひたすら読みだせばできそうです。 nextFrame() が返すオブジェクトのメンバーに frameNoというメンバもあります。
//ダメな例
fun getFrame(pos : Long) : Bitmap{
val file = File("/sdcard/000.h264")
val buf = NIOUtils.fetchFromFile(file)
val es = BufferH264ES(buf)
var nextFrame = es.nextFrame()
val decoder = H264Decoder()
val pic = Picture.create(1280, 1024, ColorSpace.YUV420)
while(nextFrame != null && nextFrame.frameNo != pos){
nextFrame = es.nextFrame()
}
val op = decoder.decodeFrame(nextFrame.data, pic.data).cropped()
return AndroidUtil.toBitmap(op)
}
これで指定したフレームのビットマップが得られそうに思うじゃないですか。ダメです。h.264は前フレームとの (正確な言い方じゃないけど) 差分を使います。なので、フレームごとにデコードしなければだめです。
fun getFrame(pos : Long) : Bitmap{
val file = File("/sdcard/000.h264")
val buf = NIOUtils.fetchFromFile(file)
val es = BufferH264ES(buf)
var nextFrame = es.nextFrame()
val decoder = H264Decoder()
val pic = Picture.create(1280, 1024, ColorSpace.YUV420)
while(nextFrame != null && nextFrame.frameNo != pos){
val op = decoder.decodeFrame(nextFrame.data, pic.data)
nextFrame = es.nextFrame()
}
val op = decoder.decodeFrame(nextFrame.data, pic.data).cropped()
return AndroidUtil.toBitmap(op)
}
これで取得できるのですが、終わりのほうのフレームが欲しい時に、これでは効率が悪いですよね?ということで、次に続く。
