|
1 | 1 | package fr.xebia.streams.video
|
2 | 2 |
|
3 | 3 | import akka.NotUsed
|
4 |
| -import akka.actor.{ActorSystem, Props} |
| 4 | +import akka.actor.{ ActorSystem, Props } |
| 5 | +import akka.http.scaladsl.Http |
| 6 | +import akka.http.scaladsl.model.{ HttpRequest, HttpResponse } |
| 7 | +import akka.stream.Materializer |
5 | 8 | import akka.stream.actor.ActorPublisher
|
6 |
| -import akka.stream.scaladsl.Source |
| 9 | +import akka.stream.scaladsl.{ Framing, Source } |
| 10 | +import akka.util.{ ByteString, Timeout } |
| 11 | +import fr.xebia.streams.RemoteWebcamWindow._ |
7 | 12 | import org.bytedeco.javacpp.opencv_core._
|
8 | 13 | import org.bytedeco.javacv.Frame
|
9 | 14 | import org.bytedeco.javacv.FrameGrabber.ImageMode
|
| 15 | +import org.slf4j.LoggerFactory |
| 16 | + |
| 17 | +import scala.concurrent.Future |
10 | 18 |
|
11 | 19 | object Webcam {
|
12 | 20 |
|
13 | 21 | object local {
|
14 | 22 |
|
15 | 23 | def apply(
|
16 |
| - deviceId: Int, |
17 |
| - dimensions: Dimensions, |
18 |
| - bitsPerPixel: Int = CV_8U, |
19 |
| - imageMode: ImageMode = ImageMode.COLOR |
20 |
| - )(implicit system: ActorSystem): Source[Frame, NotUsed] = { |
| 24 | + deviceId: Int, |
| 25 | + dimensions: Dimensions, |
| 26 | + bitsPerPixel: Int = CV_8U, |
| 27 | + imageMode: ImageMode = ImageMode.COLOR |
| 28 | + )(implicit system: ActorSystem): Source[Frame, NotUsed] = { |
21 | 29 | val props: Props = LocalCamFramePublisher.props(deviceId, dimensions.width, dimensions.height, bitsPerPixel, imageMode)
|
22 | 30 | val webcamActorRef = system.actorOf(props)
|
23 |
| - val webcamActorPublisher = ActorPublisher[Frame](webcamActorRef) |
| 31 | + val localActorPublisher = ActorPublisher[Frame](webcamActorRef) |
24 | 32 |
|
25 |
| - Source.fromPublisher(webcamActorPublisher) |
| 33 | + Source.fromPublisher(localActorPublisher) |
26 | 34 | }
|
27 | 35 | }
|
28 | 36 |
|
29 | 37 | object remote {
|
30 | 38 |
|
31 |
| - def apply(host: String, port: String) |
32 |
| - (implicit system: ActorSystem): Source[Frame, NotUsed] = { |
33 |
| - Source.fromPublisher(???) |
| 39 | + import scala.concurrent.duration._ |
| 40 | + val logger = LoggerFactory.getLogger(getClass) |
| 41 | + |
| 42 | + implicit val timeout = Timeout(5.seconds) |
| 43 | + |
| 44 | + val beginOfFrame = ByteString(0xff, 0xd8) |
| 45 | + |
| 46 | + val endOfFrame = ByteString(0xff, 0xd9) |
| 47 | + |
| 48 | + //http://doc.akka.io/docs/akka/2.4/scala/stream/stream-cookbook.html#chunking-up-a-stream-of-bytestrings-into-limited-size-bytestrings |
| 49 | + def apply(host: String)(implicit system: ActorSystem, mat: Materializer): Future[Source[ByteString, Any]] = { |
| 50 | + implicit val ec = system.dispatcher |
| 51 | + val httpRequest = HttpRequest(uri = "/html/cam_pic_new.php") |
| 52 | + |
| 53 | + Http() |
| 54 | + .singleRequest(httpRequest) |
| 55 | + .map { response => logger.info(response.toString()); response } |
| 56 | + .map(_.entity.dataBytes) |
| 57 | + .map(_.via(Framing.delimiter(endOfFrame, maximumFrameLength = 100, allowTruncation = true))) |
| 58 | + .map(_.map(_.dropWhile(_ != beginOfFrame))) |
34 | 59 | }
|
35 | 60 |
|
36 | 61 | }
|
|
0 commit comments