|
我现在一边在linux上用opencv抓取摄像头图像,encode之后用udp分包发送到另一端android端。然后在android端重新整合数据包并解码显示在imageview里。现在卡在了安卓端解码显示的部分,求教如何整理数据包并解码(android端是纯java开发,不是C++和jni调用的方式,因为android也不太熟)代码如下,linux上c++图像抓取代码,encode成.jpg格式:
- try {
- UDPSocket sock;
- int jpegqual = ENCODE_QUALITY; // Compression Parameter
- Mat frame, send;
- vector < uchar > encoded;
- VideoCapture cap(0); // Grab the camera
- namedWindow("send", CV_WINDOW_AUTOSIZE);
- if (!cap.isOpened()) {
- cerr << "OpenCV Failed to open camera";
- exit(1);
- }
- clock_t last_cycle = clock();
- while (1) {
- cap >> frame;
- if(frame.size().width==0)continue;//simple integrity check; skip erroneous data...
- resize(frame, send, Size(FRAME_WIDTH, FRAME_HEIGHT), 0, 0, INTER_LINEAR);
- vector < int > compression_params;
- compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
- compression_params.push_back(jpegqual);
- imencode(".jpg", send, encoded, compression_params);
- imshow("send", send);
- int total_pack = 1 + (encoded.size() - 1) / PACK_SIZE;
- int ibuf[1];
- ibuf[0] = total_pack;
- sock.sendTo(ibuf, sizeof(int), servAddress, servPort);
- for (int i = 0; i < total_pack; i++)
- sock.sendTo( & [i * PACK_SIZE], PACK_SIZE, servAddress, servPort);
- waitKey(FRAME_INTERVAL);
- clock_t next_cycle = clock();
- double duration = (next_cycle - last_cycle) / (double) CLOCKS_PER_SEC;
- cout << "\teffective FPS:" << (1 / duration) << " \tkbps:" << (PACK_SIZE * total_pack / duration / 1024 * 8) << endl;
- cout << next_cycle - last_cycle;
- last_cycle = next_cycle;
- }
- // Destructor closes the socket
- } catch (SocketException & e) {
- cerr << e.what() << endl;
- exit(1);
- }
复制代码 android上图像接收代码,用了asynctask方法。在doinbackground方法里接收数据包并重新整合,转换成string形式后publish到onprogressupdated方法里转换回byte然后放入mat解码并转换位bitmap显示。
- AsyncTask<Void, String, Void> camera = new AsyncTask<Void, String, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- try {
- DatagramSocket sock = new DatagramSocket(10003);
- String sendStr = "I'm the client.";
- byte[] sendbuf;
- sendbuf = sendStr.getBytes();
- InetAddress addr = InetAddress.getByName(message);
- DatagramPacket sendPacket = new DatagramPacket(sendbuf, sendbuf.length, addr, 10000); // vehicle side port set to 10000
- sock.send(sendPacket);
- //DatagramSocket server = new DatagramSocket(10003);
- //server.setBroadcast(true);
- byte[] buffer = new byte[65540];
- DatagramPacket recvPacket = new DatagramPacket(buffer, buffer.length);
- while(true) {
- do {
- sock.receive(recvPacket);
- } while (recvPacket.getLength() > 4); // int size 4
- byte[] longbuf = new byte[PACK_SIZE * total_pack];
- for (int i = 0; i < total_pack; i++) {
- sock.receive(recvPacket);
- System.arraycopy(buffer, 0, longbuf, i*PACK_SIZE, recvPacket.getLength());
- }
- String pic = new String(longbuf);
- //publishProgress("mark place success");
- publishProgress(pic);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- @Override
- protected void onProgressUpdate(String... values) {
复制代码 现在的问题是在上述imdecode那个地方程序会跑崩,直接闪退。抛出CvException。不知道是数据包整合的不对还是解码的api使用有问题。求大神指教。
这个接收端其实原来室友一个C++版本的,也就是说一段linux抓摄像头,一段linux上接受并解码。然后安卓端这个是我自己“翻译”过来的。如果需要C++原版,请参考如下部分。
- do {
- recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort);
- } while (recvMsgSize > sizeof(int));
- int total_pack = ((int * ) buffer)[0];
- cout << "expecting length of packs:" << total_pack << endl;
- char * longbuf = new char[PACK_SIZE * total_pack];
- for (int i = 0; i < total_pack; i++) {
- recvMsgSize = sock.recvFrom(buffer, BUF_LEN, sourceAddress, sourcePort);
- if (recvMsgSize != PACK_SIZE) {
- cerr << "Received unexpected size pack:" << recvMsgSize << endl;
- continue;
- }
- memcpy( & longbuf[i * PACK_SIZE], buffer, PACK_SIZE);
- }
- cout << "Received packet from " << sourceAddress << ":" << sourcePort << endl;
-
- Mat rawData = Mat(1, PACK_SIZE * total_pack, CV_8UC1, longbuf);
- Mat frame = imdecode(rawData, CV_LOAD_IMAGE_COLOR);
- if (frame.size().width == 0) {
- cerr << "decode failure!" << endl;
- continue;
- }
- imshow("recv", frame);
- free(longbuf);
复制代码
|
|